Britain’s GCHQ has launched an online code test that aims to identify potential spies and codebreakers.
The solution was written in English/简体中文/日本語
[tabs style=”1″]
Here is the problem: http://canyoucrackit.co.uk/
Part 1:
[frame align=”center”] [/frame]
It contains about 10×16=160 bytes of information, first I find out all the strings involved.
$ strings raw \X=AAAAuCX=BBBBu;Z
It only includes AAAA and BBBB. I have no idea what it means.
But I noticed that the first byte is 0xEB, 0xEB(JMP) is often used in cracking! So, does it meaning that this is a executable binary file?
$ gobjdump -D -b binary -mi386 raw raw: file format binary Disassembly of section .data: 00000000 <.data>: 0: eb 04 jmp 0x6 2: af scas %es:(%edi),%eax 3: c2 bf a3 ret $0xa3bf 6: 81 ec 00 01 00 00 sub $0x100,%esp c: 31 c9 xor %ecx,%ecx e: 88 0c 0c mov %cl,(%esp,%ecx,1) 11: fe c1 inc %cl 13: 75 f9 jne 0xe 15: 31 c0 xor %eax,%eax 17: ba ef be ad de mov $0xdeadbeef,%edx 1c: 02 04 0c add (%esp,%ecx,1),%al 1f: 00 d0 add %dl,%al 21: c1 ca 08 ror $0x8,%edx 24: 8a 1c 0c mov (%esp,%ecx,1),%bl 27: 8a 3c 04 mov (%esp,%eax,1),%bh 2a: 88 1c 04 mov %bl,(%esp,%eax,1) 2d: 88 3c 0c mov %bh,(%esp,%ecx,1) 30: fe c1 inc %cl 32: 75 e8 jne 0x1c 34: e9 5c 00 00 00 jmp 0x95 39: 89 e3 mov %esp,%ebx 3b: 81 c3 04 00 00 00 add $0x4,%ebx 41: 5c pop %esp 42: 58 pop %eax 43: 3d 41 41 41 41 cmp $0x41414141,%eax 48: 75 43 jne 0x8d 4a: 58 pop %eax 4b: 3d 42 42 42 42 cmp $0x42424242,%eax 50: 75 3b jne 0x8d 52: 5a pop %edx 53: 89 d1 mov %edx,%ecx 55: 89 e6 mov %esp,%esi 57: 89 df mov %ebx,%edi 59: 29 cf sub %ecx,%edi 5b: f3 a4 rep movsb %ds:(%esi),%es:(%edi) 5d: 89 de mov %ebx,%esi 5f: 89 d1 mov %edx,%ecx 61: 89 df mov %ebx,%edi 63: 29 cf sub %ecx,%edi 65: 31 c0 xor %eax,%eax 67: 31 db xor %ebx,%ebx 69: 31 d2 xor %edx,%edx 6b: fe c0 inc %al 6d: 02 1c 06 add (%esi,%eax,1),%bl 70: 8a 14 06 mov (%esi,%eax,1),%dl 73: 8a 34 1e mov (%esi,%ebx,1),%dh 76: 88 34 06 mov %dh,(%esi,%eax,1) 79: 88 14 1e mov %dl,(%esi,%ebx,1) 7c: 00 f2 add %dh,%dl 7e: 30 f6 xor %dh,%dh 80: 8a 1c 16 mov (%esi,%edx,1),%bl 83: 8a 17 mov (%edi),%dl 85: 30 da xor %bl,%dl 87: 88 17 mov %dl,(%edi) 89: 47 inc %edi 8a: 49 dec %ecx 8b: 75 de jne 0x6b 8d: 31 db xor %ebx,%ebx 8f: 89 d8 mov %ebx,%eax 91: fe c0 inc %al 93: cd 80 int $0x80 95: 90 nop 96: 90 nop 97: e8 9d ff ff ff call 0x39 9c: 41 inc %ecx 9d: 41 inc %ecx 9e: 41 inc %ecx 9f: 41 inc %ecx
It is strange that JMP appeared first.
At line 0x97, when it calls 0x39, 0x9C will be pushed into stack, but at line 0x42 and 0x4A which pop eax twice are meaningless。
At 0x43、it is comparing EAX with “AAAA”, and EAX stored with “AAAA”, so the result must be true.
At the next line, it is comparing EAX with “BBBB”, but EAX is uncertainty. So some things that were missed after line 0x9f.
Download the picture, dump the hex code, we will see:
$ hexdump -C cyber.png 00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| 00000010 00 00 02 e4 00 00 01 04 08 02 00 00 00 ef 6a b6 |..............j.| 00000020 2d 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 |-....sRGB.......| 00000030 00 09 70 48 59 73 00 00 0b 13 00 00 0b 13 01 00 |..pHYs..........| 00000040 9a 9c 18 00 00 00 07 74 49 4d 45 07 db 08 05 0e |.......tIME.....| 00000050 12 33 7e 39 c1 70 00 00 00 5d 69 54 58 74 43 6f |.3~9.p...]iTXtCo| 00000060 6d 6d 65 6e 74 00 00 00 00 00 51 6b 4a 43 51 6a |mment.....QkJCQj| 00000070 49 41 41 41 43 52 32 50 46 74 63 43 41 36 71 32 |IAAACR2PFtcCA6q2| 00000080 65 61 43 38 53 52 2b 38 64 6d 44 2f 7a 4e 7a 4c |eaC8SR+8dmD/zNzL| 00000090 51 43 2b 74 64 33 74 46 51 34 71 78 38 4f 34 34 |QC+td3tFQ4qx8O44| 000000a0 37 54 44 65 75 5a 77 35 50 2b 30 53 73 62 45 63 |7TDeuZw5P+0SsbEc| 000000b0 59 52 0a 37 38 6a 4b 4c 77 3d 3d 32 ca be f1 00 |YR.78jKLw==2....| ...
In the header block,
QkJCQjIAAACR2PFtcCA6q2eaC8SR+8dmD/zNzLQC+td3tFQ4qx8O447TDeuZw5P+0SsbEcYR.78jKLw==
are stored, you can see “==” at the end of line. It may mean that this code is encoded with base64.
Decode:
$ echo 'QkJCQjIAAACR2PFtcCA6q2eaC8SR+8dmD/zNzLQC+td3tFQ4qx8O447TDeuZw5P+0SsbEcYR78jKLw==' | base64 -D -o decoded.bin $ hexdump -C decoded.bin 00000000 42 42 42 42 32 00 00 00 91 d8 f1 6d 70 20 3a ab |BBBB2......mp :.| 00000010 67 9a 0b c4 91 fb c7 66 0f fc cd cc b4 02 fa d7 |g......f........| 00000020 77 b4 54 38 ab 1f 0e e3 8e d3 0d eb 99 c3 93 fe |w.T8............| 00000030 d1 2b 1b 11 c6 11 ef c8 ca 2f |.+......./| 0000003a
Woo! BBBB are appeared, combine 2 parts of binary codes, and view the execution results.
#include <stdio.h> #include <sys/types.h> #include <sys/mman.h> main(){ int i; static unsigned char shellcode[] = { 0xEB,0x04,0xAF,0xC2,0xBF,0xA3,0x81,0xEC, 0x00,0x01,0x00,0x00,0x31,0xC9,0x88,0x0C, 0x0C,0xFE,0xC1,0x75,0xF9,0x31,0xC0,0xBA, 0xEF,0xBE,0xAD,0xDE,0x02,0x04,0x0C,0x00, 0xD0,0xC1,0xCA,0x08,0x8A,0x1C,0x0C,0x8A, 0x3C,0x04,0x88,0x1C,0x04,0x88,0x3C,0x0C, 0xFE,0xC1,0x75,0xE8,0xE9,0x5C,0x00,0x00, 0x00,0x89,0xE3,0x81,0xC3,0x04,0x00,0x00, 0x00,0x5C,0x58,0x3D,0x41,0x41,0x41,0x41, 0x75,0x43,0x58,0x3D,0x42,0x42,0x42,0x42, 0x75,0x3B,0x5A,0x89,0xD1,0x89,0xE6,0x89, 0xDF,0x29,0xCF,0xF3,0xA4,0x89,0xDE,0x89, 0xD1,0x89,0xDF,0x29,0xCF,0x31,0xC0,0x31, 0xDB,0x31,0xD2,0xFE,0xC0,0x02,0x1C,0x06, 0x8A,0x14,0x06,0x8A,0x34,0x1E,0x88,0x34, 0x06,0x88,0x14,0x1E,0x00,0xF2,0x30,0xF6, 0x8A,0x1C,0x16,0x8A,0x17,0x30,0xDA,0x88, 0x17,0x47,0x49,0x75,0xDE,0x31,0xDB,0x89, 0xD8,0xFE,0xC0,0xCD,0x80,0x90,0x90,0xE8, 0x9D,0xFF,0xFF,0xFF,0x41,0x41,0x41,0x41, 0x42,0x42,0x42,0x42,0x32,0x00,0x00,0x00, 0x91,0xD8,0xF1,0x6D,0x70,0x20,0x3A,0xAB, 0x67,0x9A,0x0B,0xC4,0x91,0xFB,0xC7,0x66, 0x0F,0xFC,0xCD,0xCC,0xB4,0x02,0xFA,0xD7, 0x77,0xB4,0x54,0x38,0xAB,0x1F,0x0E,0xE3, 0x8E,0xD3,0x0D,0xEB,0x99,0xC3,0x93,0xFE, 0xD1,0x2B,0x1B,0x11,0xC6,0x11,0xEF,0xC8, 0xCA,0x2F }; /* * patch INT 0x80 to INT 3 to throw an exception signal to debugger * 0xCD -> 0xCC */ printf("patching shellcode...\n"); for(i = 0; i < sizeof(shellcode); i++){ if(*(unsigned short*)&shellcode[i] == 0x80CD){ shellcode[i] = 0xCC; printf("patch done\n"); break; } } unsigned int page = ((unsigned int)shellcode)&0xfffff000; if(-1 == mprotect((void*)page, 4096, PROT_READ | PROT_WRITE | PROT_EXEC)) perror("mprotect error"); ((int(*)())shellcode)(); }
The results are stored in EDI ~ EDI-0x32, at line 0x87.
$ gcc -arch i386 -g stage1.c -o stage1 $ gdb stage1 (gdb) r (gdb) x/s $edi-0x32 0xbffff79a: "GET /15b436de1f9107f3778aad525e5d0b20.js HTTP/1.1"
Part 2:
the result of part1 are: URL
//-------------------------------------------------------------------------------------------------- // // stage 2 of 3 // // challenge: // reveal the solution within VM.mem // // disclaimer: // tested in ie 9, firefox 6, chrome 14 and v8 shell (http://code.google.com/apis/v8/build.html), // other javascript implementations may or may not work. // //-------------------------------------------------------------------------------------------------- var VM = { cpu: { ip: 0x00, r0: 0x00, r1: 0x00, r2: 0x00, r3: 0x00, cs: 0x00, ds: 0x10, fl: 0x00, firmware: [0xd2ab1f05, 0xda13f110] }, mem: [ 0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50, 0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8, 0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56, 0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9, 0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69, 0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60, 0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8, 0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d, 0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67, 0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a, 0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9, 0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e, 0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55, 0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3, 0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f, 0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d, 0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1, 0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94, 0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62, 0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b, 0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1, 0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61, 0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14, 0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2, 0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1, 0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], exec: function() { // virtual machine architecture // ++++++++++++++++++++++++++++ // // segmented memory model with 16-byte segment size (notation seg:offset) // // 4 general-purpose registers (r0-r3) // 2 segment registers (cs, ds equiv. to r4, r5) // 1 flags register (fl) // // instruction encoding // ++++++++++++++++++++ // // byte 1 byte 2 (optional) // bits [ 7 6 5 4 3 2 1 0 ] [ 7 6 5 4 3 2 1 0 ] // opcode - - - // mod - // operand1 - - - - // operand2 - - - - - - - - // // operand1 is always a register index // operand2 is optional, depending upon the instruction set specified below // the value of mod alters the meaning of any operand2 // 0: operand2 = reg ix // 1: operand2 = fixed immediate value or target segment (depending on instruction) // // instruction set // +++++++++++++++ // // Notes: // * r1, r2 => operand 1 is register 1, operand 2 is register 2 // * movr r1, r2 => move contents of register r2 into register r1 // // opcode | instruction | operands (mod 0) | operands (mod 1) // -------+-------------+------------------+----------------- // 0x00 | jmp | r1 | r2:r1 // 0x01 | movr | r1, r2 | rx, imm // 0x02 | movm | r1, [ds:r2] | [ds:r1], r2 // 0x03 | add | r1, r2 | r1, imm // 0x04 | xor | r1, r2 | r1, imm // 0x05 | cmp | r1, r2 | r1, imm // 0x06 | jmpe | r1 | r2:r1 // 0x07 | hlt | N/A | N/A // // flags // +++++ // // cmp r1, r2 instruction results in: // r1 == r2 => fl = 0 // r1 < r2 => fl = 0xff // r1 > r2 => fl = 1 // // jmpe r1 // => if (fl == 0) jmp r1 // else nop throw "VM.exec not yet implemented"; } }; //-------------------------------------------------------------------------------------------------- try { VM.exec(); } catch(e) { alert('\nError: ' + e + '\n'); } //--------------------------------------------------------------------------------------------------
We need make a virtual CPU for executing these codes.
#include <stdio.h> static unsigned char mem[] = { 0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50, 0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8, 0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56, 0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9, 0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69, 0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60, 0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8, 0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d, 0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67, 0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a, 0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9, 0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e, 0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55, 0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3, 0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f, 0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d, 0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1, 0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94, 0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62, 0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b, 0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1, 0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61, 0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14, 0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2, 0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1, 0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #define adr(seg, off) ((seg << 4) + off) typedef unsigned char byte; typedef unsigned short word; typedef unsigned int dword; typedef struct _CPU { byte ip; byte regs[6]; byte fl; } _CPU; _CPU cpu; enum _REGISTER { r0, r1, r2, r3, cs, ds }; typedef struct _INSTRUCTION { byte opcode; byte mod; byte operand1; byte operand2; byte unknown[2]; } _INSTRUCTION, *pInstruction; _INSTRUCTION ins; enum _OPCODE { JMP, MOVR, MOVM, ADD, XOR, CMP, JMPE, HLT }; void fetchDecode(pInstruction pIns){ word currentIP = adr(cpu.regs[cs], cpu.ip); pIns->opcode = (mem[currentIP] >> 5) & 0x07; pIns->mod = (mem[currentIP] >> 4) & 0x01; pIns->operand1 = mem[currentIP] & 0x0F; pIns->operand2 = mem[currentIP+1]; pIns->unknown[0] = mem[currentIP]; pIns->unknown[1] = mem[currentIP+1]; cpu.ip += 2; } void exec(pInstruction pIns){ printf("IP:%d\t", cpu.ip); switch(pIns->opcode) { case JMP: if(!pIns->mod){ cpu.ip = cpu.regs[pIns->operand1]; printf("JMP %d\n", pIns->operand1); } else{ cpu.regs[cs] = pIns->operand2; cpu.ip = (cpu.regs[cs] << 4) + cpu.regs[pIns->operand1]; printf("JMP %d: %d\n", pIns->operand2, pIns->operand1); } break; case MOVR: if(!pIns->mod){ cpu.regs[pIns->operand1] = cpu.regs[pIns->operand2]; printf("MOVR %d, %d\n", pIns->operand1, pIns->operand2); } else{ cpu.regs[pIns->operand1] = pIns->operand2; printf("MOVR %d, %02X\n", pIns->operand1, pIns->operand2); } break; case MOVM: if(!pIns->mod){ cpu.regs[pIns->operand1] = mem[adr(cpu.regs[ds], cpu.regs[pIns->operand2])]; printf("MOVM %d, [DS: %d]\n", pIns->operand1, pIns->operand2); } else{ mem[adr(cpu.regs[ds], cpu.regs[pIns->operand1])] = cpu.regs[pIns->operand2]; printf("MOVM [DS: %d], %d\n", pIns->operand1, pIns->operand2); } break; case ADD: if(!pIns->mod){ cpu.regs[pIns->operand1] += cpu.regs[pIns->operand2]; printf("ADD %d, %d\n", pIns->operand1, pIns->operand2); } else{ cpu.regs[pIns->operand1] += pIns->operand2; printf("ADD %d, %02X\n", pIns->operand1, pIns->operand2); } break; case XOR: if(!pIns->mod){ cpu.regs[pIns->operand1] ^= cpu.regs[pIns->operand2]; printf("XOR %d, R%d\n", pIns->operand1, pIns->operand2); } else{ cpu.regs[pIns->operand1] ^= pIns->operand2; printf("XOR %d, %02X\n", pIns->operand1, pIns->operand2); } break; case CMP: if(!pIns->mod){ cpu.fl = cpu.regs[pIns->operand1] == cpu.regs[pIns->operand2]? 0x00: (cpu.regs[pIns->operand1] < cpu.regs[pIns->operand2]? 0xff: 0x01); printf("CMP %d, %d\n", pIns->operand1, pIns->operand2); } else{ cpu.fl = cpu.regs[pIns->operand1] == pIns->operand2? 0x00: (cpu.regs[pIns->operand1] < pIns->operand2? 0xff: 0x01); printf("CMP %d, %02X\n", pIns->operand1, pIns->operand2); } break; case JMPE: if(!cpu.fl){ if(!pIns->mod){ cpu.ip = adr(cpu.regs[cs], cpu.regs[pIns->operand1]); printf("JMPE %d\n", pIns->operand1); } else{ cpu.ip = adr(cpu.regs[cs], adr(cpu.regs[pIns->operand2], cpu.regs[pIns->operand1])); printf("JMPE %d: %d\n", pIns->operand2, pIns->operand1); } break; } --cpu.ip; printf("JMPE NOP\n"); break; case HLT: pIns->opcode = HLT; printf("HLT\n"); break; default: pIns->opcode = HLT; printf("UNKNOW %02Xh, %02Xh\n", pIns->unknown[0], pIns->unknown[1]); break; }; } main(){ cpu.ip = 0x00; cpu.regs[r0] = 0x00; cpu.regs[r1] = 0x00; cpu.regs[r2] = 0x00; cpu.regs[r3] = 0x00; cpu.regs[cs] = 0x00; cpu.regs[ds] = 0x10; cpu.fl = 0x00; int i = 0; while ( ++i < (2<<16) && ins.opcode != HLT) { fetchDecode(&ins); exec(&ins); } FILE *fp = fopen("mem.dump", "w"); dword dataStart = adr(cpu.regs[ds], 0); fwrite((void*)(mem+dataStart), sizeof(mem)-dataStart, 1, fp); fclose(fp); }
Execute it:
$ gcc -arch i386 -g stage2_vm.c -o stage2_vm $ ./stage2_vm ... IP:22 JMPE NOP IP:23 CMP 0, 00 IP:25 MOVR 0, 1B IP:27 JMPE 0 IP:29 HLT $ strings mem.dump GET /da75370fe15c4148bd4ceec861fbdaa5.exe HTTP/1.0 h%2w b#[GUS0 k6oofU0 t\?)+f= EFg }D kEmT `bUZJfa xvar>7#Vsqyc| Z//NN
/da75370fe15c4148bd4ceec861fbdaa5.exe is the answer of part 2.
Part 3:
The result of part2 are URL, it need cygwin environment for executing, so you need get Windows or wine.
Have a look at which strings it contains.
$ strings da75370fe15c4148bd4ceec861fbdaa5.exe ... hqDTK7b8K2rvw keygen.exe usage: keygen.exe hostname license.txt error: license.txt not found loading stage1 license key(s)... loading stage2 license key(s)... error: license.txt invalid error: gethostbyname() failed error: connect("%s") failed GET /%s/%x/%x/%x/key.txt HTTP/1.0 ...
Many useful staffs are shown;
First, rename da75370fe15c4148bd4ceec861fbdaa5.exe to keygen.exe.
usage:
keygen.exe canyoucrackit.co.uk
And, license.txt is necessary.
This is a part of disassembling codes, pick up from IDA Pro 6.1.110530 Evaluation version
.text:00401120 loc_401120: .text:00401120 mov [esp+78h+var_70], 18h .text:00401128 mov [esp+78h+hqDTK7b8K2rvw_copy], 0 .text:00401130 lea eax, [ebp+license1] .text:00401133 mov [esp+78h+license2], eax .text:00401136 call memset .text:0040113B lea eax, [ebp+license1] .text:0040113E mov [esp+78h+var_70], eax .text:00401142 mov [esp+78h+hqDTK7b8K2rvw_copy], offset aS ; "%s" .text:0040114A mov eax, [ebp+var_4C] .text:0040114D mov [esp+78h+license2], eax .text:00401150 call fscanf .text:00401155 mov eax, [ebp+var_4C] .text:00401158 mov [esp+78h+license2], eax .text:0040115B call fclose .text:00401160 mov [ebp+var_4C], 0 .text:00401167 cmp [ebp+license1], 'qhcg' // head 4 chars of license are qhcg .text:0040116E jnz short loc_4011CF .text:00401170 mov eax, hqDTK7b8K2rvw .text:00401175 mov [esp+78h+hqDTK7b8K2rvw_copy], eax .text:00401179 lea eax, [ebp+license1] .text:0040117C add eax, 4 .text:0040117F mov [esp+78h+license2], eax // char *crypt(const char *key, const char *salt); // key are 8 chars、salt are 2 chars .text:00401182 call crypt // crypt("license", "hq"); .text:00401187 mov edx, eax .text:00401189 mov eax, hqDTK7b8K2rvw .text:0040118E mov [esp+78h+hqDTK7b8K2rvw_copy], eax .text:00401192 mov [esp+78h+license2], edx .text:00401195 call strcmp .text:0040119A test eax, eax .text:0040119C jnz short loc_4011A5 .text:0040119E mov [ebp+var_C], 1 .text:004011A5 .text:004011A5 loc_4011A5: .text:004011A5 mov [esp+78h+license2], offset aLoadingStage1L ; "loading stage1 license key(s)...\n" .text:004011AC call printf .text:004011B1 mov eax, [ebp+license3] .text:004011B4 mov [ebp+license3_copy], eax .text:004011B7 mov [esp+78h+license2], offset aLoadingStage2L ; "loading stage2 license key(s)...\n\n" .text:004011BE call printf .text:004011C3 mov eax, [ebp+license4] .text:004011C6 mov [ebp+license4_copy], eax .text:004011C9 mov eax, [ebp+license5] .text:004011CC mov [ebp+license5_copy], eax .text:004011CF .text:004011CF loc_4011CF: .text:004011CF cmp [ebp+var_C], 0 .text:004011D3 jnz short loc_4011EA .text:004011D5 mov [esp+78h+license2], offset aErrorLicense_0 ; "error: license.txt invalid\n" .text:004011DC call printf .text:004011E1 mov [ebp+var_50], 0FFFFFFFFh .text:004011E8 jmp short loc_401204 .text:004011EA ; --------------------------------------------------------------------------- .text:004011EA .text:004011EA loc_4011EA: .text:004011EA lea eax, [ebp+license3_copy] .text:004011ED mov [esp+78h+hqDTK7b8K2rvw_copy], eax .text:004011F1 mov eax, [ebp+hostname] .text:004011F4 add eax, 4 .text:004011F7 mov eax, [eax] .text:004011F9 mov [esp+78h+license2], eax .text:004011FC call genURL //for generating URL only need license3,4,5 .text:00401201 mov [ebp+var_50], eax .text:00401204 .text:00401204 loc_401204: .text:00401204 .text:00401204 mov eax, [ebp+var_50] .text:00401207 leave .text:00401208 retn .text:00401208 sub_401090 endp
This is the structure of license.txt
qhcg + 8 chars of crypt + license3(4bytes) + license4(4bytes) + license5(4bytes)
Where can we found license3 ~ license5?
This is the hint:
"loading stage1 license key(s)...\n" "loading stage2 license key(s)...\n\n"
It tell us, in part1 has 1 key, and in part2 have two keys.
license3: In part1, the first op is JMP: 0: eb 04 jmp 0x6 2: af scas %es:(%edi),%eax 3: c2 bf a3 ret $0xa3bf So 0x2 0x3 should never be used, it is the answer. notice: x86 is using Little endian, afc2bfa3 need be written in a3bfc2af. license4,5: The firmware in cpu structure of part 2 are never used. firmware: [0xd2ab1f05, 0xda13f110] It is the answer.
But I dont know where is the hidden license2 in.
Change jnz in .text:0040119C to jmp can easily solve this problem. 0x75 -> 0xEB
I googled license2, cyberwin is the answer.
Finally, the license.txt is
67636871637962657277696EAFC2BFA3051FABD210F113DA
save it with HEX.
$ ./keygen.exe canyoucrackit.co.uk keygen.exe loading stage1 license key(s)... loading stage2 license key(s)... request: GET /hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txt HTTP/1.0
http://canyoucrackit.co.uk/hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txtを開くと、
Pr0t3ct!on#cyber_security@12*12.2011+
This is the final answer.
[frame align=”center”][/frame]
Crackded it!
Reference:
The Mac Hacker’s Handbook
http://pastebin.com/GAZ2aCLm
[/tab]
问题出处: http://canyoucrackit.co.uk/
第1部分:
[frame align=”center”] [/frame]
从图片中可以看到共有10×16=160字节的信息、因为是16进制编码的, 乍看之下也没有什么头绪, 首先先来查看下里面含有哪些ASCII文字.
$ strings raw \X=AAAAuCX=BBBBu;Z
只有AAAA, BBBB. 看不出什么特别的意思.
回到16进制, 可以看到第一个字节是0xEB、0xEB(JMP)这个无条件跳转经常在破解中用到. 难道说这个是2进制可执行文件?
$ gobjdump -D -b binary -mi386 raw raw: file format binary Disassembly of section .data: 00000000 <.data>: 0: eb 04 jmp 0x6 2: af scas %es:(%edi),%eax 3: c2 bf a3 ret $0xa3bf 6: 81 ec 00 01 00 00 sub $0x100,%esp c: 31 c9 xor %ecx,%ecx e: 88 0c 0c mov %cl,(%esp,%ecx,1) 11: fe c1 inc %cl 13: 75 f9 jne 0xe 15: 31 c0 xor %eax,%eax 17: ba ef be ad de mov $0xdeadbeef,%edx 1c: 02 04 0c add (%esp,%ecx,1),%al 1f: 00 d0 add %dl,%al 21: c1 ca 08 ror $0x8,%edx 24: 8a 1c 0c mov (%esp,%ecx,1),%bl 27: 8a 3c 04 mov (%esp,%eax,1),%bh 2a: 88 1c 04 mov %bl,(%esp,%eax,1) 2d: 88 3c 0c mov %bh,(%esp,%ecx,1) 30: fe c1 inc %cl 32: 75 e8 jne 0x1c 34: e9 5c 00 00 00 jmp 0x95 39: 89 e3 mov %esp,%ebx 3b: 81 c3 04 00 00 00 add $0x4,%ebx 41: 5c pop %esp 42: 58 pop %eax 43: 3d 41 41 41 41 cmp $0x41414141,%eax 48: 75 43 jne 0x8d 4a: 58 pop %eax 4b: 3d 42 42 42 42 cmp $0x42424242,%eax 50: 75 3b jne 0x8d 52: 5a pop %edx 53: 89 d1 mov %edx,%ecx 55: 89 e6 mov %esp,%esi 57: 89 df mov %ebx,%edi 59: 29 cf sub %ecx,%edi 5b: f3 a4 rep movsb %ds:(%esi),%es:(%edi) 5d: 89 de mov %ebx,%esi 5f: 89 d1 mov %edx,%ecx 61: 89 df mov %ebx,%edi 63: 29 cf sub %ecx,%edi 65: 31 c0 xor %eax,%eax 67: 31 db xor %ebx,%ebx 69: 31 d2 xor %edx,%edx 6b: fe c0 inc %al 6d: 02 1c 06 add (%esi,%eax,1),%bl 70: 8a 14 06 mov (%esi,%eax,1),%dl 73: 8a 34 1e mov (%esi,%ebx,1),%dh 76: 88 34 06 mov %dh,(%esi,%eax,1) 79: 88 14 1e mov %dl,(%esi,%ebx,1) 7c: 00 f2 add %dh,%dl 7e: 30 f6 xor %dh,%dh 80: 8a 1c 16 mov (%esi,%edx,1),%bl 83: 8a 17 mov (%edi),%dl 85: 30 da xor %bl,%dl 87: 88 17 mov %dl,(%edi) 89: 47 inc %edi 8a: 49 dec %ecx 8b: 75 de jne 0x6b 8d: 31 db xor %ebx,%ebx 8f: 89 d8 mov %ebx,%eax 91: fe c0 inc %al 93: cd 80 int $0x80 95: 90 nop 96: 90 nop 97: e8 9d ff ff ff call 0x39 9c: 41 inc %ecx 9d: 41 inc %ecx 9e: 41 inc %ecx 9f: 41 inc %ecx
第一行出现JMP让人感到莫名其妙. 但是从整个代码来看, 基本上能确定是正常的可执行文件片段.
有几个地方在执行的时候会出现问题:
0x97行在调用了0x39的同时把0x9C压入栈中、但是在0x42、0x4A两行都是pop指令的话, 第2次的pop会是没有意义的.
0x9c~0x9f行的内容是0x41414141、也就是ASCIIのAAAA. 在先前的文字搜索的时候还出现了BBBB.
0x43行、比较了EAX和AAAA的值、因为EAX储存的是0x9c~0x9f行のAAAA、其結果必然是真。
但是在下一行, 于BBBB进行比较的时候、EAX的值是不确定的。从这边可以看出0x9f行的后面可能遗漏了部分代码.
把问题的照片下载下来, 看下照片的16进制代码:
$ hexdump -C cyber.png 00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| 00000010 00 00 02 e4 00 00 01 04 08 02 00 00 00 ef 6a b6 |..............j.| 00000020 2d 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 |-....sRGB.......| 00000030 00 09 70 48 59 73 00 00 0b 13 00 00 0b 13 01 00 |..pHYs..........| 00000040 9a 9c 18 00 00 00 07 74 49 4d 45 07 db 08 05 0e |.......tIME.....| 00000050 12 33 7e 39 c1 70 00 00 00 5d 69 54 58 74 43 6f |.3~9.p...]iTXtCo| 00000060 6d 6d 65 6e 74 00 00 00 00 00 51 6b 4a 43 51 6a |mment.....QkJCQj| 00000070 49 41 41 41 43 52 32 50 46 74 63 43 41 36 71 32 |IAAACR2PFtcCA6q2| 00000080 65 61 43 38 53 52 2b 38 64 6d 44 2f 7a 4e 7a 4c |eaC8SR+8dmD/zNzL| 00000090 51 43 2b 74 64 33 74 46 51 34 71 78 38 4f 34 34 |QC+td3tFQ4qx8O44| 000000a0 37 54 44 65 75 5a 77 35 50 2b 30 53 73 62 45 63 |7TDeuZw5P+0SsbEc| 000000b0 59 52 0a 37 38 6a 4b 4c 77 3d 3d 32 ca be f1 00 |YR.78jKLw==2....| ...
在文件的头部
QkJCQjIAAACR2PFtcCA6q2eaC8SR+8dmD/zNzLQC+td3tFQ4qx8O447TDeuZw5P+0SsbEcYR.78jKLw==
是这样写的. 文字的最后是”==”, 这就提醒了我, 这段代码应该是通过Base64进行编码的.
BASE64中对”.”是没有定义的、这边”.”实际上是换行符0x0A、应该被省略。
解码:
$ echo 'QkJCQjIAAACR2PFtcCA6q2eaC8SR+8dmD/zNzLQC+td3tFQ4qx8O447TDeuZw5P+0SsbEcYR78jKLw==' | base64 -D -o decoded.bin $ hexdump -C decoded.bin 00000000 42 42 42 42 32 00 00 00 91 d8 f1 6d 70 20 3a ab |BBBB2......mp :.| 00000010 67 9a 0b c4 91 fb c7 66 0f fc cd cc b4 02 fa d7 |g......f........| 00000020 77 b4 54 38 ab 1f 0e e3 8e d3 0d eb 99 c3 93 fe |w.T8............| 00000030 d1 2b 1b 11 c6 11 ef c8 ca 2f |.+......./| 0000003a
BBBB出现了, 把这段代码和先前代码合并后, 执行看下.
#include <stdio.h> #include <sys/types.h> #include <sys/mman.h> main(){ int i; static unsigned char shellcode[] = { 0xEB,0x04,0xAF,0xC2,0xBF,0xA3,0x81,0xEC, 0x00,0x01,0x00,0x00,0x31,0xC9,0x88,0x0C, 0x0C,0xFE,0xC1,0x75,0xF9,0x31,0xC0,0xBA, 0xEF,0xBE,0xAD,0xDE,0x02,0x04,0x0C,0x00, 0xD0,0xC1,0xCA,0x08,0x8A,0x1C,0x0C,0x8A, 0x3C,0x04,0x88,0x1C,0x04,0x88,0x3C,0x0C, 0xFE,0xC1,0x75,0xE8,0xE9,0x5C,0x00,0x00, 0x00,0x89,0xE3,0x81,0xC3,0x04,0x00,0x00, 0x00,0x5C,0x58,0x3D,0x41,0x41,0x41,0x41, 0x75,0x43,0x58,0x3D,0x42,0x42,0x42,0x42, 0x75,0x3B,0x5A,0x89,0xD1,0x89,0xE6,0x89, 0xDF,0x29,0xCF,0xF3,0xA4,0x89,0xDE,0x89, 0xD1,0x89,0xDF,0x29,0xCF,0x31,0xC0,0x31, 0xDB,0x31,0xD2,0xFE,0xC0,0x02,0x1C,0x06, 0x8A,0x14,0x06,0x8A,0x34,0x1E,0x88,0x34, 0x06,0x88,0x14,0x1E,0x00,0xF2,0x30,0xF6, 0x8A,0x1C,0x16,0x8A,0x17,0x30,0xDA,0x88, 0x17,0x47,0x49,0x75,0xDE,0x31,0xDB,0x89, 0xD8,0xFE,0xC0,0xCD,0x80,0x90,0x90,0xE8, 0x9D,0xFF,0xFF,0xFF,0x41,0x41,0x41,0x41, 0x42,0x42,0x42,0x42,0x32,0x00,0x00,0x00, 0x91,0xD8,0xF1,0x6D,0x70,0x20,0x3A,0xAB, 0x67,0x9A,0x0B,0xC4,0x91,0xFB,0xC7,0x66, 0x0F,0xFC,0xCD,0xCC,0xB4,0x02,0xFA,0xD7, 0x77,0xB4,0x54,0x38,0xAB,0x1F,0x0E,0xE3, 0x8E,0xD3,0x0D,0xEB,0x99,0xC3,0x93,0xFE, 0xD1,0x2B,0x1B,0x11,0xC6,0x11,0xEF,0xC8, 0xCA,0x2F }; /* * patch INT 0x80 to INT 3 to throw an exception signal to debugger * 0xCD -> 0xCC */ printf("patching shellcode...\n"); for(i = 0; i < sizeof(shellcode); i++){ if(*(unsigned short*)&shellcode[i] == 0x80CD){ shellcode[i] = 0xCC; printf("patch done\n"); break; } } unsigned int page = ((unsigned int)shellcode)&0xfffff000; if(-1 == mprotect((void*)page, 4096, PROT_READ | PROT_WRITE | PROT_EXEC)) perror("mprotect error"); ((int(*)())shellcode)(); }
代码的执行结果在0x87行中的, EDI到EDI-0x32(解码后得到的BBBB后面的那个字节).
$ gcc -arch i386 -g stage1.c -o stage1 $ gdb stage1 (gdb) r (gdb) x/s $edi-0x32 0xbffff79a: "GET /15b436de1f9107f3778aad525e5d0b20.js HTTP/1.1"
第2部分:
第1部分中得到的结果URL
//-------------------------------------------------------------------------------------------------- // // stage 2 of 3 // // challenge: // reveal the solution within VM.mem // // disclaimer: // tested in ie 9, firefox 6, chrome 14 and v8 shell (http://code.google.com/apis/v8/build.html), // other javascript implementations may or may not work. // //-------------------------------------------------------------------------------------------------- var VM = { cpu: { ip: 0x00, r0: 0x00, r1: 0x00, r2: 0x00, r3: 0x00, cs: 0x00, ds: 0x10, fl: 0x00, firmware: [0xd2ab1f05, 0xda13f110] }, mem: [ 0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50, 0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8, 0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56, 0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9, 0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69, 0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60, 0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8, 0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d, 0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67, 0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a, 0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9, 0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e, 0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55, 0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3, 0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f, 0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d, 0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1, 0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94, 0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62, 0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b, 0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1, 0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61, 0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14, 0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2, 0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1, 0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], exec: function() { // virtual machine architecture // ++++++++++++++++++++++++++++ // // segmented memory model with 16-byte segment size (notation seg:offset) // // 4 general-purpose registers (r0-r3) // 2 segment registers (cs, ds equiv. to r4, r5) // 1 flags register (fl) // // instruction encoding // ++++++++++++++++++++ // // byte 1 byte 2 (optional) // bits [ 7 6 5 4 3 2 1 0 ] [ 7 6 5 4 3 2 1 0 ] // opcode - - - // mod - // operand1 - - - - // operand2 - - - - - - - - // // operand1 is always a register index // operand2 is optional, depending upon the instruction set specified below // the value of mod alters the meaning of any operand2 // 0: operand2 = reg ix // 1: operand2 = fixed immediate value or target segment (depending on instruction) // // instruction set // +++++++++++++++ // // Notes: // * r1, r2 => operand 1 is register 1, operand 2 is register 2 // * movr r1, r2 => move contents of register r2 into register r1 // // opcode | instruction | operands (mod 0) | operands (mod 1) // -------+-------------+------------------+----------------- // 0x00 | jmp | r1 | r2:r1 // 0x01 | movr | r1, r2 | rx, imm // 0x02 | movm | r1, [ds:r2] | [ds:r1], r2 // 0x03 | add | r1, r2 | r1, imm // 0x04 | xor | r1, r2 | r1, imm // 0x05 | cmp | r1, r2 | r1, imm // 0x06 | jmpe | r1 | r2:r1 // 0x07 | hlt | N/A | N/A // // flags // +++++ // // cmp r1, r2 instruction results in: // r1 == r2 => fl = 0 // r1 < r2 => fl = 0xff // r1 > r2 => fl = 1 // // jmpe r1 // => if (fl == 0) jmp r1 // else nop throw "VM.exec not yet implemented"; } }; //-------------------------------------------------------------------------------------------------- try { VM.exec(); } catch(e) { alert('\nError: ' + e + '\n'); } //--------------------------------------------------------------------------------------------------
问题已经写的很清楚了, 设计一个虚拟CPU, 执行2进制代码后的的结果便是答案。
#include <stdio.h> static unsigned char mem[] = { 0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50, 0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8, 0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56, 0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9, 0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69, 0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60, 0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8, 0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d, 0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67, 0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a, 0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9, 0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e, 0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55, 0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3, 0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f, 0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d, 0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1, 0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94, 0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62, 0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b, 0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1, 0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61, 0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14, 0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2, 0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1, 0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #define adr(seg, off) ((seg << 4) + off) typedef unsigned char byte; typedef unsigned short word; typedef unsigned int dword; typedef struct _CPU { byte ip; byte regs[6]; byte fl; } _CPU; _CPU cpu; enum _REGISTER { r0, r1, r2, r3, cs, ds }; typedef struct _INSTRUCTION { byte opcode; byte mod; byte operand1; byte operand2; byte unknown[2]; } _INSTRUCTION, *pInstruction; _INSTRUCTION ins; enum _OPCODE { JMP, MOVR, MOVM, ADD, XOR, CMP, JMPE, HLT }; void fetchDecode(pInstruction pIns){ word currentIP = adr(cpu.regs[cs], cpu.ip); pIns->opcode = (mem[currentIP] >> 5) & 0x07; pIns->mod = (mem[currentIP] >> 4) & 0x01; pIns->operand1 = mem[currentIP] & 0x0F; pIns->operand2 = mem[currentIP+1]; pIns->unknown[0] = mem[currentIP]; pIns->unknown[1] = mem[currentIP+1]; cpu.ip += 2; } void exec(pInstruction pIns){ printf("IP:%d\t", cpu.ip); switch(pIns->opcode) { case JMP: if(!pIns->mod){ cpu.ip = cpu.regs[pIns->operand1]; printf("JMP %d\n", pIns->operand1); } else{ cpu.regs[cs] = pIns->operand2; cpu.ip = (cpu.regs[cs] << 4) + cpu.regs[pIns->operand1]; printf("JMP %d: %d\n", pIns->operand2, pIns->operand1); } break; case MOVR: if(!pIns->mod){ cpu.regs[pIns->operand1] = cpu.regs[pIns->operand2]; printf("MOVR %d, %d\n", pIns->operand1, pIns->operand2); } else{ cpu.regs[pIns->operand1] = pIns->operand2; printf("MOVR %d, %02X\n", pIns->operand1, pIns->operand2); } break; case MOVM: if(!pIns->mod){ cpu.regs[pIns->operand1] = mem[adr(cpu.regs[ds], cpu.regs[pIns->operand2])]; printf("MOVM %d, [DS: %d]\n", pIns->operand1, pIns->operand2); } else{ mem[adr(cpu.regs[ds], cpu.regs[pIns->operand1])] = cpu.regs[pIns->operand2]; printf("MOVM [DS: %d], %d\n", pIns->operand1, pIns->operand2); } break; case ADD: if(!pIns->mod){ cpu.regs[pIns->operand1] += cpu.regs[pIns->operand2]; printf("ADD %d, %d\n", pIns->operand1, pIns->operand2); } else{ cpu.regs[pIns->operand1] += pIns->operand2; printf("ADD %d, %02X\n", pIns->operand1, pIns->operand2); } break; case XOR: if(!pIns->mod){ cpu.regs[pIns->operand1] ^= cpu.regs[pIns->operand2]; printf("XOR %d, R%d\n", pIns->operand1, pIns->operand2); } else{ cpu.regs[pIns->operand1] ^= pIns->operand2; printf("XOR %d, %02X\n", pIns->operand1, pIns->operand2); } break; case CMP: if(!pIns->mod){ cpu.fl = cpu.regs[pIns->operand1] == cpu.regs[pIns->operand2]? 0x00: (cpu.regs[pIns->operand1] < cpu.regs[pIns->operand2]? 0xff: 0x01); printf("CMP %d, %d\n", pIns->operand1, pIns->operand2); } else{ cpu.fl = cpu.regs[pIns->operand1] == pIns->operand2? 0x00: (cpu.regs[pIns->operand1] < pIns->operand2? 0xff: 0x01); printf("CMP %d, %02X\n", pIns->operand1, pIns->operand2); } break; case JMPE: if(!cpu.fl){ if(!pIns->mod){ cpu.ip = adr(cpu.regs[cs], cpu.regs[pIns->operand1]); printf("JMPE %d\n", pIns->operand1); } else{ cpu.ip = adr(cpu.regs[cs], adr(cpu.regs[pIns->operand2], cpu.regs[pIns->operand1])); printf("JMPE %d: %d\n", pIns->operand2, pIns->operand1); } break; } --cpu.ip; printf("JMPE NOP\n"); break; case HLT: pIns->opcode = HLT; printf("HLT\n"); break; default: pIns->opcode = HLT; printf("UNKNOW %02Xh, %02Xh\n", pIns->unknown[0], pIns->unknown[1]); break; }; } main(){ cpu.ip = 0x00; cpu.regs[r0] = 0x00; cpu.regs[r1] = 0x00; cpu.regs[r2] = 0x00; cpu.regs[r3] = 0x00; cpu.regs[cs] = 0x00; cpu.regs[ds] = 0x10; cpu.fl = 0x00; int i = 0; while ( ++i < (2<<16) && ins.opcode != HLT) { fetchDecode(&ins); exec(&ins); } FILE *fp = fopen("mem.dump", "w"); dword dataStart = adr(cpu.regs[ds], 0); fwrite((void*)(mem+dataStart), sizeof(mem)-dataStart, 1, fp); fclose(fp); }
执行:
$ gcc -arch i386 -g stage2_vm.c -o stage2_vm $ ./stage2_vm ... IP:22 JMPE NOP IP:23 CMP 0, 00 IP:25 MOVR 0, 1B IP:27 JMPE 0 IP:29 HLT $ strings mem.dump GET /da75370fe15c4148bd4ceec861fbdaa5.exe HTTP/1.0 h%2w b#[GUS0 k6oofU0 t\?)+f= EFg }D kEmT `bUZJfa xvar>7#Vsqyc| Z//NN
/da75370fe15c4148bd4ceec861fbdaa5.exe 是第2部分的答案
第3部分
第2部分取得的URL需要cygwin环境的支持、因此要在Windows或者wine中执行。
在执行之前先搜索下代码中包含了哪些文字
$ strings da75370fe15c4148bd4ceec861fbdaa5.exe ... hqDTK7b8K2rvw keygen.exe usage: keygen.exe hostname license.txt error: license.txt not found loading stage1 license key(s)... loading stage2 license key(s)... error: license.txt invalid error: gethostbyname() failed error: connect("%s") failed GET /%s/%x/%x/%x/key.txt HTTP/1.0 ...
这次有很多有意义的结果.
首先把da75370fe15c4148bd4ceec861fbdaa5.exe重命名为keygen.exe。
使用方法:
keygen.exe canyoucrackit.co.uk
另外需要license.txt这个文件才能执行.
下面这段是反汇编的结果, 取自IDA Pro 6.1.110530 Evaluation version
.text:00401120 loc_401120: .text:00401120 mov [esp+78h+var_70], 18h .text:00401128 mov [esp+78h+hqDTK7b8K2rvw_copy], 0 .text:00401130 lea eax, [ebp+license1] .text:00401133 mov [esp+78h+license2], eax .text:00401136 call memset .text:0040113B lea eax, [ebp+license1] .text:0040113E mov [esp+78h+var_70], eax .text:00401142 mov [esp+78h+hqDTK7b8K2rvw_copy], offset aS ; "%s" .text:0040114A mov eax, [ebp+var_4C] .text:0040114D mov [esp+78h+license2], eax .text:00401150 call fscanf .text:00401155 mov eax, [ebp+var_4C] .text:00401158 mov [esp+78h+license2], eax .text:0040115B call fclose .text:00401160 mov [ebp+var_4C], 0 .text:00401167 cmp [ebp+license1], 'qhcg' // license开始4个字是qhcg .text:0040116E jnz short loc_4011CF .text:00401170 mov eax, hqDTK7b8K2rvw .text:00401175 mov [esp+78h+hqDTK7b8K2rvw_copy], eax .text:00401179 lea eax, [ebp+license1] .text:0040117C add eax, 4 .text:0040117F mov [esp+78h+license2], eax // char *crypt(const char *key, const char *salt); // key:8字、salt:2字 .text:00401182 call crypt // crypt("license第5个字以后", "hq"); .text:00401187 mov edx, eax .text:00401189 mov eax, hqDTK7b8K2rvw .text:0040118E mov [esp+78h+hqDTK7b8K2rvw_copy], eax .text:00401192 mov [esp+78h+license2], edx .text:00401195 call strcmp .text:0040119A test eax, eax .text:0040119C jnz short loc_4011A5 .text:0040119E mov [ebp+var_C], 1 .text:004011A5 .text:004011A5 loc_4011A5: .text:004011A5 mov [esp+78h+license2], offset aLoadingStage1L ; "loading stage1 license key(s)...\n" .text:004011AC call printf .text:004011B1 mov eax, [ebp+license3] .text:004011B4 mov [ebp+license3_copy], eax .text:004011B7 mov [esp+78h+license2], offset aLoadingStage2L ; "loading stage2 license key(s)...\n\n" .text:004011BE call printf .text:004011C3 mov eax, [ebp+license4] .text:004011C6 mov [ebp+license4_copy], eax .text:004011C9 mov eax, [ebp+license5] .text:004011CC mov [ebp+license5_copy], eax .text:004011CF .text:004011CF loc_4011CF: .text:004011CF cmp [ebp+var_C], 0 .text:004011D3 jnz short loc_4011EA .text:004011D5 mov [esp+78h+license2], offset aErrorLicense_0 ; "error: license.txt invalid\n" .text:004011DC call printf .text:004011E1 mov [ebp+var_50], 0FFFFFFFFh .text:004011E8 jmp short loc_401204 .text:004011EA ; --------------------------------------------------------------------------- .text:004011EA .text:004011EA loc_4011EA: .text:004011EA lea eax, [ebp+license3_copy] .text:004011ED mov [esp+78h+hqDTK7b8K2rvw_copy], eax .text:004011F1 mov eax, [ebp+hostname] .text:004011F4 add eax, 4 .text:004011F7 mov eax, [eax] .text:004011F9 mov [esp+78h+license2], eax .text:004011FC call genURL //生成URL需要license的3,4,5部分 .text:00401201 mov [ebp+var_50], eax .text:00401204 .text:00401204 loc_401204: .text:00401204 .text:00401204 mov eax, [ebp+var_50] .text:00401207 leave .text:00401208 retn .text:00401208 sub_401090 endp
总结这段代码, license的构成应该是:
qhcg + crypt用的8字符的密匙(可省略) + license3(4字节) + license4(4字节) + license5(4字节)
license3 ~ license5在哪边能找到呢?
这里有一段提示:
"loading stage1 license key(s)...\n" "loading stage2 license key(s)...\n\n"
也就是说、第1部分中有1个密匙、第2部分中有2个密匙
license3: 第1部分中代码开始部分就JMP了, 这边值得怀疑 0: eb 04 jmp 0x6 2: af scas %es:(%edi),%eax 3: c2 bf a3 ret $0xa3bf JMP后面的4字节afc2bfa3就是答案. 注意: x86是小尾序、afc2bfa3 应该写成 a3bfc2af。 license4,5: CPU的结构体中定义的firmware实际上并没有使用 firmware: [0xd2ab1f05, 0xda13f110] 这就是答案了
license2如果不知道的话
.text:0040119C的jnz 改成jmp就行了 0x75 -> 0xEB
google后发现, license2的答案是cyberwin。
license.txt的内容:
67636871637962657277696EAFC2BFA3051FABD210F113DA
用16进制保存.
$ ./keygen.exe canyoucrackit.co.uk keygen.exe loading stage1 license key(s)... loading stage2 license key(s)... request: GET /hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txt HTTP/1.0
打开http://canyoucrackit.co.uk/hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txt
Pr0t3ct!on#cyber_security@12*12.2011+
这就是最终的答案
[frame align=”center”][/frame]
成功!!!
参考引用:
The Mac Hacker’s Handbook
http://pastebin.com/GAZ2aCLm
[/tab]
[tab title=”日本語”]
Blogの更新も久しぶりだね、今回のテーマは、イギリスの政府通信本部GCHQからの求職問題です。
問題はここ: http://canyoucrackit.co.uk/
Part 1:
[frame align=”center”] [/frame]
目に見える生データは10×16=160バイトの情報です、そのままじゃ考えにくいので、その中に何かの文字を入っているかを確認する。
$ strings raw \X=AAAAuCX=BBBBu;Z
AAAA, BBBBしか無い、それはヒントにならない!
ちょっと、最初のバイトは0xEBだ、0xEB(JMP)はクラッキングによく使うよね! もしかして、実行できるBinaryファイルなの? 確認しよう!
$ gobjdump -D -b binary -mi386 raw raw: file format binary Disassembly of section .data: 00000000 <.data>: 0: eb 04 jmp 0x6 2: af scas %es:(%edi),%eax 3: c2 bf a3 ret $0xa3bf 6: 81 ec 00 01 00 00 sub $0x100,%esp c: 31 c9 xor %ecx,%ecx e: 88 0c 0c mov %cl,(%esp,%ecx,1) 11: fe c1 inc %cl 13: 75 f9 jne 0xe 15: 31 c0 xor %eax,%eax 17: ba ef be ad de mov $0xdeadbeef,%edx 1c: 02 04 0c add (%esp,%ecx,1),%al 1f: 00 d0 add %dl,%al 21: c1 ca 08 ror $0x8,%edx 24: 8a 1c 0c mov (%esp,%ecx,1),%bl 27: 8a 3c 04 mov (%esp,%eax,1),%bh 2a: 88 1c 04 mov %bl,(%esp,%eax,1) 2d: 88 3c 0c mov %bh,(%esp,%ecx,1) 30: fe c1 inc %cl 32: 75 e8 jne 0x1c 34: e9 5c 00 00 00 jmp 0x95 39: 89 e3 mov %esp,%ebx 3b: 81 c3 04 00 00 00 add $0x4,%ebx 41: 5c pop %esp 42: 58 pop %eax 43: 3d 41 41 41 41 cmp $0x41414141,%eax 48: 75 43 jne 0x8d 4a: 58 pop %eax 4b: 3d 42 42 42 42 cmp $0x42424242,%eax 50: 75 3b jne 0x8d 52: 5a pop %edx 53: 89 d1 mov %edx,%ecx 55: 89 e6 mov %esp,%esi 57: 89 df mov %ebx,%edi 59: 29 cf sub %ecx,%edi 5b: f3 a4 rep movsb %ds:(%esi),%es:(%edi) 5d: 89 de mov %ebx,%esi 5f: 89 d1 mov %edx,%ecx 61: 89 df mov %ebx,%edi 63: 29 cf sub %ecx,%edi 65: 31 c0 xor %eax,%eax 67: 31 db xor %ebx,%ebx 69: 31 d2 xor %edx,%edx 6b: fe c0 inc %al 6d: 02 1c 06 add (%esi,%eax,1),%bl 70: 8a 14 06 mov (%esi,%eax,1),%dl 73: 8a 34 1e mov (%esi,%ebx,1),%dh 76: 88 34 06 mov %dh,(%esi,%eax,1) 79: 88 14 1e mov %dl,(%esi,%ebx,1) 7c: 00 f2 add %dh,%dl 7e: 30 f6 xor %dh,%dh 80: 8a 1c 16 mov (%esi,%edx,1),%bl 83: 8a 17 mov (%edi),%dl 85: 30 da xor %bl,%dl 87: 88 17 mov %dl,(%edi) 89: 47 inc %edi 8a: 49 dec %ecx 8b: 75 de jne 0x6b 8d: 31 db xor %ebx,%ebx 8f: 89 d8 mov %ebx,%eax 91: fe c0 inc %al 93: cd 80 int $0x80 95: 90 nop 96: 90 nop 97: e8 9d ff ff ff call 0x39 9c: 41 inc %ecx 9d: 41 inc %ecx 9e: 41 inc %ecx 9f: 41 inc %ecx
なんで最初からJMPしているかがよく分からないが、コード全体は基本OPしかないので、実行できそうな感じ。
ただ、0x97行のところから、0x39行にCALLしている間に、0x9C行をstackにpushしているのに、0x42行、0x4A行二回連続POPするとはあり得ない。
0x9c~0x9f行は0x41414141になっているけど、それはASCIIのAAAAだね、先文字列を検索するときに、BBBBも出ていたよ。
0x43行に見たら、EAXとAAAAをCMPしている、EAXは0x9c~0x9f行のAAAAを格納しているので、結果がtrueのことが分かったね。
問題は、その次の行がBBBBとCMPしているのに、EAXは何かが格納しているのは分からない。即ち、0x9f行の後ろが何かのデータが抜いている。
問題の写真をダウンロードして、HEXコードを見ていたら、
$ hexdump -C cyber.png 00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| 00000010 00 00 02 e4 00 00 01 04 08 02 00 00 00 ef 6a b6 |..............j.| 00000020 2d 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 |-....sRGB.......| 00000030 00 09 70 48 59 73 00 00 0b 13 00 00 0b 13 01 00 |..pHYs..........| 00000040 9a 9c 18 00 00 00 07 74 49 4d 45 07 db 08 05 0e |.......tIME.....| 00000050 12 33 7e 39 c1 70 00 00 00 5d 69 54 58 74 43 6f |.3~9.p...]iTXtCo| 00000060 6d 6d 65 6e 74 00 00 00 00 00 51 6b 4a 43 51 6a |mment.....QkJCQj| 00000070 49 41 41 41 43 52 32 50 46 74 63 43 41 36 71 32 |IAAACR2PFtcCA6q2| 00000080 65 61 43 38 53 52 2b 38 64 6d 44 2f 7a 4e 7a 4c |eaC8SR+8dmD/zNzL| 00000090 51 43 2b 74 64 33 74 46 51 34 71 78 38 4f 34 34 |QC+td3tFQ4qx8O44| 000000a0 37 54 44 65 75 5a 77 35 50 2b 30 53 73 62 45 63 |7TDeuZw5P+0SsbEc| 000000b0 59 52 0a 37 38 6a 4b 4c 77 3d 3d 32 ca be f1 00 |YR.78jKLw==2....| ...
最初の当たりに
QkJCQjIAAACR2PFtcCA6q2eaC8SR+8dmD/zNzLQC+td3tFQ4qx8O447TDeuZw5P+0SsbEcYR.78jKLw==
が書いている。後ろが”==”になっていることは、もしかして、Base64でエンコードしているのかを疑ったいる。
BASE64では”.”が定義していないが、ここの”.”は実際に改行記号の0x0Aなので、要らない。
Decode:
$ echo 'QkJCQjIAAACR2PFtcCA6q2eaC8SR+8dmD/zNzLQC+td3tFQ4qx8O447TDeuZw5P+0SsbEcYR78jKLw==' | base64 -D -o decoded.bin $ hexdump -C decoded.bin 00000000 42 42 42 42 32 00 00 00 91 d8 f1 6d 70 20 3a ab |BBBB2......mp :.| 00000010 67 9a 0b c4 91 fb c7 66 0f fc cd cc b4 02 fa d7 |g......f........| 00000020 77 b4 54 38 ab 1f 0e e3 8e d3 0d eb 99 c3 93 fe |w.T8............| 00000030 d1 2b 1b 11 c6 11 ef c8 ca 2f |.+......./| 0000003a
Woo! BBBBが出てきたぞ! それを前のコードを合併して、実行してみよう!
#include <stdio.h> #include <sys/types.h> #include <sys/mman.h> main(){ int i; static unsigned char shellcode[] = { 0xEB,0x04,0xAF,0xC2,0xBF,0xA3,0x81,0xEC, 0x00,0x01,0x00,0x00,0x31,0xC9,0x88,0x0C, 0x0C,0xFE,0xC1,0x75,0xF9,0x31,0xC0,0xBA, 0xEF,0xBE,0xAD,0xDE,0x02,0x04,0x0C,0x00, 0xD0,0xC1,0xCA,0x08,0x8A,0x1C,0x0C,0x8A, 0x3C,0x04,0x88,0x1C,0x04,0x88,0x3C,0x0C, 0xFE,0xC1,0x75,0xE8,0xE9,0x5C,0x00,0x00, 0x00,0x89,0xE3,0x81,0xC3,0x04,0x00,0x00, 0x00,0x5C,0x58,0x3D,0x41,0x41,0x41,0x41, 0x75,0x43,0x58,0x3D,0x42,0x42,0x42,0x42, 0x75,0x3B,0x5A,0x89,0xD1,0x89,0xE6,0x89, 0xDF,0x29,0xCF,0xF3,0xA4,0x89,0xDE,0x89, 0xD1,0x89,0xDF,0x29,0xCF,0x31,0xC0,0x31, 0xDB,0x31,0xD2,0xFE,0xC0,0x02,0x1C,0x06, 0x8A,0x14,0x06,0x8A,0x34,0x1E,0x88,0x34, 0x06,0x88,0x14,0x1E,0x00,0xF2,0x30,0xF6, 0x8A,0x1C,0x16,0x8A,0x17,0x30,0xDA,0x88, 0x17,0x47,0x49,0x75,0xDE,0x31,0xDB,0x89, 0xD8,0xFE,0xC0,0xCD,0x80,0x90,0x90,0xE8, 0x9D,0xFF,0xFF,0xFF,0x41,0x41,0x41,0x41, 0x42,0x42,0x42,0x42,0x32,0x00,0x00,0x00, 0x91,0xD8,0xF1,0x6D,0x70,0x20,0x3A,0xAB, 0x67,0x9A,0x0B,0xC4,0x91,0xFB,0xC7,0x66, 0x0F,0xFC,0xCD,0xCC,0xB4,0x02,0xFA,0xD7, 0x77,0xB4,0x54,0x38,0xAB,0x1F,0x0E,0xE3, 0x8E,0xD3,0x0D,0xEB,0x99,0xC3,0x93,0xFE, 0xD1,0x2B,0x1B,0x11,0xC6,0x11,0xEF,0xC8, 0xCA,0x2F }; /* * patch INT 0x80 to INT 3 to throw an exception signal to debugger * 0xCD -> 0xCC */ printf("patching shellcode...\n"); for(i = 0; i < sizeof(shellcode); i++){ if(*(unsigned short*)&shellcode[i] == 0x80CD){ shellcode[i] = 0xCC; printf("patch done\n"); break; } } unsigned int page = ((unsigned int)shellcode)&0xfffff000; if(-1 == mprotect((void*)page, 4096, PROT_READ | PROT_WRITE | PROT_EXEC)) perror("mprotect error"); ((int(*)())shellcode)(); }
結果は0x87行あたりに、EDIに格納しているアドレスから、EDI-(新しい取ったデータのBBBBの後ろの1バイト0x32)に保存している。
$ gcc -arch i386 -g stage1.c -o stage1 $ gdb stage1 (gdb) r (gdb) x/s $edi-0x32 0xbffff79a: "GET /15b436de1f9107f3778aad525e5d0b20.js HTTP/1.1"
Part 2:
part1で取ったURL
//-------------------------------------------------------------------------------------------------- // // stage 2 of 3 // // challenge: // reveal the solution within VM.mem // // disclaimer: // tested in ie 9, firefox 6, chrome 14 and v8 shell (http://code.google.com/apis/v8/build.html), // other javascript implementations may or may not work. // //-------------------------------------------------------------------------------------------------- var VM = { cpu: { ip: 0x00, r0: 0x00, r1: 0x00, r2: 0x00, r3: 0x00, cs: 0x00, ds: 0x10, fl: 0x00, firmware: [0xd2ab1f05, 0xda13f110] }, mem: [ 0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50, 0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8, 0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56, 0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9, 0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69, 0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60, 0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8, 0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d, 0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67, 0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a, 0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9, 0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e, 0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55, 0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3, 0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f, 0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d, 0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1, 0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94, 0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62, 0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b, 0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1, 0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61, 0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14, 0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2, 0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1, 0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], exec: function() { // virtual machine architecture // ++++++++++++++++++++++++++++ // // segmented memory model with 16-byte segment size (notation seg:offset) // // 4 general-purpose registers (r0-r3) // 2 segment registers (cs, ds equiv. to r4, r5) // 1 flags register (fl) // // instruction encoding // ++++++++++++++++++++ // // byte 1 byte 2 (optional) // bits [ 7 6 5 4 3 2 1 0 ] [ 7 6 5 4 3 2 1 0 ] // opcode - - - // mod - // operand1 - - - - // operand2 - - - - - - - - // // operand1 is always a register index // operand2 is optional, depending upon the instruction set specified below // the value of mod alters the meaning of any operand2 // 0: operand2 = reg ix // 1: operand2 = fixed immediate value or target segment (depending on instruction) // // instruction set // +++++++++++++++ // // Notes: // * r1, r2 => operand 1 is register 1, operand 2 is register 2 // * movr r1, r2 => move contents of register r2 into register r1 // // opcode | instruction | operands (mod 0) | operands (mod 1) // -------+-------------+------------------+----------------- // 0x00 | jmp | r1 | r2:r1 // 0x01 | movr | r1, r2 | rx, imm // 0x02 | movm | r1, [ds:r2] | [ds:r1], r2 // 0x03 | add | r1, r2 | r1, imm // 0x04 | xor | r1, r2 | r1, imm // 0x05 | cmp | r1, r2 | r1, imm // 0x06 | jmpe | r1 | r2:r1 // 0x07 | hlt | N/A | N/A // // flags // +++++ // // cmp r1, r2 instruction results in: // r1 == r2 => fl = 0 // r1 < r2 => fl = 0xff // r1 > r2 => fl = 1 // // jmpe r1 // => if (fl == 0) jmp r1 // else nop throw "VM.exec not yet implemented"; } }; //-------------------------------------------------------------------------------------------------- try { VM.exec(); } catch(e) { alert('\nError: ' + e + '\n'); } //--------------------------------------------------------------------------------------------------
問題の主旨ははっきり分かる、仮想CPUを作って、バイナリコードを実行し結果を得られる。
低いレベルのプログラミングになるね、CS,DSなどを復習したら、出来ると思う。
#include <stdio.h> static unsigned char mem[] = { 0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50, 0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8, 0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56, 0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9, 0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69, 0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60, 0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8, 0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d, 0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67, 0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a, 0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9, 0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e, 0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55, 0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3, 0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f, 0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d, 0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1, 0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94, 0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62, 0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b, 0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1, 0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61, 0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14, 0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2, 0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1, 0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #define adr(seg, off) ((seg << 4) + off) typedef unsigned char byte; typedef unsigned short word; typedef unsigned int dword; typedef struct _CPU { byte ip; byte regs[6]; byte fl; } _CPU; _CPU cpu; enum _REGISTER { r0, r1, r2, r3, cs, ds }; typedef struct _INSTRUCTION { byte opcode; byte mod; byte operand1; byte operand2; byte unknown[2]; } _INSTRUCTION, *pInstruction; _INSTRUCTION ins; enum _OPCODE { JMP, MOVR, MOVM, ADD, XOR, CMP, JMPE, HLT }; void fetchDecode(pInstruction pIns){ word currentIP = adr(cpu.regs[cs], cpu.ip); pIns->opcode = (mem[currentIP] >> 5) & 0x07; pIns->mod = (mem[currentIP] >> 4) & 0x01; pIns->operand1 = mem[currentIP] & 0x0F; pIns->operand2 = mem[currentIP+1]; pIns->unknown[0] = mem[currentIP]; pIns->unknown[1] = mem[currentIP+1]; cpu.ip += 2; } void exec(pInstruction pIns){ printf("IP:%d\t", cpu.ip); switch(pIns->opcode) { case JMP: if(!pIns->mod){ cpu.ip = cpu.regs[pIns->operand1]; printf("JMP %d\n", pIns->operand1); } else{ cpu.regs[cs] = pIns->operand2; cpu.ip = (cpu.regs[cs] << 4) + cpu.regs[pIns->operand1]; printf("JMP %d: %d\n", pIns->operand2, pIns->operand1); } break; case MOVR: if(!pIns->mod){ cpu.regs[pIns->operand1] = cpu.regs[pIns->operand2]; printf("MOVR %d, %d\n", pIns->operand1, pIns->operand2); } else{ cpu.regs[pIns->operand1] = pIns->operand2; printf("MOVR %d, %02X\n", pIns->operand1, pIns->operand2); } break; case MOVM: if(!pIns->mod){ cpu.regs[pIns->operand1] = mem[adr(cpu.regs[ds], cpu.regs[pIns->operand2])]; printf("MOVM %d, [DS: %d]\n", pIns->operand1, pIns->operand2); } else{ mem[adr(cpu.regs[ds], cpu.regs[pIns->operand1])] = cpu.regs[pIns->operand2]; printf("MOVM [DS: %d], %d\n", pIns->operand1, pIns->operand2); } break; case ADD: if(!pIns->mod){ cpu.regs[pIns->operand1] += cpu.regs[pIns->operand2]; printf("ADD %d, %d\n", pIns->operand1, pIns->operand2); } else{ cpu.regs[pIns->operand1] += pIns->operand2; printf("ADD %d, %02X\n", pIns->operand1, pIns->operand2); } break; case XOR: if(!pIns->mod){ cpu.regs[pIns->operand1] ^= cpu.regs[pIns->operand2]; printf("XOR %d, R%d\n", pIns->operand1, pIns->operand2); } else{ cpu.regs[pIns->operand1] ^= pIns->operand2; printf("XOR %d, %02X\n", pIns->operand1, pIns->operand2); } break; case CMP: if(!pIns->mod){ cpu.fl = cpu.regs[pIns->operand1] == cpu.regs[pIns->operand2]? 0x00: (cpu.regs[pIns->operand1] < cpu.regs[pIns->operand2]? 0xff: 0x01); printf("CMP %d, %d\n", pIns->operand1, pIns->operand2); } else{ cpu.fl = cpu.regs[pIns->operand1] == pIns->operand2? 0x00: (cpu.regs[pIns->operand1] < pIns->operand2? 0xff: 0x01); printf("CMP %d, %02X\n", pIns->operand1, pIns->operand2); } break; case JMPE: if(!cpu.fl){ if(!pIns->mod){ cpu.ip = adr(cpu.regs[cs], cpu.regs[pIns->operand1]); printf("JMPE %d\n", pIns->operand1); } else{ cpu.ip = adr(cpu.regs[cs], adr(cpu.regs[pIns->operand2], cpu.regs[pIns->operand1])); printf("JMPE %d: %d\n", pIns->operand2, pIns->operand1); } break; } --cpu.ip; printf("JMPE NOP\n"); break; case HLT: pIns->opcode = HLT; printf("HLT\n"); break; default: pIns->opcode = HLT; printf("UNKNOW %02Xh, %02Xh\n", pIns->unknown[0], pIns->unknown[1]); break; }; } main(){ cpu.ip = 0x00; cpu.regs[r0] = 0x00; cpu.regs[r1] = 0x00; cpu.regs[r2] = 0x00; cpu.regs[r3] = 0x00; cpu.regs[cs] = 0x00; cpu.regs[ds] = 0x10; cpu.fl = 0x00; int i = 0; while ( ++i < (2<<16) && ins.opcode != HLT) { fetchDecode(&ins); exec(&ins); } FILE *fp = fopen("mem.dump", "w"); dword dataStart = adr(cpu.regs[ds], 0); fwrite((void*)(mem+dataStart), sizeof(mem)-dataStart, 1, fp); fclose(fp); }
実行してみる:
$ gcc -arch i386 -g stage2_vm.c -o stage2_vm $ ./stage2_vm ... IP:22 JMPE NOP IP:23 CMP 0, 00 IP:25 MOVR 0, 1B IP:27 JMPE 0 IP:29 HLT $ strings mem.dump GET /da75370fe15c4148bd4ceec861fbdaa5.exe HTTP/1.0 h%2w b#[GUS0 k6oofU0 t\?)+f= EFg }D kEmT `bUZJfa xvar>7#Vsqyc| Z//NN
/da75370fe15c4148bd4ceec861fbdaa5.exe はPart 2で得られた結果!!
Part 3:
part2で取ったURLはcygwin環境が必要なので、Windowsもしくはwineで実行しよう。
実行する前に文字検索するね
$ strings da75370fe15c4148bd4ceec861fbdaa5.exe ... hqDTK7b8K2rvw keygen.exe usage: keygen.exe hostname license.txt error: license.txt not found loading stage1 license key(s)... loading stage2 license key(s)... error: license.txt invalid error: gethostbyname() failed error: connect("%s") failed GET /%s/%x/%x/%x/key.txt HTTP/1.0 ...
お!、結構情報入ってるじゃん。
まずda75370fe15c4148bd4ceec861fbdaa5.exeをkeygen.exeにrenameする。
使い方は:
keygen.exe canyoucrackit.co.uk
後、license.txtというファイルが用意せんとだめよね。
Disassemblyしたコードの抜粹です, IDA Pro 6.1.110530 Evaluation versionより
.text:00401120 loc_401120: .text:00401120 mov [esp+78h+var_70], 18h .text:00401128 mov [esp+78h+hqDTK7b8K2rvw_copy], 0 .text:00401130 lea eax, [ebp+license1] .text:00401133 mov [esp+78h+license2], eax .text:00401136 call memset .text:0040113B lea eax, [ebp+license1] .text:0040113E mov [esp+78h+var_70], eax .text:00401142 mov [esp+78h+hqDTK7b8K2rvw_copy], offset aS ; "%s" .text:0040114A mov eax, [ebp+var_4C] .text:0040114D mov [esp+78h+license2], eax .text:00401150 call fscanf .text:00401155 mov eax, [ebp+var_4C] .text:00401158 mov [esp+78h+license2], eax .text:0040115B call fclose .text:00401160 mov [ebp+var_4C], 0 .text:00401167 cmp [ebp+license1], 'qhcg' // license先頭の4文字がqhcg .text:0040116E jnz short loc_4011CF .text:00401170 mov eax, hqDTK7b8K2rvw .text:00401175 mov [esp+78h+hqDTK7b8K2rvw_copy], eax .text:00401179 lea eax, [ebp+license1] .text:0040117C add eax, 4 .text:0040117F mov [esp+78h+license2], eax // char *crypt(const char *key, const char *salt); // keyは8文字、saltは2文字 .text:00401182 call crypt // crypt("license5文字以後", "hq"); .text:00401187 mov edx, eax .text:00401189 mov eax, hqDTK7b8K2rvw .text:0040118E mov [esp+78h+hqDTK7b8K2rvw_copy], eax .text:00401192 mov [esp+78h+license2], edx .text:00401195 call strcmp .text:0040119A test eax, eax .text:0040119C jnz short loc_4011A5 .text:0040119E mov [ebp+var_C], 1 .text:004011A5 .text:004011A5 loc_4011A5: .text:004011A5 mov [esp+78h+license2], offset aLoadingStage1L ; "loading stage1 license key(s)...\n" .text:004011AC call printf .text:004011B1 mov eax, [ebp+license3] .text:004011B4 mov [ebp+license3_copy], eax .text:004011B7 mov [esp+78h+license2], offset aLoadingStage2L ; "loading stage2 license key(s)...\n\n" .text:004011BE call printf .text:004011C3 mov eax, [ebp+license4] .text:004011C6 mov [ebp+license4_copy], eax .text:004011C9 mov eax, [ebp+license5] .text:004011CC mov [ebp+license5_copy], eax .text:004011CF .text:004011CF loc_4011CF: .text:004011CF cmp [ebp+var_C], 0 .text:004011D3 jnz short loc_4011EA .text:004011D5 mov [esp+78h+license2], offset aErrorLicense_0 ; "error: license.txt invalid\n" .text:004011DC call printf .text:004011E1 mov [ebp+var_50], 0FFFFFFFFh .text:004011E8 jmp short loc_401204 .text:004011EA ; --------------------------------------------------------------------------- .text:004011EA .text:004011EA loc_4011EA: .text:004011EA lea eax, [ebp+license3_copy] .text:004011ED mov [esp+78h+hqDTK7b8K2rvw_copy], eax .text:004011F1 mov eax, [ebp+hostname] .text:004011F4 add eax, 4 .text:004011F7 mov eax, [eax] .text:004011F9 mov [esp+78h+license2], eax .text:004011FC call genURL //URL生成するにはlicenseの3,4,5だけで出来る .text:00401201 mov [ebp+var_50], eax .text:00401204 .text:00401204 loc_401204: .text:00401204 .text:00401204 mov eax, [ebp+var_50] .text:00401207 leave .text:00401208 retn .text:00401208 sub_401090 endp
まとめてすると、licenseと構成は
qhcg + crypt用8文字のキー(無くてもおk) + license3(4バイト) + license4(4バイト) + license5(4バイト)
license3 ~ license5はどこで探せんるんだ?
ヒントは
"loading stage1 license key(s)...\n" "loading stage2 license key(s)...\n\n"
即ち、part1のところから1つと、part2からキー2つがどこかに隠していると考えられる。
これは運で言うものか、よく分からんだけど、答えとしては
license3: part1の最初がJMPしたよね? そこがヒントにならん? 0: eb 04 jmp 0x6 2: af scas %es:(%edi),%eax 3: c2 bf a3 ret $0xa3bf ここの afc2bfa3 が答え! 注意: x86はLittle endianのため、afc2bfa3 は a3 bf c2 afで書くね。 license4,5: cpu構造体の中に定義したfirmwareは実際使ってないじゃない? firmware: [0xd2ab1f05, 0xda13f110] それが答え!
license2はどこかに隠しているのは分からないが、分からなかったら、
.text:0040119Cのjnz をjmpにするだけてできる。 0x75 -> 0xEB
ネットで検索すると、license2はcyberwinが答えになってる。分かる方は是非教えてください。
最終的にlicense.txtの内容を
67636871637962657277696EAFC2BFA3051FABD210F113DA
HEXで保存するね。
$ ./keygen.exe canyoucrackit.co.uk keygen.exe loading stage1 license key(s)... loading stage2 license key(s)... request: GET /hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txt HTTP/1.0
http://canyoucrackit.co.uk/hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txtを開くと、
Pr0t3ct!on#cyber_security@12*12.2011+
これが最終の答えだ! 入力してみると
[frame align=”center”][/frame]
成功!!!
参考引用:
The Mac Hacker’s Handbook
http://pastebin.com/GAZ2aCLm
[/tab]
[/tabs]