A forum for reverse engineering, OS internals and malware analysis 

Ask your beginner questions here.
 #17359  by hanan
 Mon Dec 24, 2012 12:49 pm
I am writing an app that enumerate every process's loaded DLLs and copy them to some remote directory for further examination. Using the EnumProcessModules API i suppose to get every module that's loaded at the target process, but what about those cases where the DLL is hiding itself by removing it's entry at the PEB (i.e CloakDLL, Ntllusion)?
I would like to get some more ideas on how to check for DLL injection in a given process, so that i can cover as much possible injected DLLs as i can.

My current knowledge are the following:
  • Use EnumProcessModules (AFAIK it uses the PEB of the target process to enum the loaded DLLs)
  • Check the memory of a given process using VirtualQuery (bruteforce, is it checking the VAD ?)
  • Check the registry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs
  • Hook LoadLibrary or CreateRemoteThread
keep in mind that my goal isn't to detect an injection at real time, but to get every DLL file that is currently loaded under a given process for further examination.

do you have any other ideas ?

BTW Since i am currently don't have any knowledge about kernel mode code i am intending to do all of these from user mode, BUT in case there is a way to do something from kernel mode code that i couldn't do from user mode don't hesitate to drop the method here (i will learn how to code kernel mode level code at some point).
 #17360  by Vrtule
 Mon Dec 24, 2012 3:16 pm
Hello,

I would recommend to use VirtualQueryEx and GetMappedFileName from PSAPI.DLL instead of EnumProcessModules. GetMappedFileName does not retrieve its data from the PEB of the target process but from the kernel mode. The routine retrieves you name of the file mapped at given address. VirtualQueryEx reports regions where PE files are mapped.
 #17363  by Alex
 Tue Dec 25, 2012 11:43 am
You can also extend querying process memory by looking for pages with PAGE_EXECUTE_* protection. Some malware which inject DLLs from kernel mode may just allocate VM and do the same job as loader but manually without creating image section. Obviously this methos is slow and will give a lot of false positives, but hopefully malware will inject its DLLs without erasing PE, so you can check PE and try to extract module name from export table. For example this is a DLL injected by TDL4:

Image
 #17370  by hanan
 Wed Dec 26, 2012 8:03 am
Vrtule wrote:Hello,

I would recommend to use VirtualQueryEx and GetMappedFileName from PSAPI.DLL instead of EnumProcessModules. GetMappedFileName does not retrieve its data from the PEB of the target process but from the kernel mode. The routine retrieves you name of the file mapped at given address. VirtualQueryEx reports regions where PE files are mapped.
I would use both methods in order to find that DLL file that doesn't show in the PEB since it will be clear indication of injection.

But i think that this method is the same as what i wrote :
  • Check the memory of a given process using VirtualQuery (bruteforce, is it checking the VAD ?)
my idea was to inject a dll to every process and use VirtualQuery and GetModuleFileName like that:
Code: Select all
BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, PVOID fImpLoad) {
    if (fdwReason == DLL_PROCESS_ATTACH) {
        char szBuf[MAX_PATH * 100] = { 0 };
        PBYTE pb = NULL;
        MEMORY_BASIC_INFORMATION mbi;
        while (VirtualQuery(pb, &mbi, sizeof(mbi)) == sizeof(mbi)) {
                int nLen;
                char szModName[MAX_PATH];
                if (mbi.State == MEM_FREE)
                mbi.AllocationBase = mbi.BaseAddress;
                if    ((mbi.AllocationBase == hInstDll) ||
                        (mbi.AllocationBase != mbi.BaseAddress) ||
                        (mbi.AllocationBase == NULL)) {
                        // Do not add the module name to the list
                        // if any of the following is true:
                        // 1. If this region contains this DLL
                        // 2. If this block is NOT the beginning of a region
                        // 3. If the address is NULL
                        nLen = 0;
                } else {
                        nLen = GetModuleFileNameA((HINSTANCE) mbi.AllocationBase,
                        szModName, _countof(szModName));
                }
                if (nLen > 0) {
                        wsprintfA(strchr(szBuf, 0), "\n%p-%s",
                        mbi.AllocationBase, szModName);
                        }
                pb += mbi.RegionSize;
                }
But i think that your method is better since it is easier and has less footprint, BUT i would like to know how it works on x64 machines (should i write two versions of my code one for X86 and one for X64)?
 #17418  by holly
 Fri Dec 28, 2012 11:33 am
my idea was to inject a dll to every process and use VirtualQuery and GetModuleFileName like that:
you don't need to inject dll,Both VirtualQueryEx and GetModuleFileName have the first param: HANDLE hProcess.