bengore
asked on
Get import table of a running process
Hello,
I know the handle of an running process ( hProcess := OpenProcess(AccessRights, FALSE, PID); ) and I want to know which DLL files it have loaded. I do not want to know which DLL is in the process space of this running process (injected DLLs can be also in the process space, but injected DLLs are not loaded from a process, because injected DLLs are injected to the process.)
That means I can not use EnumProcessModules or Module32First, because these functions also enumerate the injected DLLs.
A solution could be to get the import table of this running process and look for the DLLs which the process is using. How can I do this? The .exe file of the running process is compressed, so I have to get the import table from the process in memory - not from the .exe file.
The solution should work on Windows NT (Win9x would be fine).
Thanky you for your answer for this difficult question
Ben
BTW: I think, here you can found something similar: Look for "function GetProcAddress32" at http://www.delphipages.com/news/detaildocs.cfm?ID=17
or look for "FindCallerModuleHandle" on http://groups.google.com
I know the handle of an running process ( hProcess := OpenProcess(AccessRights, FALSE, PID); ) and I want to know which DLL files it have loaded. I do not want to know which DLL is in the process space of this running process (injected DLLs can be also in the process space, but injected DLLs are not loaded from a process, because injected DLLs are injected to the process.)
That means I can not use EnumProcessModules or Module32First, because these functions also enumerate the injected DLLs.
A solution could be to get the import table of this running process and look for the DLLs which the process is using. How can I do this? The .exe file of the running process is compressed, so I have to get the import table from the process in memory - not from the .exe file.
The solution should work on Windows NT (Win9x would be fine).
Thanky you for your answer for this difficult question
Ben
BTW: I think, here you can found something similar: Look for "function GetProcAddress32" at http://www.delphipages.com/news/detaildocs.cfm?ID=17
or look for "FindCallerModuleHandle" on http://groups.google.com
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
"import table" may contain not all DLLs. How about DLLs loaded by LoadLibrary?
Could you tell more detailed what do you want to make?
ASKER
GloomyFriar, thank you for your comments.
How about DLLs linked static (not loaded by LoadLibrary). Is there a way to get this DLLs via "import table"?
How about DLLs linked static (not loaded by LoadLibrary). Is there a way to get this DLLs via "import table"?
ASKER
More details? I have a DLL file. I want to know if a processes (somethimes with comressed .exe files) needs this DLL file (static linked).
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
DaFox, I think ImgWalk.dll use EnumProcessModules or Module32First and enumerate also injected DLLs.
>> I think ImgWalk.dll use EnumProcessModules or Module32First
nope, it uses VirtualQuery that fills the MEMORY_BASIC_INFORMATION structure.
>> injected DLLs
that's right, and therefore it also gets dynamically loaded dlls.
Markus
nope, it uses VirtualQuery that fills the MEMORY_BASIC_INFORMATION structure.
>> injected DLLs
that's right, and therefore it also gets dynamically loaded dlls.
Markus
>How about DLLs linked static (not loaded by LoadLibrary). Is there a way to get this DLLs via "import table"?
Yes of course.
You just need to open the exe file and read its PE header.
Yes of course.
You just need to open the exe file and read its PE header.
Something like that (it work with running exe, but you can do the same with a file):
function FindUsablePage(hProcess: THANDLE; PProcessBase: pointer): pointer;
var peHdrOffset: DWORD;
cBytesMoved: DWORD;
ntHdr: IMAGE_NT_HEADERS;
pSection: ^IMAGE_SECTION_HEADER;
i: ULONG;
tmpPtr: PBYTE;
section: IMAGE_SECTION_HEADER;
SecName: string;
begin
Result := nil;
// Read in the offset of the PE header within the debuggee
tmpPtr := PBYTE(PProcessBase);
inc(tmpPtr, $3C);
if ReadProcessMemory(ProcessI nformation .hProcess,
tmpPtr,
@peHdrOffset,
sizeof(peHdrOffset),
cBytesMoved) = False then Exit;
// Read in the IMAGE_NT_HEADERS.OptionalH eader.Base OfCode field
tmpPtr := PBYTE(PProcessBase);
inc(tmpPtr, peHdrOffset);
if ReadProcessMemory(ProcessI nformation .hProcess,
tmpPtr, @ntHdr, sizeof(ntHdr),
cBytesMoved) = False then Exit;
tmpPtr := PBYTE(PProcessBase);
inc(tmpPtr, peHdrOffset + 4 + sizeof(ntHdr.FileHeader) +
ntHdr.FileHeader.SizeOfOpt ionalHeade r);
pSection := pointer(tmpPtr);//(PIMAGE_ SECTION_HE ADER)
for i:=0 to Pred(ntHdr.FileHeader.Numb erOfSectio ns) do begin
//{IMAGE_SECTION_HEADER section;
if ReadProcessMemory(ProcessI nformation .hProcess,
pSection, @section, sizeof(section),
cBytesMoved) = False then Exit;
// OutputDebugString( "trying section:
// OutputDebugString( section.Name )'
// OutputDebugString( "\r\n" )'
SecName := StrPas(@section.Name[0]);
// If it's writeable, and not the .idata section, we'll go with it
if(((section.Characteristi cs and IMAGE_SCN_MEM_WRITE) <> 0) and
(StrLComp(@section.Name[0] , '.idata', 6) <> 0)) then begin
OutputDebugString(PChar('u sing section.' + StrPas(@section.Name[0]) + #10 + #13));
Result := pointer(DWORD(PProcessBase ) + section.VirtualAddress);
//Exit;
end;
Inc(pSection); // Not this section. Advance to next section.
end;
end;
function FindUsablePage(hProcess: THANDLE; PProcessBase: pointer): pointer;
var peHdrOffset: DWORD;
cBytesMoved: DWORD;
ntHdr: IMAGE_NT_HEADERS;
pSection: ^IMAGE_SECTION_HEADER;
i: ULONG;
tmpPtr: PBYTE;
section: IMAGE_SECTION_HEADER;
SecName: string;
begin
Result := nil;
// Read in the offset of the PE header within the debuggee
tmpPtr := PBYTE(PProcessBase);
inc(tmpPtr, $3C);
if ReadProcessMemory(ProcessI
tmpPtr,
@peHdrOffset,
sizeof(peHdrOffset),
cBytesMoved) = False then Exit;
// Read in the IMAGE_NT_HEADERS.OptionalH
tmpPtr := PBYTE(PProcessBase);
inc(tmpPtr, peHdrOffset);
if ReadProcessMemory(ProcessI
tmpPtr, @ntHdr, sizeof(ntHdr),
cBytesMoved) = False then Exit;
tmpPtr := PBYTE(PProcessBase);
inc(tmpPtr, peHdrOffset + 4 + sizeof(ntHdr.FileHeader) +
ntHdr.FileHeader.SizeOfOpt
pSection := pointer(tmpPtr);//(PIMAGE_
for i:=0 to Pred(ntHdr.FileHeader.Numb
//{IMAGE_SECTION_HEADER section;
if ReadProcessMemory(ProcessI
pSection, @section, sizeof(section),
cBytesMoved) = False then Exit;
// OutputDebugString( "trying section:
// OutputDebugString( section.Name )'
// OutputDebugString( "\r\n" )'
SecName := StrPas(@section.Name[0]);
// If it's writeable, and not the .idata section, we'll go with it
if(((section.Characteristi
(StrLComp(@section.Name[0]
OutputDebugString(PChar('u
Result := pointer(DWORD(PProcessBase
//Exit;
end;
Inc(pSection); // Not this section. Advance to next section.
end;
end;
Here is the code that read exports, but it's rather easy to make it read imports.
If any problems I'll can help tomorrow.
https://www.experts-exchange.com/questions/20079575/functions-in-DLL.html
If any problems I'll can help tomorrow.
https://www.experts-exchange.com/questions/20079575/functions-in-DLL.html
ASKER
Hi GloomyFriar, thank you for your FindUsablePage source and the other links. I will check it.
> You just need to open the exe file and read its PE header.
This is not usefull, if the .exe file is compressed.
> You just need to open the exe file and read its PE header.
This is not usefull, if the .exe file is compressed.
>This is not usefull, if the .exe file is compressed.
Which compressor is used?
Are you sure that import sections is changed by the compressor?
Which compressor is used?
Are you sure that import sections is changed by the compressor?