The UK govt created a challenge to find eligible code crackers. The website is http://www.canyoucrackit.co.uk/.
I got close, but my skills aren't up to par. Here is as far as I got. They give you the following code:
What jumps out at me first are the nops (90 90) in the last line. My mind automagically tells me this is shellcode. I wasn't 100% sure, but it was the only guess I had. I copied the code over into gedit, and made the following adjustments.
I then saved this into a shellcode.c file:
Running it simply returned the "done" being printed by printf. This told me that the shellcode was at least not crashing, so it was probably valid shellcode. Looks like my first impression was correct. So I jumped to the asm that the shellcode produced to get a better understanding of it:
Definitely legitimate shellcode. The x86 asm gcc spits out is exactly what I wanted to see. Not only that, but do you see the 0xdeadbeef?
Once I knew I was in the right direction, I loaded the binary into gdb. I through a breakpoint on the printf line with
Oh well. Maybe next time if I have more time I can get a bit further.
I got close, but my skills aren't up to par. Here is as far as I got. They give you the following code:
eb 04 af c2 bf a3 81 ec 00 01 00 00 31 c9 88 0c
0c fe c1 75 f9 31 c0 ba ef be ad de 02 04 0c 00
d0 c1 ca 08 8a 1c 0c 8a 3c 04 88 1c 04 88 3c 0c
fe c1 75 e8 e9 5c 00 00 00 89 e3 81 c3 04 00 00
00 5c 58 3d 41 41 41 41 75 43 48 3d 42 42 42 42
75 3b 5a 89 d1 89 e6 89 df 29 cf f3 a4 89 de 89
d1 89 df 29 cf 31 c0 31 db 31 d2 fe c0 02 1c 06
8a 14 06 8a 34 1e 88 34 06 88 14 1e 00 f2 30 f6
8a 1c 16 8a 17 30 da 88 17 47 49 75 de 31 db 89
d8 fe c0 cd 80 90 90 e8 9d ff ff ff 41 41 41 41
What jumps out at me first are the nops (90 90) in the last line. My mind automagically tells me this is shellcode. I wasn't 100% sure, but it was the only guess I had. I copied the code over into gedit, and made the following adjustments.
\xeb\x04\xaf\xc2\xbf\xa3\x81\xec\x00\x01\x00\x00\x31\xc9\x88\x0c
\x0c\xfe\xc1\x75\xf9\x31\xc0\xba\xef\xbe\xad\xde\x02\x04\x0c\x00
\xd0\xc1\xca\x08\x8a\x1c\x0c\x8a\x3c\x04\x88\x1c\x04\x88\x3c\x0c
\xfe\xc1\x75\xe8\xe9\x5c\x00\x00\x00\x89\xe3\x81\xc3\x04\x00\x00
\x00\x5c\x58\x3d\x41\x41\x41\x41\x75\x43\x48\x3d\x42\x42\x42\x42
\x75\x3b\x5a\x89\xd1\x89\xe6\x89\xdf\x29\xcf\xf3\xa4\x89\xde\x89
\xd1\x89\xdf\x29\xcf\x31\xc0\x31\xdb\x31\xd2\xfe\xc0\x02\x1c\x06
\x8a\x14\x06\x8a\x34\x1e\x88\x34\x06\x88\x14\x1e\x00\xf2\x30\xf6
\x8a\x1c\x16\x8a\x17\x30\xda\x88\x17\x47\x49\x75\xde\x31\xdb\x89
\xd8\xfe\xc0\xcd\x80\x90\x90\xe8\x9d\xff\xff\xff\x41\x41\x41\x41
I then saved this into a shellcode.c file:
char shellcode[] = "\xeb\x04\xaf\xc2\xbf\xa3\x81\xec\x00\x01\x00\x00\x31\xc9\x88\x0c\x0c\xfe\xc1\x75\xf9\x31\xc0\xba\xef\xbe\xad\xde\x02\x04\x0c\x00\xd0\xc1\xca\x08\x8a\x1c\x0c\x8a\x3c\x04\x88\x1c\x04\x88\x3c\x0c\xfe\xc1\x75\xe8\xe9\x5c\x00\x00\x00\x89\xe3\x81\xc3\x04\x00\x00\x00\x5c\x58\x3d\x41\x41\x41\x41\x75\x43\x48\x3d\x42\x42\x42\x42\x75\x3b\x5a\x89\xd1\x89\xe6\x89\xdf\x29\xcf\xf3\xa4\x89\xde\x89\xd1\x89\xdf\x29\xcf\x31\xc0\x31\xdb\x31\xd2\xfe\xc0\x02\x1c\x06\x8a\x14\x06\x8a\x34\x1e\x88\x34\x06\x88\x14\x1e\x00\xf2\x30\xf6\x8a\x1c\x16\x8a\x17\x30\xda\x88\x17\x47\x49\x75\xde\x31\xdb\x89\xd8\xfe\xc0\xcd\x80\x90\x90\xe8\x9d\xff\xff\xff\x41\x41\x41\x41";
void main() {
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
printf("done");
}
Running it simply returned the "done" being printed by printf. This told me that the shellcode was at least not crashing, so it was probably valid shellcode. Looks like my first impression was correct. So I jumped to the asm that the shellcode produced to get a better understanding of it:
0000000000601040 :
601040: eb 04 jmp 601046
601042: af scas %es:(%rdi),%eax
601043: c2 bf a3 retq $0xa3bf
601046: 81 ec 00 01 00 00 sub $0x100,%esp
60104c: 31 c9 xor %ecx,%ecx
60104e: 88 0c 0c mov %cl,(%rsp,%rcx,1)
601051: fe c1 inc %cl
601053: 75 f9 jne 60104e
601055: 31 c0 xor %eax,%eax
601057: ba ef be ad de mov $0xdeadbeef,%edx
60105c: 02 04 0c add (%rsp,%rcx,1),%al
60105f: 00 d0 add %dl,%al
601061: c1 ca 08 ror $0x8,%edx
601064: 8a 1c 0c mov (%rsp,%rcx,1),%bl
601067: 8a 3c 04 mov (%rsp,%rax,1),%bh
60106a: 88 1c 04 mov %bl,(%rsp,%rax,1)
60106d: 88 3c 0c mov %bh,(%rsp,%rcx,1)
601070: fe c1 inc %cl
601072: 75 e8 jne 60105c
601074: e9 5c 00 00 00 jmpq 6010d5
601079: 89 e3 mov %esp,%ebx
60107b: 81 c3 04 00 00 00 add $0x4,%ebx
601081: 5c pop %rsp
601082: 58 pop %rax
601083: 3d 41 41 41 41 cmp $0x41414141,%eax
601088: 75 43 jne 6010cd
60108a: 48 3d 42 42 42 42 cmp $0x42424242,%rax
601090: 75 3b jne 6010cd
601092: 5a pop %rdx
601093: 89 d1 mov %edx,%ecx
601095: 89 e6 mov %esp,%esi
601097: 89 df mov %ebx,%edi
601099: 29 cf sub %ecx,%edi
60109b: f3 a4 rep movsb %ds:(%rsi),%es:(%rdi)
60109d: 89 de mov %ebx,%esi
60109f: 89 d1 mov %edx,%ecx
6010a1: 89 df mov %ebx,%edi
6010a3: 29 cf sub %ecx,%edi
6010a5: 31 c0 xor %eax,%eax
6010a7: 31 db xor %ebx,%ebx
6010a9: 31 d2 xor %edx,%edx
6010ab: fe c0 inc %al
6010ad: 02 1c 06 add (%rsi,%rax,1),%bl
6010b0: 8a 14 06 mov (%rsi,%rax,1),%dl
6010b3: 8a 34 1e mov (%rsi,%rbx,1),%dh
6010b6: 88 34 06 mov %dh,(%rsi,%rax,1)
6010b9: 88 14 1e mov %dl,(%rsi,%rbx,1)
6010bc: 00 f2 add %dh,%dl
6010be: 30 f6 xor %dh,%dh
6010c0: 8a 1c 16 mov (%rsi,%rdx,1),%bl
6010c3: 8a 17 mov (%rdi),%dl
6010c5: 30 da xor %bl,%dl
6010c7: 88 17 mov %dl,(%rdi)
6010c9: 47 rex.RXB
6010ca: 49 75 de rex.WB jne 6010ab
6010cd: 31 db xor %ebx,%ebx
6010cf: 89 d8 mov %ebx,%eax
6010d1: fe c0 inc %al
6010d3: cd 80 int $0x80
6010d5: 90 nop
6010d6: 90 nop
6010d7: e8 9d ff ff ff callq 601079
6010dc: 41 rex.B
6010dd: 41 rex.B
6010de: 41 rex.B
6010df: 41 00 00 add %al,(%r8)
Definitely legitimate shellcode. The x86 asm gcc spits out is exactly what I wanted to see. Not only that, but do you see the 0xdeadbeef?
Once I knew I was in the right direction, I loaded the binary into gdb. I through a breakpoint on the printf line with
break printfand ran the binary. I looked at the stack frame, traversed through the memory and found the strings I suspected were what we were supposed to be looking for. However, they seemed to be all multi-byte characters. I wasn't able to decipher any of them within the time limit. I had found out about the contest about 2 hours before it was over. This took me about an hour to get to traversing the stack for the strings, and I got stuck.
Oh well. Maybe next time if I have more time I can get a bit further.