|
Unpinning Importet dll's
HI. ever wantet to unload a .dll from memory which was importet via the Import Table ? no , well i have , and turns out that windows prevents you from doing this , for security obiviously , as it would be pretty bad to unload a .dll by accident youd later need :) , but none the less i did some research and found out its more then possible if you preform a little magic , so here are the steps described which are required to do this. 1) Unpinning dll's when windows Loads a .dll into your process space , the .dll is added to the PEB to be more exact in the PEB->LoaderData this Double linked list contains all the Modules Loaded into our image space , lets take a look what it looks like. typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA; now you see it contains multiple things , for this article the only ones we are interestet in are the 3 LIST_ENTRY's , these 3 are pointers to double linked lists , each entry in the double linked lists contains 1 typedef struct _LDR_MODULE { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; LIST_ENTRY HashTableEntry; ULONG TimeDateStamp; } LDR_MODULE, *PLDR_MODULE now all this , is various info about our .dll , but lets go back to when Windows Loads a .dll , Everytime you call LoadLibraryA("mydll.dll") windows will add a entry ( if it doesent excist already) and increase the LoadCount by 1 , now what happens when it loads a .dll via our ImportTable ? well more or less the same except it sets LoadCount to -1 , which means the .dll is pinned , and if this is the case windows will refuse to unload the .dll from memory. So how do we change this ? well take a look at this code: bool Mem_Manager::UnPinnAlldlls() { OutputDebugStringA("UnPinning All Dll's"); DWORD PebAddr = 0; __asm { mov eax,DWORD PTR FS:[0x18] mov eax,DWORD PTR DS:[eax+0x30] mov PebAddr,eax } PPEB Peb = (PPEB)PebAddr; _LDR_MODULE *peb_ldr_module; peb_ldr_module = (_LDR_MODULE*)Peb->Ldr->InLoadOrderModuleList.Flink; // Go through each modules one by one in their load order. DWORD First = 0; while((DWORD)peb_ldr_module != First) { if(First == 0) { First = (DWORD)peb_ldr_module; } peb_ldr_module->LoadCount = 1; peb_ldr_module = (_LDR_MODULE*)peb_ldr_module->InLoadOrderModuleList.Flink; } return true; } what happens is: 1. Gets Addr of PEB via __asm{} block 2. Access PEB->PEB_LDR_DATA 3. Get First Loaded Module via : Peb->Ldr->InLoadOrderModuleList.Flink 4. Log Address of First Entry ( as its a Recursive Double linked list , so we stop once we been all the way round) 5. Set RefCount of LoadedModule to 1 , so we can unload it with FreeLibrary 6. Get Next LoadedModule Via: peb_ldr_module->InLoadOrderModuleList.Flink so once , these steps have been preformed , you can unload any .dll with a simpel call to FreeLibrary("dllName.dll") and it will be free'd from memory hope somebody finds this usefull , else oh well :) Comments
| ||||||