randorRE
randorRE

Reputation: 11

Enumerating all modules for a binary using Python (pefile / win32api)

I want to use PEfile or another Python library to enumerate all modules. I thought I had it, but then I go into WinDbg because some obvious ones were missing, and I saw there were a number of missing ones.

For filezilla.exe:

00400000 00fe7000   image00400000 image00400000
01c70000 01ecc000   combase  C:\WINDOWS\SysWOW64\combase.dll
6f590000 6f5ac000   SRVCLI   C:\WINDOWS\SysWOW64\SRVCLI.DLL
6f640000 6f844000   COMCTL32 C:\WINDOWS\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.17134.472_none_42ecd1cc44e43e73\COMCTL32.DLL
70610000 7061b000   NETUTILS C:\WINDOWS\SysWOW64\NETUTILS.DLL
70720000 70733000   NETAPI32 C:\WINDOWS\SysWOW64\NETAPI32.dll
72910000 72933000   winmmbase C:\WINDOWS\SysWOW64\winmmbase.dll
729d0000 729d8000   WSOCK32  C:\WINDOWS\SysWOW64\WSOCK32.DLL
72b40000 72b64000   WINMM    C:\WINDOWS\SysWOW64\WINMM.DLL
72b70000 72b88000   MPR      C:\WINDOWS\SysWOW64\MPR.DLL
73c60000 73c6a000   CRYPTBASE C:\WINDOWS\SysWOW64\CRYPTBASE.dll
73c70000 73c90000   SspiCli  C:\WINDOWS\SysWOW64\SspiCli.dll
74120000 741b6000   OLEAUT32 C:\WINDOWS\SysWOW64\OLEAUT32.dll
741c0000 7477a000   windows_storage C:\WINDOWS\SysWOW64\windows.storage.dll
74780000 7487c000   ole32    C:\WINDOWS\SysWOW64\ole32.dll
74880000 74908000   shcore   C:\WINDOWS\SysWOW64\shcore.dll
74910000 7498d000   msvcp_win C:\WINDOWS\SysWOW64\msvcp_win.dll
74990000 74a4f000   msvcrt   C:\WINDOWS\SysWOW64\msvcrt.dll
74a50000 74a72000   GDI32    C:\WINDOWS\SysWOW64\GDI32.dll
74bd0000 74bde000   MSASN1   C:\WINDOWS\SysWOW64\MSASN1.dll
74be0000 74c47000   WS2_32   C:\WINDOWS\SysWOW64\WS2_32.dll
74c70000 74d30000   RPCRT4   C:\WINDOWS\SysWOW64\RPCRT4.dll
74d30000 74d37000   Normaliz C:\WINDOWS\SysWOW64\Normaliz.dll
74d40000 74d79000   cfgmgr32 C:\WINDOWS\SysWOW64\cfgmgr32.dll
74fe0000 75025000   powrprof C:\WINDOWS\SysWOW64\powrprof.dll
75150000 7526e000   ucrtbase C:\WINDOWS\SysWOW64\ucrtbase.dll
75280000 75416000   CRYPT32  C:\WINDOWS\SysWOW64\CRYPT32.dll
75420000 75584000   gdi32full C:\WINDOWS\SysWOW64\gdi32full.dll
755c0000 755c8000   FLTLIB   C:\WINDOWS\SysWOW64\FLTLIB.DLL
755d0000 755e8000   profapi  C:\WINDOWS\SysWOW64\profapi.dll
755f0000 75635000   SHLWAPI  C:\WINDOWS\SysWOW64\SHLWAPI.dll
75640000 7698a000   SHELL32  C:\WINDOWS\SysWOW64\SHELL32.dll
76990000 76b74000   KERNELBASE C:\WINDOWS\SysWOW64\KERNELBASE.dll
76cf0000 76cff000   kernel_appcore C:\WINDOWS\SysWOW64\kernel.appcore.dll
76d00000 76d17000   win32u   C:\WINDOWS\SysWOW64\win32u.dll
76db0000 76e86000   COMDLG32 C:\WINDOWS\SysWOW64\COMDLG32.DLL
76e90000 7701d000   USER32   C:\WINDOWS\SysWOW64\USER32.dll
77020000 77064000   sechost  C:\WINDOWS\SysWOW64\sechost.dll
77100000 771e0000   KERNEL32 C:\WINDOWS\SysWOW64\KERNEL32.DLL
771e0000 77238000   bcryptPrimitives C:\WINDOWS\SysWOW64\bcryptPrimitives.dll
77240000 772b8000   ADVAPI32 C:\WINDOWS\SysWOW64\ADVAPI32.dll
773b0000 77540000   ntdll    ntdll.dll   

This is the output that I obtained from pefile by using a simlar script:

ADVAPI32.dll
COMCTL32.DLL
COMDLG32.DLL
CRYPT32.dll
GDI32.dll
KERNEL32.dll
MPR.DLL
msvcrt.dll
NETAPI32.dll
Normaliz.dll
ole32.dll
OLEAUT32.dll
POWRPROF.dll
SHELL32.DLL
USER32.dll
WINMM.DLL
WS2_32.dll
WSOCK32.DLL

def findDLL():
    pe = pefile.PE(name)
    for each in pe.DIRECTORY_ENTRY_IMPORT:
        print entry.dll

Is there something else in Pefile I should be looking at to obtain more complete listing of modules that will be loaded?

Is there something in win32api or win32con that could get me this information? I would prefer pefile if possible, but either works. I need to be able to output a listing of all modules that would be loaded. I am working in Python and inflexible about changing.

Upvotes: 0

Views: 502

Answers (2)

mox
mox

Reputation: 6314

As a matter of fact, there are different types of techniques to import modules. The type is determined by the way the referenced module is bound to the executable. As far as I know, PEfile does only lists the dynamic link libraries that are statically bound to the executable through the Imports table. Other types of dynamic link libraries are: explicit (those called via LoadLibrary/GetProcAddress APIs), Forwarded (those loaded via a PE mechanism that allow forwarding API calls) and delayed (those loaded via a PE mechanism that allow delayed loading of API calls).

Please find below a schema representing these methods (which is part of my slides available https://winitor.com/pdf/DynamicLinkLibraries.pdf

I hope that helps.

enter image description here

Upvotes: 0

kichik
kichik

Reputation: 34704

Modules can be loaded into a process in many ways. Imported DLLs are just one way.

  1. Imported DLLs may import DLLs for themselves too. foobar.exe may depend on user32.dll, but user32.dll in turn also depends on kernel32.dll so that will be loaded into your process. If you want a complete list, you may want to check the imported DLLs if your executable's dependencies.
  2. Modules can be dynamically loaded in code with LoadLibrary(). You will not see those in the import directory. You'll have to disassemble the code for that and even then the library name can be generated on the fly so it will be hard to tell.
  3. There are some more unsupported methods of loading modules that malware can use.

As the comments mentioned, getting a list of loaded modules through debugging APIs is probably simpler. But it all depends on what you're actually trying to do with this data.

Upvotes: 1

Related Questions