逆向攻防世界CTF系列54-crypt

64位无壳

int __fastcall main(int argc, const char **argv, const char **envp){
  strcpy(Str, "12345678abcdefghijklmnopqrspxyz");
  memset(&Str[32], 0, 0x60ui64);
  memset(v10, 0, 0x17ui64);
  sub_1400054D0("%s", v10);
  v9 = malloc(0x408ui64);
  v3 = strlen(Str);
  sub_140001120(v9, Str, v3);
  v4 = strlen(v10);
  sub_140001240(v9, v10, v4);
  for ( i = 0; i < 22; ++i ){
    if (((unsigned __int8)v10[i] ^ 0x22) != byte_14013B000[i]){
      v5 = (void *)sub_1400015A0(&off_14013B020, "error");
      _CallMemberFunction0(v5, sub_140001F10);
      return 0;
    }
  }
  v7 = (void *)sub_1400015A0(&off_14013B020, "nice job");
  _CallMemberFunction0(v7, sub_140001F10);
  return 0;
}

看起来是一个flag解密校验题,先提出byte_14013B000

[
  0x9E, 0xE7, 0x30, 0x5F, 0xA7, 0x01, 0xA6, 0x53, 0x59, 0x1B, 
  0x0A, 0x20, 0xF1, 0x73, 0xD1, 0x0E, 0xAB, 0x09, 0x84, 0x0E, 
  0x8D, 0x2B, 0x00, 0x00
]

1240和1120应该做了某种处理,跟进看了1240后,发现用到v9,所以先看1120

__int64 __fastcall sub_140001120(_DWORD *a1, __int64 a2, int a3){
  *a1 = 0;
  a1[1] = 0;
  v9 = a1 + 2;
  for ( i = 0; i < 256; ++i ) v9[i] = i;
  v6 = 0;
  result = 0i64;
  LOBYTE(v7) = 0;
  for ( j = 0; j < 256; ++j ){
    v8 = v9[j];
    v7 = (unsigned __int8)(*(_BYTE *)(a2 + v6) + v8 + v7);
    v9[j] = v9[v7];
    v9[v7] = v8;
    if ( ++v6 >= a3 )
      v6 = 0;
    result = (unsigned int)(j + 1);
  }
  return result;
}

先初始化,然后交换v9[j]和v9[v7]也就是v9[byte(Str[v6]) + v8 + v7],得v9脚本:

def sub_140001120(a2: bytes, a3: int):
    v9 = list(range(256))  # 初始化v9为0-255
    v6 = 0
    v7 = 0
    for j in range(256):
        v7 = (v7 + a2[v6] + v9[j]) % 256
        v9[j], v9[v7] = v9[v7], v9[j]
        v6 += 1
        if v6 >= a3:
            v6 = 0

    return v9

def main():
    Str = b"12345678abcdefghijklmnopqrspxyz"
    v3 = len(Str)
    v9 = sub_140001120(Str, v3)
    print("v9 = ", v9)

if __name__ == "__main__":
    main()

逆向就行

_DWORD *__fastcall sub_140001240(_DWORD *a1, __int64 a2, int a3){
  v5 = *a1;
  v6 = a1[1];
  v9 = a1 + 2;
  for ( i = 0; i < a3; ++i ){
    v5 = (unsigned __int8)(v5 + 1);
    v7 = v9[v5];
    v6 = (unsigned __int8)(v7 + v6);
    v8 = v9[v6];
    v9[v5] = v8;
    v9[v6] = v7;
    *(_BYTE *)(a2 + i) ^= LOBYTE(v9[(unsigned __int8)(v8 + v7)]);
  }
  *a1 = v5;
  result = a1;
  a1[1] = v6;
  return result;
}

最终代码:

def sub_140001120(a2: bytes, a3: int):
    v9 = list(range(256))  # 初始化v9为0-255
    v6 = 0
    v7 = 0
    for j in range(256):
        v7 = (v7 + a2[v6] + v9[j]) % 256
        v9[j], v9[v7] = v9[v7], v9[j]
        v6 += 1
        if v6 >= a3:
            v6 = 0

    return v9

def sub_140001240(v9: list, v10: list, a3: int):
    v5 = 0
    v6 = 0
    for i in range(a3):
        v5 = (v5 + 1) % 256
        v7 = v9[v5]
        v6 = (v6 + v7) % 256
        v9[v5], v9[v6] = v9[v6], v9[v5] 
        v10[i] ^= v9[(v9[v5] + v9[v6]) % 256] 
    return v10

def main():
    Str = b"12345678abcdefghijklmnopqrspxyz"
    v3 = len(Str)
    v9 = sub_140001120(Str, v3)
    print("v9 = ", v9)
    v10 = [
      0x9E, 0xE7, 0x30, 0x5F, 0xA7, 0x01, 0xA6, 0x53, 0x59, 0x1B,
      0x0A, 0x20, 0xF1, 0x73, 0xD1, 0x0E, 0xAB, 0x09, 0x84, 0x0E,
      0x8D, 0x2B
    ]
    v10 = [k ^ 0x22 for k in v10]
    print("v10 = ", v10)
    v10 = sub_140001240(v9, v10, 22)
    for i in range(len(v10)):
        print(chr(v10[i]), end="")

if __name__ == "__main__":
    main()

flag{nice_to_meet_you}

但其实这是个RC4算法,先生成S盒,再生成密钥流,这种异或类得加密算法只需要重写逻辑即可