News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Retrieve ImageBase of a loaded DLL

Started by FlySky, November 06, 2008, 05:54:14 PM

Previous topic - Next topic

FlySky

Hey guys,

Just playing around with asm and trying to learn things about retrieving the module base of a dll loaded in memory.

Although I succesfully managed to retrieve the modulebase of the dll I want to retrieve the base from I noticed some weird memory leak. Although I think it's because of this function:

This source has been posted on the net I just applied it for me to play with and noticed the weird behaviour of my memory when using this function. It retrieves the imagebase perfectly but my memory keeps going up and up.

GetModuleBaseAddress PROC iProcID:DWORD, DLLName:DWORD
                LOCAL hSnap:DWORD
                LOCAL xModule:MODULEENTRY32
        mov eax, [iProcID]
        mov eax, [eax]
        invoke  CreateToolhelp32Snapshot, TH32CS_SNAPMODULE, eax
        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

thanks in advance

donkey

You have to close the handle of your snapshot...

invoke CloseHandle, hSnap
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

Here's a couple of functions I wrote to demonstrate finding a module using an address. Since they reside inside a library there are a few checks and also the functions are loaded dynamically in order to avoid errors when run on different Windows versions so the two can reside in the same program and be selected based on OS version.

For 9x

GetModuleByAddr9x FRAME Address,pModuleName
LOCAL pID :D
LOCAL hSnap :D
LOCAL me32 :MODULEENTRY32
LOCAL hlib :D
LOCAL pCreateToolhelp32Snapshot :D
LOCAL pModule32First :D
LOCAL pModule32Next :D

mov D[me32.dwSize],SIZEOF MODULEENTRY32

invoke IsBadWritePtr,[pModuleName],1
or eax,eax
jz >
xor eax,eax
dec eax
ret
:

invoke GetModuleHandleA,"Kernel32.dll"
mov [hlib],eax
or eax,eax
jnz >
dec eax
ret
:
mov [hlib],eax
invoke GetProcAddress,[hlib],"CreateToolhelp32Snapshot"
mov [pCreateToolhelp32Snapshot],eax
or eax,eax
jnz >
dec eax
ret
:
invoke GetProcAddress,[hlib],"Module32First"
mov [pModule32First],eax
or eax,eax
jnz >
dec eax
ret
:
invoke GetProcAddress,[hlib],"Module32Next"
mov [pModule32Next],eax
or eax,eax
jnz >
dec eax
ret
:

mov eax,[pModuleName]
mov B[eax],0

invoke GetCurrentProcessId
mov [pID],eax

push [pID]
push 8 ;TH32CS_SNAPMODULE
call [pCreateToolhelp32Snapshot]
mov [hSnap],eax

push offset me32
push [hSnap]
call [pModule32First]
jmp >L2
L1:
mov eax,[me32.modBaseAddr]
mov ecx,[me32.modBaseSize]
add ecx,eax
cmp [Address],eax
jb >
cmp [Address],ecx
ja >
invoke lstrcpyA,[pModuleName],OFFSET me32.szModule
jmp >.DONE
:
push offset me32
push [hSnap]
call [pModule32Next]
L2:
or eax,eax
jnz <L1
.DONE
invoke CloseHandle,[hSnap]
invoke lstrlenA,[pModuleName]
or eax,eax // Set the flags
RET
ENDF


For NT

GetModuleByAddrNT FRAME Address,pModuleName
uses edi,esi,ebx
LOCAL pID :D
LOCAL hProcess :D
LOCAL hMods[1024] :D
LOCAL cbNeeded :D
LOCAL modinfo :MODULEINFO
LOCAL hModule :D
LOCAL hlib :D
LOCAL pEnumProcessModules :D
LOCAL pGetModuleInformation :D
LOCAL ModName[MAX_PATH] :B

invoke IsBadWritePtr,[pModuleName],1
or eax,eax
jz >

xor eax,eax
dec eax
ret
:

invoke LoadLibraryA,"psapi.dll"
or eax,eax
jnz >
dec eax
ret
:
mov [hlib],eax
invoke GetProcAddress,[hlib],"EnumProcessModules"
mov [pEnumProcessModules],eax
or eax,eax
jnz >
invoke FreeLibrary,[hlib]
xor eax,eax
dec eax
ret
:
invoke GetProcAddress,[hlib],"GetModuleInformation"
mov [pGetModuleInformation],eax
or eax,eax
jnz >
invoke FreeLibrary,[hlib]
xor eax,eax
dec eax
ret
:

mov eax,[pModuleName]
mov B[eax],0

mov ebx,[Address]
invoke GetCurrentProcessId
mov [pID],eax
invoke OpenProcess,PROCESS_QUERY_INFORMATION+PROCESS_VM_READ,FALSE,[pID]
mov [hProcess],eax
or eax,eax
jnz >
invoke FreeLibrary,[hlib]
xor eax,eax
dec eax
ret
:

push offset cbNeeded
push 1024
push offset hMods
push [hProcess]
call [pEnumProcessModules]
or eax,eax
jz >>.DONE
mov edi,[cbNeeded]
shr edi,2
mov esi,offset hMods
L1:
mov eax,[esi]
mov [hModule],eax
add esi,4

push SIZEOF MODULEINFO
push offset modinfo
push [hModule]
push [hProcess]
call [pGetModuleInformation]
or eax,eax
jz >.DONE
cmp ebx,[modinfo.lpBaseOfDll]
jg >L2
dec edi
or edi,edi
js >.DONE
jmp <L1
L2:
mov eax,[modinfo.SizeOfImage]
add eax,[modinfo.lpBaseOfDll]
cmp ebx,eax
jl >L3
dec edi
or edi,edi
js >.DONE
jmp <L1
L3:
invoke GetModuleFileNameA,[hModule],OFFSET ModName,256
invoke GetFileTitleA,OFFSET ModName,[pModuleName],256

.DONE
invoke CloseHandle,[hProcess]
invoke FreeLibrary,[hlib]
invoke lstrlenA,[pModuleName]
test eax,eax // Set the flags
RET
ENDF
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

FlySky

Thanks for the reply donkey, everything is working perfect now. :dance: