The Geometry of Innocent Flesh on the Bone
Return-into-libc without Function Calls (on the x86)
Hovav Shacham hovav@cs.ucsd.edu CCS ‘07
The Geometry of Innocent Flesh on the Bone Return-into-libc without - - PowerPoint PPT Presentation
The Geometry of Innocent Flesh on the Bone Return-into-libc without Function Calls (on the x86) Hovav Shacham CCS 07 hovav@cs.ucsd.edu Technical Background Gadget: a short instructions sequence (e.x. pop %edx; ret;)
Hovav Shacham hovav@cs.ucsd.edu CCS ‘07
attacker can induce arbitrary behavior in a program whose control flow he has diverted, without injecting any code
vulnerable program to jump to some existing code which is already loaded into the memory
○ Overwriting a return address on the stack
○ Injecting code into the process image
Marks all writeable(“W”) locations in a process’ address space as non-executable(“X”)
Linux (via PaX patches); OpenBSD; Windows; OS X;
Intel “XD” bit, AMD “NX” bit
○ the attacker can execute only straight-line code ■ calling one libc function after another ○ the attacker can be restricted ■ removing certain functions from libc
○ can be removed by the maintainers of libc
○ very difficult to eliminate
We rely on the following:
○ we can make out more words on the page
○ random byte stream can be interpreted as a series of valid instruction with high probability ➔ Our goal ◆ Find sequences that end in a return instruction ( c3 )
f7 c7 07 00 00 00 test $0x00000007, %edi 0f 95 45 c3 setnzb -61(%ebp) Starting one byte later c7 07 00 00 00 0f movl $0x0f000000, (%edi) 95 xchg %ebp, %eax 45 inc %ebp c3 ret
➔ Cons ◆ Code compiled for this scheme cannot call libraries not compiled for this ◆ May introduce slowdowns
unlike function-call interface is standard.
so are not easily removed.
○ could be used on our gadgets ○ end in a ret instruction ➔ None of the instructions should cause the processor to transfer execution away ( not reaching the ret ) ➔ ret causes the processor to continue to the next step
e.g. If we find "a; b; c; ret" then "b; c; ret" also exist
➔ We chose to record sequences on a trie ➔ root of the trie is the ret
The Idea
➔ Some sequences ending with ret are ignored ◆ leave; ret; ◆ pop %ebp; ret; ◆ ret; or unconditional jump
➔ Results ◆ Analyzed 1,189,501 bytes of libc's executable segment
execute
but the “ret” at end of each instruction sequence does
○ Loading a Constant ○ Loading from Memory ○ Storing to Memory
○ Unconditional Jump ○ Conditional Jumps
○ Add ○ Exclusive OR (XOR) ○ And, Or, Not ○ Shift and Rotate
Strategy:
○ clears CF if equal to zero or sets CF otherwise
esp_delta is the amount we’d like to perturb %esp by
(using esp_delta or 0)
○ move the arguments from the stack to the registers
arguments are loaded in register %ebx, %ecx, %edx, %esi, %edi, %ebp (in this order)
○ set the syscall number in %eax ○ trap into the kernel ○ check for error and translate the return value ➔ we can invoke any syscall we want by: ◆ setting up the parameters ourselves ◆ jump into a wrapper that is immediately before lcall
➢ Invokes the execve system call to run a shell. Requirements: ➔ Set the system call index in %eax to 0xb (execve) ➔ Set the path of the program to run in %ebx to the string “/bin/sh” ➔ Set the argument vector argv in %ecx ➔ Set the environment vector envp in %edx
lacll is invoked with arguments:
○ belongs to a function exported in libc’s SYMTAB section ■ disassemble the function until we discover which instruction includes the c3 ➔ Out of 975,626 covered bytes, 5,483 are c3 bytes (one in every 178)
( early exits jump to this point )
(or written using instruction other than mov )
➔ Drawbacks ◆ compiler would be less transparent and complicated ◆ loss of efficiency in the use of registers
○ near return
○ near return with stack unwind
○ far return
○ far return with stack unwind
➔ Last three variants are more difficult to use in the exploits we described
Παπαδόπουλος Παναγιώτης-Ηλίας Παπαδογιαννάκη Ευαγγελία Κλεφτογιώργος Κωνσταντίνος