-
-
[原创] KCTF 2023 第七题 wp - 98k
-
2023-9-17 10:27 3421
-
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; } |
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
赞赏
他的文章