380 likes | 542 Views
Advanced Return Address Discovery using Context-Aware Machine Code Emulation. Presented by Derek Soeder, Ryan Permeh, & Yuji Ukai. Return Addresses and You. Introduction. What is a Return Address? . Subverting a function pointer So you have EIP, now what? Redirecting flow of execution.
E N D
Advanced Return Address Discovery using Context-Aware Machine Code Emulation Presented by Derek Soeder, Ryan Permeh, & Yuji Ukai
Return Addresses and You Introduction
What is a Return Address? • Subverting a function pointer • So you have EIP, now what? • Redirecting flow of execution Stack buffer OVERFLOW Caller’s EIP Our EIP Our payload …
Return Addresses in the Past • Static address of a stack buffer • Unix versus Windows stacks • Problems with dynamic stacks and heap buffers
Return Addresses: Present • Simple one- or two-instruction redirects (e.g., CALL/JMP reg) • Scanning for byte sequences • Change across image versions CALL reg: FF/D0 .. FF/D7 JMP reg: FF/E0 .. FF/E7 PUSH reg / RET: 50/C2 .. 57/C2 or 50/C3 .. 57/C3
Enter EEREAP Exhaustive Return Address Discovery using Machine Code Emulation • Similarities to current solutions • Finds viable points to execution • Examines process snapshot
EEREAP Exhaustive Return Address Discovery using Machine Code Emulation • Differences from current solutions • Emulates machine code at each candidate address to see if it will reach payload • EEREAP doesn't search for byte sequences – it actually emulates at each address to see if that code can get execution to a specified target
EEREAP Continued Exhaustive Return Address Discovery using Machine Code Emulation • Benefits of this approach • Finds more than simple instructions • Potentially every viable path will be uncovered • More possible addresses to match across various revisions of victim code – more universal or ASCII return addresses?
EEREAP Concluded Exhaustive Return Address Discovery using Machine Code Emulation • The execution flow beginning when a candidate address is loaded is the real-world determinant of its effectiveness. • Emulating at each candidate is a theoretically-ideal solution, limited only by the amount of context information and engine capabilities.
Welcome to the EEREAP Magical Mystery Tour How It Works
Overview • EEREAP is an Intel 32-bit machine code emulation engine that supports nondeterminism (undefined values) and abstract address spaces • Accepts a “state” and emulates at each candidate address to determine which will cause execution to reach a target memory region
EEREAP – State State is given as a process memory snapshot and a context stating any available information on registers and memory contents. • A path from the registers to a target buffer must exist • Requires user observation to construct • If there is a way from the initial state to the target buffer, EEREAP is designed to find it
EEREAP – Memory Regions Memory regions are expressed abstractly because their locations shift between instances of a vulnerable process Example: ESP EDI (pointer to payload in heap) Run 1: 0012FEC4 025470A8 Run 2: 0032FEC4 0252F308 Run 3: 0022FEC4 025206A0 “Stack” and “heap block” are both identifiable memory regions whose addresses shift between runs, due to the dynamic nature of thread creation and heap memory allocation.
EEREAP – Context Supplies register and memory values (integers or pointers) and defines memory regions • Integers are tracked on the bit level (each bit is maintained as 0, 1, or X) – especially important for EFLAGS • Pointers are a memory region ('virt' – the 4GB virtual address space – or a user-defined region) plus an integer offset
EEREAP – Context 2 Memory regions must be given a size, and can be defined with certain attributes as appropriate • Size is usually just a guess, because an exact size often cannot be determined • Attributes: • Read-Only – emulation fails on write access; useful for protecting payload • Target – region contains a payload; emulation ends successfully for return address candidate if execution reaches it
EEREAP – Context 3 • Memory regions can be “mapped” by specifying that one region starts at a relative offset within another • For instance, a target buffer could be located in the stack, or a data area could be assigned a virtual address • On dereference, attributes of all regions overlapping at address apply
EEREAP – Context Example # defines STACK as a 64KB writable address space STACK = 00XXXXXXh : 65536, RW # ESP is a pointer to offset E000h within ‘STACK’ ESP = STACK + E000h # BUFFER maps into STACK at offset E09Ch BUFFER @ STACK + E09Ch : 128, TARGET, RO # memory at STACK + E004h contains a pointer into BUFFER [STACK+E004h] = BUFFER + 8 EAX = 0 ECX = 3FFXXXXXh EBP = STACK + E134h [EBP] = STACK + E180h ESI = STACK + E01Ch TIB = 7FFXX000h : 4096, RW FS = TIB EFLAGS = 0010000X0X1Xb
EEREAP – Emulation • For each return address candidate, emulation is started fresh: • EIP points to that address • Other registers and memory are initialized according to the context • These runs will be referred to as “emulation threads,” although only one is really performed at a time
EEREAP – Emulation 2 Each instruction is emulated as faithfully as possible… • Arithmetic attempts to preserve the destination as a pointer (if possible), then as an integer • Takes unknown bits into account, erring on the side of nondeterminism • EFLAGS are also modified and may be partially undefined
EEREAP – Emulation 3 But sometimes faith just isn’t enough • The thread dies if anything occurs that could affect execution unpredictably: • A pointer dereference exceeds the bounds of its memory region • A write occurs on read-only memory • A 'virt' pointer accesses invalid memory • An invalid opcode, privileged instruction, potential divide-by-zero, etc., occurs
EEREAP – Emulation 4 Loops and Branches • An instruction execution countdown is used to prevent infinite loops • If a Jcc or LOOPcc is reached with EFLAGS/ECX undefined, we follow both possible execution paths • Parent succeeds if both children “threads” reach a target buffer • Each child gets a copy of parent's context with the instruction countdown halved
EEREAP – Emulation 5 Success! If an emulation thread (or both of its children, if it forked) reaches a memory region marked as Target, the return address candidate at which it started is considered a success and is logged.
Don’t Fear the EEREAPer How to Use It / Demonstration
EEREAP – How-To • Crash the target process using the vulnerability to be exploited • Should put the process as close as possible to the state that will be in effect when execution is hijacked • e.g., a finished exploit with an invalid return address (0x41414141, anyone?) • Process should definitely have a debugger on it with first-chance exceptions caught
EEREAP – How-To 2 • Use 'psnap' to grab a process memory snapshot C:\>psnap.exe --priority --suspend -a:r -c:w 260 lsass.ees * Record: micdhstp --- * Write: --c----- --- [#] 00010000..00010FFF .................................. Recorded [#] 00020000..00020FFF .................................. Recorded [ ] 00030000..00065FFF ................................... Ignored [G] 00066000..00066FFF ................................... Ignored [#] 00067000..0006FFFF .................................. Recorded [#] 00070000..00120FFF Heap .............................. Recorded [ ] 00121000..0016FFFF Heap ............................... Ignored ... [#] 00CAA000..00CAFFFF Stack ............................. Recorded [#] 01000000..01000FFF Image - lsass.exe ................ Recorded [#] 01001000..01001FFF Code - lsass.exe:.text ........... Written [#] 01002000..01002FFF Data - lsass.exe:.data .......... Recorded [#] 01003000..01009FFF Data - lsass.exe:.rsrc .......... Recorded [ ] 01090000..010C8FFF Stack .............................. Ignored [G] 010C9000..010C9FFF Stack .............................. Ignored ... Saved process 260 snapshot to "lsass.ees" (12795328 bytes).
EEREAP – How-To 3 • Create the context • Study the environment at crash time: consistent pointers and integers; memory regions of interest • Reverse engineer as desired • Context and snapshot are both specific to one version of the vulnerable process
EEREAP – How-To 4 • Context for exploiting LSASS (SP4) STACK = 0XXXA000H:6000H,RW EAX=00000000H EBX=00000000H ECX=STACK+5D38H EDX=785B2C60H ESI=00000004H EDI=STACK+5A58H ESP=STACK+5A14H EBP=XXXXXXXXH EFLAGS=0296H BUFFER@STACK+5A14H:10H,RO,TARGET
EEREAP – How-To 5 • Run EEREAP! Tested Platform : • Windows 2000 Advanced Server (English) No SP/Patch • Windows 2000 Advanced Server (English) SP3 No Patch • Windows 2000 Advanced Server (English) SP4 No Patch Tested Process : LSASS.EXE (MS04-011)
EEREAP – Result 1 • Result - Performance Comparison with common used return address finder - (jmp esp, call esp, push esp/ret) Windows 2000 SP4 824 167 Windows 2000 SP3 796 143 542 Windows 2000 SP0 126 0 200 400 600 800 EEREAP Simple Search
EEREAP – Result 2 • Distribution: number of instructions to target buffer - Windows 2000 SP0 Maximum # of instructions = 80
EEREAP – Result 3 • Distribution: number of instructions to target buffer - Windows 2000 SP3 Maximum # of instructions = 79
EEREAP – Result 4 • Distribution: number of instructions to target buffer - Windows 2000 SP4 Maximum # of instructions = 91
EEREAP – Result 5 • Return addresses exist onWindows 2000 SP0, SP3, and SP4 750231e2H 751c255eH 7732c167H 773e661fH 77836305H 77836307H 77836309H
EEREAP – Result 6 • Example return address for SP4 with 27 instructions 78599354 push esp 78599355 and al,0Ch 78599357 push edi 78599358 push 7 7859935A xor eax,eax 7859935C pop ecx 7859935D mov edi,edx 7859935F rep stosd 78599361 mov eax,[esp+0Ch] 78599365 xor ecx,ecx 78599367 mov [edx],eax 78599369 mov eax, [esp+8] 7859936D cmp eax,ecx 7859936F mov [edx+0Ch],cl 78599372 je 78599384 78599374 mov [edx+4],eax 78599377 mov [edx+8],10h 7859937E xor eax,eax 78599380 pop edi 78599381 ret 0Ch 78599384 mov [edx+4],ecx 78599387 mov [edx+8],ecx 7859937E xor eax,eax 78599380 pop edi 78599381 ret 0Ch
EEREAP – Demonstration • Plug in a suitable return address and try it out…
EEREAP – To Do • Use EEREAP to find a completely universal offset (all languages/versions) • Maintain results of pointer arithmetic as expressions (e.g., ~((~ptr)+1) = ptr-1, rather than ~ptr = X, X+1 = X, ~X = X) • Automated context reconnaissance? (could be done third-party *hint*) • Emulate exception handlers?
Ask an eEye Engineer Price $1.00 Questions?! Questions? Comments? Email <eereap@eeye.com> today!