Posted about 1 year ago, by Ksbunker

Unlike exe's, dll's do not always get loaded into the same address space (i.e. 00400000). This address is called the 'Base Address' and is a pointer to the "M" in the "MZ" signature (which is if you dont know, is the first two bytes in any portable executable [i.e. exe's and dll's, any some other files]).

If when we are memory editing an executable and the address we wish to change is 400123, it will always be 400123. HOWEVER, if the address we wish to modify resides inside a DLL loaded by a process, the chances of that dll being loaded into the same location in memory everytime that process runs or calls the DLL is slim to none.

So, to get the address in a usable form we must subtract the image base from the desired address. If for example, the address we wanted to patch in a dll was 10001099, and the ImageBase of that DLL was 10001000, we would simply subtract the ImageBase from the Relative Address.

e.g. 10001099h (wanted address) - 10001000h (ImageBase) = 99h

This is handy because now we can enumerate through all loaded dlls on your system (using toolhelp api) for the one we are after, then retrieve the base address of this dll and subsequently add our computed value (in this case 99h) to the ImageBase. And this will now give us a perfectly valid and usable address to write to memory with using WriteProcessMemory.

Enough ranting, here's the code. (The code is in

NB: szCLASS is a pointer to a string holding the class name of the process we want to mess with and that has loaded the dll. I havn't included all the source, only the main snippets, such as my GetModuleBaseAddress function and some of the code that calls this. GetModuleBaseAddress takes two parameters, the first which is the ProcessID of the target process (retrieved from OpenProcess) and secondly, a string to the dll we are searching for. If the function suceeds it will return the base address of the chosen dll, if it failed, eax will return 0.

After this call, you would see a very basic instruction "add eax, 1440hh". This is the value I calculated using the method as described earlier on. As you notice in the WPM() call, in the address parameter it has EAX, which is the address of the ImageBase PLUS the pointer value (in my case it was 14408h).

Viola! That's it. As you have seen it's a bit harder than writing to a exe, but overall, not too difficult. None of the code here is specific to asm and can be ported to any language with relative ease. Hopefully someone finds this useful!

 Invoke FindWindow, ADDR szCLASS, 0
 Invoke GetWindowThreadProcessId, eax, addr ProcessID
 Invoke OpenProcess, PROCESS_VM_READ + PROCESS_VM_WRITE + PROCESS_VM_OPERATION, 0, ProcessID
 mov ebx, eax
 Invoke GetModuleBaseAddress, ProcessID, ADDR szDLL
 add eax, 14408h
 invoke WriteProcessMemory, ebx, eax, ADDR bytes, 6, NULL
 invoke CloseHandle, ebx

GetModuleBaseAddress proc iProcID:DWORD, DLLName:DWORD
 LOCAL hSnap:DWORD
 LOCAL xModule:MODULEENTRY32

 invoke CreateToolhelp32Snapshot, TH32CS_SNAPMODULE, iProcID
 mov hSnap,eax
 mov xModule.dwSize, sizeof xModule
 invoke Module32First, hSnap, addr xModule
 test eax, eax
 jnz @getdll
 mov eax, 0
 ret

@getdll:
 invoke Module32Next, hSnap, addr xModule
 test eax, eax
 jnz @checkdll
 mov eax, 0
 ret
 
@checkdll:
 invoke lstrcmpi, DLLName, addr xModule.szModule
 test eax, eax
 jnz @getdll
 mov eax, xModule.modBaseAddr
 ret
GetModuleBaseAddress endp

Author Info Comment