Arcane

Unpinning Importet .dll's

Rate this Entry
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 found this interesting , else oh well

Submit "Unpinning Importet .dll's" to Digg Submit "Unpinning Importet .dll's" to del.icio.us Submit "Unpinning Importet .dll's" to StumbleUpon Submit "Unpinning Importet .dll's" to Google

Categories
Uncategorized

Comments