Reversing : The Hacker's Guide to Reverse Engineering

(ff) #1
characters. The buffer can only hold 200 Unicode characters, but the check is
going to allow 400 characters.
As with many buffer overflow conditions, exploiting this bug isn’t as easy as
it seems. First of all, whatever you do you wouldn’t be able to affect Decode
URLEscapes, only CVariableSet::AddExtensionControlBlock. That’s
because the vulnerable local variable is part of CVariableSet::Add
ExtensionControlBlock’s stack area, and DecodeURLEscapesstores
its local variables in a lower address in the stack. You can overwrite as many
as 400 bytes of stack space beyond the end of the WCHARlocal variable (that’s
the difference between the real buffer size and the maximum bytes the bound-
ary check would let us write). This means that you can definitely get to
CVariableSet::AddExtensionControlBlock’s return value, and proba-
bly to the return values of several calls back. It turns out that it’s not so simple.
First of all, take a look at what CVariableSet::AddExtensionControl
Blockdoes after DecodeURLEscapesreturns. Assuming that the function
succeeds, it goes on to perform some additional processing on the converted
string (it calls DecodeHtmlNumericand wcsuprto convert the string to
uppercase). In most cases, these operations will be unaffected by the fact that the
stack has been overwritten, so the function will simply keep on running. The
trouble starts afterward, at 6e90088fwhen the function is reading the pointer
to EXTENSION_CONTROL_BLOCK from [ebp+0x8]—there is no way to mod-
ify the function’s return value without affecting this parameter. That’s because
even if the last bit of data transmitted is a carefully selected return address
for CVariableSet::AddExtensionControlBlock, DecodeURLEscapes
would still overwrite 2 bytes at [ebp+0x8]when it adds a Unicode NULL
terminator.
This creates a problem because the function tries to access the EXTENSION
_CONTROL_BLOCKbefore it returns. Corrupting the pointer at [ebp+0x8]
means that the function will crash before it jumps to the new return value (this
will probably happen at 6e900896, when the function tries to access offset +8 in
that structure). The solution here is to use the exception handler pointer instead
of the function’s return value. If you go back to the beginning of CVariable
Set::AddExtensionControlBlock, you’ll see that it starts by setting EAXto
0x6e906af8and then calls idq!_EH_prolog. This sequence sets up excep-
tion handling for the function. 0x6e906af8is a pointer to code that the system
will execute in case of an exception.
The call to idq!_EH_prologis essentially pushing exception-handling
information into the stack. The system is keeping a pointer to this stack
address in a special memory location that is accessed through fs:[0]. When
the buffer overflow occurs, it’s also overwriting this exception-handling data
structure, and you can replace the exception handler’s address with what-
ever you wish. This way, you don’t have to worry about corrupting the

270 Chapter 7

Free download pdf