Arcane

  1. 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 found this interesting , else oh well
    Categories
    Uncategorized