Presentation on theme: "Third Generation Exploitation"— Presentation transcript:
1 Third Generation Exploitation Smashing the Heap under Win2kBlackhat Briefings Windows 2002Halvar FlakeReverse EngineerBlackhat Consulting
2 Third Generation Exploits Overview (I)IntroductionFirst Generation ExploitsSecond Generation ExploitsThird Generation ExploitsHeap Structure ExploitationGeneralitiesWin2k Heap ManagerBorland C++ libcDemonstrationThe future of Exploitation
3 Third Generation Exploits Overview (II)Format String BugsHistoryAutomated DetectionExploitationExploitation reliabilityProblem definitionUnhandled Exception Filter AttackThread Environment Structure OverwriteFree time for questions, answers and discussions
4 First Generation Exploits (I) IntroductionFirst Generation Exploits (I)localvariablesof aFunctionStarts writing bytes intoa local stack bufferData suppliedby the attackerFrame PointerReturn address issupplied by the attackerReturn AddressReturn Address
5 First Generation Exploits IntroductionFirst Generation ExploitsSimple stack smashesDocumented ad nauseamEIP completely takenHardware-specific feature (e.g. RET instruction)strcpy(), gets(), sprintf() …Trivial to exploitCan be detected via stress-testingBug Species almost extinct
6 Second generation exploits IntroductionSecond generation exploitsCast screw-ups, off-by-one’sstrncat(), strncpy(), manual pointer handling, …Fairly well documentedEIP not overwritten, EBP manipulatedCompiler functionality (e.g. standard function prologue/epilogue for C compilers)Can be quite hard to detect, but can be detected via stress testingTakes control of execution after a small detourDue to the hard-to-find nature, a few of these are still around
7 Off-by-one-exploitation (I) IntroductionOff-by-one-exploitation (I)saved_EBP‘s lowest byte is set to 0x00Buffer to whichwe appendFunction epilogue: mov esp, ebpsaved_EBPsaved_EIP
8 Off-by-one-exploitation (II) IntroductionOff-by-one-exploitation (II)saved_EBPFunction epilogue: pop ebpsaved_EIP
9 Off-by-one-exploitation (III) IntroductionOff-by-one-exploitation (III)The value in EBP (the frame pointer) is nowour modified value !saved_EIPFunction epilogue: ret
10 Off-by-one-exploitation (IV) IntroductionOff-by-one-exploitation (IV)Next function epilogue:mov esp, ebpESP slides upwards (as its lowest order byte wasoverwritten) into the user-supplied data. We cannow supply a new return address to gain controlUser-supplieddata.. but it lands here ...ESP should be here ...saved_EBPsaved_EIP
11 Third Generation: Format Strings IntroductionThird Generation: Format StringsNew bug class surfaced in Summer 2000*printf() - family functionsTrivial to spotFairly well-documented and widely exploitedAllows reading from & writing to arbitrary addressesNo CPU registers overwrittenSpecific libc-functionality which is documented in the ANSI/ISO C specificationSimple to exploit, powerful, easy to find hunted to extinction within a very short time
12 Third Generation: Heap Structure Exploits IntroductionThird Generation: Heap Structure ExploitsPublically documented by Solar DesignerTakes advantage of libc-specific implementations for malloc()/free()More abstract than Generation I/II, less standardized than format string bugsAllows writing of arbitrary data to arbitrary addressesDocumented in Phrack 57 / Undocumented for NTHard/impossible to detect via stress testingSimilarly hard to spot as Generation II
13 Generalities on Heap Management Heap Structure Exploit GeneralitiesGeneralities on Heap ManagementEvery libc/compiler has different algorithms, philosophies & internal structures for heap management (Vranhalia lists at least 8 different Kernel Memory allocators under *NIX)Customized optimization of heap management gives huge performance leaps for applications, thus many large-scale applications have their own heap management algorithmsOperating systems (such as WinNT2kXP) may provide their own heap management algorithms which the application might use
16 RtlAllocateHeap (I) RtlAllocate HeapSlowly() Check Flags and smaller than 1024Allocate fromLookaside TableNew allocationfrom the heapReturn block…
17 RtlAllocateHeap (II) New allocation from the heap Large-Heap Allocator Smaller than 1024 BytesLarger than BytesLarge-HeapAllocatorSmall-HeapAllocatorSizecheck
18 Heap Structure Exploits Win2k Heap Manager (II)After two allocations of 32 bytes each our heap memoryshould look like this:Block Acontrol dataMemory Block A+0+32+64Block Bcontrol dataMemory Block BUninteresting memory
19 Win2k Heap Manager (III) Heap Structure ExploitsWin2k Heap Manager (III)Now we assume that we can overflow the first bufferso that we overwrite the Block B control data.Block Acontrol dataMemory Block A+0+32+64Block Bcontrol dataMemory Block BUninteresting memory
20 Heap Structure Exploits Win2k Heap Manager (IV)When Block B is being freed, an attacker has supplied theentire control block for it. Here is the rough layout:Size of this Blockdivided by 8Size of the previousBlock divided by 8+0+4Field_48 bit forFlagsIf we analyze the disassembly of _RtlHeapFree() in NTDLL,we can see that our supplied block needs to have a fewproperties in order to allow us to do anything evil.
21 Heap Structure Exploits Win2k Heap Manager (V)Properties our block must have:Bit 0 of Flags must be setBit 3 of Flags must be setField_4 must be smaller than 0x40The first field (own size) must be larger than 0x80The block ‘XXXX99XX’ meets all requirements.We reach the following code now:
25 Heap Structure Exploits Win2k Heap Manager (IX)If we can overwrite a complete control block (or at least 6 bytes of it) and have control over the data 24 bytes before that, we can easily write any value to any memory location.It should be noted that other ways of exploiting exist for smaller/different overruns – use your Disassembler and your imagination.
26 Borland C++ run-time library (I) Heap Structure ExploitsBorland C++ run-time library (I)We have the same situation as before, but control blocksare 4 bytes in length only:AdataMemory Block A+0+32+64BdataMemory Block BUninteresting memory
27 Borland C++ run-time library (II) Heap Structure ExploitsBorland C++ run-time library (II)The control structure is only one DWORD large.AdataMemory Block A+0+32+64BdataMemory Block BUninteresting memory
28 Borland C++ run-time library (III) Heap Structure ExploitsBorland C++ run-time library (III)Control structure contains the size of the nextallocated blockLibc checks: Is block smaller than0x (ca. 1MB)If larger, page deallocator is calledIf smaller, small_free() – function is calledThe dangerous code is in small_free()We cannot overwrite the control block completely if we wantto do anything useful.
29 Borland C++ off-by-one exploitation (I) Heap Structure ExploitsBorland C++ off-by-one exploitation (I)Assuming we overwrite the lowest byte of the controlblock of a 32-byte byte buffer which we control (whichis not the one we overrun):Buffer which we overrun+0+32+64Control Blocks(size | FLAGS)Adjancent Buffer which we controlSome more memory…
30 Borland C++ off-by-one exploitation (II) Heap Structure ExploitsBorland C++ off-by-one exploitation (II)Instead of 0x20 OR’ed with the FLAGS, we get 0x00due to the off-by-one NULL-byte.Buffer which we overrun+0+32+64Gets overwritten with 0x00Adjancent Buffer which we controlSome more memory…
31 Borland C++ off-by-one exploitation (III) Heap Structure ExploitsBorland C++ off-by-one exploitation (III)The libc tries to determine if the next buffer is a free buffer(to coalesce the two if so) – it attempts to skip the next blockof memory by adding the value of the control structure. Wemodified this value, so it now points into the buffer we control.Buffer which we overrun+0+32+64Adjancent Buffer which we controlSome more memory…Should pointhere ……but pointshere !
32 Borland C++ off-by-one exploitation (IV) Heap Structure ExploitsBorland C++ off-by-one exploitation (IV)If we have bit 0 of the first byte of our trailing bufferset, the libc tries to coalesce the two “free” buffersusing the code:Buffer which we overrun+0+32+64Adjancent Buffer which we controlSome more memory…mov ebx, [edx+8]mov ecx, [edx+4]mov [ecx+8], ebx ; arbitrary memory overwriteEDX
33 Heap Structure Exploits Summary (I)The only constant is change – especially in the world of bugs:Stack-based overflows are slowly “being hunted to near extinction”Biological Analogies can be seen: A particularly valuable and easy-to-hunt animal/bug has been hunted to near extinction (format string bugs)Some bug-hunters see bugs as a natural resource which is slowly being depleted – thus the ‘save the bugs movements’ and more push in the underground to keep bugs secret
37 Exploitation Reliability (I) Exploitation of buffer overruns under modern OS’sfaces a bunch of difficulties:Variations in shared libraries & installs create incertainity concerning the right return addressMulti-threading instead of forks create incertainity concerning the address of the stackShooting down a web-server is not very stealthyUnder NT (not 2k), services are not automatically restarted one try and you’re outMethods are needed which improve reliability of exploitation !
38 Pointer to the format string ReliabilityFormat String Bugs (I)Stack layout during regular printf()-call:printf(“%lx---%s----%d”, v1, puf, var2);arbitrary local dataReturn addressPointer to the format string
39 Format String Bugs (II) ReliabilityFormat String Bugs (II)Stack layout during malicious printf()-call :printf(stuff); // Stuff is set to contain// “%.200lx%n%.40lx%n“attacker-supplied malicious dataReturn addressPointer to the format string
40 Exploitation Reliability (II) Windows NT/2k/ME provides a powerful feature which can beabused to increase reliability of exploitation:Structured Exception Handling (SEH)As with all powerful features, this can be abused in various ways – Two of them are:Unhandled Exception Filter Attacks (UEFA)Thread Exception Structure Overwrites (TESO)Various other ways exists – where do you want to go today ?
41 Exploitation Reliability (III) Structured Exception Handling (SEH) allows an application to handle exceptions on it’s own, similar to signal handlers under most UNIX variants.Two of the key types of exception handlers are:Final Exception Handlers installed through a function called SetUnhandledExceptionFilter()Per-thread exception handlers installed by modifying a structure at fs: and creating handler structures on the stack
42 Exploitation Reliability (IV) SetUnhandledExceptionFilter() installs a handler which will be called once all other handlers have failed, e.g. in a GPF or Page Fault (==UNIX SIG_SEGV)A disassembly of the relevant function in KERNEL32.DLL looks like this:mov ecx, [esp+lpTopLevelExceptionFilter]mov eax, dword_77EE044Cmov dword_77EE044C, ecxretn 4
43 Exploitation Reliability (V) Overwrite pointer at 0x7FEE044C with a pointer to our shellcodeTrigger an exception We seize control of the exception-handling threadDrawback: We need to know exact KERNEL32.DLL version, language (under NT) and loading addressAdvantage: We just need to write one DWORD and then trigger an exception
44 Exploitation Reliability (VI) A thread creates/installs a per-thread exception handler like this:push offset handlerpush dword fs:mov fs:, espand creates a structure on the stack which looks like this:Pointer to next structure+0+4Pointer to handler code
45 Exploitation Reliability (VII) fs: forms a linked list of these structuresThe topmost handler gets called upon exceptionIf it cannot handle the exception, control is passed down to the next handlerRepeat the above until no more exception handlers are leftIf we can overwrite the value at fs: we can gain control !
46 Exploitation Reliability (VIII) Cross-segment writing is impossible with string bugs and heap overwritesThe structure starting at fs: is called Thread Environment Block and is documented in both the NT DDK header files and by the Wine projectUndocumented: The TEB’s are created at highly predictable addressesBy predicting these addresses and writing to the Thread Environment Block, we can hijack exception handlers
47 Exploitation Reliability (IX) Example of TEB allocation (identical on any NT2kXP):1st Thread TEB: 0x7FFDE0002nd Thread TEB: 0x7FFDD0003rd Thread TEB: 0x7FFDE000………………….11th Thread TEB: 0x7FFD400012th Thread TEB: 0x7FFAF00012+N-th Thread: 0x7FFAF000-N*0x1000
48 Exploitation Reliability (X) Example of TEB fragmentation:Thread 1 is createdThread 2 is createdThread 2 finishes & exits -- NONPAGEDThread 3 is createdThread 4 is created
49 Exploitation Reliability (XI) Example of TEB fragmentation:Thread 1 is createdThread 5 fills gapThread 3 is createdThread 4 is createdThread 6 is createdThread 7 is createdThread 8 is createdThread 9 is createdThread 10 is created
50 Exploitation Reliability (XII) Example of TEB fragmentation:Thread 1 finishes & exits -- NONPAGEDThread 1 is createdThread 5 fills gapThread 3 is createdThread 4 finishes & exits -- NONPAGEDThread 4 is createdThread 6 finishes & exits -- NONPAGEDThread 6 is createdThread 7 is createdThread 8 is createdThread 9 finishes & exits -- NONPAGEDThread 9 is createdThread 10 is created
51 Exploitation Reliability (XIII) We’re facing some difficulties:We do not know which thread we’re working withThus we do not know where ‘our’ TEB is atThe TEB-memory is fragmented due to constant dying/creating of threads in a production environmentThus we cannot overwrite them sequentually as odds are that we hit a page-fault before we get to our TEB
52 Exploitation Reliability (XIV) Strategy for exploitation:Create large number of threadsLet lots of them dieCreate our exploiting threadCreate a large number of additional threads to fill gapsStart overwriting TEBs sequentuallyResults: 80-90% reliability independent of NT2kXP version, service pack or hotfix