68cc6a36 sub edi,[ebp+0x10]
68cc6a39 mov eax,[ebp+0xc]
68cc6a3c push dword ptr [ebp-0x3c]
68cc6a3f or dword ptr [ebp-0x4],0xffffffff
68cc6a43 sar edi,1
68cc6a45 mov [eax],edi
68cc6a47 call query!ciDelete (68d4a9ae)
68cc6a4c mov ecx,[ebp-0xc]
68cc6a4f pop edi
68cc6a50 pop esi
68cc6a51 mov fs:[00000000],ecx
68cc6a58 pop ebx
68cc6a59 leave
68cc6a5a ret 0x10
.
.
.
Listing 7.3 (continued)
Before you start inspecting DecodeURLEscapes, you must remember that
the first parameter it receives is a pointer to the source string, and the third is a
pointer to the local variable area in the stack. That local variable is where one
expects the function will be writing a decoded copy of the source string. The first
parameter is loaded into ESIand the third into EDI. The second parameter is a
pointer to the string length and is copied into [ebp-0x10]. So much for setups.
The function then gets into a copying loop that copies ASCII characters from
ESIinto BX(this is that MOVZXinstruction at 68cc69b4). It then writes them
into the address from EDIas zero-extended 16-bit values (this happens at
68cc6a06). This is simply a conversion into Unicode, where the Unicode
string is being written into a local variable whose pointer was passed from
CVariableSet::AddExtensionControlBlock.
In the process, the function is looking for special characters in the string
which indicate special values within the string that need to be decoded (most
of the decoding sequences are not included in this listing). The important thing
to notice is how the function is decrementing the value at [ebp-0x10]and
checking that it’s nonzero. You now have a full picture of what causes this bug.
CVariableSet::AddExtensionControlBlockis allocating what seems
to be a 400-bytes-long buffer that receives the decoded string from Decode
URLEscapes. The function is checking that the source string (which is in ASCII)
is 400 characters long, but DecodeURLEscapesis writing the string in Unicode!
Most likely the buffer in CVariableSet::AddExtensionControlBlock
was defined as a 200-character Unicode string (usually defined using the WCHAR
type). The bug is that the length comparison is confusing bytes with Unicode
Auditing Program Binaries 269