【CTF对抗-2024春秋杯网络安全联赛冬季赛 RE所有题目WP】此文章归类为:CTF对抗。
第一次在看雪发复现的完整比赛WP,望大佬们轻喷菜鸡
学习到了新的知识:断点检测0xcc(后面Hgame里又碰到了类似的题目)
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
|
unsigned __int64 main_program()
{ unsigned int seed[2]; // [rsp+20h] [rbp-80h] BYREF
__int64 v2; // [rsp+28h] [rbp-78h]
char s[48]; // [rsp+30h] [rbp-70h] BYREF
char s1[56]; // [rsp+60h] [rbp-40h] BYREF
unsigned __int64 v5; // [rsp+98h] [rbp-8h]
v5 = __readfsqword(0x28u);
*(_QWORD *)seed = 0LL;
v2 = 0LL;
custom_md5_init(seed);
srand (seed[0]);
printf ( "Enter input: " );
fgets (s, 43, stdin);
if ( strlen (s) == 42 )
{
memset (s1, 0, 0x2BuLL);
xor_string_with_rand(s, s1);
if ( ! memcmp (s1, &ida_chars, 0x2BuLL) )
puts ( "right" );
else
puts ( "wrong" );
}
else
{
puts ( "Invalid input length." );
}
return v5 - __readfsqword(0x28u);
} void __fastcall xor_string_with_rand( __int64 a1, __int64 a2)
{ int i; // [rsp+18h] [rbp-8h]
for ( i = 0; i <= 41; ++i )
*(_BYTE *)(i + a2) = ( rand () % 127) ^ *(_BYTE *)(i + a1);
} |
custom_md5_init里很关键,发现对文件函数内容做了md5加密,位置为custom_md5_init + 1024后
1
2
3
4
5
6
7
8
9
10
11
12
13
|
unsigned __int64 __fastcall custom_md5_init( __int64 a1)
{ char v2[96]; // [rsp+20h] [rbp-470h] BYREF
char v3[1032]; // [rsp+80h] [rbp-410h] BYREF
unsigned __int64 v4; // [rsp+488h] [rbp-8h]
v4 = __readfsqword(0x28u);
qmemcpy(v3, custom_md5_init, 0x400uLL);
MD5_Init(v2, ( char *)custom_md5_init + 1024, 128LL);
MD5_Update(v2, v3, 1024LL);
MD5_Final(a1, v2);
return v4 - __readfsqword(0x28u);
} |
为了保证动态调试获取正确的srand seed值,需要保证断点下在custom_md5_init函数前,查看汇编代码发现只有main函数在前头,因此只需在这里下断点,然后xor_string_with_rand下个断点打印rand()%127值
直接脚本异或获取flag
1
2
3
4
5
6
|
xor = [ 58 , 26 , 43 , 31 , 110 , 0 , 50 , 69 , 82 , 68 , 34 , 85 , 58 , 55 , 125 , 67 , 123 , 35 , 82 , 28 , 96 , 70 , 10 , 7 , 86 , 56 , 114 , 121 , 16 , 29 , 82 , 74 , 47 , 117 , 97 , 22 , 117 , 20 , 92 , 65 , 88 , 118 ]
cmp = [ 0x5C , 0x76 , 0x4A , 0x78 , 0x15 , 0x62 , 0x05 , 0x7C , 0x6B , 0x21 , 0x40 , 0x66 , 0x5B , 0x1A , 0x48 , 0x7A , 0x1E , 0x46 , 0x7F ,
0x28 , 0x02 , 0x75 , 0x68 , 0x2A , 0x34 , 0x0C , 0x4B , 0x1D , 0x3D , 0x2E , 0x6B , 0x7A , 0x17 , 0x45 , 0x07 , 0x75 , 0x47 , 0x27 ,
0x39 , 0x78 , 0x61 , 0x0B ]
for i in range ( 42 ):
print ( chr (xor[i] ^ cmp [i]), end = "")
|
ida反编译的是假flag逻辑,查看汇编代码发现有花指令,大部分是jz、jnz,直接nop
真正函数逻辑如下
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
int __cdecl sub_402B60( int a1, signed int Size)
{ char v3; // [esp+0h] [ebp-124h]
signed int i; // [esp+D0h] [ebp-54h]
_BYTE *v5; // [esp+DCh] [ebp-48h]
char v6[14]; // [esp+E8h] [ebp-3Ch]
char v7[38]; // [esp+F6h] [ebp-2Eh] BYREF
int v8; // [esp+11Ch] [ebp-8h]
v8 = strlen (Str);
v6[0] = 24;
v6[1] = -100;
v6[2] = 71;
v6[3] = 61;
v6[4] = 59;
v6[5] = -31;
v6[6] = 41;
v6[7] = 39;
v6[8] = -97;
v6[9] = 52;
v6[10] = -125;
v6[11] = -43;
v6[12] = -19;
v6[13] = -75;
qmemcpy(v7, "nY" , 2);
v7[2] = 127;
v7[3] = -34;
v7[4] = 71;
v7[5] = -41;
v7[6] = 101;
v7[7] = 63;
v7[8] = 122;
v7[9] = 51;
v7[10] = 91;
v7[11] = 100;
v7[12] = -74;
v7[13] = -6;
v7[14] = -108;
v7[15] = 85;
v7[16] = -121;
v7[17] = 66;
v7[18] = 32;
v7[19] = 6;
v7[20] = 12;
v7[21] = 105;
v7[22] = -2;
v7[23] = 114;
v7[24] = -87;
v7[25] = -28;
v7[26] = -47;
v7[27] = 124;
v5 = malloc (Size);
if ( !v5 )
return -1;
sub_4012AD(a1, ( int )v5, Size, ( int )Str, v8);
for ( i = 0; i < Size; ++i )
{
if ( v6[i] != v5[i] )
return 0;
}
sub_401096( "yes" , v3);
return Size;
} |
sub_4012AD是rc4加密,里面的异或魔改为减法操作,注意Str已经被hook替换掉了
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
|
def KSA(key):
""" Key-Scheduling Algorithm (KSA) 密钥调度算法"""
S = list ( range ( 256 ))
j = 0
for i in range ( 256 ):
j = (j + S[i] + key[i % len (key)]) % 256
S[i], S[j] = S[j], S[i]
return S
def PRGA(S):
""" Pseudo-Random Generation Algorithm (PRGA) 伪随机数生成算法"""
i, j = 0 , 0
while True :
i = (i + 1 ) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) % 256 ]
yield K
def RC4(key, text):
""" RC4 encryption/decryption """
S = KSA(key)
keystream = PRGA(S)
res = []
for char in text:
res.append((char + next (keystream))& 0xff )
return bytes(res)
key = b "DDDDAAAASSSS"
text = [ 24 , - 100 , 71 , 61 , 59 , - 31 , 41 , 39 , - 97 , 52 , - 125 , - 43 , - 19 , - 75 , ord ( "n" ), ord ( "Y" ), 127 , - 34 , 71 , - 41 , 101 , 63 , 122 , 51 , 91 , 100 , - 74 , - 6 , - 108 , 85 , - 121 , 66 , 32 , 6 , 12 , 105 , - 2 , 114 , - 87 , - 28 , - 47 , 124 ]
print (RC4(key, text).decode())
|
第一天的题发现直接其实早就出了,没读好题,爆破出来的key为oadi,输入发现有提示only xxx can get right flag啥的以为做的不对,结果最后才发现zip早就正确还原了
函数逻辑为:
由于key只有四位可以爆破,检查最终前四位是zip文件头504b0304即可
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
|
from base64 import b64encode
from itertools import product
from string import ascii_letters, digits
c = list (ascii_letters + digits)
xor = [ 0x0000000000000001 , 0x0000000000000057 , 0x000000000000002C , 0x000000000000007C , 0x00000000000000C7 , 0x0000000000000072 , 0x0000000000000020 , 0x0000000000000070 , 0x00000000000000A5 , 0x0000000000000096 , 0x0000000000000021 , 0x00000000000000DC , 0x00000000000000A8 , 0x0000000000000076 , 0x0000000000000069 , 0x0000000000000014 , 0x00000000000000C5 , 0x0000000000000024 , 0x0000000000000025 , 0x0000000000000002 , 0x00000000000000B7 , 0x000000000000007A , 0x00000000000000FC , 0x00000000000000F0 , 0x00000000000000C4 , 0x0000000000000049 , 0x0000000000000056 , 0x00000000000000C2 , 0x00000000000000C1 , 0x0000000000000095 , 0x00000000000000EC , 0x0000000000000026 , 0x00000000000000CC , 0x00000000000000F7 , 0x00000000000000FF , 0x0000000000000073 , 0x00000000000000E1 , 0x000000000000003F , 0x0000000000000084 , 0x0000000000000046 , 0x00000000000000A9 , 0x00000000000000F9 , 0x000000000000003D , 0x000000000000000E , 0x0000000000000045 , 0x00000000000000F1 , 0x00000000000000DA , 0x0000000000000092 , 0x00000000000000CE , 0x000000000000003B , 0x000000000000003C , 0x00000000000000A0 , 0x0000000000000016 , 0x00000000000000BC , 0x000000000000002D , 0x00000000000000BD , 0x00000000000000A4 , 0x0000000000000032 , 0x0000000000000090 , 0x0000000000000062 , 0x000000000000009D , 0x000000000000000C , 0x00000000000000DE , 0x00000000000000AD , 0x0000000000000040 , 0x00000000000000CF , 0x000000000000004B , 0x000000000000004D , 0x000000000000006E , 0x0000000000000079 , 0x00000000000000C8 , 0x0000000000000085 , 0x00000000000000D2 , 0x00000000000000AC , 0x0000000000000099 , 0x00000000000000E8 , 0x000000000000001E , 0x00000000000000C9 , 0x00000000000000D4 , 0x0000000000000006 , 0x0000000000000034 , 0x0000000000000066 , 0x00000000000000B8 , 0x00000000000000D3 , 0x0000000000000013 , 0x00000000000000F4 , 0x0000000000000042 , 0x000000000000001B , 0x0000000000000063 , 0x000000000000005F , 0x0000000000000082 , 0x000000000000005B , 0x0000000000000091 , 0x000000000000002A , 0x0000000000000033 , 0x000000000000005D , 0x00000000000000B9 , 0x000000000000007D , 0x00000000000000D5 , 0x000000000000006C , 0x000000000000000D , 0x0000000000000028 , 0x0000000000000008 , 0x000000000000009B , 0x0000000000000018 , 0x000000000000002E , 0x00000000000000A2 , 0x0000000000000067 , 0x000000000000005A , 0x00000000000000E6 , 0x000000000000008A , 0x0000000000000019 , 0x0000000000000050 , 0x000000000000009C , 0x00000000000000B1 , 0x00000000000000EF , 0x000000000000001F , 0x0000000000000012 , 0x00000000000000BA , 0x0000000000000086 , 0x0000000000000083 , 0x0000000000000077 , 0x0000000000000060 , 0x0000000000000094 , 0x00000000000000FD , 0x00000000000000F6 , 0x0000000000000054 , 0x00000000000000BF , 0x00000000000000A1 , 0x0000000000000093 , 0x0000000000000003 , 0x00000000000000E7 , 0x0000000000000058 , 0x00000000000000E5 , 0x000000000000009A , 0x000000000000007F , 0x0000000000000022 , 0x00000000000000BE , 0x00000000000000D9 , 0x0000000000000038 , 0x0000000000000027 , 0x0000000000000065 , 0x00000000000000D7 , 0x0000000000000023 , 0x00000000000000FB , 0x0000000000000071 , 0x00000000000000FA , 0x000000000000008F , 0x00000000000000F5 , 0x000000000000006D , 0x0000000000000051 , 0x000000000000009E , 0x00000000000000D6 , 0x000000000000008B , 0x0000000000000089 , 0x0000000000000011 , 0x00000000000000CA , 0x000000000000000F , 0x000000000000008E , 0x00000000000000CB , 0x00000000000000B3 , 0x00000000000000BB , 0x00000000000000F2 , 0x0000000000000087 , 0x0000000000000075 , 0x000000000000005C , 0x000000000000002F , 0x0000000000000098 , 0x000000000000002B , 0x000000000000001C , 0x00000000000000B4 , 0x00000000000000C6 , 0x000000000000000A , 0x000000000000004C , 0x0000000000000036 , 0x000000000000001A , 0x0000000000000015 , 0x0000000000000088 , 0x000000000000001D , 0x00000000000000E4 , 0x00000000000000C3 , 0x0000000000000097 , 0x0000000000000053 , 0x0000000000000030 , 0x000000000000004A , 0x000000000000003A , 0x00000000000000B5 , 0x0000000000000061 , 0x0000000000000055 , 0x00000000000000C0 , 0x00000000000000A7 , 0x00000000000000DB , 0x0000000000000029 , 0x0000000000000068 , 0x00000000000000E2 , 0x00000000000000E0 , 0x0000000000000010 , 0x0000000000000009 , 0x0000000000000041 , 0x0000000000000031 , 0x00000000000000F3 , 0x00000000000000AF , 0x00000000000000B6 , 0x000000000000006A , 0x000000000000006F , 0x0000000000000000 , 0x0000000000000005 , 0x000000000000000B , 0x00000000000000E3 , 0x00000000000000D1 , 0x000000000000008D , 0x0000000000000047 , 0x0000000000000074 , 0x0000000000000078 , 0x000000000000007B , 0x0000000000000064 , 0x00000000000000DD , 0x00000000000000AB , 0x00000000000000B0 , 0x0000000000000039 , 0x0000000000000037 , 0x00000000000000FE , 0x00000000000000ED , 0x0000000000000052 , 0x00000000000000CD , 0x0000000000000081 , 0x00000000000000F8 , 0x00000000000000AA , 0x0000000000000048 , 0x000000000000006B , 0x00000000000000D0 , 0x00000000000000EB , 0x000000000000008C , 0x0000000000000044 , 0x0000000000000059 , 0x0000000000000017 , 0x000000000000009F , 0x000000000000004F , 0x00000000000000B2 , 0x0000000000000035 , 0x00000000000000A3 , 0x000000000000007E , 0x00000000000000EE , 0x000000000000004E , 0x00000000000000DF , 0x00000000000000E9 , 0x0000000000000007 , 0x0000000000000043 , 0x00000000000000A6 , 0x00000000000000AE , 0x00000000000000D8 , 0x00000000000000EA , 0x0000000000000080 , 0x000000000000003E , 0x0000000000000004 , 0x000000000000005E ]
print (xor[ ord ( "S" )])
standard_base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
custom_base64_chars = "TSRQPONMLKJIHGFEDCBAUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
encode_map = {standard_base64_chars[i]: custom_base64_chars[i] for i in range ( 64 )}
with open ( "zip.zip" , "rb" ) as f:
data = f.read()
for i in product(c, repeat = 4 ):
s = "".join(i)
encode_s = b64encode(s.encode()).decode()
encode_s = list (''.join([encode_map.get(c, c) for c in encode_s]).encode())
for j in range ( 8 ):
if encode_s[j] ! = ord ( "=" ):
encode_s[j] = encode_s[j]^ 12
encode_s[ 0 ] ^ = 2
encode_s[ 2 ] ^ = 2
encode_s[ 3 ] ^ = 5
encode_s[ 4 ] ^ = 5
encode_s[ 5 ] ^ = 2
encode_s[ 7 ] ^ = 2
new_data = []
for j in range ( 4 ):
if data[j]:
new_data.append(data[j] ^ xor[encode_s[j % 8 ]] ^ encode_s[j % 8 ] ^ encode_s[j % 2 + 4 ])
else :
new_data.append( 0 )
if new_data = = [ 0x50 , 0x4b , 3 , 4 ]:
print ("".join(i))
break
|
得到key值直接运行main输入即可得到正确zip,里面就是flag
虽然对控制流进行了混淆,但还是可以看出来是tea类型的魔改加密,但挺让人恼火的是他魔改有点太狠了
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
int __cdecl sub_F91E00(_BYTE *a1, int a2)
{ int result; // eax
__int64 v3; // [esp-8h] [ebp-2C8h]
int j; // [esp+148h] [ebp-178h]
int v5; // [esp+154h] [ebp-16Ch]
int v6[21]; // [esp+158h] [ebp-168h]
int i; // [esp+1ACh] [ebp-114h]
int *v8; // [esp+1B8h] [ebp-108h]
_BYTE *v9; // [esp+1C4h] [ebp-FCh]
_DWORD *v10; // [esp+1D0h] [ebp-F0h]
_DWORD *v11; // [esp+1DCh] [ebp-E4h]
int v12; // [esp+1E8h] [ebp-D8h]
int v13; // [esp+1F4h] [ebp-CCh]
int v14; // [esp+200h] [ebp-C0h]
unsigned int v15; // [esp+20Ch] [ebp-B4h]
unsigned int v16; // [esp+218h] [ebp-A8h]
int v17; // [esp+224h] [ebp-9Ch]
unsigned int v18; // [esp+230h] [ebp-90h]
int v19; // [esp+23Ch] [ebp-84h]
int v20; // [esp+248h] [ebp-78h]
int v21; // [esp+254h] [ebp-6Ch] BYREF
int v22; // [esp+260h] [ebp-60h]
int v23; // [esp+26Ch] [ebp-54h]
int v24; // [esp+278h] [ebp-48h]
int v25; // [esp+284h] [ebp-3Ch]
int v26; // [esp+290h] [ebp-30h]
int v27; // [esp+29Ch] [ebp-24h]
int v28; // [esp+2A8h] [ebp-18h]
int v29; // [esp+2B4h] [ebp-Ch]
__CheckForDebuggerJustMyCode(&unk_F9D015);
a1[36] = 0;
a1[37] = 0;
a1[38] = 0;
a1[39] = 0;
v17 = 0xABCDEF12;
v16 = 0;
v15 = 0;
v14 = 0;
v13 = 0;
v12 = 1;
v11 = 0;
v10 = 0;
v9 = 0;
while ( 2 )
{
switch ( *(_DWORD *)(a2 + 4 * v14) )
{
case 0x66:
if ( v12 == 32 )
{
v8 = &v21;
for ( i = 0; i < 4; ++i )
*((_BYTE *)v8 + i) = byte_F9B000[4 * *((unsigned __int8 *)v8 + i)];
*v11 = v21;
*v10 = v20;
v14 -= 31;
v12 = 1;
++v13;
v16 = 0;
}
else
{
++v12;
v14 -= 31;
}
if ( v13 != 5 )
continue ;
v9 = a1;
v5 = 0x83845981;
v6[0] = 0;
v6[1] = 0x34402115;
v6[2] = 0;
v6[3] = 0xFB1F53D2;
v6[4] = 0;
v6[5] = 0x547564C9;
v6[6] = 0;
v6[7] = 0x3B42FCC6;
v6[8] = 0;
v6[9] = 0x2B67FCDE;
v6[10] = 0;
v6[11] = 0x675AB09C;
v6[12] = 0;
v6[13] = 0x1D47F41A;
v6[14] = 0;
v6[15] = 0x876D3272;
v6[16] = 0;
result = 0;
v6[17] = 0x734D7D95;
v6[18] = 0;
for ( j = 0; j < 10; ++j )
{
if ( *(_DWORD *)&v9[4 * j] != v6[2 * j - 1] || v6[2 * j] )
{
puts ( "You are Wrong!" );
exit (0);
}
result = j + 1;
}
return result;
case 0xA1:
v16 += xor(v17, 0x8BE8CF37); // 0x20252025
v15 = v16 >> 7; // 0x404a40
++v14;
continue ;
case 0xA2:
if ( v12 == 1 )
v11 = &a1[8 * v13];
else
*v11 = v21;
v21 = *v11 + v22;
++v14;
continue ;
case 0xA3:
v20 = *v10 + v22;
++v14;
continue ;
case 0xB2:
if ( v12 == 1 )
v10 = &a1[8 * v13 + 4];
else
*v10 = v20;
v29 = v14 + 1;
*(_DWORD *)(a2 + 4 * (v14 + 1)) = *v10;
v14 += 2;
continue ;
case 0xB3:
if ( v12 == 1 )
v11 = &a1[8 * v13];
else
*v11 = v21 - v22;
v29 = v14 + 1;
v24 = v22 + *v11;
*(_DWORD *)(a2 + 4 * v29) = v24;
v14 += 2;
continue ;
case 0xC4:
v29 = v14 + 1;
v18 = *(_DWORD *)(a2 + 4 * v14 - 4);
v27 = shl(v18, *(_DWORD *)(a2 + 4 * (v14 + 1)));
v14 += 2;
continue ;
case 0xC5:
v29 = v14 + 1;
v18 = *(_DWORD *)(a2 + 4 * v14 - 4);
v26 = shr(v18, *(_DWORD *)(a2 + 4 * (v14 + 1)));
v14 += 2;
continue ;
case 0xC6:
v19 = dword_F9B400[v28] + v16; // 这里基本确定是key值
v22 = xor(v25, v19);
v22 = xor(v22, 3);
++v14;
continue ;
case 0xD7:
v25 = xor(v27, v26);
v25 = xor(v25, 66);
++v14;
continue ;
case 0xD8:
v29 = v14 + 1;
HIDWORD(v3) = *(_DWORD *)(a2 + 4 * (v14 + 1));
if ( v15 )
{
LODWORD(v3) = v15;
v28 = sub_F91037(v3);
v15 = 0;
}
else
{
LODWORD(v3) = v16;
v28 = sub_F91037(v3);
}
v14 += 2;
continue ;
case 0xF4:
if ( *(_DWORD *)(a2 + 4 * v14 + 4) == 0xE1 )
v23 = v24;
if ( *(_DWORD *)(a2 + 4 * v14 + 4) == 0xE2 )
v23 = *v10;
v25 += v23;
v14 += 2;
continue ;
default :
puts ( "error" );
continue ;
}
}
} |
只能动态调试一步步看,纯考验调试耐心了,这是我当时记下来的加密流程
1
2
|
a = ((((s[ 4 : 8 ]<< 4 )^(s[ 4 : 8 ]>> 6 )^ 66 ) + s[ 4 : 8 ])^(total + 2 )^ 3 )
(((((a + s[: 4 ])<< 4 )^((a + s[: 4 ])>> 6 )^ 66 ) + (a + s[: 4 ]))^( 0x20252025 + 2 )^ 3 ) + s[ 4 : 8 ]
|
比赛后复现wp发现几乎接近了,还是key那里的操作没搞懂;然后最后xtea加密完的结果前四字节做了字节替换,因此逆向要先把字节替换还原再xtea解密
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
|
import struct
from ctypes import c_uint32
def xtea_encrypt(r, v, key):
v0, v1 = c_uint32(v[ 0 ]), c_uint32(v[ 1 ])
delta = 0x20252025
total = c_uint32( 0 )
for i in range (r):
v0.value + = (((v1.value << 4 ) ^ (v1.value >> 6 ) ^ 66 ) + v1.value) ^ (total.value + key[total.value & 3 ]) ^ 3
total.value + = delta
v1.value + = (((v0.value << 4 ) ^ (v0.value >> 6 ) ^ 66 ) + v0.value) ^ (total.value + key[(total.value >> 7 ) & 3 ]) ^ 3
return v0.value, v1.value
def xtea_decrypt(r, v, key):
v0, v1 = c_uint32(v[ 0 ]), c_uint32(v[ 1 ])
delta = 0x20252025
total = c_uint32(delta * r)
for i in range (r):
v1.value - = (((v0.value << 4 ) ^ (v0.value >> 6 ) ^ 66 ) + v0.value) ^ (total.value + key[(total.value >> 7 ) & 3 ]) ^ 3
total.value - = delta
v0.value - = (((v1.value << 4 ) ^ (v1.value >> 6 ) ^ 66 ) + v1.value) ^ (total.value + key[total.value & 3 ]) ^ 3
return v0.value, v1.value
if __name__ = = "__main__" :
key = [ 2 , 0 , 2 , 5 ]
b = [ 0x000000A4 , 0x000000C4 , 0x00000004 , 0x000000CE , 0x00000014 , 0x00000095 , 0x000000E9 , 0x00000011 , 0x00000031 , 0x00000018 , 0x000000B6 , 0x000000B0 , 0x00000001 , 0x00000026 , 0x00000024 , 0x0000006A , 0x0000007B , 0x00000012 , 0x000000CB , 0x00000067 , 0x000000DB , 0x000000F8 , 0x000000D2 , 0x0000007E , 0x0000009D , 0x000000D0 , 0x0000000C , 0x0000005F , 0x00000082 , 0x00000021 , 0x00000087 , 0x00000083 , 0x00000086 , 0x0000007C , 0x000000C2 , 0x0000009F , 0x00000029 , 0x000000CA , 0x000000BF , 0x00000049 , 0x000000DE , 0x0000004E , 0x000000CD , 0x00000062 , 0x00000053 , 0x000000BE , 0x000000A7 , 0x00000003 , 0x0000002F , 0x000000B5 , 0x000000AB , 0x00000094 , 0x000000CC , 0x0000002E , 0x0000001D , 0x000000F3 , 0x00000036 , 0x00000010 , 0x000000BA , 0x000000D7 , 0x00000013 , 0x00000035 , 0x000000E5 , 0x000000B3 , 0x00000081 , 0x0000001A , 0x000000A0 , 0x000000E7 , 0x00000025 , 0x00000075 , 0x000000AF , 0x00000051 , 0x00000043 , 0x0000005C , 0x00000050 , 0x00000048 , 0x000000D8 , 0x000000A3 , 0x0000003F , 0x00000071 , 0x0000007A , 0x000000C7 , 0x000000C6 , 0x00000090 , 0x000000B1 , 0x000000BB , 0x000000FA , 0x000000DD , 0x000000B9 , 0x000000F6 , 0x000000A9 , 0x000000B7 , 0x00000064 , 0x00000038 , 0x000000DF , 0x000000E0 , 0x00000008 , 0x000000B2 , 0x00000077 , 0x00000033 , 0x0000005B , 0x00000002 , 0x0000005E , 0x00000079 , 0x00000061 , 0x00000007 , 0x00000069 , 0x00000023 , 0x00000057 , 0x0000004A , 0x000000FD , 0x000000C0 , 0x0000002B , 0x000000A1 , 0x000000D1 , 0x00000028 , 0x00000009 , 0x0000006F , 0x00000080 , 0x00000055 , 0x000000FE , 0x00000042 , 0x000000E3 , 0x00000047 , 0x00000044 , 0x000000E1 , 0x000000FF , 0x000000BC , 0x0000007D , 0x0000008B , 0x0000009A , 0x00000060 , 0x000000AD , 0x00000097 , 0x000000FB , 0x0000008D , 0x000000D6 , 0x000000AC , 0x0000001E , 0x0000000F , 0x00000045 , 0x000000EA , 0x000000F5 , 0x0000004B , 0x0000002D , 0x0000003B , 0x00000022 , 0x0000001C , 0x0000005A , 0x00000072 , 0x00000046 , 0x000000C3 , 0x000000E4 , 0x0000005D , 0x000000DA , 0x00000092 , 0x0000009B , 0x0000000A , 0x000000BD , 0x00000099 , 0x00000085 , 0x00000034 , 0x00000073 , 0x000000A5 , 0x00000056 , 0x00000037 , 0x0000004C , 0x00000016 , 0x00000084 , 0x000000A2 , 0x000000B4 , 0x0000006D , 0x00000054 , 0x000000E6 , 0x000000C1 , 0x0000001F , 0x00000017 , 0x0000003D , 0x00000088 , 0x000000F7 , 0x00000015 , 0x00000058 , 0x000000EF , 0x0000004D , 0x000000EE , 0x00000089 , 0x00000068 , 0x00000059 , 0x000000B8 , 0x00000020 , 0x000000E8 , 0x000000DC , 0x000000C9 , 0x00000091 , 0x000000FC , 0x000000D5 , 0x000000C8 , 0x00000041 , 0x0000009E , 0x00000076 , 0x00000078 , 0x00000032 , 0x00000019 , 0x00000066 , 0x00000065 , 0x00000039 , 0x0000006B , 0x000000C5 , 0x00000052 , 0x00000027 , 0x000000A8 , 0x00000006 , 0x0000008E , 0x000000A6 , 0x0000000D , 0x00000098 , 0x0000008C , 0x000000F9 , 0x00000005 , 0x0000001B , 0x00000040 , 0x0000008F , 0x0000004F , 0x0000003C , 0x000000EB , 0x00000070 , 0x000000D9 , 0x00000063 , 0x000000D3 , 0x000000E2 , 0x0000002C , 0x000000F0 , 0x00000093 , 0x0000003A , 0x000000F4 , 0x00000000 , 0x000000F2 , 0x000000AA , 0x0000007F , 0x0000002A , 0x00000030 , 0x000000EC , 0x0000006C , 0x00000074 , 0x0000006E , 0x000000F1 , 0x0000000E , 0x0000003E , 0x000000ED , 0x00000096 , 0x000000AE , 0x0000008A , 0x000000CF , 0x0000000B , 0x0000009C , 0x000000D4 ]
v = [ 0x83845981 , 0x34402115 , 0xFB1F53D2 , 0x547564C9 , 0x3B42FCC6 , 0x2B67FCDE , 0x675AB09C , 0x1D47F41A , 0x876D3272 , 0x734D7D95 ]
for k in range ( 0 , len (v), 2 ):
v[k] = list (struct.pack( "<> , v[k]))
for i in range ( len (v[k])):
v[k][i] = b.index(v[k][i])
v[k] = struct.unpack( "<> , bytes(v[k]))[ 0 ]
for i in range ( 0 , len (v), 2 ):
v[i:i + 2 ] = xtea_decrypt( 32 , v[i:i + 2 ], key)
str_list = []
for i in range ( len (v)):
str_list.append(struct.pack( '<> , v[i]).decode())
print ( 'decrypted: %s' % ''.join(str_list))
|
jeb反编译可知检查了用户名和密码,其中用户名调用so文件来检查,ida分析可知是des加密,里面的各种盒全被魔改了
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
from Crypto.Util.number import long_to_bytes
# 初始置换IP IP = [ 0x3A , 0x32 , 0x2A , 0x22 , 0x1A , 0x12 , 0x0A , 0x02 , 0x3C , 0x34 , 0x2C , 0x24 , 0x1C , 0x14 , 0x0C , 0x04 , 0x3E , 0x36 , 0x2E , 0x26 , 0x1E , 0x16 , 0x0E , 0x06 , 0x40 , 0x38 , 0x30 , 0x28 , 0x20 , 0x18 , 0x10 , 0x08 , 0x39 , 0x31 , 0x29 , 0x21 , 0x19 , 0x11 , 0x09 , 0x01 , 0x3B , 0x33 , 0x2B , 0x23 , 0x1B , 0x13 , 0x0B , 0x03 , 0x3D , 0x35 , 0x2D , 0x25 , 0x1D , 0x15 , 0x0D , 0x05 , 0x3F , 0x37 , 0x2F , 0x27 , 0x1F , 0x17 , 0x0F , 0x07 ]
# 逆初始置换IP^-1 IP_INV = [ 0x28 , 0x08 , 0x30 , 0x10 , 0x38 , 0x18 , 0x40 , 0x20 , 0x27 , 0x07 , 0x2F , 0x0F , 0x37 , 0x17 , 0x3F , 0x1F , 0x26 , 0x06 , 0x2E , 0x0E , 0x36 , 0x16 , 0x3E , 0x1E , 0x25 , 0x05 , 0x2D , 0x0D , 0x35 , 0x15 , 0x3D , 0x1D , 0x24 , 0x04 , 0x2C , 0x0C , 0x34 , 0x14 , 0x3C , 0x1C , 0x23 , 0x03 , 0x2B , 0x0B , 0x33 , 0x13 , 0x3B , 0x1B , 0x22 , 0x02 , 0x2A , 0x0A , 0x32 , 0x12 , 0x3A , 0x1A , 0x21 , 0x01 , 0x29 , 0x09 , 0x31 , 0x11 , 0x39 , 0x19 ]
# 循环左移位数表 SHIFT_TABLE = [
1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1
] # 初始密钥置换PC-1 ''' PC-1是用于从初始密钥中生成56位的中间密钥(C0和D0)的置换表。 它从64位的初始密钥中筛选出56位,并丢弃了8位奇偶校验位。 这个置换是DES算法中的第一步,用于准备子密钥生成。 ''' PC_1 = [ 0x39 , 0x31 , 0x29 , 0x21 , 0x19 , 0x11 , 0x09 , 0x01 , 0x3A , 0x32 , 0x2A , 0x22 , 0x1A , 0x12 , 0x0A , 0x02 , 0x3B , 0x33 , 0x2B , 0x23 , 0x1B , 0x13 , 0x0B , 0x03 , 0x3C , 0x34 , 0x2C , 0x24 , 0x3F , 0x37 , 0x2F , 0x27 , 0x1F , 0x17 , 0x0F , 0x07 , 0x3E , 0x36 , 0x2E , 0x26 , 0x1E , 0x16 , 0x0E , 0x06 , 0x3D , 0x35 , 0x2D , 0x25 , 0x1D , 0x15 , 0x0D , 0x05 , 0x1C , 0x14 , 0x0C , 0x04 ]
# 子密钥置换PC-2 ''' PC-2是用于从56位中间密钥生成每一轮的48位子密钥的置换表。 在DES中,子密钥是通过对中间密钥进行轮次迭代和置换生成的。 PC-2负责选择并排列中间密钥的位,以生成48位的子密钥。 ''' PC_2 = [ 0x0E , 0x11 , 0x0B , 0x18 , 0x01 , 0x05 , 0x03 , 0x1C , 0x0F , 0x06 , 0x15 , 0x0A , 0x17 , 0x13 , 0x0C , 0x04 , 0x1A , 0x08 , 0x10 , 0x07 , 0x1B , 0x14 , 0x0D , 0x02 , 0x29 , 0x34 , 0x1F , 0x25 , 0x2F , 0x37 , 0x1E , 0x28 , 0x33 , 0x2D , 0x21 , 0x30 , 0x2C , 0x31 , 0x27 , 0x38 , 0x22 , 0x35 , 0x2E , 0x2A , 0x32 , 0x24 , 0x1D , 0x20 ]
# S-盒 S_BOX = [ 0x06 , 0x06 , 0x04 , 0x09 , 0x06 , 0x07 , 0x04 , 0x0B , 0x00 , 0x02 , 0x08 , 0x0C , 0x0A , 0x08 , 0x00 , 0x01 , 0x0C , 0x06 , 0x09 , 0x09 , 0x03 , 0x07 , 0x0B , 0x05 , 0x04 , 0x0D , 0x01 , 0x03 , 0x0F , 0x08 , 0x0A , 0x0D , 0x05 , 0x0D , 0x0A , 0x02 , 0x0C , 0x00 , 0x0E , 0x0D , 0x0B , 0x0E , 0x05 , 0x03 , 0x02 , 0x08 , 0x0E , 0x03 , 0x0E , 0x04 , 0x0B , 0x07 , 0x0F , 0x05 , 0x01 , 0x07 , 0x01 , 0x0C , 0x09 , 0x00 , 0x0A , 0x02 , 0x0F , 0x0F , 0x0A , 0x02 , 0x04 , 0x08 , 0x0C , 0x0F , 0x03 , 0x0A , 0x04 , 0x08 , 0x03 , 0x04 , 0x0E , 0x05 , 0x07 , 0x0F , 0x0F , 0x08 , 0x00 , 0x07 , 0x09 , 0x04 , 0x0D , 0x00 , 0x05 , 0x08 , 0x0B , 0x0E , 0x06 , 0x02 , 0x02 , 0x06 , 0x0D , 0x09 , 0x02 , 0x03 , 0x0A , 0x07 , 0x01 , 0x09 , 0x05 , 0x0F , 0x01 , 0x0B , 0x09 , 0x0E , 0x0D , 0x0B , 0x07 , 0x0C , 0x0C , 0x05 , 0x01 , 0x0A , 0x0E , 0x06 , 0x06 , 0x00 , 0x00 , 0x0C , 0x03 , 0x01 , 0x0B , 0x0D , 0x0A , 0x00 , 0x00 , 0x06 , 0x05 , 0x0D , 0x09 , 0x0E , 0x03 , 0x01 , 0x01 , 0x08 , 0x0D , 0x09 , 0x08 , 0x0F , 0x0C , 0x07 , 0x01 , 0x03 , 0x0F , 0x07 , 0x0B , 0x07 , 0x05 , 0x0A , 0x03 , 0x0A , 0x02 , 0x06 , 0x08 , 0x0A , 0x09 , 0x03 , 0x02 , 0x0E , 0x0E , 0x0B , 0x0B , 0x02 , 0x0D , 0x0F , 0x07 , 0x06 , 0x08 , 0x04 , 0x04 , 0x0C , 0x00 , 0x01 , 0x0E , 0x05 , 0x0C , 0x0C , 0x04 , 0x02 , 0x06 , 0x09 , 0x04 , 0x05 , 0x0B , 0x0F , 0x00 , 0x0D , 0x06 , 0x0C , 0x01 , 0x0B , 0x0E , 0x00 , 0x04 , 0x04 , 0x04 , 0x02 , 0x0F , 0x03 , 0x03 , 0x01 , 0x01 , 0x02 , 0x08 , 0x00 , 0x09 , 0x06 , 0x00 , 0x08 , 0x0D , 0x02 , 0x0C , 0x03 , 0x03 , 0x0A , 0x07 , 0x0F , 0x0C , 0x08 , 0x0F , 0x0E , 0x07 , 0x04 , 0x06 , 0x0E , 0x01 , 0x07 , 0x07 , 0x09 , 0x06 , 0x09 , 0x0F , 0x05 , 0x0B , 0x00 , 0x0A , 0x0D , 0x0D , 0x09 , 0x0D , 0x05 , 0x05 , 0x0B , 0x0C , 0x0B , 0x08 , 0x02 , 0x05 , 0x0A , 0x0E , 0x0A , 0x05 , 0x05 , 0x07 , 0x09 , 0x09 , 0x0D , 0x00 , 0x05 , 0x06 , 0x0B , 0x0C , 0x05 , 0x04 , 0x0F , 0x00 , 0x0C , 0x0B , 0x0D , 0x0D , 0x0A , 0x08 , 0x02 , 0x0D , 0x03 , 0x03 , 0x0E , 0x0E , 0x06 , 0x09 , 0x03 , 0x00 , 0x07 , 0x0A , 0x09 , 0x07 , 0x08 , 0x0A , 0x02 , 0x01 , 0x00 , 0x06 , 0x0E , 0x0F , 0x08 , 0x0E , 0x0F , 0x02 , 0x01 , 0x07 , 0x06 , 0x0F , 0x0A , 0x03 , 0x0C , 0x0C , 0x04 , 0x01 , 0x08 , 0x04 , 0x0B , 0x02 , 0x01 , 0x0B , 0x04 , 0x0E , 0x06 , 0x0E , 0x06 , 0x00 , 0x0D , 0x09 , 0x05 , 0x05 , 0x0B , 0x00 , 0x07 , 0x02 , 0x03 , 0x00 , 0x00 , 0x03 , 0x0D , 0x08 , 0x02 , 0x0F , 0x09 , 0x01 , 0x07 , 0x09 , 0x01 , 0x0C , 0x04 , 0x0A , 0x09 , 0x08 , 0x0B , 0x04 , 0x01 , 0x06 , 0x0F , 0x0C , 0x0E , 0x0B , 0x02 , 0x05 , 0x0E , 0x0D , 0x04 , 0x03 , 0x07 , 0x01 , 0x0F , 0x0B , 0x0A , 0x03 , 0x07 , 0x08 , 0x08 , 0x0F , 0x05 , 0x0C , 0x0C , 0x0A , 0x0A , 0x04 , 0x06 , 0x0D , 0x02 , 0x0F , 0x0E , 0x0A , 0x03 , 0x03 , 0x0F , 0x0C , 0x0E , 0x00 , 0x02 , 0x0E , 0x0C , 0x08 , 0x00 , 0x05 , 0x06 , 0x0E , 0x02 , 0x00 , 0x01 , 0x08 , 0x01 , 0x0D , 0x04 , 0x0B , 0x04 , 0x07 , 0x0B , 0x09 , 0x0F , 0x01 , 0x0C , 0x05 , 0x00 , 0x07 , 0x0D , 0x06 , 0x0A , 0x06 , 0x0C , 0x0B , 0x06 , 0x0D , 0x03 , 0x08 , 0x04 , 0x09 , 0x09 , 0x0D , 0x04 , 0x02 , 0x05 , 0x01 , 0x07 , 0x09 , 0x05 , 0x07 , 0x02 , 0x08 , 0x0F , 0x03 , 0x0A , 0x0A , 0x0B , 0x04 , 0x07 , 0x04 , 0x0F , 0x00 , 0x05 , 0x09 , 0x0E , 0x08 , 0x0B , 0x0D , 0x00 , 0x07 , 0x03 , 0x01 , 0x02 , 0x01 , 0x06 , 0x07 , 0x05 , 0x0C , 0x04 , 0x0D , 0x0D , 0x08 , 0x01 , 0x05 , 0x0C , 0x0B , 0x09 , 0x05 , 0x0B , 0x06 , 0x0A , 0x03 , 0x01 , 0x0F , 0x0E , 0x0E , 0x0F , 0x09 , 0x09 , 0x0F , 0x02 , 0x0C , 0x0C , 0x0E , 0x00 , 0x04 , 0x08 , 0x06 , 0x03 , 0x0B , 0x07 , 0x03 , 0x06 , 0x0A , 0x02 , 0x00 , 0x02 , 0x08 , 0x0A , 0x0A , 0x0D ]
S_BOX = [[[S_BOX[i * 64 + row * 16 + col] for col in range ( 16 )] for row in range ( 4 )] for i in range ( 8 )]
# 扩展置换 E置换 E = [ 0x20 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 , 0x09 , 0x08 , 0x09 , 0x0A , 0x0B , 0x0C , 0x0D , 0x0C , 0x0D , 0x0E , 0x0F , 0x10 , 0x11 , 0x10 , 0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x14 , 0x15 , 0x16 , 0x17 , 0x18 , 0x19 , 0x18 , 0x19 , 0x1A , 0x1B , 0x1C , 0x1D , 0x1C , 0x1D , 0x1E , 0x1F , 0x20 , 0x01 ]
# P-盒 P = [ 0x10 , 0x07 , 0x14 , 0x15 , 0x1D , 0x0C , 0x1C , 0x11 , 0x01 , 0x0F , 0x17 , 0x1A , 0x05 , 0x12 , 0x1F , 0x0A , 0x02 , 0x08 , 0x18 , 0x0E , 0x20 , 0x1B , 0x03 , 0x09 , 0x13 , 0x0D , 0x1E , 0x06 , 0x16 , 0x0B , 0x04 , 0x19 ]
def permute(block, table):
"""根据置换表对输入块进行置换"""
return [block[i - 1 ] for i in table]
def left_shift(bits, n):
"""左移n位"""
return bits[n:] + bits[:n]
def generate_subkeys(key):
"""生成16个子密钥"""
# 初始密钥置换(PC-1)
key = permute(key, PC_1)
# 分为左右两部分
left = key[: 28 ]
right = key[ 28 :]
subkeys = []
for i in range ( 16 ):
# 左移
left = left_shift(left, SHIFT_TABLE[i])
right = left_shift(right, SHIFT_TABLE[i])
# 合并并置换(PC-2)
combined = left + right
subkey = permute(combined, PC_2)
subkeys.append(subkey)
return subkeys
def s_box_substitution(bits):
"""S盒替换"""
output = []
for i in range ( 8 ):
# 每6位输入到S盒
row = (bits[i * 6 ] << 1 ) + bits[i * 6 + 5 ]
col = (bits[i * 6 + 1 ] << 3 ) + (bits[i * 6 + 2 ] << 2 ) + (bits[i * 6 + 3 ] << 1 ) + bits[i * 6 + 4 ]
val = S_BOX[i][row][col]
output.extend([ int (bit) for bit in format (val, '04b' )])
return output
def des_encrypt_block(block, subkeys):
"""加密一个64位的数据块"""
# 初始置换
block = permute(block, IP)
# 分为左右两部分
left = block[: 32 ]
right = block[ 32 :]
# 16轮Feistel网络
for i in range ( 16 ):
# 扩展置换(E)
expanded = permute(right, E)
# 与子密钥异或
xored = [expanded[j] ^ subkeys[i][j] for j in range ( 48 )]
# S盒替换
sbox_output = s_box_substitution(xored)
# P置换
p_output = permute(sbox_output, P)
# 与左半部分异或
new_right = [left[j] ^ p_output[j] for j in range ( 32 )]
# 更新左右部分
left = right
right = new_right
# 合并左右部分
combined = right + left
# 逆初始置换
ciphertext = permute(combined, IP_INV)
return ciphertext
def des_decrypt_block(block, subkeys):
"""解密一个64位的数据块"""
# 解密与加密过程类似,只是子密钥顺序相反
return des_encrypt_block(block, subkeys[:: - 1 ])
def num2bin(n):
s = bin (n)[ 2 :]
s = s.zfill( round ( len (s) / 64 ) * 64 )
return [ int (i) for i in s]
# 示例 if __name__ = = "__main__" :
# 密钥(64位)
# key = num2bin(0x2179656B2179656B)
key = num2bin( 0x6b6579216b657921 )
# 生成子密钥
subkeys = generate_subkeys(key)
# 加密
ciphertext = num2bin( 0x7deae0db1bd66d55d1e9c0710c01132b )
for i in range ( 0 , len (ciphertext), 64 ):
# 解密
decrypted_text = des_decrypt_block(ciphertext[i:i + 64 ], subkeys)
print (long_to_bytes( int ("".join([ str (i) for i in decrypted_text]), 2 )))
b '7d77cfe8'
b '\x08\x08\x08\x08\x08\x08\x08\x08'
|
借着chatgpt好不容易实现了个可以用的python脚本,易知用户名为'7d77cfe8'
checkpassword是skip32算法,要注意的是算法类里的FTABLE被jni hook替换了,还是借助try进行了隐藏
。
frida已会一点:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
Java.perform( function () {
var Skip32 = Java.use( 'com.ex.skip.Skip32' );
// 保存原始FTABLE的引用
var originalFTABLE = Skip32.FTABLE.value;
console.log(originalFTABLE);
// Hook g函数
var gFunc = Skip32.g;
gFunc.implementation = function (arg3, arg4, arg5) {
// 执行原始函数
var result = this .call(arg3, arg4, arg5);
// 调用后的FTABLE值
console.log(originalFTABLE);
console.log( "g函数返回值: " + result);
return result;
};
}); |
解密脚本很简单,skip32就是对称加密,只需要把skip32最后一个参数设置为0即可进行解密
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
class Skip32:
FTABLE = [ 164 , 216 , 10 , 132 , 249 , 73 , 247 , 245 , 180 , 34 , 22 , 121 , 154 , 178 , 176 , 250 , 232 , 46 , 78 , 139 , 207 , 77 , 203 , 47 , 83 , 150 , 218 , 31 , 79 , 57 , 69 , 41 , 11 , 224 , 3 , 161 , 24 , 242 , 97 , 105 , 19 , 184 , 123 , 196 , 234 , 251 , 62 , 84 , 151 , 133 , 108 , 187 , 243 , 100 , 155 , 26 , 125 , 175 , 230 , 246 , 248 , 23 , 107 , 163 , 58 , 183 , 124 , 16 , 194 , 148 , 130 , 28 , 239 , 181 , 27 , 235 , 209 , 146 , 48 , 185 , 86 , 186 , 219 , 134 , 64 , 66 , 192 , 225 , 91 , 89 , 129 , 96 , 103 , 12 , 217 , 145 , 54 , 214 , 193 , 168 , 52 , 7 , 102 , 106 , 70 , 1 , 149 , 87 , 110 , 153 , 156 , 119 , 152 , 253 , 179 , 195 , 177 , 255 , 220 , 33 , 226 , 236 , 215 , 229 , 222 , 72 , 75 , 30 , 67 , 238 , 159 , 111 , 74 , 61 , 206 , 68 , 40 , 211 , 8 , 213 , 223 , 200 , 104 , 25 , 138 , 204 , 49 , 32 , 142 , 199 , 144 , 171 , 201 , 117 , 221 , 202 , 94 , 93 , 50 , 165 , 113 , 137 , 98 , 45 , 160 , 14 , 44 , 136 , 81 , 131 , 85 , 101 , 39 , 126 , 4 , 65 , 53 , 76 , 29 , 116 , 210 , 197 , 254 , 60 , 205 , 252 , 128 , 172 , 231 , 63 , 92 , 166 , 174 , 5 , 36 , 157 , 21 , 82 , 35 , 241 , 42 , 122 , 114 , 127 , 0 , 141 , 15 , 227 , 13 , 240 , 189 , 115 , 118 , 112 , 56 , 162 , 237 , 212 , 143 , 99 , 140 , 135 , 17 , 233 , 9 , 120 , 18 , 191 , 147 , 80 , 37 , 198 , 51 , 55 , 158 , 208 , 244 , 167 , 188 , 173 , 95 , 109 , 170 , 20 , 88 , 38 , 182 , 228 , 190 , 169 , 59 , 2 , 6 , 90 , 43 , 71 ]
@staticmethod
def checkpass(password, key):
target = [ 52 , 0x8E , 0xE2 , 0xAC , 108 , 94 , 80 , 51 , 11 , 0xFB , 68 , 0xA4 , 0xE7 , 6 , 0x7C , 0xDF , 100 , 62 , 0x74 , 70 ]
password_array = target.copy()
# password_array = Skip32.string_to_ascii_array(password)
if len (password_array) ! = 20 :
return False
for i in range ( 0 , len (password_array), 4 ):
block = (password_array[i] << 24 ) | (password_array[i + 1 ] << 16 ) | (password_array[i + 2 ] << 8 ) | password_array[i + 3 ]
encrypted_block = Skip32.eee(block, key)
password_array[i] = (encrypted_block >> 24 ) & 0xFF
password_array[i + 1 ] = (encrypted_block >> 16 ) & 0xFF
password_array[i + 2 ] = (encrypted_block >> 8 ) & 0xFF
password_array[i + 3 ] = encrypted_block & 0xFF
print ("".join( map ( chr , password_array)))
for i in range ( len (target)):
if target[i] ! = password_array[i]:
return False
return True
@staticmethod
def eee(value, key):
v = [(value >> 24 ) & 0xFF , (value >> 16 ) & 0xFF , (value >> 8 ) & 0xFF , value & 0xFF ]
Skip32.skip32(key, v, False )
return (v[ 0 ] << 24 ) | (v[ 1 ] << 16 ) | (v[ 2 ] << 8 ) | v[ 3 ]
@staticmethod
def g(key, round , value):
v5 = value & 0xFF
v0 = (value >> 8 ) ^ Skip32.FTABLE[key[( round * 4 ) % 8 ] ^ v5]
v5_1 = v5 ^ Skip32.FTABLE[key[(( round * 4 ) + 1 ) % 8 ] ^ v0]
v0_1 = v0 ^ Skip32.FTABLE[key[(( round * 4 ) + 2 ) % 8 ] ^ v5_1]
return (v0_1 << 8 ) | (Skip32.FTABLE[key[(( round * 4 ) + 3 ) % 8 ] ^ v0_1] ^ v5_1)
@staticmethod
def skip32(key, data, encrypt):
if encrypt:
round_start, round_step = 0 , 1
else :
round_start, round_step = 23 , - 1
v3 = (data[ 0 ] << 8 ) | data[ 1 ]
v5 = (data[ 2 ] << 8 ) | data[ 3 ]
for _ in range ( 12 ):
v5 ^ = Skip32.g(key, round_start, v3) ^ round_start
round_start + = round_step
v3 ^ = Skip32.g(key, round_start, v5) ^ round_start
round_start + = round_step
data[ 0 ] = (v5 >> 8 ) & 0xFF
data[ 1 ] = v5 & 0xFF
data[ 2 ] = (v3 >> 8 ) & 0xFF
data[ 3 ] = v3 & 0xFF
@staticmethod
def string_to_ascii_array(s):
return [ ord (c) for c in s]
# 示例 if __name__ = = "__main__" :
key = b "7d77cfe8" # 8字节密钥,也就是前面的用户名8字节
password = "testpassword12345678" # 20字节密码
skip32 = Skip32()
result = skip32.checkpass(password, key)
|
最终答案是flag{username+password}
纯恶心人的,上千行main只能动态一点点调试分析,也没啥逆向技术含金量
我把大概加密流程贴出来
输入字符串
检查长度30(输入a4来测试)
此时只需要关注这个qword,发现他做的运算如下
正好两两一组,相当于做了哈希
后面有15组比较
到这里就明了了,测试下发现正好是逆序
ok爆破启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from string import printable
qword = 0xCBF29CE484222325
s = "08985807b541d18fd5f2d079088c0b172282110ea367087223826d0a97ceea455feb92ec9da6ccc6418727fdc0a2295bbf325bb7f6fb98b90669076ed7c9bfb3d905a4abf3eb7f225f5741aae1954e6c8f70569021c638dde77f76949e5db63a7f98a3f5e1b1e3409b7cd1e5a8dea236d3c21142b990e7b8"
def brute(qword, i):
q = qword
for c1 in printable:
for c2 in printable:
q = qword
q = 0x100000001B3 * (q ^ ord (c1)) & 0xffffffffffffffff
q = 0x100000001B3 * (q ^ ord (c2)) & 0xffffffffffffffff
if q = = int (s[ 16 * i: 16 * i + 16 ], 16 ):
return c1 + c2, q
flag = ""
for i in range ( 15 ):
f, qword = brute(qword, i)
flag + = f
print (flag) # flag{BanGDream!ItsMyRust!!!!!}
|
首先题目给的exe会在C:\Users\xxx\AppData\Local\Temp\onefile_xxxx\
下生成新的exe以及python dll,查看可知程序是python打包过来的
还是动态调试不停的找输入点如下,这个函数里有“input”字符串且动调这里输入(测试字符为aaaaaaa),因此合理猜测当前函数是主函数
往下动调发现len函数
接着是cmp函数,发现要求输入长度为40否则v14、v15为0,进入if打印wrong并退出
重新输入40个a测试,发现进入大循环,下图这里出现了取值操作
更多【CTF对抗-2024春秋杯网络安全联赛冬季赛 RE所有题目WP】相关视频教程:www.yxfzedu.com