Buffer Overflow Attack Proofing of Code Binary Gopal
Buffer Overflow Attack Proofing of Code Binary Gopal Gupta, Parag Doshi, R. Reghuramalingam, Doug Harris The University of Texas at Dallas
Buffer Overflow Attacks • Buffer Overflow Attacks (B. O. A): A majority of attacks • • for which advisories are issued are based on B. O. A. Other forms of attacks, such as distributed denial of service attacks, sometimes rely on B. O. A. exploit the memory organization of the traditional activation stack model to overwrite the return address B. O. A. becomes possible due to bad SW engg practices Software purchaser has no way to prevent these bad practices and really can’t do much.
Security Concern • Percentage of buffer overflows listed in CERT advisories each year • Some examples include Windows 2003 server, sendmail, windows HTML conversion library Buffer Overflows Per Year as listed by CERT
Most Recent Warning • Microsoft Windows animated cursor stack buffer overflow • • • Public Date: March 29, 2007 Date Last Updated: April 4, 2007 Source: US-CERT • Impact • A remote, unauthenticated attacker may be able to execute arbitrary code or cause a denial-of-service condition • System affected • Microsoft Windows 2000 SP 4 through Vista • Overview • Microsoft Windows contains a stack buffer overflow in the handling of animated cursor files. This vulnerability may allow a remote attacker to execute arbitrary code or cause a denial-of-service condition.
Background – Memory Layout Code Lower Memory Location Data Heap Stack growth Memory write direction Local Data Base Pointer Return Address Function Arguments Stack Higher Memory Location
Background – Function Call Sample Code void foo( char * Arg 1) { char Buffer[64]; . . . } void main ( ) {. . . . foo( “abc” ); . . . } ESP EBP Local Data – Buffer[64] Base Pointer Return Address Stack Frame of foo function Function Arguments – “abc” ESP Local Data EBP Base Pointer Return Address Function Arguments Stack Frame of main function
Buffer Overflow – Example Sample Code void fn (char *str) { char buffer[8]; strcpy (buffer, str); } void main( ) { char Large. String[256] ; for (int i=0; i<255; i++) Large. String [i] = ‘A’; fn(Large. String); . . . } Return address has changed !!!! ESP not 41 initialized 41 Buffer 41 41=41 41 EBP Base 41 41 Pointer 41 41 Return 41 41 Address 41 41 Pointer to Large. String 41 41 ESP 41 41=41 41 41 Large. String not 41 initialized 41 41 EBP Base Pointer Return Address Function Arguments Stack 64 bytes long data
Issues in tackling BOA • Do I have to modify my hardware? • Do I have to modify my executable code? • Do I have to modify my source code? • Do I have to modify my compiler? • Do I have to modify all of the above?
Buffer Overflow Solutions • RAD: Ret. Addr. Defender stores return addr. in RAR area • Impl. as a gcc compiler patch. All code has to be recompiled • Stackguard: Stackguard inserts a ‘canary’ word to protect return address • The ‘canary’ word can be compromised • Propolice: stackguard + place buffers after pointers • Same weaknesses as stackguard • Splint: Splint allows the user to write annotations in the code that define allocated and used sizes • User is required to write annotations • Wagner’s Prevention Method: Static analysis solution • Depends on source code availability
Binary. Secure: An Overview • Buffer Overflow is achieved by overwriting the return address • If a return address is recorded in a separate area, away from the buffer overflow, then it cannot be overwritten • So modify the memory organization to add a new auxiliary return address stack, allocated in an area opposite to the direction of buffer write/overflow • When a function call returns, it uses the return address from this new stack • Transform the binary to make it consistent with this new memory organization.
Binary. Secure: An Overview • The return address is saved as part of the program execution stack • This stack is uncompromised as memory writes occur in the opposite direction Code Lower Memory Location Data Heap Memory write direction New Stack Local Data Base Pointer Return Address Stack growth direction Function Arguments Stack Higher Memory Location
Binary. Secure: An Overview Step - 1 Disassembled file & Metadata Executable file Opcodes to be modified Executable file Step – 2 Step - 3 Disassembled file & Metadata Executable file Code flow graph Executable with Modified opcodes Opcodes to be modified Final executable with new instructions Code flow graph
Binary Secure: Specifications • These are some of the conditions that must hold • • • Code must be re-entrant Code should not modify the stack pointer Processor: Intel x 386 Compiler: Dev C++ compiler 4. 9. 9. 1 Platform: Windows
Advantages • Binary code is analyzed. This can be used on third-party software where one does not have access to source code. • Run-time checks require modification to the source code (Splint) • Compiler modifications are costly and performing changes to all available compilers is not possible. (RAD, Stackguard) • Return addresses are stored on the stack itself. Hence overhead incurred while accessing addresses in other areas is reduced.
Unresolved Problems • Off by One • Instead of return address, attacker targets base address, i. e. , EBP. Buffer Local Data EBP EIP Function Arguments Caller’s Frame Before buffer overflow stored EBP points to caller’s frame After buffer overflow stored EBP points to somewhere inside frame
Unresolved Problems • Function Pointers Vulnerability • Buffer overruns may change local function pointers • Virtual function tables and Call back functions are also vulnerable. Some Function Buffer Function Pointer EBP Return Address Function Argument Stack Other Function Before buffer overflow Function Pointer points to some function in program After buffer overflow stored Function Pointer points to other malicious function
Unresolved Problems • Format String Attack • Sprintf and its variants in C and its derivatives use variable number of arguments; attacker can exploit format tokens in first argument and gain control of the system. • The attacker can perform arbitrary writes in the stack and exploit any of previous vulnerabilities.
New Approach – Split Stack Code – Static Data Lower Memory Location Function Pointers Control Base Pointer Return Address Memory write direction Arguments with FPs Control Stack Heap Solution • Split stack in two part • One part contains ‘data’ • Other part has ‘control’ • Store control in opposite to memory write direction Non FP – Local Data Stack growth direction Problems • Off by One • Have to protect base pointer as it is main target in this attack. • Function Pointer Vulnerability • Have to protect function pointers in local data. Data Base Pointer Non FP Arguments Data Stack Higher Memory Location
Current State • Split Stack follows same approach as Binary Secure but eliminates more vulnerabilities. • Technique currently being evaluated; system for transforming the binary to be implemented (Doshi’s MS thesis; in progress). • Issue: in splitting stack would be to detect function pointers. Solution? : • keep all function pointers (incl. GOT) in control stack. • Keep all other pointers and data in data stack
Questions…
- Slides: 20