首页
社区
课程
招聘
[原创] KCTF 2023 第七题 wp - 98k
2023-9-17 10:27 10150

[原创] KCTF 2023 第七题 wp - 98k

2023-9-17 10:27
10150

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;
}

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞5
打赏
分享
最新回复 (1)
雪    币: 19431
活跃值: (29097)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-9-18 08:47
2
1
感谢分享
游客
登录 | 注册 方可回帖
返回