This is a rather generic question, but I'll give it a shot.
For starters imports from DLLs can exist roughly in three forms:
- static imports
- delay-load imports
- dynamic imports
Now one could argue that the delay-load and dynamic imports should be in the same group and yes, there is some truth to it. However, delay-loading uses structures in the PE file and requires some support in the linker and loader, too. So I think it can equally stand on its own.
Static imports mean that the loader will resolve the name of the DLL and then attempt to resolve each of the functions imported from that DLL before your main thread even gets to start.
Delay-loading puts the onus of resolving DLL name and functions on the application itself, provided the application overrides certain callbacks (see delayimp.h
). This allows for more graceful error handling or even for providing fallback functionality on a downlevel Windows version.
Dynamic imports typically use LoadLibrary
and/or LoadLibraryEx
to load the DLL in question and GetProcAddress
to retrieve the function addresses in the loaded DLL, which can then be called subsequently.
Only the first two (static and delay-load) will show up in the PE image. To find out dynamic imports you need to reverse engineer the binary and look for calls to LoadLibrary
and GetProcAddress
. This can be arbitrarily hard, depending on obfuscation or protection schemes applied to the PE image. A debugger (dynamic analysis) is theoretically also an option, but not for malware. The last possibility I see is using the Bochs Debugger in IDA or something like Unicorn or Qilin. Obviously some Sandboxes could also be an option and may answer what DLLs get loaded at what point by the malware (unless the malware has sandbox detection and behaves differently inside a sandbox).
Now to the incorrectly named DLL. There are two ways to look at it (at least).
- The DLL name could have changed
- the .exe requires the DLL to have a particular name
The first scenario can often be spotted by looking at the export table, which also sometimes contains a DLL name (IMAGE_EXPORT_DIRECTORY::Name
). But this isn't 100% waterproof, because this field may be NULL, as far as I know. But it's still good to know.
The second scenario means you need to find out what DLL name the .exe expects (via reverse engineering). It could be as easy as looking at the import table or delay-load imports, but you tried that already. So chances are you need a disassembler or similar tool to dig deeper.
I'd probably try a few common DLL names which are prone to DLL placement attacks, such as version.dll
and cryptsp.dll
. By looking in the object manager namespace (using WinObj etc), you can weed out the "safe" DLLs from those that are prone to DLL placement attack by looking in \KnownDlls
(and its 32-bit counterpart on a 64-bit Windows).
If these don't yield results you have to employ a disassembler or similar, because you're out of the "cheaper" options. And that's where your question isn't specific enough (e.g. there is no file sample to look at) to be of further help.
LoadLibrary
andGetprocAddress
so check the exe for such calls. So an example here: docs.microsoft.com/en-us/windows/win32/dlls/…