Reversing : The Hacker's Guide to Reverse Engineering

(ff) #1
0040107c call Chapter7!strcat (00401190)
00401081 lea eax,[esp+0x10]
00401085 push eax
00401086 call Chapter7!system (004010e7)
0040108b add esp,0x78
0040108e ret

Before dealing with the specifics of the overflow bug in this code, let’s try to
figure out the basics of this function. The function was defined with the cdecl
calling convention, so the parameters are unwound by the caller. This means
that the RETinstruction can’t be used for determining how many parameters the
function takes. Let’s try to figure out the stack layout in this function. Start by
reading a parameter from [esp+0x4], and then subtract ESPby 100 bytes, to
make room for local variables. If you go to the end of the function, you’ll see the
code that moves ESPback to where it was when I first entered the function. This
is the add esp, 0x78, but why is it adding 120 bytes instead of 100? If you look
at the function, you’ll see three function calls to strcpy, strcat, and system.
If you look inside those functions, you’ll see that they are all cdeclfunctions (as
are all C runtime library functions), and, as already mentioned, in cdeclfunc-
tions the caller is responsible for unwinding the parameters from the stack. In
this function, instead of adding an add esp, NumberOfBytesafter each call,
the compiler has chosen to optimize the unwinding process by simply unwind-
ing the parameters from all three function calls at once.
This approach makes for a slightly less “reverser-friendly” function because
every time the stack is accessed through ESP, you have to try to figure out
where ESPis pointing to for each instruction. Of course, this problem only
exists when you’re studying a static disassembly—in a live debugger, you can
always just look at the value of ESPat any given moment.

From the program’s perspective, the unwinding of the stack at the end of the
function has another disadvantage: The function ends up using a bit more stack
space. This is because the parameters from each of the function calls made
during the function’s lifetime stay in the stack for the remainder of the
function. On the other hand, stack space is generally not a problem in user-
mode threads in Windows (as opposed to kernel-mode threads, which have a
very limited stack space).

So, what do each of the ESPreferences in this function access? If you look
closely, you’ll see that other than the first access at [esp+0x4], the last three
stack accesses are all going to the same place. The first is accessing [esp+0x4]
and then pushes it into the stack (where it stays until launchreturns). The
next time the same address is accessed, the offset from ESPhas to be higher
because ESPis now 4 bytes less than what it was before.

248 Chapter 7

Free download pdf