main 函数挺大,不过没加混淆,其他函数都是加了混淆的。看看混淆模式后写个脚本提取指令去混淆:
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
|
#!/usr/bin/env python3
# import ida_bytes
import
keystone
import
capstone
def
set_x86():
global
ks, cs
ks
=
keystone.Ks(keystone.KS_ARCH_X86, keystone.KS_MODE_32)
cs
=
capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32)
set_x86()
def
asm(code, addr
=
0
):
return
bytes(ks.asm(code, addr)[
0
])
def
disasm(code, addr
=
0
):
for
i
in
cs.disasm(code, addr):
return
(
'%s %s'
%
(i.mnemonic, i.op_str))
def
ins_len(code):
return
len
(
next
(cs.disasm(code,
0
)).bytes)
def
to_char(x):
assert
0
<
=
x <
0x100
if
x >
=
0x80
: x
-
=
0x100
return
x
def
to_int(b):
assert
len
(b)
=
=
4
x
=
int
.from_bytes(b,
'little'
)
if
x >
=
1
<<
31
: x
-
=
1
<<
32
return
x
def
make_label(i):
return
'_%x'
%
(i
+
ob_start)
ob_start
=
0x403AC0
ob_end
=
0x617DE0
def
extract_block(ins, i):
# print('extract block: 0x%x' % (ob_start + i))
is_zero
=
False
ebx_ebp
=
False
push_eax
=
False
push_ebx
=
False
push_eax_i
=
None
push_ebx_i
=
None
eax_value
=
None
eax_value_i
=
None
eax_value_2
=
None
eax_value_2_i
=
None
ebx_value
=
None
ebx_value_i
=
None
test_eax
=
False
push_value
=
None
last_i
=
None
while
True
:
if
i
in
ins:
if
last_i:
ins[last_i]
+
=
'\njmp %s'
%
make_label(i)
return
[]
# print(hex(i + ob_start))
if
data[i]
=
=
0x0f
and
0x80
<
=
data[i
+
1
] <
0x90
:
# j?? dword
offset
=
to_int(data[i
+
2
: i
+
6
])
if
data[i
+
6
]
=
=
0x0f
and
data[i
+
7
]
=
=
data[i
+
1
] ^
1
and
\
offset
=
=
6
+
to_int(data[i
+
8
: i
+
12
]):
ins[i]
=
'jmp %s'
%
make_label(i
+
6
+
offset)
last_i
=
None
i
+
=
6
+
offset
elif
data[i
+
1
]
=
=
0x84
and
is_zero:
# jz
ins[i]
=
'jmp %s'
%
make_label(i
+
6
+
offset)
last_i
=
None
i
+
=
6
+
offset
elif
data[i
+
1
]
=
=
0x85
and
test_eax:
# jnz
ins[i]
=
'jmp %s'
%
make_label(i
+
6
+
offset)
last_i
=
None
i
+
=
6
+
offset
else
:
mnem
=
disasm(data[i: i
+
6
]).split(
' '
)[
0
]
ins[i]
=
'%s %s\njmp %s'
%
(mnem, make_label(i
+
6
+
offset), make_label(i
+
6
))
return
[i
+
6
, i
+
6
+
offset]
elif
data[i]
=
=
0x3b
and
data[i
+
1
]
=
=
0xc0
:
# cmp eax, eax
is_zero
=
True
test_eax
=
False
ins[i]
=
'cmp eax, eax'
last_i
=
i
i
+
=
2
elif
data[i]
=
=
0x3b
and
data[i
+
1
]
=
=
0xdb
:
# cmp ebx, ebx
is_zero
=
True
test_eax
=
False
ins[i]
=
'cmp ebx, ebx'
last_i
=
i
i
+
=
2
elif
data[i]
=
=
0x50
and
eax_value:
# push eax
push_eax_i
=
i
push_eax
=
True
ins[i]
=
'push eax'
last_i
=
i
i
+
=
1
elif
data[i]
=
=
0x53
:
# push ebx
push_ebx_i
=
i
push_ebx
=
True
ins[i]
=
'push ebx'
last_i
=
i
i
+
=
1
elif
data[i]
=
=
0x68
:
# push dword
value
=
to_int(data[i
+
1
: i
+
5
])
if
data[i
+
5
]
=
=
0xc3
:
# ret
ins[i]
=
'jmp %s'
%
make_label(value
-
ob_start)
last_i
=
None
i
=
value
-
ob_start
else
:
push_value
=
value
push_value_i
=
i
ins[i]
=
'push 0x%x'
%
push_value
last_i
=
i
i
+
=
5
elif
0x70
<
=
data[i] <
0x80
:
# j?? short
offset
=
to_char(data[i
+
1
])
if
data[i
+
2
]
=
=
data[i] ^
1
and
offset
=
=
2
+
to_char(data[i
+
3
]):
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
offset)
last_i
=
None
i
+
=
2
+
offset
elif
data[i]
=
=
0x74
and
is_zero:
# jz short
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
offset)
last_i
=
None
i
+
=
2
+
offset
elif
data[i]
=
=
0x75
and
test_eax:
# jnz short
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
offset)
last_i
=
None
i
+
=
2
+
offset
else
:
mnem
=
disasm(data[i: i
+
2
]).split(
' '
)[
0
]
ins[i]
=
'%s %s\njmp %s'
%
(mnem, make_label(i
+
2
+
offset), make_label(i
+
2
))
return
[i
+
2
, i
+
2
+
offset]
elif
data[i]
=
=
0x85
and
data[i
+
1
]
=
=
0xc0
and
eax_value:
# test eax, eax
if
eax_value_2 !
=
None
:
assert
eax_value_2 !
=
0
# call_dst
else
:
pass
test_eax
=
True
is_zero
=
False
ins[i]
=
'test eax, eax'
last_i
=
i
i
+
=
2
elif
data[i]
=
=
0x87
and
data[i
+
1
]
=
=
0x1c
and
data[i
+
2
]
=
=
0x24
and
push_ebx:
# xchg ebx, [esp]
if
ebx_value:
assert
not
ebx_ebp
ins[push_ebx_i]
=
'nop'
ins[ebx_value_i]
=
'push 0x%x'
%
ebx_value
ins[i]
=
'nop'
push_ebx
=
False
push_value
=
ebx_value
ebx_value
=
None
push_value_i
=
ebx_value_i
elif
ebx_ebp:
ins[push_ebx_i]
=
'push ebp'
ins[ebx_ebp_i]
=
'nop'
ins[i]
=
'nop'
push_ebx
=
False
ebx_ebp
=
False
else
:
ins[i]
=
'xchg ebx, [esp]'
push_ebx
=
False
last_i
=
i
i
+
=
3
elif
data[i]
=
=
0x8b
and
data[i
+
1
]
=
=
0xdd
and
push_ebx:
# mov ebx, ebp
ins[i]
=
'mov ebx, ebp'
last_i
=
i
ebx_ebp_i
=
i
ebx_ebp
=
True
i
+
=
2
elif
data[i]
=
=
0x90
:
# nop
ins[i]
=
'nop'
last_i
=
i
i
+
=
1
elif
data[i]
=
=
0xb8
:
# mov eax, dword
value
=
to_int(data[i
+
1
: i
+
5
])
ins[i]
=
'mov eax, 0x%x'
%
value
last_i
=
i
if
not
eax_value:
eax_value_i
=
i
eax_value
=
value
else
:
assert
push_eax
eax_value_2_i
=
i
eax_value_2
=
value
i
+
=
5
elif
data[i]
=
=
0xbb
and
push_ebx:
# mov ebx, dword
value
=
to_int(data[i
+
1
: i
+
5
])
ins[i]
=
'mov ebx, 0x%x'
%
value
last_i
=
i
ebx_value_i
=
i
ebx_value
=
value
i
+
=
5
elif
data[i]
=
=
0xe9
:
# jmp
ins[i]
=
'jmp %s'
%
make_label(i
+
5
+
to_int(data[i
+
1
: i
+
5
]))
last_i
=
None
i
+
=
5
+
to_int(data[i
+
1
: i
+
5
])
elif
data[i]
=
=
0xeb
:
# jmp short
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
to_char(data[i
+
1
]))
last_i
=
None
i
+
=
2
+
to_char(data[i
+
1
])
elif
data[i]
=
=
0xc3
:
# ret
if
push_value:
ins[i]
=
'ud2'
i
=
push_value_i
j
=
i
+
ob_start
dst
=
push_value
offset
=
dst
-
j
-
5
&
0xffffffff
ins[i]
=
'jmp %s'
%
make_label(dst
-
ob_start)
last_i
=
None
push_value
=
None
i
=
dst
-
ob_start
else
:
ins[i]
=
'ret'
return
[]
elif
data[i]
=
=
0xff
and
data[i
+
1
]
=
=
0xe0
:
# jmp eax
assert
push_eax
and
eax_value
and
eax_value_2
ins[i]
=
'ud2'
i
=
eax_value_2_i
j
=
i
+
ob_start
dst
=
eax_value_2
offset
=
dst
-
j
-
5
&
0xffffffff
ins[eax_value_i]
=
'nop'
ins[push_eax_i]
=
'nop'
ins[i]
=
'call f%s'
%
make_label(dst
-
ob_start)
funcs_to_handle.append(dst)
i
+
=
5
j
=
i
+
ob_start
dst
=
eax_value
offset
=
dst
-
j
-
5
&
0xffffffff
ins[i]
=
'jmp %s'
%
make_label(dst
-
ob_start)
last_i
=
None
i
=
dst
-
ob_start
push_eax
=
False
eax_value
=
None
eax_value_2
=
None
else
:
is_zero
=
False
test_eax
=
False
push_ebx
=
False
ebx_ebp
=
False
ebx_value
=
None
push_value
=
None
push_eax
=
False
eax_value
=
None
eax_value_2
=
None
l
=
ins_len(data[i: i
+
20
])
ins[i]
=
disasm(data[i: i
+
l], i
+
ob_start)
last_i
=
i
i
+
=
l
def
extract_function(function):
print
(
'// function: 0x%x'
%
function)
branches_to_handle
=
[function
-
ob_start]
ins
=
dict
()
while
branches_to_handle:
addr
=
branches_to_handle.pop(
0
)
if
addr
in
ins:
continue
branches_to_handle
+
=
extract_block(ins, addr)
code
=
'f%s:\n'
%
make_label(function
-
ob_start)
in_pushal
=
False
in_pushfd
=
False
for
i
in
ins:
if
in_pushal:
assert
ins[i] !
=
'pushal '
code
+
=
'%s:\n'
%
make_label(i)
if
ins[i].startswith(
'popal '
):
in_pushal
=
False
for
j
in
ins[i].splitlines()[
1
: ]:
code
+
=
j
+
'\n'
elif
in_pushfd:
assert
ins[i] !
=
'pushfd '
code
+
=
'%s:\n'
%
make_label(i)
if
ins[i].startswith(
'popfd '
):
in_pushfd
=
False
for
j
in
ins[i].splitlines()[
1
: ]:
code
+
=
j
+
'\n'
elif
ins[i]
=
=
'pushal '
:
code
+
=
'%s:\n'
%
make_label(i)
in_pushal
=
True
elif
ins[i]
=
=
'pushfd '
:
code
+
=
'%s:\n'
%
make_label(i)
in_pushfd
=
True
else
:
code
+
=
'%s:\n%s\n'
%
(make_label(i), ins[i])
return
code
offset
=
0x400c00
data
=
open
(
'./KCTF_CrackMe.exe'
,
'rb'
).read()[ob_start
-
offset: ob_end
-
offset]
funcs_to_handle
=
[
0x611e44
,
0x611513
,
0x610baf
,
0x60f9f2
,
0x60f17a
,
0x60e8b9
,
0x60df9a
,
0x60d635
,
0x60cce7
,
0x60c3ba
,
0x60bac0
,
0x60b190
,
0x60a819
,
0x609f67
,
0x609604
,
0x608ca6
,
0x608375
,
0x607aaa
,
0x60714f
,
0x6067da
,
0x605eba
,
0x60557e
,
0x604c95
,
0x604305
,
0x603a11
,
0x603091
,
0x60277c
,
0x601e0d
,
0x601434
,
0x600b97
,
0x60027e
,
0x5ff957
,
0x5fef61
,
0x5fe61e
,
0x5fdd3d
,
0x5fd517
,
0x5fcbc4
,
0x5fc2cb
,
0x5fb9af
,
0x5fb07f
,
0x5fa795
,
0x5f9e5c
,
0x5f94be
,
0x5f8bb2
,
0x5f822a
,
0x5f792b
,
0x5f700b
,
0x5f673f
,
0x40f9af
,
0x5f52e3
,
0x409de1
,
0x40e62d
,
0x403aca
,
0x5f50e0
]
funcs_to_handle
+
=
[
0x4055C4
,
0x404F6B
]
funcs_handled
=
set
()
code
=
''
while
funcs_to_handle:
f
=
funcs_to_handle.pop(
0
)
if
f
in
funcs_handled:
continue
funcs_handled.add(f)
if
ob_start <
=
f < ob_end:
code
+
=
extract_function(f)
else
:
print
(
"// unknown func (maybe library function): f%s"
%
make_label(f
-
ob_start))
code
+
=
'f%s:\njmp 0x%x\n'
%
(make_label(f
-
ob_start), f)
code
+
=
'\n\n.string "================"\n\n'
# print('\n' + code)
with
open
(
'out.s'
,
'w'
) as f:
f.write(code)
print
(
'OK'
)
|
得到指令后编译为二进制:
1
2
3
4
5
6
7
8
9
10
|
import
pwn
# pwn.context.os = 'windows' # not needed
pwn.context.arch
=
'i386'
code
=
open
(
'out.s'
,
'r'
).read()
with
open
(
'out'
,
'wb'
) as f:
f.write(pwn.asm(code, vma
=
0x800000
))
print
(
'OK'
)
|
最后在 ida 里新加一个段,起始地址 0x800000 ,将指令放进去
1
2
3
4
5
|
import
ida_bytes
with
open
(
'out'
,
'rb'
) as f:
data
=
f.read()
ida_bytes.patch_bytes(
0x800000
, data)
|
得到的这些函数再手动处理一下多余的指令,逻辑就基本上出来了。
main 前面大部分逻辑都是与用户名相关的,直接跳到最后的判断逻辑:
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
|
printf
(v597);
// 输入序列号:
gets_s(password, 0x100u);
if
(
strlen
(password) >= 0x21 )
goto
LABEL_20;
for
( k = 0; ; ++k )
{
v5 =
strlen
(password);
if
( k >= v5 )
break
;
if
( password[k] >= 97 && password[k] <= 122 )
goto
LABEL_20;
}
v525 = (
char
*)((
int
(__cdecl *)(
char
*,
int
))loc_40E62D)(password, 32);
// hex to bytes
memset
(input, 0, 0x100u);
j_AES_encrypt(v525, v609, input);
// ...
j_decrypt1(&Source[189], output, input);
memcpy
(&output[8], v573, 8u);
j_decrypt1(&Source[180], v602, output);
memcpy
(&v602[8], v594, 8u);
j_decrypt1(&Source[171], output, v602);
memcpy
(&output[8], v593, 8u);
j_decrypt1(&Source[162], v602, output);
memcpy
(&v602[8], v592, 8u);
j_decrypt1(&Source[153], output, v602);
memcpy
(&output[8], v591, 8u);
j_decrypt1(&Source[144], v602, output);
memcpy
(&v602[8], v590, 8u);
j_decrypt1(&Source[135], output, v602);
memcpy
(&output[8], v589, 8u);
j_decrypt1(&Source[126], v602, output);
memcpy
(&v602[8], v588, 8u);
j_decrypt1(&Source[117], output, v602);
memcpy
(&output[8], v587, 8u);
j_decrypt1(&Source[108], v602, output);
memcpy
(&v602[8], v586, 8u);
j_decrypt1(&Source[99], output, v602);
memcpy
(&output[8], v585, 8u);
j_decrypt1(&Source[90], v602, output);
memcpy
(&v602[8], v584, 8u);
j_decrypt1(&Source[81], output, v602);
memcpy
(&output[8], v583, 8u);
j_decrypt1(&Source[72], v602, output);
memcpy
(&v602[8], v582, 8u);
j_decrypt1(&Source[63], output, v602);
memcpy
(&output[8], v581, 8u);
j_decrypt1(&Source[54], v602, output);
memcpy
(&v602[8], v580, 8u);
j_decrypt1(&Source[45], output, v602);
memcpy
(&output[8], v579, 8u);
j_decrypt1(&Source[36], v602, output);
memcpy
(&v602[8], v578, 8u);
j_decrypt1(&Source[27], output, v602);
memcpy
(&output[8], v577, 8u);
j_decrypt1(&Source[18], v602, output);
memcpy
(&v602[8], v575, 8u);
j_decrypt1(&Source[9], output, v602);
memcpy
(&output[8], v576, 8u);
j_decrypt1(Source, v602, output);
Str2[8] = 0;
memcpy
(Str2, v602, 8u);
memset
(Destination, 0, 0x1F4u);
for
( l = 0; l < 50; strcat_s(Destination, 0x400u, &Source[9 * l++]) )
;
memmove
(vm_key, Destination, 500u);
j_vm_encrypt(vm_key, Str2, 1);
if
( !
strcmp
(Str1, Str2) )
MessageBoxA(0,
"success"
,
"success"
, 0);
else
LABEL_20:
MessageBoxA(0,
"fail"
,
"fail"
, 0);
return
0;
}
|
输入 password 后 16 转成字节数组,传入魔改的 aes 加密,之后又用魔改的 des 加密 22 轮,再用个简单的虚拟机加密,再和最终的目标值比较。密钥和比较的值都应该是固定的或者只与用户名有关,所以调试拿值就行。
aes 实现方式:
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
|
void
__cdecl AES_encrypt(
char
*input,
char
*key,
char
*output)
{
char
v3[176];
// [esp+1Ch] [ebp-ECh] BYREF
char
v4[16];
// [esp+CCh] [ebp-3Ch] BYREF
int
v5;
// [esp+DCh] [ebp-2Ch]
char
state[16];
// [esp+E0h] [ebp-28h] BYREF
DWORD
v7;
// [esp+F0h] [ebp-18h] BYREF
Params *v8;
// [esp+F4h] [ebp-14h]
int
j;
// [esp+F8h] [ebp-10h]
Params *v10;
// [esp+FCh] [ebp-Ch]
int
i;
// [esp+100h] [ebp-8h]
v5 = 0;
j_memset_0(state, 0,
sizeof
(state));
j_memset_0(v4, 0,
sizeof
(v4));
j_memset_0(v3, 0,
sizeof
(v3));
j_AES_set_state(input, state);
j_AES_set_state(key, v4);
j_AES_KeyExpansion(v4, v3);
j_AES_AddRoundKey(state, v3, 4 * aes_lock_index);
aes_lock_index += 2;
j_AES_ShiftRows(state);
j_AES_SubBytes(state);
v7 = 1;
for
( i = 8; i <= 20; i += 4 )
{
v10 = (Params *)j_calloc_0(0xCu, 1u);
v10->index = i;
v10->state = state;
v10->exkey = v3;
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_1, v10, 0, &v7);
}
for
( j = 18; j > 0; j -= 4 )
{
v8 = (Params *)j_calloc_0(0xCu, 1u);
v8->index = j;
v8->state = state;
v8->exkey = v3;
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_2, v8, 0, &v7);
}
while
( aes_lock_index != -1 )
;
j_AES_AddRoundKey(state, v3, 0);
AES_get_state(state, output);
}
void
__cdecl thread_1(Params *p)
{
while
( aes_lock_index != p->index / 2 )
;
j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
AES_MixColumns(p->state);
j_AES_ShiftRows(p->state);
j_AES_SubBytes(p->state);
if
( aes_lock_index == 10 )
--aes_lock_index;
else
aes_lock_index += 2;
j_free(p);
}
void
__cdecl thread_2(Params *p)
{
while
( aes_lock_index != p->index / 2 )
;
j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
AES_MixColumns(p->state);
j_AES_ShiftRows(p->state);
j_AES_SubBytes(p->state);
aes_lock_index -= 2;
j_free(p);
}
|
多线程但是用一个全局锁控制流程,只有一种执行方式。部分 AES 的实现做了魔改,改一下 aes 板子即可
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
|
#include <stdio.h>
#include <string.h>
#include <assert.h>
// AES
typedef
struct
{
unsigned
char
rk[4][11][4];
// round key
unsigned
char
iv[16];
} AES_CONTEXT;
const
unsigned
char
Sbox[256] = {
0x28, 0xC2, 0xE8, 0x57, 0x48, 0x24, 0x97, 0xC5, 0x18, 0x8C, 0x9B, 0x72, 0xF7, 0x99, 0xDE, 0xD3,
0x85, 0x58, 0x7A, 0x0B, 0x44, 0xD1, 0xB0, 0x47, 0xC7, 0xAE, 0xF0, 0x6D, 0x53, 0xE1, 0x60, 0xB4,
0x4B, 0x5C, 0x10, 0x52, 0x01, 0x39, 0xB9, 0x90, 0xAB, 0x00, 0xD4, 0x73, 0x64, 0x32, 0x9F, 0xA1,
0x6A, 0x1C, 0x6B, 0x21, 0xF1, 0xEF, 0x3F, 0x67, 0x95, 0xF2, 0x79, 0xE0, 0x0C, 0xD0, 0x66, 0x7F,
0x2C, 0xC3, 0x12, 0x5A, 0x34, 0xEB, 0x15, 0xA6, 0xBC, 0x7D, 0xA0, 0xB8, 0x55, 0x49, 0xC1, 0xFB,
0xE9, 0x08, 0x3C, 0xE2, 0x56, 0x2F, 0x30, 0x9E, 0x0E, 0xCB, 0x25, 0xE3, 0x46, 0x5D, 0xEC, 0x4C,
0x09, 0xBE, 0x87, 0x04, 0x89, 0xD8, 0x19, 0x3D, 0x71, 0x40, 0x7E, 0x5F, 0x16, 0x7B, 0x3A, 0x27,
0x43, 0x76, 0x45, 0x8A, 0x35, 0x96, 0xF9, 0x07, 0x8F, 0x0F, 0x54, 0xCF, 0xBA, 0x38, 0x83, 0xCE,
0x2A, 0xAC, 0x68, 0xF4, 0x80, 0x31, 0xA4, 0xFE, 0x93, 0xB3, 0x7C, 0xCA, 0xB6, 0x75, 0xDA, 0xA8,
0xD7, 0xB1, 0x37, 0xC4, 0x6C, 0x6F, 0xD5, 0x4F, 0x23, 0x14, 0x98, 0xAA, 0xDC, 0x65, 0x74, 0x42,
0xC8, 0x41, 0x8D, 0xA5, 0x22, 0xEA, 0x4D, 0xB5, 0x17, 0x02, 0x1E, 0x88, 0x91, 0x33, 0xC6, 0x78,
0x3B, 0x2D, 0xD9, 0xFC, 0x1B, 0x9A, 0xCD, 0xE6, 0x1F, 0xED, 0x92, 0x29, 0x4A, 0xFA, 0x1A, 0xEE,
0x0D, 0xE7, 0x63, 0x8E, 0xFF, 0x06, 0x3E, 0x1D, 0xF8, 0xAD, 0xE5, 0x36, 0x05, 0x70, 0xA2, 0x69,
0x84, 0xBF, 0xA9, 0x8B, 0x03, 0xD6, 0x26, 0x2E, 0x82, 0x62, 0x81, 0xE4, 0x94, 0xA7, 0xAF, 0x5E,
0x9D, 0xD2, 0xB2, 0x86, 0x2B, 0x51, 0xCC, 0xDD, 0x13, 0xF5, 0x77, 0x50, 0xC0, 0xB7, 0x0A, 0x59,
0x4E, 0xC9, 0xBB, 0x11, 0xA3, 0x6E, 0xDB, 0xF6, 0x61, 0x9C, 0x20, 0xDF, 0xFD, 0xBD, 0x5B, 0xF3
};
unsigned
char
InvSbox[256] = {
};
void
KeyExpansion(AES_CONTEXT *ctx,
const
unsigned
char
* key) {
int
i, j, r, c;
unsigned
char
rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
ctx->rk[r][0][c] = key[r + c * 4];
}
}
for
(i = 1; i <= 10; i++) {
for
(j = 0; j < 4; j++) {
unsigned
char
t[4];
for
(r = 0; r < 4; r++) {
t[r] = j ? ctx->rk[r][i][j - 1] : ctx->rk[r][i - 1][3];
}
if
(j == 0) {
unsigned
char
temp = t[0];
for
(r = 0; r < 3; r++) {
t[r] = Sbox[t[(r + 1) % 4]];
}
t[3] = Sbox[temp];
t[0] ^= rc[i - 1];
}
for
(r = 0; r < 4; r++) {
ctx->rk[r][i][j] = ctx->rk[r][i - 1][j] ^ t[r];
}
}
}
}
unsigned
char
FFmul(unsigned
char
a, unsigned
char
b) {
unsigned
char
bw[4];
unsigned
char
res = 0;
int
i;
bw[0] = b;
for
(i = 1; i < 4; i++) {
bw[i] = bw[i-1] << 1;
if
(bw[i - 1] & 0x80) {
bw[i] ^= 0x1b;
}
}
for
(i=0; i<4; i++) {
if
((a >> i) & 0x01) {
res ^= bw[i];
}
}
return
res;
}
void
SubBytes(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
int
r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
state[r][c] = Sbox[state[r][c]];
}
}
}
unsigned
int
ror4(unsigned
int
x,
int
n) {
return
(x >> n) | (x << (32 - n));
}
unsigned
int
rol4(unsigned
int
x,
int
n) {
return
ror4(x, 32 - n);
}
void
ShiftRows(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
int
* _s = (unsigned
int
*) state;
_s[0] = ror4(_s[0], 0);
_s[1] = ror4(_s[1], 8);
_s[2] = ror4(_s[2], 24);
_s[3] = ror4(_s[3], 16);
}
void
MixColumns(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
char
t[4];
int
r, c;
for
(c = 0; c < 4; c++) {
for
(r = 0; r < 4; r++) {
t[r] = state[r][c];
}
for
(r=0; r<4; r++) {
state[r][c] = FFmul(0x0e, t[r]) ^ FFmul(0x0b, t[(r + 1) % 4]) ^ FFmul(0x0d, t[(r + 2) % 4]) ^ FFmul(0x09, t[(r + 3) % 4]);
}
}
}
void
AddRoundKey(AES_CONTEXT *ctx, unsigned
char
state[][4], unsigned
char
k[][11][4],
int
index) {
int
r, c;
for
(c = 0; c < 4; c++) {
for
(r = 0; r < 4; r++) {
state[c][r] ^= k[c][index][r];
}
}
}
void
InvSubBytes(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
int
r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
state[r][c] = InvSbox[state[r][c]];
}
}
}
void
InvShiftRows(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
int
* _s = (unsigned
int
*) state;
_s[0] = rol4(_s[0], 0);
_s[1] = rol4(_s[1], 8);
_s[2] = rol4(_s[2], 24);
_s[3] = rol4(_s[3], 16);
}
void
InvMixColumns(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
char
t[4];
int
r, c;
for
(c = 0; c < 4; c++) {
for
(r = 0; r < 4; r++) {
t[r] = state[r][c];
}
for
(r = 0; r < 4; r++) {
state[r][c] = FFmul(0x02, t[r]) ^ FFmul(0x03, t[(r + 1) % 4]) ^ FFmul(0x01, t[(r + 2) % 4]) ^ FFmul(0x01, t[(r + 3) % 4]);
}
}
}
void
aes_init(AES_CONTEXT *ctx,
const
unsigned
char
* key,
const
void
* iv) {
for
(
int
i = 0; i < 16; i++) {
for
(
int
j = 0; j < 16; j++) {
InvSbox[Sbox[16 * i + j]] = 16 * i + j;
}
}
KeyExpansion(ctx, key);
if
(iv)
memcpy
(ctx->iv, iv, 16);
}
unsigned
char
* aes_encrypt_block(AES_CONTEXT* ctx, unsigned
char
* input) {
unsigned
char
state[4][4];
int
i, r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4 ;c++) {
state[r][c] = input[c * 4 + r];
}
}
AddRoundKey(ctx, state, ctx->rk, 2);
ShiftRows(ctx, state);
SubBytes(ctx, state);
for
(i = 8; i <= 20; i += 4) {
AddRoundKey(ctx, state, ctx->rk, i / 2);
MixColumns(ctx, state);
ShiftRows(ctx, state);
SubBytes(ctx, state);
}
for
(i = 18; i > 0; i -= 4) {
AddRoundKey(ctx, state, ctx->rk, i / 2);
MixColumns(ctx, state);
ShiftRows(ctx, state);
SubBytes(ctx, state);
}
AddRoundKey(ctx, state, ctx->rk, 0);
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4 ;c++) {
input[c * 4 + r] = state[r][c];
}
}
return
input;
}
unsigned
char
* aes_decrypt_block(AES_CONTEXT *ctx, unsigned
char
* input) {
unsigned
char
state[4][4];
int
i, r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
state[r][c] = input[c * 4 + r];
}
}
AddRoundKey(ctx, state, ctx->rk, 0);
for
(
int
i = 2; i <= 18; i += 4) {
InvSubBytes(ctx, state);
InvShiftRows(ctx, state);
InvMixColumns(ctx, state);
AddRoundKey(ctx, state, ctx->rk, i / 2);
}
for
(i = 20; i >= 8; i -= 4) {
InvSubBytes(ctx, state);
InvShiftRows(ctx, state);
InvMixColumns(ctx, state);
AddRoundKey(ctx, state, ctx->rk, i / 2);
}
InvSubBytes(ctx, state);
InvShiftRows(ctx, state);
AddRoundKey(ctx, state, ctx->rk, 2);
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4 ;c++) {
input[c * 4 + r] = state[r][c];
}
}
return
input;
}
void
aes_encrypt_ecb(
const
void
* key,
void
* data,
int
data_len) {
assert
(data_len % 16 == 0);
AES_CONTEXT ctx;
aes_init(&ctx, (
const
unsigned
char
*) key, NULL);
unsigned
char
* _data = (unsigned
char
*) data;
for
(
int
i = 0; i < data_len / 16; i++) {
aes_encrypt_block(&ctx, _data);
_data += 16;
}
}
void
aes_decrypt_ecb(
const
void
* key,
void
* data,
int
data_len) {
assert
(data_len % 16 == 0);
AES_CONTEXT ctx;
aes_init(&ctx, (
const
unsigned
char
*) key, NULL);
unsigned
char
* _data = (unsigned
char
*) data;
for
(
int
i = 0; i < data_len / 16; i++) {
aes_decrypt_block(&ctx, _data);
_data += 16;
}
}
|
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
|
void
__cdecl decrypt1(
char
*key,
char
*output,
char
*input)
{
DES_key_expansion(key);
des_decrypt(output, input, 18, 18);
}
void
__cdecl DES_key_expansion(
char
*key)
{
int
i;
// [esp+10h] [ebp-8h]
DES_D = key_block;
DES_C = &key_block[28];
bytes_to_bits(key_block, key, 64);
table_trans(key_block, key_block, DES_PC1, 56);
for
( i = 0; i < 16; ++i )
{
rol(DES_D, DES_iteration_shift[i], 28);
rol(DES_C, DES_iteration_shift[i], 28);
table_trans(sub_key[i], key_block, DES_PC2, 48);
}
}
void
__cdecl des_decrypt(
char
*output,
char
*input,
int
index1,
int
index2)
{
int
i;
// [esp+Ch] [ebp-8h]
hex_string_to_bits(block, input, 64);
table_trans(block, block, DES_IP, 64);
for
( i = 15; i >= 0; --i )
{
uint_cpy(tmp_2, block_left_ptr, 32);
encrypt_round(block_left_ptr, sub_key[i], index1, index2);
bits_xor(block_left_ptr, block_right_ptr, 32);
uint_cpy(block_right_ptr, tmp_2, 32);
}
table_trans(block, block, DES_PI, 64);
bits_to_bytes(output, block, 64);
}
|
与标准的 DES 中的常量相比, S 改了两个值, PC2 改了一个值。抄写出来得到:
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
|
/* Initial Permutation Table */
static
char
IP[] = {
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
};
/* Inverse Initial Permutation Table */
static
char
PI[] = {
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
};
/*Expansion table */
static
char
E[] = {
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
};
/* Post S-Box permutation */
static
char
P[] = {
16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25
};
/* The S-Box tables */
static
char
S[8][64] = {{
/* S1 */
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
},{
/* S2 */
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
},{
/* S3 */
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
},{
/* S4 */
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
},{
/* S5 */
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
},{
/* S6 */
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
// 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
10, 15, 4, 2, 7, 12, 0, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
},{
/* S7 */
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
// 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
13, 0, 11, 7, 4, 0, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
},{
/* S8 */
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}};
/* Permuted Choice 1 Table */
static
char
PC1[] = {
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
};
/* Permuted Choice 2 Table */
static
char
PC2[] = {
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
// 30, 40, 51, 45, 33, 48,
30, 40, 51, 34, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
};
/* Iteration Shift Array */
static
char
iteration_shift[] = {
/* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
unsigned
int
sub_key[16][48];
void
bytes_to_bits(unsigned
int
*dst,
const
char
*src,
int
length) {
char
v3;
// cl
int
i;
// [esp+Ch] [ebp-8h]
for
( i = 0; i < length; ++i ) {
v3 = i & 7;
dst[i] = (src[i / 8] >> v3) & 1;
}
}
void
uint_cpy(unsigned
int
*dst, unsigned
int
*src,
int
size) {
int
i;
// [esp+10h] [ebp-8h]
for
( i = 0; i < size; ++i )
dst[i] = src[i];
}
void
table_trans(unsigned
int
*output, unsigned
int
*input,
char
*trans_table,
int
size) {
int
i;
// [esp+Ch] [ebp-8h]
unsigned
int
tmp[256];
for
( i = 0; i < size; ++i )
tmp[i] = input[trans_table[i] - 1];
uint_cpy(output, tmp, size);
}
void
rol(unsigned
int
*arr,
int
n,
int
size) {
unsigned
int
tmp[256];
uint_cpy(tmp, arr, n);
uint_cpy(arr, &arr[n], size - n);
uint_cpy(&arr[size - n], tmp, n);
}
void
DES_key_expansion(
const
char
* key) {
unsigned
int
key_block[64];
unsigned
int
* DES_D = key_block;
unsigned
int
* DES_C = key_block + 28;
bytes_to_bits(key_block, key, 64);
table_trans(key_block, key_block, PC1, 56);
for
(
int
i = 0; i < 16; ++i) {
rol(DES_D, iteration_shift[i], 28);
rol(DES_C, iteration_shift[i], 28);
table_trans(sub_key[i], key_block, PC2, 48);
}
}
void
bits_xor(unsigned
int
*dst, unsigned
int
*src,
int
size) {
int
i;
// [esp+10h] [ebp-8h]
for
( i = 0; i < size; ++i )
dst[i] ^= src[i];
}
void
DES_SBOX(unsigned
int
*output, unsigned
int
*input) {
int
i;
// [esp+14h] [ebp-8h]
for
( i = 0; i < 8; ++i ) {
bytes_to_bits(output, &S[i][32 * *input + 16 * input[5] + 8 * input[1] + 4 * input[2] + 2 * input[3] + input[4]], 4);
input += 6;
output += 4;
}
}
void
encrypt_round(unsigned
int
*R, unsigned
int
*_sub_key,
int
i,
int
j) {
char
v4;
// [esp+10h] [ebp-8h]
unsigned
int
DES_s_input[48];
table_trans(DES_s_input, R, E, 48);
bits_xor(DES_s_input, _sub_key, 48);
DES_SBOX(R, DES_s_input);
v4 = P[i];
P[i] = P[j];
P[j] = v4;
table_trans(R, R, P, 32);
}
void
decrypt_round(unsigned
int
*R, unsigned
int
*_sub_key,
int
i,
int
j) {
char
v4;
// [esp+10h] [ebp-8h]
unsigned
int
DES_s_input[48];
table_trans(DES_s_input, R, E, 48);
bits_xor(DES_s_input, _sub_key, 48);
DES_SBOX(R, DES_s_input);
table_trans(R, R, P, 32);
v4 = P[i];
P[i] = P[j];
P[j] = v4;
}
void
bits_to_hex_string(
char
*output, unsigned
int
*input,
int
size) {
for
(
int
i = 0; i < size / 4 + 1; i++) output[i] = 0;
for
(
int
i = 0; i < size / 4; i++) {
for
(
int
j = 0; j < 4; j++) {
output[i] |= input[4 * i + j] << j;
}
if
(output[i] <= 9) output[i] +=
'0'
;
else
output[i] += - 10 +
'A'
;
}
}
void
DES_encrypt_inner(
const
char
*input,
char
*output,
int
index1,
int
index2) {
int
i;
// [esp+10h] [ebp-8h]
unsigned
int
block[64];
unsigned
int
tmp[32];
bytes_to_bits(block, input, 64);
table_trans(block, block, IP, 64);
for
( i = 0; i < 16; ++i ) {
uint_cpy(tmp, block + 32, 32);
encrypt_round(block + 32, sub_key[i], index1, index2);
bits_xor(block + 32, block, 32);
uint_cpy(block, tmp, 32);
}
table_trans(block, block, PI, 64);
bits_to_hex_string(output, block, 64);
}
void
DES_encrypt(
const
char
* key,
const
char
* input,
char
* output,
int
index1,
int
index2) {
DES_key_expansion(key);
DES_encrypt_inner(input, output, index1, index2);
}
void
hex_string_to_bits(unsigned
int
*output,
const
char
*input,
int
size) {
for
(
int
i = 0; i < size; i++) {
char
c = input[i / 4];
if
(c <= 0x39) c -=
'0'
;
else
c -=
'A'
- 10;
output[i] = (c >> (i & 3)) & 1;
}
}
void
bits_to_bytes(
char
*output, unsigned
int
*input,
int
size) {
int
i;
// [esp+10h] [ebp-8h]
int
j;
// [esp+10h] [ebp-8h]
for
( i = 0; i < size / 8 + 1; ++i )
output[i] = 0;
for
( j = 0; j < size; ++j )
output[j / 8] |= input[j] << (j % 8);
}
void
DES_decrypt_inner(
char
* output,
const
char
* input,
int
index1,
int
index2) {
unsigned
int
block[64];
unsigned
int
tmp[32];
int
i;
// [esp+Ch] [ebp-8h]
hex_string_to_bits(block, input, 64);
table_trans(block, block, IP, 64);
for
( i = 15; i >= 0; --i ) {
uint_cpy(tmp, block, 32);
encrypt_round(block, sub_key[i], index1, index2);
bits_xor(block, block + 32, 32);
uint_cpy(block + 32, tmp, 32);
}
table_trans(block, block, PI, 64);
bits_to_bytes(output, block, 64);
}
void
DES_decrypt(
const
char
* key,
const
char
* input,
char
* output,
int
index1,
int
index2) {
DES_key_expansion(key);
DES_decrypt_inner(output, input, index1, index2);
}
void
DES_decrypt_decrypt_inner(
const
char
*input,
char
*output,
int
index1,
int
index2) {
int
i;
// [esp+10h] [ebp-8h]
unsigned
int
block[64];
unsigned
int
tmp[32];
bytes_to_bits(block, input, 64);
table_trans(block, block, IP, 64);
for
( i = 0; i < 16; ++i ) {
uint_cpy(tmp, block + 32, 32);
decrypt_round(block + 32, sub_key[i], index1, index2);
bits_xor(block + 32, block, 32);
uint_cpy(block, tmp, 32);
}
table_trans(block, block, PI, 64);
bits_to_hex_string(output, block, 64);
}
void
DES_decrypt_decrypt(
const
char
* key,
const
char
* input,
char
* output,
int
index1,
int
index2) {
DES_key_expansion(key);
DES_decrypt_decrypt_inner(input, output, index1, index2);
}
|
最后还有个简单的虚拟机的形式的加密,抄写出来写逆:
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
|
void
vm_encrypt(
const
char
* key,
char
* data,
char
flag) {
const
char
* code =
"188314639360140916609214592753355241102748157658325077451310433873512805611046964127739955621255841702411199825520291475473529536531735880099500596431514601528872505540869163506318442965625785468536063896163123867531708491350401766156647550166763071341544"
;
int
v3;
// [esp+14h] [ebp-18h]
signed
int
output_len;
// [esp+18h] [ebp-14h]
int
v5;
// [esp+1Ch] [ebp-10h]
int
v6;
// [esp+20h] [ebp-Ch]
signed
int
i;
// [esp+24h] [ebp-8h]
output_len =
strlen
(data);
if
( output_len < 8 )
output_len = 8;
i = 0;
v3 = 0;
while
( i < output_len ) {
if
( v3 ==
strlen
(key) )
v3 = 0;
v5 = key[v3];
if
( code[v5] ) {
v6 = code[v5] -
'0'
;
if
( flag && code[v5] !=
'0'
&& code[v5] !=
'9'
) {
if
( v6 % 2 )
++v6;
else
v6 = code[v5] -
'1'
;
}
switch
( v6 ) {
case
1:
data[i] += code[v5 + 1] - 48;
break
;
case
2:
data[i] -= code[v5 + 1] - 48;
break
;
case
3:
data[i] += code[v5 + 1] + code[v5] - 96;
break
;
case
4:
data[i] -= code[v5 + 1] + code[v5] - 96;
break
;
case
5:
data[i] += code[v5 + 1] + code[v5] - 48;
break
;
case
6:
data[i] -= code[v5 + 1] + code[v5] - 48;
break
;
case
7:
data[i] += code[v5 + 1] + code[v5] - 48;
break
;
case
8:
data[i] -= code[v5 + 1] + code[v5] - 48;
break
;
case
9:
data[i] ^= code[v5 + 1] - 48;
break
;
}
}
++i;
++v3;
}
}
void
vm_decrypt(
const
char
* key,
char
* data,
int
flag) {
const
char
* code =
"188314639360140916609214592753355241102748157658325077451310433873512805611046964127739955621255841702411199825520291475473529536531735880099500596431514601528872505540869163506318442965625785468536063896163123867531708491350401766156647550166763071341544"
;
int
v3;
// [esp+14h] [ebp-18h]
signed
int
output_len;
// [esp+18h] [ebp-14h]
int
v5;
// [esp+1Ch] [ebp-10h]
int
v6;
// [esp+20h] [ebp-Ch]
signed
int
i;
// [esp+24h] [ebp-8h]
output_len =
strlen
(data);
if
( output_len < 8 )
output_len = 8;
i = output_len - 1;
v3 = (output_len - 1) %
strlen
(key);
while
( i >= 0 ) {
if
( v3 == -1 )
v3 =
strlen
(key) - 1;
v5 = key[v3];
if
( code[v5] ) {
v6 = code[v5] -
'0'
;
if
( flag && code[v5] !=
'0'
&& code[v5] !=
'9'
) {
if
( v6 % 2 )
++v6;
else
v6 = code[v5] -
'1'
;
}
switch
( v6 ) {
case
1:
data[i] -= code[v5 + 1] - 48;
break
;
case
2:
data[i] += code[v5 + 1] - 48;
break
;
case
3:
data[i] -= code[v5 + 1] + code[v5] - 96;
break
;
case
4:
data[i] += code[v5 + 1] + code[v5] - 96;
break
;
case
5:
data[i] -= code[v5 + 1] + code[v5] - 48;
break
;
case
6:
data[i] += code[v5 + 1] + code[v5] - 48;
break
;
case
7:
data[i] -= code[v5 + 1] + code[v5] - 48;
break
;
case
8:
data[i] += code[v5 + 1] + code[v5] - 48;
break
;
case
9:
data[i] ^= code[v5 + 1] - 48;
break
;
}
}
--i;
--v3;
}
}
|
将最终结果以及各个密钥动调拿出来,写逆得到密码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
int
main() {
const
char
* vm_key =
"\x6f\x7c\x78\x33\x41\x39\x38\x3d\x72\x7f\x6b\x3a\x30\x4a\x46\x36\x71\x7c\x79\x3b\x2b\x48\x46\x3d\x6e\x73\x69\x49\x2f\x45\x36\x3b\x7e\x7e\x79\x48\x3d\x4a\x49\x3a\x71\x71\x66\x39\x2e\x3a\x4a\x4a\x7e\x6b\x6a\x48\x2f\x3b\x47\x48\x7e\x6b\x65\x3a\x31\x34\x3e\x3a\x80\x74\x76\x37\x2d\x35\x4b\x4a\x6d\x6c\x6a\x3a\x33\x36\x46\x49\x7e\x80\x6a\x45\x41\x4a\x3d\x35\x7c\x81\x69\x38\x3e\x36\x4b\x3c\x72\x6d\x6a\x3b\x30\x45\x49\x36\x7d\x6e\x78\x34\x3c\x3b\x39\x46\x81\x6b\x6c\x35\x31\x46\x37\x3d\x6e\x6c\x66\x49\x3d\x48\x3b\x4a\x6b\x81\x67\x36\x33\x48\x3e\x46\x7c\x6c\x7b\x3a\x40\x35\x49\x3b\x6b\x7d\x78\x35\x2b\x38\x3b\x35\x7f\x7d\x6b\x44\x40\x3b\x46\x36\x7d\x80\x65\x34\x3e\x48\x48\x38\x7e\x71\x79\x46\x2b\x38\x3e\x3a\x80\x7e\x76\x35\x32\x47\x3e\x3d"
;
char
data[32] =
"5528f900"
;
vm_decrypt(vm_key, data, 1);
puts
(data);
char
tmp[64];
tmp[17] = 0;
for
(
int
i = 0; i < 22; i++) {
DES_decrypt_decrypt(vm_key + 8 * i, data, tmp, 18, 18);
memcpy
(data, tmp, 17);
// puts(data);
}
aes_decrypt_ecb(
"40041A36A4B0C478"
, data, 16);
for
(
int
i = 0; i < 16; i++) {
printf
(
"%02X"
, data[i] & 0xff);
}
putchar
(
'\n'
);
// 8BCBB6979E174CB7ECAEACDA104522CA
return
0;
}
|
更多【 KCTF 2023 第七题 wp - 98k】相关视频教程:www.yxfzedu.com