I am trying to follow along an explanation of bypassing stack cookies by overwriting the stack exception handler (SEH) located here: https://www.corelan.be/index.php/2009/09/21/exploit-writing-tutorial-part-6-bypassing-stack-cookies-safeseh-hw-dep-and-aslr/
PDF link to the same page: https://repo.zenk-security.com/Reversing%20.%20cracking/%20Bypassing%20Stack%20Cookies,%20SafeSeh,%20HW%20DEP%20and%20ASLR.pdf
The section I have a question about is under Stack cookie bypass demonstration 2 : Virtual Function call of the website or page 30 of the PDF
Initial state of registers:
The post then says:
...these 4 instructions are executed, attempting to load the address of the function into eax…
0040104D |. 8B45 F0 MOV EAX,DWORD PTR SS:[EBP-10]
00401050 |. 8B10 MOV EDX,DWORD PTR DS:[EAX]
00401052 |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10]
00401055 |. 8B02 MOV EAX,DWORD PTR DS:[EDX]
The end result of these 4 instructions is
and then CALL EAX
would be called, executing the modified function pointer address in EAX.
My question:
How do EAX and EDX point to the overwritten string after the 4 mentioned instructions?
My understanding is the after the first instruction,
MOV EAX,DWORD PTR SS:[EBP-10]
EBP (0012FF6C) minus 10 (hex?) equals 0012FF5C. Value at location 0012FF5C is 0012FF78. 0012FF78 is the location of the SEH further up in the stack passed as a parameter. So EAX = 0012FF78. So far so good, since 0012FF78 is the address of the pointer to the SEH further up the stack.
Second instruction,
MOV EDX,DWORD PTR DS:[EAX]
EDX is set to the value at the location pointed to by EAX. Value at location 0012FF78 is 0040211C. EDX = 0040211C?
Third instruction,
MOV ECX,DWORD PTR SS:[EBP-10]
ECX is set to 0012FF78 which is the same as the first instruction but with ECX instead of EAX. Does this instruction matter for this context?
Fourth instruction,
MOV EAX,DWORD PTR DS:[EDX]
EAX is set to the value referenced by EDX (0040211C). EAX = ??? whatever is at that location in memory.
My computed EAX (???) and EDX (0040211C) do not match the post's listed after values of EAX (42424242) and EDX (0012FF78).
What went wrong with my interpretation? Shouldn't EDX == ECX? Thanks.
Yes, it seems there is a mistake
The method described bypasses the GS protection by diverting the execution flow before the function returns (and checks the canary).
This is accomplished through the tainting of the vtable
of a C++ object allocated further up in the stack by the mean of a buffer overflow.
The layout of a C++ object with a virtual member is augmented with a hidden pointer to the vtable
.
This pointer is the first member of the class laid out in memory, see this.
The object is allocated somewhere on the stack but a pointer to it is stored at [ebp-10h]
(effective address 0x12FF5C), you can see this by looking at the instruction 10 00401010 894df0 mov dword ptr [ebp-10h],ecx
(more on this below) found on page 27 of the PDF where the victim function's disassembly is shown.
With MOV EAX,DWORD PTR SS:[EBP-10]
we have eax
holding the pointer to the C++ object i.e.this
since we are inside a member function and [ebp-10h] = original ecx
(see below). eax = 12FF78h (ptr to this C++ object)
.
With MOV EDX,DWORD PTR DS:[EAX]
we have edx
holding the pointer to this[0]
i.e. this.vtable
. edx = 40211ch
(ptr to this C++ object's vtable).
With MOV EAX,DWORD PTR DS:[EDX]
we have eax
holding the pointer to this.vtable[0]
ie &bar
. eax = 401070h (ptr to bar)
.
The MOV ECX,DWORD PTR SS:[EBP-10]
just moves this
into ecx
, this is the thiscall
(no pun intended) calling convention.
This is also why I recognized that [ebp-10h]
was this
and not a pointer to another object.
After the copy the stack is (exactly as you posted):
We can see that the C++ object has not been touched, the copied buffer is too short.
The attacker would need one more DWORD, containing a pointer inside the buffer where they crafted a new vtable
.