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

64位无壳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

1
2
3
4
5
[
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
__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脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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()

逆向就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
_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;
}

最终代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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盒,再生成密钥流,这种异或类得加密算法只需要重写逻辑即可