While I was trying the code by Joachim Bauch I noticed a strange behaviour loading user32.dll. The test program I’m using to do some tests crashes with an eccess violation error on a portion of memory virtually loaded at runtime.
For those who has not read the article I present a quick sum up of the technique, focusing on the necessary steps only:
1. allocate the necessary bytes required to store all the bytes of the dll
2. copy the original dll bytes inside the new allocated memory buffer
3. perform base relocation adjusting the necessary references
4. call DllEntryPoint directly from the new allocated buffer
5. when you don’t need the dll anymore it frees the allocated buffer
The error occours when the buffer is completely deallocated. The technique seems to be right but the question arises: why the hell someone needs to access an address inside a deallocated memory?
The problem is not strictly related with Joachim’s code itself, it’s an error caused by the use of user32.dll! At the moment I haven’t tried all the system dll, but if you understand the problem I’m pretty sure you’ll be able to solve it with another dll involved.
I have all the source code in front of me but when the problem is not totally related with it I prefer to use a debugger approach.
When the exception occours your debugger breaks here:
7C91E464 MOV EAX,DWORD PTR FS:[18] ; TEB
7C91E46A MOV EAX,DWORD PTR DS:[EAX+30] ; PEB
7C91E46D MOV EAX,DWORD PTR DS:[EAX+2C] ; PEB.KernelCallbackTable
7C91E470 CALL DWORD PTR DS:[EAX+EDX*4] ; call dword ptr [0xB72A10], access violation occours here!
The address (0xB72A10) is inside the allocated buffer, it’s obviously an entry of a vector. EAX represents the starting address of the vector and EDX is an index, each dword is an element of the vector. Starting address is 0xB72970, I only have to understand what’s behind that address.
Load user32.dll inside IDA and look at the vector, the xref will bring you inside DllEntryPoint:
7E39B3F6 mov eax, large fs:18h ; TEB
7E39B3FC mov eax, [eax+30h] ; PEB
7E39B3FF mov eax, [eax+18h] ; PEB.ProcessHeap
7E39B402 mov hHeap, eax
7E39B407 mov eax, large fs:18h
7E39B40D mov eax, [eax+30h]
7E39B410 mov dword ptr [eax+2Ch], offset off_7E392970 ; PEB.KernelCallbackTable
Can you see where the problem is? No!?! Ok, take a look at the same code that has been copied inside the allocated buffer (base relocation performed!):
00B7B3F6 MOV EAX,DWORD PTR FS:[18]
00B7B3FC MOV EAX,DWORD PTR DS:[EAX+30]
00B7B3FF MOV EAX,DWORD PTR DS:[EAX+18]
00B7B402 MOV DWORD PTR DS:[BD1224],EAX
00B7B407 MOV EAX,DWORD PTR FS:[18]
00B7B40D MOV EAX,DWORD PTR DS:[EAX+30]
00B7B410 MOV DWORD PTR DS:[EAX+2C],0B72970 <-- look here!!!
At the beginning of user32.dll there’s a particular initialization, it involves the heap and the KernelCallbackTable address. Both values are changed according to the new image base address but they will not be changed back to the old values.
If you don’t want an access violation inside your program you’ll have to restore the old values, nothing else…
The conclusion is simple, the code is perfectly right but it may be prone to this kind of weird conceptual bug… pay attention when you load a system dll!