The challenge is to crack the challenge by answering it right.
seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? 1
^C
[2]+ Stopped ./bonus_reverse-challenge
seed@seed-desktop:~/projects/2$ file ./bonus_reverse-challenge
./bonus_reverse-challenge: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, stripped
This is a stripped binary so cannot find main in objdump output. So the guess is since "Are you feeling lucky today?" is printed by
a call to printf with the string as an argument in the program. we need to find where the string is and where is getting loaded to stack
just before a call to printf, then we know that we are somewhere in code section and check what happens after that to our input.
(gdb) p/x 'A'
$1 = 0x41
(gdb) p/x 'r'
$2 = 0x72
(gdb)
"Are you feeling lucky today?" starts with 'A' and 'r' so we try to find 41 and 72 in objdump.
seed@seed-desktop:~/projects/2$ objdump -D ./bonus_reverse-challenge > obj
seed@seed-desktop:~/projects/2$ grep -n "41 72" obj
1018: 8048bfa: 00 41 72 add %al,0x72(%ecx)
(gdb) x/s 0x8048bfb
0x8048bfb: "Are you feeling lucky today? "
searching 8048bfb to figuring who is loading it to stack in objdump gives.
8048997: b8 fb 8b 04 08 mov $0x8048bfb,%eax
804899c: 89 04 24 mov %eax,(%esp)
804899f: e8 0c fb ff ff call 80484b0 <printf@plt>
80489a4: a1 60 a0 04 08 mov 0x804a060,%eax
80489a9: 89 04 24 mov %eax,(%esp)
80489ac: e8 0f fb ff ff call 80484c0 <fflush@plt>
80489b1: c7 44 24 08 ff 01 00 movl $0x1ff,0x8(%esp)
80489b8: 00
80489b9: 8d 44 24 20 lea 0x20(%esp),%eax
80489bd: 89 44 24 04 mov %eax,0x4(%esp)
80489c1: c7 04 24 00 00 00 00 movl $0x0,(%esp)
80489c8: e8 d3 fa ff ff call 80484a0 <read@plt>
80489cd: 8d 44 24 20 lea 0x20(%esp),%eax
80489d1: c7 44 24 1c ff ff ff movl $0xffffffff,0x1c(%esp)
80489d8: ff
80489d9: 89 c2 mov %eax,%edx
80489db: b8 00 00 00 00 mov $0x0,%eax
80489e0: 8b 4c 24 1c mov 0x1c(%esp),%ecx
80489e4: 89 d7 mov %edx,%edi
80489e6: f2 ae repnz scas %es:(%edi),%al
80489e8: 89 c8 mov %ecx,%eax
80489ea: f7 d0 not %eax
80489ec: 83 e8 01 sub $0x1,%eax
80489ef: 89 84 24 28 02 00 00 mov %eax,0x228(%esp)
80489f6: 8b 84 24 28 02 00 00 mov 0x228(%esp),%eax
80489fd: 83 e8 01 sub $0x1,%eax
8048a00: 0f b6 44 04 20 movzbl 0x20(%esp,%eax,1),%eax
8048a05: 3c 0a cmp $0xa,%al
8048a07: 75 0f jne 8048a18 <close@plt+0x498>
8048a09: 8b 84 24 28 02 00 00 mov 0x228(%esp),%eax
8048a10: 83 e8 01 sub $0x1,%eax
8048a13: c6 44 04 20 00 movb $0x0,0x20(%esp,%eax,1)
8048a18: 0f b6 44 24 20 movzbl 0x20(%esp),%eax
8048a1d: 0f be c0 movsbl %al,%eax
8048a20: 83 f8 42 cmp $0x42,%eax
8048a23: 74 17 je 8048a3c <close@plt+0x4bc>
8048a25: 83 f8 43 cmp $0x43,%eax
8048a28: 74 1f je 8048a49 <close@plt+0x4c9>
8048a2a: 83 f8 41 cmp $0x41,%eax
8048a2d: 75 27 jne 8048a56 <close@plt+0x4d6>
8048a2f: c7 84 24 2c 02 00 00 movl $0x804872b,0x22c(%esp)
8048a36: 2b 87 04 08
8048a3a: eb 1c jmp 8048a58 <close@plt+0x4d8>
8048a3c: c7 84 24 2c 02 00 00 movl $0x8048644,0x22c(%esp)
8048a43: 44 86 04 08
8048a47: eb 0f jmp 8048a58 <close@plt+0x4d8>
8048a49: c7 84 24 2c 02 00 00 movl $0x80486ca,0x22c(%esp)
8048a50: ca 86 04 08
8048a54: eb 02 jmp 8048a58 <close@plt+0x4d8>
8048a56: eb fe jmp 8048a56 <close@plt+0x4d6>
8048a58: 0f b6 44 24 20 movzbl 0x20(%esp),%eax
8048a5d: 0f be c0 movsbl %al,%eax
8048a60: 83 e8 42 sub $0x42,%eax
8048a63: 89 84 24 24 02 00 00 mov %eax,0x224(%esp)
8048a6a: 8b 84 24 24 02 00 00 mov 0x224(%esp),%eax
8048a71: 89 44 24 04 mov %eax,0x4(%esp)
8048a75: 8d 44 24 20 lea 0x20(%esp),%eax
8048a79: 83 c0 01 add $0x1,%eax
8048a7c: 89 04 24 mov %eax,(%esp)
8048a7f: 8b 84 24 2c 02 00 00 mov 0x22c(%esp),%eax
8048a86: ff d0 call *%eax
8048a88: 89 84 24 20 02 00 00 mov %eax,0x220(%esp)
8048a8f: 83 bc 24 20 02 00 00 cmpl $0x0,0x220(%esp)
8048a96: 00
8048a97: 74 1a je 8048ab3 <close@plt+0x533>
8048a99: b8 19 8c 04 08 mov $0x8048c19,%eax
8048a9e: 8d 54 24 20 lea 0x20(%esp),%edx
8048aa2: 83 c2 01 add $0x1,%edx
8048aa5: 89 54 24 04 mov %edx,0x4(%esp)
8048aa9: 89 04 24 mov %eax,(%esp)
8048aac: e8 ff f9 ff ff call 80484b0 <printf@plt>
8048ab1: eb 23 jmp 8048ad6 <close@plt+0x556>
8048ab3: 0f b6 44 24 20 movzbl 0x20(%esp),%eax
8048ab8: 3c 42 cmp $0x42,%al
As you can see this is similar to reverse-ex:
printf("Are you feeling lucky today?");
fflush()
read(0,buf,511)
if (buf[n
n = strlen(buf);
if(buf[n-1] = '\n')
buf[n-1] = 0;
switch[buf[0])
case 0x42:
calls 0x8048644
break;
case 0x43:
calls $0x80486ca
break;
case 0x41:
calls 0x804872b
break;
default:
loop
Let's test above analysis.
seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? A
[~] Maybe.
seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? B
[-] Nope.
seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? C
[~] Maybe.
seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? D
^C
[4]+ Stopped ./bonus_reverse-challenge
looks like some progress. Let's choose B route since it is different. Other's will lead to dead-end
but interesting stuff.
So jumping to 0x8048644 the 'B' related answer. This function gets called with two arguments (buf + 1) and (buf[0] - 0x42 = 0).
8048644: 55 push %ebp
8048645: 89 e5 mov %esp,%ebp
8048647: 57 push %edi
8048648: 56 push %esi
8048649: 83 ec 10 sub $0x10,%esp
804864c: 8b 45 08 mov 0x8(%ebp),%eax
804864f: 89 45 f4 mov %eax,-0xc(%ebp)
8048652: 8b 55 0c mov 0xc(%ebp),%edx
8048655: 50 push %eax
8048656: 31 c0 xor %eax,%eax
8048658: 68 64 86 04 08 push $0x8048664
804865d: 58 pop %eax
804865e: 01 d0 add %edx,%eax
8048660: 50 push %eax
8048661: c3 ret
Here ret is popping 0x8048664 and jumping to it, Now instruction pointer is at 0x8048664.
8048662: b8 01 c7 45 f0 mov $0xf045c701,%eax
8048667: fa cli
8048668: 00 00 add %al,(%eax)
804866a: 00 58 eb add %bl,-0x15(%eax)
804866d: 17 pop %ss
804866e: 8b 45 f4 mov -0xc(%ebp),%eax
8048671: 0f b6 00 movzbl (%eax),%eax
...
As you can 0x8048664 is middle of instruction at 0x8048662, so this means objdump disassembly for this piece of
code is bad, let's fix it to find the right instructions which get executed.
code jumps to 8048664 which is the middle of disassembled instruction at 8048662.
So we need to find to what extent the disassembly is bad and of-course the real
opcodes that will be executed.
So implemented a simple C code which converts hex to binary for the opcodes in hex
from address 8048664 for some bytes till the new disassembly (got from feeding the
binary output to objdump) matches the original disassembly.
seed@seed-desktop:~/projects/2$ cat x.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
unsigned char a[64] = {0xc7,0x45,0xf0,0xfa,0x00,0x00,0x00,0x58,
0xeb,0x17,0x8b,0x45,0xf4,0x0f,0xb6,0x00,
0x8b,0x55,0xf0,0x83,0xe2,0x2b,0x31,0xc2,
0x8b,0x45,0xf4,0x88,0x10,0x83,0x45,0xf4,
0x01,0x8b,0x45,0xf4,0x0f,0xb6,0x00,0x84,
0xc0,0x75,0xdf,0x8b,0x45,0x08,0x89,0xc2,
0xb8,0xc0,0x8b,0x04,0x08,0xb9,0x0f,0x00,
0x00,0x00,0x89,0xd6,0x89,0xc7,0xf3,0xa6};
main()
{
int fd;
int ret;
fd = open("c", O_CREAT|O_WRONLY);
if (fd > 0) {
ret = write(fd,a, 64);
}
printf("%d %d\n", fd, ret);
}
seed@seed-desktop:~/projects/2$ gcc x.c
seed@seed-desktop:~/projects/2$ ./a.out
3 64
seed@seed-desktop:~/projects/2$ objdump -D -b binary -mi386 c
c: file format binary
Disassembly of section .data:
00000000 <.data>:
0: c7 45 f0 fa 00 00 00 movl $0xfa,-0x10(%ebp)
7: 58 pop %eax
8: eb 17 jmp 0x21
a: 8b 45 f4 mov -0xc(%ebp),%eax
d: 0f b6 00 movzbl (%eax),%eax
10: 8b 55 f0 mov -0x10(%ebp),%edx
13: 83 e2 2b and $0x2b,%edx
16: 31 c2 xor %eax,%edx
18: 8b 45 f4 mov -0xc(%ebp),%eax
1b: 88 10 mov %dl,(%eax)
1d: 83 45 f4 01 addl $0x1,-0xc(%ebp)
21: 8b 45 f4 mov -0xc(%ebp),%eax
24: 0f b6 00 movzbl (%eax),%eax
27: 84 c0 test %al,%al
29: 75 df jne 0xa
2b: 8b 45 08 mov 0x8(%ebp),%eax
2e: 89 c2 mov %eax,%edx
30: b8 c0 8b 04 08 mov $0x8048bc0,%eax
35: b9 0f 00 00 00 mov $0xf,%ecx
3a: 89 d6 mov %edx,%esi
3c: 89 c7 mov %eax,%edi
3e: f3 a6 repz cmpsb %es:(%edi),%ds:(%esi)
So only the hex bytes (\xc7\x45\xf0\x00\x00\x00\x58\xeb\x17) are the bad disassembled codes
otherwise everything remains the same.
8048662: b8 01 c7 45 f0 mov $0xf045c701,%eax
8048667: fa cli
8048668: 00 00 add %al,(%eax)
804866a: 00 58 eb add %bl,-0x15(%eax)
804866d: 17 pop %ss
is equivalent to
0: c7 45 f0 fa 00 00 00 movl $0xfa,-0x10(%ebp)
7: 58 pop %eax
8: eb 17 jmp 0x21
The following remaining disassembled instructions are valid.
804866e: 8b 45 f4 mov -0xc(%ebp),%eax
8048671: 0f b6 00 movzbl (%eax),%eax
8048674: 8b 55 f0 mov -0x10(%ebp),%edx <== 0xfa gets loaded here.
8048677: 83 e2 2b and $0x2b,%edx
804867a: 31 c2 xor %eax,%edx
804867c: 8b 45 f4 mov -0xc(%ebp),%eax
804867f: 88 10 mov %dl,(%eax)
8048681: 83 45 f4 01 addl $0x1,-0xc(%ebp)
8048685: 8b 45 f4 mov -0xc(%ebp),%eax
8048688: 0f b6 00 movzbl (%eax),%eax
804868b: 84 c0 test %al,%al
804868d: 75 df jne 804866e <close@plt+0xee>
...
So it jumps to 804868d which jumps back to 804866e. As you can see this piece of code
is xoring 0x2b with (buf contents bitwise AND with 0xFA) and storing it to buf contents till buf[blah] string reaches a 0 (NULL character).
804868f: 8b 45 08 mov 0x8(%ebp),%eax
8048692: 89 c2 mov %eax,%edx
8048694: b8 c0 8b 04 08 mov $0x8048bc0,%eax
8048699: b9 0f 00 00 00 mov $0xf,%ecx
804869e: 89 d6 mov %edx,%esi
80486a0: 89 c7 mov %eax,%edi
80486a2: f3 a6 repz cmpsb %es:(%edi),%ds:(%esi)
80486a4: 0f 97 c2 seta %dl
80486a7: 0f 92 c0 setb %al
80486aa: 89 d1 mov %edx,%ecx
80486ac: 28 c1 sub %al,%cl
80486ae: 89 c8 mov %ecx,%eax
80486b0: 0f be c0 movsbl %al,%eax
80486b3: 85 c0 test %eax,%eax
80486b5: 75 07 jne 80486be <close@plt+0x13e>
80486b7: b8 01 00 00 00 mov $0x1,%eax <== Success
80486bc: eb 05 jmp 80486c3 <close@plt+0x143>
80486be: b8 00 00 00 00 mov $0x0,%eax
80486c3: 83 c4 10 add $0x10,%esp
80486c6: 5e pop %esi
80486c7: 5f pop %edi
80486c8: 5d pop %ebp
80486c9: c3 ret
so modified input = (input ^ (0xfa & 0x2b)) = input ^ 0x2a.
(gdb) p/x 0xfa & 0x2b
$5 = 0x2a
The above code strcmp(modified input, $0x8048bc0)
(gdb) x/s 0x8048bc0
0x8048bc0: "xKZl_^_XCY^CIE"
input ^ 0x2a = "xKZl_^_XCY^CIE"
input ^ 0x2a ^ 0x2a = "xKZl_^_XCY^CIE" ^ 0x2a (xoring for all characters).
input = "xKZl_^_XCY^CIE" ^ 0x2a (xoring for all characters).
$ python -c 'print "".join([chr(ord(c)^0x2a) for c in "xKZl_^_XCY^CIE"])'
RapFuturistico
So the input is "BRapFuturistico".
seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? BRapFuturistico
[+] WooT!: xKZl_^_XCY^CIE
DONE...
[NOTE:]
Actual disassembly of the function for option 'B':
8048644: 55 push %ebp
8048645: 89 e5 mov %esp,%ebp
8048647: 57 push %edi
8048648: 56 push %esi
8048649: 83 ec 10 sub $0x10,%esp
804864c: 8b 45 08 mov 0x8(%ebp),%eax
804864f: 89 45 f4 mov %eax,-0xc(%ebp)
8048652: 8b 55 0c mov 0xc(%ebp),%edx
8048655: 50 push %eax
8048656: 31 c0 xor %eax,%eax
8048658: 68 64 86 04 08 push $0x8048664
804865d: 58 pop %eax
804865e: 01 d0 add %edx,%eax
8048660: 50 push %eax
8048661: c3 ret
Replace following from
8048662: b8 01 c7 45 f0 mov $0xf045c701,%eax
8048667: fa cli
8048668: 00 00 add %al,(%eax)
804866a: 00 58 eb add %bl,-0x15(%eax)
804866d: 17 pop %ss
to
0: c7 45 f0 fa 00 00 00 movl $0xfa,-0x10(%ebp)
7: 58 pop %eax
8: eb 17 jmp 0x21 (0x 8048685)
804866e: 8b 45 f4 mov -0xc(%ebp),%eax
8048671: 0f b6 00 movzbl (%eax),%eax
8048674: 8b 55 f0 mov -0x10(%ebp),%edx
8048677: 83 e2 2b and $0x2b,%edx
804867a: 31 c2 xor %eax,%edx
804867c: 8b 45 f4 mov -0xc(%ebp),%eax
804867f: 88 10 mov %dl,(%eax)
8048681: 83 45 f4 01 addl $0x1,-0xc(%ebp)
8048685: 8b 45 f4 mov -0xc(%ebp),%eax
8048688: 0f b6 00 movzbl (%eax),%eax
804868b: 84 c0 test %al,%al
804868d: 75 df jne 804866e <close@plt+0xee>
804868f: 8b 45 08 mov 0x8(%ebp),%eax
8048692: 89 c2 mov %eax,%edx
8048694: b8 c0 8b 04 08 mov $0x8048bc0,%eax
8048699: b9 0f 00 00 00 mov $0xf,%ecx
804869e: 89 d6 mov %edx,%esi
80486a0: 89 c7 mov %eax,%edi
80486a2: f3 a6 repz cmpsb %es:(%edi),%ds:(%esi)
80486a4: 0f 97 c2 seta %dl
80486a7: 0f 92 c0 setb %al
80486aa: 89 d1 mov %edx,%ecx
80486ac: 28 c1 sub %al,%cl
80486ae: 89 c8 mov %ecx,%eax
80486b0: 0f be c0 movsbl %al,%eax
80486b3: 85 c0 test %eax,%eax
80486b5: 75 07 jne 80486be <close@plt+0x13e>
80486b7: b8 01 00 00 00 mov $0x1,%eax
80486bc: eb 05 jmp 80486c3 <close@plt+0x143>
80486be: b8 00 00 00 00 mov $0x0,%eax
80486c3: 83 c4 10 add $0x10,%esp
80486c6: 5e pop %esi
80486c7: 5f pop %edi
80486c8: 5d pop %ebp
80486c9: c3 ret