KEMBAR78
Return oriented programming | PDF
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Return-oriented programming
Sebastian Neuser
Hackspace Siegen
May 8, 2014
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
1 Introduction
What is return-oriented programming?
Before we begin...
Examples
History
2 Return-oriented programming in a nutshell
x86 crash course
Stack buffer overflow
Gadgets
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
3 Demonstration
ROPgadget – a ROP compiler
Stupid vulnerable program
Showtime!
4 Countermeasures
ASLR and PIE
Stack canaries and shadow stacks
CFI and ROPdefender
5 Conclusion
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
1 Introduction
What is return-oriented programming?
Before we begin...
Examples
History
2 Return-oriented programming in a nutshell
3 Demonstration
4 Countermeasures
5 Conclusion
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
What is return-oriented programming?
Buffer overflow vulnerabilities
simple example:
• fixed size character buffer
• program reads a string from the keyboard and copies it to the
buffer without bounds checking
• number of input characters > buffer size ; buffer overflow
• variables on the stack are overwritten – possibly including the
current function’s return address
• best case scenario: SIGSEGV
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
What is return-oriented programming?
Return-oriented programming
• generalization of return-to-libc exploitation
• attacker uses buffer overflow-vulnerability or something similar
to inject return addresses into the stack
• return-to-libc-exploits chain together calls to library
functions (libc in most cases)
• return-oriented exploits jump a few instructions before a
function’s ret to perform small operations
By carefully chaining together such jumps, an attacker can perform
arbitrary computations!
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
What is return-oriented programming?
Why care?
• 45% of all recorded security vulnerabilities in Ubuntu:
; buffer overflow vulnerabilities
• buffer overflow exploits have been implemented in numerous
malicious programs across different platforms
• Return-oriented programming:
• probably the most advanced buffer overflow exploitation
technique so far
• developed and refined over decades
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Before we begin...
Terms of service
• Although I don’t intend to, unfortunately I tend to
• become overzealous,
• talk too fast and
• speak with a slur.
; Please insult me, if I do!
• By sitting here and listening to the talk, you agree that
• you will not use the knowledge provided here to harm anyone,
• I am not responsible for anything you break while messing
around with the techniques I present,
• vim is the name of the one true editor,
• proprietary software is inherently evil.
• Feel free to ask questions at any time.
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Before we begin...
Stack diagrams
Stack diagrams are depicted from the stack’s top to bottom:
pointers addresses values
stack top 0xbf8c73c0:
0xbf8c73c4:
0xbf8c73c8:
0x1337c0de
0xdeadc0de
0xdeadbeef
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Before we begin...
Platform
Examples and demo compiled and tested with
• gcc version 4.7.2
• gdb version 7.4.1
• 32 bit Debian GNU/Linux 7.1
; instruction set architecture: IA-32
• Intel Core 2 Duo P7450
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Examples
Computer worms
• The Morris worm aka. ”Great Worm”
• utilized a buffer overflow-vulnerability in the fingerd program
on Unix systems
• rendered infected systems unusable within 90 minutes
• The Slammer worm
• used buffer overflow-vulnerabilities in Microsoft’s ”SQL Server
2000” and ”Desktop Engine 2000”
• infected roughly 75000 servers in approximately 30 minutes
• caused network overloads on a great scale
• The Sasser worm
• exploited a vulnerability in Microsoft’s LSASS
• caused systems to shut down
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
History
Timeline of buffer overflow exploits
1988 Morris worm
1996 Aleph One: ”Smashing The Stack For Fun And Profit”
1997 Solar Designer: return-to-libc basics
1998 Solar Designer: security patch for the Linux kernel
2000 PaX: Implementation of W⊕X
2001 Nergal: function chaining with return-to-libc
2007 Hovav Shacham: ”Return-into-libc without function calls”
; return-oriented programming
since more and more proof, that return-oriented programming is a
real threat
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
1 Introduction
2 Return-oriented programming in a nutshell
x86 crash course
Stack buffer overflow
Gadgets
3 Demonstration
4 Countermeasures
5 Conclusion
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Register set
%eax holds the return value of a function call.
%ebx holds a pointer to some data.
%ecx is used for counters in string- and loop instructions.
%edx holds a I/O pointers.
%esi is the source pointer in some instructions.
%edi is the destination pointer in some instructions.
%ebp is the stack frame- or base pointer.
%esp is the stack pointer.
%eip is the instruction pointer.
%eflags is the status and control register.
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Instruction set
mov %esp, %ebp Copies the stack pointer %esp to the base
pointer %ebp.
push %ebp Updates the stack pointer %esp and writes
the value of %ebp to the new top of the stack.
pop %ebp Reads the value at the top of the stack – the
memory location that %esp points to, writes
it into %ebp and discards the value from the
stack by adjusting %esp.
call func Pushes the return address, which is the ad-
dress of the next instruction (%eip+5) onto
the stack and jumps to the instruction la-
beled by ”func:”.
ret Pops the return address from the top of the
stack and writes it into %eip.
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
The stack
• data section in a process’ address space
• contains local variables and buffers
• arguments to function calls and return addresses are also
implemented using the stack
• x86-family of CPUs:
• stack grows from higher to lower memory addresses
• memory is addressed byte-wise
; push decrements %esp by 4, pop increments %esp by 4
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Function calls – cdecl
• parameters are pushed to the stack in reverse order
• call pushes the address of the next instruction onto the stack
• function prologue (enter):
• save the base pointer %ebp
• copy %esp to %ebp for base pointer addressing
• decrement %esp to allocate stack memory for local variables
• function epilogue (leave):
• discard local variables by copying %ebp to %esp
• restore %ebp by popping it from the stack
• ret pops the return address off the stack and jumps to it
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Function calls – stack diagram
%esp
%ebp
0xbf8c73d0:
0xbf8c73d4:
local var 0
saved %ebp
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Function calls – stack diagram
%esp
%ebp
0xbf8c73cc:
0xbf8c73d0:
0xbf8c73d4:
parameter 2
local var 0
saved %ebp
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Function calls – stack diagram
%esp
%ebp
0xbf8c73c8:
0xbf8c73cc:
0xbf8c73d0:
0xbf8c73d4:
parameter 1
parameter 2
local var 0
saved %ebp
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Function calls – stack diagram
%esp
%ebp
0xbf8c73c4:
0xbf8c73c8:
0xbf8c73cc:
0xbf8c73d0:
0xbf8c73d4:
parameter 0
parameter 1
parameter 2
local var 0
saved %ebp
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Function calls – stack diagram
%esp
%ebp
0xbf8c73c0:
0xbf8c73c4:
0xbf8c73c8:
0xbf8c73cc:
0xbf8c73d0:
0xbf8c73d4:
return addr
parameter 0
parameter 1
parameter 2
local var 0
saved %ebp
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Function calls – stack diagram
%esp
%ebp
0xbf8c73bc:
0xbf8c73c0:
0xbf8c73c4:
0xbf8c73c8:
0xbf8c73cc:
0xbf8c73d0:
0xbf8c73d4:
saved %ebp
return addr
parameter 0
parameter 1
parameter 2
local var 0
saved %ebp
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Function calls – stack diagram
%esp,%ebp 0xbf8c73bc:
0xbf8c73c0:
0xbf8c73c4:
0xbf8c73c8:
0xbf8c73cc:
0xbf8c73d0:
0xbf8c73d4:
saved %ebp
return addr
parameter 0
parameter 1
parameter 2
local var 0
saved %ebp
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
x86 crash course
Function calls – stack diagram
%esp
%ebp
0xbf8c73b4:
0xbf8c73b8:
0xbf8c73bc:
0xbf8c73c0:
0xbf8c73c4:
0xbf8c73c8:
0xbf8c73cc:
0xbf8c73d0:
0xbf8c73d4:
local var 1
local var 0
saved %ebp
return addr
parameter 0
parameter 1
parameter 2
local var 0
saved %ebp
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stack buffer overflow
Before...
%esp
%ebp
0xbffff8b4:
0xbffff8b8:
0xbffff8bc:
...
0xbffff93c:
0xbffff940:
0xbffff944:
buffer[0]
buffer[1]
. . .
local var 1
local var 0
saved %ebp
return addr
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stack buffer overflow
Meanwhile...
%esp
%ebp
0xbffff8b4:
0xbffff8b8:
0xbffff8bc:
...
0xbffff93c:
0xbffff940:
0xbffff944:
buffer[0]
buffer[1]
. . .
local var 1
local var 0
saved %ebp
return addr
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stack buffer overflow
Meanwhile...
%esp
%ebp
0xbffff8b4:
0xbffff8b8:
0xbffff8bc:
...
0xbffff93c:
0xbffff940:
0xbffff944:
buffer[0]
buffer[1]
. . .
local var 1
local var 0
saved %ebp
return addr
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stack buffer overflow
Meanwhile...
%esp
%ebp
0xbffff8b4:
0xbffff8b8:
0xbffff8bc:
...
0xbffff93c:
0xbffff940:
0xbffff944:
buffer[0]
buffer[1]
. . .
local var 1
local var 0
saved %ebp
return addr
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stack buffer overflow
Meanwhile...
%esp
%ebp
0xbffff8b4:
0xbffff8b8:
0xbffff8bc:
...
0xbffff93c:
0xbffff940:
0xbffff944:
buffer[0]
buffer[1]
. . .
local var 1
local var 0
saved %ebp
return addr
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stack buffer overflow
Boom!
%esp
%ebp
0xbffff8b4:
0xbffff8b8:
0xbffff8bc:
...
0xbffff93c:
0xbffff940:
0xbffff944:
buffer[0]
buffer[1]
. . .
local var 1
local var 0
saved %ebp
return addr
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Gadgets
What is a gadget?
• attacker searches for short instruction sequences that perform
small tasks and end with ret
; for example poping some values into registers
• gadget: combination of one or more addresses of short
instruction sequences and the values that they should pop off
the stack
• payload: chain of gadgets
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Gadgets
A very simple gadget
ret addr
. . .
{prev gadg}
0x0000002a
{next gadg}
. . .
pop %eax
ret
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
1 Introduction
2 Return-oriented programming in a nutshell
3 Demonstration
ROPgadget – a ROP compiler
Stupid vulnerable program
Showtime!
4 Countermeasures
5 Conclusion
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
ROPgadget – a ROP compiler
ROPgadget
• finds and lists gadgets that are available in a specified binary
• constructs shellcode, a payload that opens a network socket
or user-specified opcodes
• prints out python commands that can be embedded in a
payload generation script
• searches and prints out addresses of instructions/opcodes and
strings in a binary
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stupid vulnerable program
log.h
1 //// io.c ////
2
3 // Appends the buffer to the log-file specified by the path
4 void append_log(char* buffer, char* path);
5
6 // Reads an input string to the buffer until EOF is read
7 void read_string_till_eof(char* buffer);
8
9
10
11 //// util.c ////
12
13 // Checks the program arguments
14 void check_args(int count, char* vector[]);
15
16 // Returns a string that describes the current timestamp
17 char* get_time_string(void);
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stupid vulnerable program
log.c
1 #include <string.h>
2 #include "log.h"
3
4 int main(int argc, char* argv[])
5 {
6 check_args(argc, argv);
7
8 char buffer[512];
9 char logfile_path[32];
10
11 strcpy(logfile_path, argv[1]);
12 if (!strcasestr(logfile_path, ".log"))
13 strcat(logfile_path, ".log");
14
15 read_string_till_eof(buffer);
16 append_log(buffer, logfile_path);
17 return 0;
18 }
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stupid vulnerable program
io.c
1 #include <stdio.h>
2 #include "log.h"
3
4 void append_log(char* buffer, char* path)
5 {
6 FILE* fp = fopen(path, "a");
7 fprintf(fp, "%s: %sn", get_time_string(), buffer);
8 fclose(fp);
9 }
10
11 void read_string_till_eof(char* buffer)
12 {
13 int c;
14 while ((c=getchar()) && c != EOF) {
15 *buffer++ = c;
16 }
17 printf("n");
18 }
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stupid vulnerable program
util.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5
6 void check_args(int count, char* vector[])
7 {
8 if (count != 2) {
9 printf("Usage: log <log file>n");
10 exit(0);
11 }
12 }
13
14 char* get_time_string(void)
15 {
16 time_t timestamp = time(NULL);
17 char* time_string = ctime(&timestamp);
18 time_string[strlen(time_string)-1] = ’0’;
19 return time_string;
20 }
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Showtime!
The fun part...
”For a moment, nothing happened.
Then, after a second or so, nothing continued to happen.”
- Douglas Adams, The Hitchhiker’s Guide to the Galaxy
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
1 Introduction
2 Return-oriented programming in a nutshell
3 Demonstration
4 Countermeasures
ASLR and PIE
Stack canaries and shadow stacks
CFI and ROPdefender
5 Conclusion
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
ASLR and PIE
ASLR and PIE
• Address Space Layout Randomization
• Position Independent Executable
• take effect at load and link time during program startup
• in the PaX implementation, the addresses of the following
segments are randomized:
• .text-segment of the binary (; executable code)
• dynamically linked libraries
• the stack
• the heap
• libraries in themselves are not randomized
; randomization can be overcome by brute-force attacks
and/or through information leakage
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stack canaries and shadow stacks
Stack canaries – Explanation
• canary word: word between local variables of a function and
the return address
• during function prologue: canary word is placed on the stack
and backed up in a different location
• during function epilogue: canary word is verified through
comparison with the stored value
• word has changed (; the canary is dead )
; program is terminated with a warning message
• Example: StackGuard
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stack canaries and shadow stacks
Stack canaries – Diagram
%esp
%ebp
0xbf9358bc:
...
0xbf935924:
0xbf935928:
0xbf93592c:
buffer
. . .
canary
saved %ebp
return addr
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Stack canaries and shadow stacks
Shadow stacks
• TRUSS: maintains shadow stack, which stores return
addresses
• function prologue: modified to push the correct return address
onto the shadow stack
• epilogue: compares return addresses
• mismatch ; program termination and error signal
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
CFI and ROPdefender
Control Flow Integrity
• control flow graph maps all function calls
• function prologues and epilogues are modified at runtime
• targets of call and ret instructions are correlated with the
anticipated control flow in the graph
• opcodes do not match ; program is aborted
• significant computational overhead with a factor typically in
the range of [1.5, 3.5]
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
CFI and ROPdefender
ROPdefender
• ROPdefender also maintains a shadow stack
• capable of detecting unintended instruction sequences
• return address of every call instruction is pushed onto the
shadow stack
• every ret instruction: comparison of the destination address
to the top of the shadow stack
• program is aborted if the addresses do not match
• computational overhead similar to CFI
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
1 Introduction
2 Return-oriented programming in a nutshell
3 Demonstration
4 Countermeasures
5 Conclusion
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Summary
• long evolution from direct code injection to ROP
• applicable to many popular architectures
• quite complex technique
• relatively recent ; few effective countermeasures
• frameworks for automation of payload generation
• ; serious threat!
• But: It’s fun!
Return-oriented programming Sebastian Neuser
Introduction Return-oriented programming in a nutshell Demonstration Countermeasures Conclusion
Thanks for your attention.
Questions?
Return-oriented programming Sebastian Neuser

Return oriented programming

  • 1.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Return-oriented programming Sebastian Neuser Hackspace Siegen May 8, 2014 Return-oriented programming Sebastian Neuser
  • 2.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion 1 Introduction What is return-oriented programming? Before we begin... Examples History 2 Return-oriented programming in a nutshell x86 crash course Stack buffer overflow Gadgets Return-oriented programming Sebastian Neuser
  • 3.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion 3 Demonstration ROPgadget – a ROP compiler Stupid vulnerable program Showtime! 4 Countermeasures ASLR and PIE Stack canaries and shadow stacks CFI and ROPdefender 5 Conclusion Return-oriented programming Sebastian Neuser
  • 4.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion 1 Introduction What is return-oriented programming? Before we begin... Examples History 2 Return-oriented programming in a nutshell 3 Demonstration 4 Countermeasures 5 Conclusion Return-oriented programming Sebastian Neuser
  • 5.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion What is return-oriented programming? Buffer overflow vulnerabilities simple example: • fixed size character buffer • program reads a string from the keyboard and copies it to the buffer without bounds checking • number of input characters > buffer size ; buffer overflow • variables on the stack are overwritten – possibly including the current function’s return address • best case scenario: SIGSEGV Return-oriented programming Sebastian Neuser
  • 6.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion What is return-oriented programming? Return-oriented programming • generalization of return-to-libc exploitation • attacker uses buffer overflow-vulnerability or something similar to inject return addresses into the stack • return-to-libc-exploits chain together calls to library functions (libc in most cases) • return-oriented exploits jump a few instructions before a function’s ret to perform small operations By carefully chaining together such jumps, an attacker can perform arbitrary computations! Return-oriented programming Sebastian Neuser
  • 7.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion What is return-oriented programming? Why care? • 45% of all recorded security vulnerabilities in Ubuntu: ; buffer overflow vulnerabilities • buffer overflow exploits have been implemented in numerous malicious programs across different platforms • Return-oriented programming: • probably the most advanced buffer overflow exploitation technique so far • developed and refined over decades Return-oriented programming Sebastian Neuser
  • 8.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Before we begin... Terms of service • Although I don’t intend to, unfortunately I tend to • become overzealous, • talk too fast and • speak with a slur. ; Please insult me, if I do! • By sitting here and listening to the talk, you agree that • you will not use the knowledge provided here to harm anyone, • I am not responsible for anything you break while messing around with the techniques I present, • vim is the name of the one true editor, • proprietary software is inherently evil. • Feel free to ask questions at any time. Return-oriented programming Sebastian Neuser
  • 9.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Before we begin... Stack diagrams Stack diagrams are depicted from the stack’s top to bottom: pointers addresses values stack top 0xbf8c73c0: 0xbf8c73c4: 0xbf8c73c8: 0x1337c0de 0xdeadc0de 0xdeadbeef Return-oriented programming Sebastian Neuser
  • 10.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Before we begin... Platform Examples and demo compiled and tested with • gcc version 4.7.2 • gdb version 7.4.1 • 32 bit Debian GNU/Linux 7.1 ; instruction set architecture: IA-32 • Intel Core 2 Duo P7450 Return-oriented programming Sebastian Neuser
  • 11.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Examples Computer worms • The Morris worm aka. ”Great Worm” • utilized a buffer overflow-vulnerability in the fingerd program on Unix systems • rendered infected systems unusable within 90 minutes • The Slammer worm • used buffer overflow-vulnerabilities in Microsoft’s ”SQL Server 2000” and ”Desktop Engine 2000” • infected roughly 75000 servers in approximately 30 minutes • caused network overloads on a great scale • The Sasser worm • exploited a vulnerability in Microsoft’s LSASS • caused systems to shut down Return-oriented programming Sebastian Neuser
  • 12.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion History Timeline of buffer overflow exploits 1988 Morris worm 1996 Aleph One: ”Smashing The Stack For Fun And Profit” 1997 Solar Designer: return-to-libc basics 1998 Solar Designer: security patch for the Linux kernel 2000 PaX: Implementation of W⊕X 2001 Nergal: function chaining with return-to-libc 2007 Hovav Shacham: ”Return-into-libc without function calls” ; return-oriented programming since more and more proof, that return-oriented programming is a real threat Return-oriented programming Sebastian Neuser
  • 13.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion 1 Introduction 2 Return-oriented programming in a nutshell x86 crash course Stack buffer overflow Gadgets 3 Demonstration 4 Countermeasures 5 Conclusion Return-oriented programming Sebastian Neuser
  • 14.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Register set %eax holds the return value of a function call. %ebx holds a pointer to some data. %ecx is used for counters in string- and loop instructions. %edx holds a I/O pointers. %esi is the source pointer in some instructions. %edi is the destination pointer in some instructions. %ebp is the stack frame- or base pointer. %esp is the stack pointer. %eip is the instruction pointer. %eflags is the status and control register. Return-oriented programming Sebastian Neuser
  • 15.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Instruction set mov %esp, %ebp Copies the stack pointer %esp to the base pointer %ebp. push %ebp Updates the stack pointer %esp and writes the value of %ebp to the new top of the stack. pop %ebp Reads the value at the top of the stack – the memory location that %esp points to, writes it into %ebp and discards the value from the stack by adjusting %esp. call func Pushes the return address, which is the ad- dress of the next instruction (%eip+5) onto the stack and jumps to the instruction la- beled by ”func:”. ret Pops the return address from the top of the stack and writes it into %eip. Return-oriented programming Sebastian Neuser
  • 16.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course The stack • data section in a process’ address space • contains local variables and buffers • arguments to function calls and return addresses are also implemented using the stack • x86-family of CPUs: • stack grows from higher to lower memory addresses • memory is addressed byte-wise ; push decrements %esp by 4, pop increments %esp by 4 Return-oriented programming Sebastian Neuser
  • 17.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Function calls – cdecl • parameters are pushed to the stack in reverse order • call pushes the address of the next instruction onto the stack • function prologue (enter): • save the base pointer %ebp • copy %esp to %ebp for base pointer addressing • decrement %esp to allocate stack memory for local variables • function epilogue (leave): • discard local variables by copying %ebp to %esp • restore %ebp by popping it from the stack • ret pops the return address off the stack and jumps to it Return-oriented programming Sebastian Neuser
  • 18.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Function calls – stack diagram %esp %ebp 0xbf8c73d0: 0xbf8c73d4: local var 0 saved %ebp Return-oriented programming Sebastian Neuser
  • 19.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Function calls – stack diagram %esp %ebp 0xbf8c73cc: 0xbf8c73d0: 0xbf8c73d4: parameter 2 local var 0 saved %ebp Return-oriented programming Sebastian Neuser
  • 20.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Function calls – stack diagram %esp %ebp 0xbf8c73c8: 0xbf8c73cc: 0xbf8c73d0: 0xbf8c73d4: parameter 1 parameter 2 local var 0 saved %ebp Return-oriented programming Sebastian Neuser
  • 21.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Function calls – stack diagram %esp %ebp 0xbf8c73c4: 0xbf8c73c8: 0xbf8c73cc: 0xbf8c73d0: 0xbf8c73d4: parameter 0 parameter 1 parameter 2 local var 0 saved %ebp Return-oriented programming Sebastian Neuser
  • 22.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Function calls – stack diagram %esp %ebp 0xbf8c73c0: 0xbf8c73c4: 0xbf8c73c8: 0xbf8c73cc: 0xbf8c73d0: 0xbf8c73d4: return addr parameter 0 parameter 1 parameter 2 local var 0 saved %ebp Return-oriented programming Sebastian Neuser
  • 23.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Function calls – stack diagram %esp %ebp 0xbf8c73bc: 0xbf8c73c0: 0xbf8c73c4: 0xbf8c73c8: 0xbf8c73cc: 0xbf8c73d0: 0xbf8c73d4: saved %ebp return addr parameter 0 parameter 1 parameter 2 local var 0 saved %ebp Return-oriented programming Sebastian Neuser
  • 24.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Function calls – stack diagram %esp,%ebp 0xbf8c73bc: 0xbf8c73c0: 0xbf8c73c4: 0xbf8c73c8: 0xbf8c73cc: 0xbf8c73d0: 0xbf8c73d4: saved %ebp return addr parameter 0 parameter 1 parameter 2 local var 0 saved %ebp Return-oriented programming Sebastian Neuser
  • 25.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion x86 crash course Function calls – stack diagram %esp %ebp 0xbf8c73b4: 0xbf8c73b8: 0xbf8c73bc: 0xbf8c73c0: 0xbf8c73c4: 0xbf8c73c8: 0xbf8c73cc: 0xbf8c73d0: 0xbf8c73d4: local var 1 local var 0 saved %ebp return addr parameter 0 parameter 1 parameter 2 local var 0 saved %ebp Return-oriented programming Sebastian Neuser
  • 26.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stack buffer overflow Before... %esp %ebp 0xbffff8b4: 0xbffff8b8: 0xbffff8bc: ... 0xbffff93c: 0xbffff940: 0xbffff944: buffer[0] buffer[1] . . . local var 1 local var 0 saved %ebp return addr Return-oriented programming Sebastian Neuser
  • 27.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stack buffer overflow Meanwhile... %esp %ebp 0xbffff8b4: 0xbffff8b8: 0xbffff8bc: ... 0xbffff93c: 0xbffff940: 0xbffff944: buffer[0] buffer[1] . . . local var 1 local var 0 saved %ebp return addr Return-oriented programming Sebastian Neuser
  • 28.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stack buffer overflow Meanwhile... %esp %ebp 0xbffff8b4: 0xbffff8b8: 0xbffff8bc: ... 0xbffff93c: 0xbffff940: 0xbffff944: buffer[0] buffer[1] . . . local var 1 local var 0 saved %ebp return addr Return-oriented programming Sebastian Neuser
  • 29.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stack buffer overflow Meanwhile... %esp %ebp 0xbffff8b4: 0xbffff8b8: 0xbffff8bc: ... 0xbffff93c: 0xbffff940: 0xbffff944: buffer[0] buffer[1] . . . local var 1 local var 0 saved %ebp return addr Return-oriented programming Sebastian Neuser
  • 30.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stack buffer overflow Meanwhile... %esp %ebp 0xbffff8b4: 0xbffff8b8: 0xbffff8bc: ... 0xbffff93c: 0xbffff940: 0xbffff944: buffer[0] buffer[1] . . . local var 1 local var 0 saved %ebp return addr Return-oriented programming Sebastian Neuser
  • 31.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stack buffer overflow Boom! %esp %ebp 0xbffff8b4: 0xbffff8b8: 0xbffff8bc: ... 0xbffff93c: 0xbffff940: 0xbffff944: buffer[0] buffer[1] . . . local var 1 local var 0 saved %ebp return addr Return-oriented programming Sebastian Neuser
  • 32.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Gadgets What is a gadget? • attacker searches for short instruction sequences that perform small tasks and end with ret ; for example poping some values into registers • gadget: combination of one or more addresses of short instruction sequences and the values that they should pop off the stack • payload: chain of gadgets Return-oriented programming Sebastian Neuser
  • 33.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Gadgets A very simple gadget ret addr . . . {prev gadg} 0x0000002a {next gadg} . . . pop %eax ret Return-oriented programming Sebastian Neuser
  • 34.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion 1 Introduction 2 Return-oriented programming in a nutshell 3 Demonstration ROPgadget – a ROP compiler Stupid vulnerable program Showtime! 4 Countermeasures 5 Conclusion Return-oriented programming Sebastian Neuser
  • 35.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion ROPgadget – a ROP compiler ROPgadget • finds and lists gadgets that are available in a specified binary • constructs shellcode, a payload that opens a network socket or user-specified opcodes • prints out python commands that can be embedded in a payload generation script • searches and prints out addresses of instructions/opcodes and strings in a binary Return-oriented programming Sebastian Neuser
  • 36.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stupid vulnerable program log.h 1 //// io.c //// 2 3 // Appends the buffer to the log-file specified by the path 4 void append_log(char* buffer, char* path); 5 6 // Reads an input string to the buffer until EOF is read 7 void read_string_till_eof(char* buffer); 8 9 10 11 //// util.c //// 12 13 // Checks the program arguments 14 void check_args(int count, char* vector[]); 15 16 // Returns a string that describes the current timestamp 17 char* get_time_string(void); Return-oriented programming Sebastian Neuser
  • 37.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stupid vulnerable program log.c 1 #include <string.h> 2 #include "log.h" 3 4 int main(int argc, char* argv[]) 5 { 6 check_args(argc, argv); 7 8 char buffer[512]; 9 char logfile_path[32]; 10 11 strcpy(logfile_path, argv[1]); 12 if (!strcasestr(logfile_path, ".log")) 13 strcat(logfile_path, ".log"); 14 15 read_string_till_eof(buffer); 16 append_log(buffer, logfile_path); 17 return 0; 18 } Return-oriented programming Sebastian Neuser
  • 38.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stupid vulnerable program io.c 1 #include <stdio.h> 2 #include "log.h" 3 4 void append_log(char* buffer, char* path) 5 { 6 FILE* fp = fopen(path, "a"); 7 fprintf(fp, "%s: %sn", get_time_string(), buffer); 8 fclose(fp); 9 } 10 11 void read_string_till_eof(char* buffer) 12 { 13 int c; 14 while ((c=getchar()) && c != EOF) { 15 *buffer++ = c; 16 } 17 printf("n"); 18 } Return-oriented programming Sebastian Neuser
  • 39.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stupid vulnerable program util.c 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <time.h> 5 6 void check_args(int count, char* vector[]) 7 { 8 if (count != 2) { 9 printf("Usage: log <log file>n"); 10 exit(0); 11 } 12 } 13 14 char* get_time_string(void) 15 { 16 time_t timestamp = time(NULL); 17 char* time_string = ctime(&timestamp); 18 time_string[strlen(time_string)-1] = ’0’; 19 return time_string; 20 } Return-oriented programming Sebastian Neuser
  • 40.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Showtime! The fun part... ”For a moment, nothing happened. Then, after a second or so, nothing continued to happen.” - Douglas Adams, The Hitchhiker’s Guide to the Galaxy Return-oriented programming Sebastian Neuser
  • 41.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion 1 Introduction 2 Return-oriented programming in a nutshell 3 Demonstration 4 Countermeasures ASLR and PIE Stack canaries and shadow stacks CFI and ROPdefender 5 Conclusion Return-oriented programming Sebastian Neuser
  • 42.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion ASLR and PIE ASLR and PIE • Address Space Layout Randomization • Position Independent Executable • take effect at load and link time during program startup • in the PaX implementation, the addresses of the following segments are randomized: • .text-segment of the binary (; executable code) • dynamically linked libraries • the stack • the heap • libraries in themselves are not randomized ; randomization can be overcome by brute-force attacks and/or through information leakage Return-oriented programming Sebastian Neuser
  • 43.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stack canaries and shadow stacks Stack canaries – Explanation • canary word: word between local variables of a function and the return address • during function prologue: canary word is placed on the stack and backed up in a different location • during function epilogue: canary word is verified through comparison with the stored value • word has changed (; the canary is dead ) ; program is terminated with a warning message • Example: StackGuard Return-oriented programming Sebastian Neuser
  • 44.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stack canaries and shadow stacks Stack canaries – Diagram %esp %ebp 0xbf9358bc: ... 0xbf935924: 0xbf935928: 0xbf93592c: buffer . . . canary saved %ebp return addr Return-oriented programming Sebastian Neuser
  • 45.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Stack canaries and shadow stacks Shadow stacks • TRUSS: maintains shadow stack, which stores return addresses • function prologue: modified to push the correct return address onto the shadow stack • epilogue: compares return addresses • mismatch ; program termination and error signal Return-oriented programming Sebastian Neuser
  • 46.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion CFI and ROPdefender Control Flow Integrity • control flow graph maps all function calls • function prologues and epilogues are modified at runtime • targets of call and ret instructions are correlated with the anticipated control flow in the graph • opcodes do not match ; program is aborted • significant computational overhead with a factor typically in the range of [1.5, 3.5] Return-oriented programming Sebastian Neuser
  • 47.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion CFI and ROPdefender ROPdefender • ROPdefender also maintains a shadow stack • capable of detecting unintended instruction sequences • return address of every call instruction is pushed onto the shadow stack • every ret instruction: comparison of the destination address to the top of the shadow stack • program is aborted if the addresses do not match • computational overhead similar to CFI Return-oriented programming Sebastian Neuser
  • 48.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion 1 Introduction 2 Return-oriented programming in a nutshell 3 Demonstration 4 Countermeasures 5 Conclusion Return-oriented programming Sebastian Neuser
  • 49.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Summary • long evolution from direct code injection to ROP • applicable to many popular architectures • quite complex technique • relatively recent ; few effective countermeasures • frameworks for automation of payload generation • ; serious threat! • But: It’s fun! Return-oriented programming Sebastian Neuser
  • 50.
    Introduction Return-oriented programmingin a nutshell Demonstration Countermeasures Conclusion Thanks for your attention. Questions? Return-oriented programming Sebastian Neuser