Figure 7.1 A function’s stack, before and after a stack overwrite.
For instance, you know that each time you run a program the stack is allo-
cated in the same place, so you can try and guess how much stack space the
program has used so far and try and jump to the right place. Alternatively, you
could pad our shellcode with NOPs and jump to the memory area where you
think the buffer has been copied. The NOPs give you significant latitude
because you don’t have to jump to an exact location—you can jump to any
address that contains your NOPs and execution will just flow into your code.
A Simple Stack Vulnerability
The most trivial overflow bugs happen when an application stores a temporary
buffer in the stack and receives variable-length input from the outside world
into that buffer. The classic case is a function that receives a null-terminated
string as input and copies that string into a local variable. Here is an example
that was disassembled using WinDbg.
Chapter7!launch:
00401060 mov eax,[esp+0x4]
00401064 sub esp,0x64
00401067 push eax
00401068 lea ecx,[esp+0x4]
0040106c push ecx
0040106d call Chapter7!strcpy (00401180)
00401072 lea edx,[esp+0x8]
00401076 push 0x408128
0040107b push edxParameter 2
32 bitsParameter 1Return AddressSaved EBPnumberstring[3]..[7]string[0]..[3]counterCopiedBuffer + 0x18
32 bitsCopiedBuffer + 0x14CopiedBuffer + 0x10CopiedBuffer + 0x0CCopiedBuffer + 0x08CopiedBuffer + 0x04CopiedBuffercounterCurrent
Value of
ESPCurrent
Value of
EBPCurrent
Value of
ESPCurrent
Value of
EBPBefore Reading string After Reading stringAuditing Program Binaries 247