元始天尊 发表于 2015-6-14 12:17:37

LoadLibrary解析(二)

为了实现隐藏dll,不得已出此文对LoadLibrary的解析,该函数比较庞大,尽管已经去除了很多无关代码,仍然有500行。
其中有重定位代码,值得借鉴

HINSTANCE WINAPI LoadLibraryExW(LPCWSTR lpLibFileName,HANDLE hFile,DWORD dwFlags)
{
        UNICODE_STRING DllName;
        HINSTANCE hInst;
        NTSTATUS Status;
        PWSTR SearchPath;
        ULONG DllCharacteristics = 0;
        BOOL FreeString = FALSE;

        RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName);
        //比较看是否为当前exe
        if (BasepExeLdrEntry && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE) && DllName.Length == BasepExeLdrEntry->FullDllName.Length)
        {
                if (RtlEqualUnicodeString(&DllName, &BasepExeLdrEntry->FullDllName, TRUE))
                {
                        return BasepExeLdrEntry->DllBase;
                }
        }
        //获取系统路径 Path
        SearchPath = BaseComputeProcessDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ?DllName.Buffer : NULL,NULL);
        Status = LdrLoadDll(SearchPath,&DllCharacteristics,&DllName,(PVOID*)&hInst);
}

NTSTATUS NTAPI LdrLoadDll(IN PWSTR SearchPath OPTIONAL,IN PULONG DllCharacteristics OPTIONAL,
        IN PUNICODE_STRING DllName, OUT PVOID *BaseAddress)
{
        //初始化加载器锁
        LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie);// Peb->LoaderLock = &LdrpLoaderLock;
        Status = LdrpLoadDll(RedirectedDll,SearchPath,DllCharacteristics,DllName,BaseAddress,TRUE);
        LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
}

NTSTATUS NTAPI LdrpLoadDll(IN BOOLEAN Redirected,IN PWSTR DllPath OPTIONAL,IN PULONG DllCharacteristics OPTIONAL,
        IN PUNICODE_STRING DllName,OUT PVOID *BaseAddress,IN BOOLEAN CallInit)
{
        PPEB Peb = NtCurrentPeb();
        NTSTATUS Status = STATUS_SUCCESS;
        const WCHAR *p;
        BOOLEAN GotExtension;
        WCHAR c;
        WCHAR NameBuffer;
        UNICODE_STRING RawDllName;
        PLDR_DATA_TABLE_ENTRY LdrEntry;
        BOOLEAN InInit = LdrpInLdrInit;

        //处理路径及后缀。。。。。。。。。

        if (!LdrpCheckForLoadedDll(DllPath,&RawDllName,FALSE,Redirected,&LdrEntry))
        {//如果未加载过则映射该DLL
                Status = LdrpMapDll(DllPath,DllPath,NameBuffer,DllCharacteristics,FALSE,Redirected,&LdrEntry);
                if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
                LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
                else if (LdrEntry->LoadCount != 0xFFFF)////如果不是dll,则只增加引用计数
                {
                        LdrEntry->LoadCount++;
                }
                //插入Ldr链
                InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,&LdrEntry->InInitializationOrderModuleList);
        }
        else
        {//检查是否为dll映像
                if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
                {//增加引用计数
                        LdrEntry->LoadCount++;
                        LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
                        LdrpClearLoadInProgress();
                }
                else
                {
                       
                        if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
                }
        }
        *BaseAddress = LdrEntry->DllBase;
}

BOOLEAN NTAPI LdrpCheckForLoadedDll(IN PWSTR DllPath,IN PUNICODE_STRING DllName,IN BOOLEAN Flag,IN BOOLEAN RedirectedDll,
        OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
{
        //指定Flag则在预先生成的哈希表中查找
lookinhash:
        if (Flag)
        {
                HashIndex = LDR_GET_HASH_ENTRY(DllName->Buffer);
                //遍历对应哈希表存储的链表
                ListHead = &LdrpHashTable;
                ListEntry = ListHead->Flink;
                while (ListEntry != ListHead)
                {
                        CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
                        if (RtlEqualUnicodeString(DllName, &CurEntry->BaseDllName, TRUE))
                        {
                                *LdrEntry = CurEntry;
                                return TRUE;
                        }
                        ListEntry = ListEntry->Flink;
                }
                return FALSE;
        }

        //未指定Flag则查找并拼合完整路径,如果是相对路径则仍然用哈希表查找,否则用Ldr查找
        if (!FullPath)//拼合过程略。。。。。。。
        {
                Flag = TRUE;
                goto lookinhash;
        }

        ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
        ListEntry = ListHead->Flink;
        while (ListEntry != ListHead)
        {
                CurEntry = CONTAINING_RECORD(ListEntry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
                ListEntry = ListEntry->Flink;
                if (!CurEntry->InMemoryOrderModuleList.Flink) continue;//如果正在被卸载
                if (RtlEqualUnicodeString(&FullDllName,&CurEntry->FullDllName,TRUE))
                {
                        *LdrEntry = CurEntry;
                        return TRUE;
                }
        }

        //如果路径名方式未能找到,则采用比对内存PE的方式决定是否加载过
        if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer,&NtPathName,NULL,NULL))
        {
                return FALSE;
        }
        //打开DLL文件并映射到虚拟内存
        InitializeObjectAttributes(&ObjectAttributes,&NtPathName,OBJ_CASE_INSENSITIVE,NULL,NULL);
        Status = NtOpenFile(&FileHandle,SYNCHRONIZE | FILE_EXECUTE,&ObjectAttributes,&Iosb,
                FILE_SHARE_READ | FILE_SHARE_DELETE,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
        RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
        Status = NtCreateSection(&SectionHandle,SECTION_MAP_READ |SECTION_MAP_EXECUTE |SECTION_MAP_WRITE,
                NULL,NULL,PAGE_EXECUTE,SEC_COMMIT,FileHandle);
        NtClose(FileHandle);
        Status = ZwMapViewOfSection(SectionHandle,NtCurrentProcess(),&ViewBase,0,0,NULL,&ViewSize,ViewShare,0,PAGE_EXECUTE);
        NtClose(SectionHandle);
        Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader);//获取NT头

        //重新遍历Ldr,这次采用PE头比较方式判断
        //LIST_ENTRY结构很有特点,双向循环链表,链表头为空节点,所以只需要遍历除了头结点以外的节点,现在终于搞清楚这个事实了^_^
        ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
        ListEntry = ListHead->Flink;
        while (ListEntry != ListHead)
        {
                CurEntry = CONTAINING_RECORD(ListEntry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
                ListEntry = ListEntry->Flink;
                if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
                if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) &&
                        (CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage))
                {
                        NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
                        if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
                        {
                                Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
                                if (NT_SUCCESS(Status))
                                {
                                        *LdrEntry = CurEntry;
                                        NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
                                        _SEH2_YIELD(return TRUE;)
                                }
                        }
                }
        }
}

NTSTATUS NTAPI LdrpMapDll(IN PWSTR SearchPath OPTIONAL,IN PWSTR DllPath2, IN PWSTR DllName OPTIONAL, IN PULONG DllCharacteristics,
      IN BOOLEAN Static,IN BOOLEAN Redirect, OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry)
{
        //检查是否加载过
SkipCheck:
    if (!SectionHandle)
    {//如果未加载
      if (LdrpResolveDllName(SearchPath, DllName,&FullDllName, &BaseDllName))
      {
            RtlDosPathNameToNtPathName_U(FullDllName.Buffer, &NtPathDllName, NULL, NULL);
            Status = LdrpCreateDllSection(&NtPathDllName,DllHandle,DllCharacteristics,&SectionHandle);
            RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
      }
    }
    else
    {
      KnownDll = TRUE;
    }

    ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
    Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
        //映射dll
    ViewBase = NULL;
    ViewSize = 0;
    Status = NtMapViewOfSection(SectionHandle,NtCurrentProcess(), &ViewBase,0,0,NULL,&ViewSize,ViewShare, 0, PAGE_READWRITE);
    Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
        NtHeaders = RtlImageNtHeader(ViewBase);//检查pe头
    LdrEntry = LdrpAllocateDataTableEntry(ViewBase);//构造链表节点
    LdrEntry->Flags = Static ? LDRP_STATIC_LINK : 0;
    if (Redirect) LdrEntry->Flags |= LDRP_REDIRECTED;
    LdrEntry->LoadCount = 0;
    LdrEntry->FullDllName = FullDllName;
    LdrEntry->BaseDllName = BaseDllName;
    LdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrEntry->DllBase);//获取入口点
    LdrpInsertMemoryTableEntry(LdrEntry);//插入新节点到ldr
    *DataTableEntry = LdrEntry;

    //如果需要重定位
    if (Status == STATUS_IMAGE_NOT_AT_BASE)
    {
      LdrEntry->Flags |= LDRP_IMAGE_NOT_AT_BASE;
      ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase;
      ImageEnd = ImageBase + ViewSize;
      ListHead = &Peb->Ldr->InLoadOrderModuleList;
      NextEntry = ListHead->Flink;
      while (NextEntry != ListHead)
      {
            CandidateEntry = CONTAINING_RECORD(NextEntry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
            NextEntry = NextEntry->Flink;
            CandidateBase = (ULONG_PTR)CandidateEntry->DllBase;
            CandidateEnd = CandidateBase + CandidateEntry->SizeOfImage;
            if (!CandidateEntry->InMemoryOrderModuleList.Flink) continue;
            if ((ImageBase >= CandidateBase && ImageBase <= CandidateEnd) ||
                (ImageEnd >= CandidateBase && ImageEnd <= CandidateEnd) ||
                (CandidateBase >= ImageBase && CandidateBase <= ImageEnd))
            {
                OverlapDllFound = TRUE;
                OverlapDll = CandidateEntry->FullDllName;
                break;
            }
      }

      if (LdrEntry->Flags & LDRP_IMAGE_DLL)
      {
            if (!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED))
            {
                RelocData = RtlImageDirectoryEntryToData(ViewBase, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC,&RelocDataSize);
            }

                        //禁止user32.dllkernel32.dll重定位
                        //更改节保护属性
            Status = LdrpSetProtection(ViewBase, FALSE);
            if (NT_SUCCESS(Status))
            {//进行重定位
                Status = LdrRelocateImageWithBias(ViewBase, 0LL, NULL, STATUS_SUCCESS,STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);//进行重定向
                if (NT_SUCCESS(Status))
                {
                  ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
                  Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
                  Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
                  Status = LdrpSetProtection(ViewBase, TRUE);//还原节保护属性
                }
            }
      }
    }
    NtClose(SectionHandle);
    return Status;
}

NTSTATUS NTAPI LdrpCreateDllSection(IN PUNICODE_STRING FullName,IN HANDLE DllHandle,IN PULONG DllCharacteristics OPTIONAL,OUT PHANDLE SectionHandle)
{
        if (!DllHandle)
        {
                InitializeObjectAttributes(&ObjectAttributes,FullName,OBJ_CASE_INSENSITIVE,NULL,NULL);
                Status = NtOpenFile(&FileHandle,SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,&ObjectAttributes,&IoStatusBlock,
                        FILE_SHARE_READ | FILE_SHARE_DELETE,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
                if (!NT_SUCCESS(Status))
                {//尝试以只读方式打开
                        Status = NtOpenFile(&FileHandle,SYNCHRONIZE | FILE_EXECUTE,&ObjectAttributes,&IoStatusBlock,
                                FILE_SHARE_READ | FILE_SHARE_DELETE,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
                }
        }
        else
        {
                FileHandle = DllHandle;
        }
        Status = NtCreateSection(SectionHandle,SECTION_MAP_READ | SECTION_MAP_EXECUTE |SECTION_MAP_WRITE | SECTION_QUERY,
                NULL,NULL,PAGE_EXECUTE,SEC_IMAGE,FileHandle);
        NtClose(FileHandle);
        return Status;
}

PLDR_DATA_TABLE_ENTRY NTAPI LdrpAllocateDataTableEntry(IN PVOID BaseAddress)
{
        PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
        PIMAGE_NT_HEADERS NtHeader;

        NtHeader = RtlImageNtHeader(BaseAddress);
        if (NtHeader)
        {
                LdrEntry = RtlAllocateHeap(RtlGetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LDR_DATA_TABLE_ENTRY));
                if (LdrEntry)
                {
                        LdrEntry->DllBase = BaseAddress;
                        LdrEntry->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
                        LdrEntry->TimeDateStamp = NtHeader->FileHeader.TimeDateStamp;
                        LdrEntry->PatchInformation = NULL;
                }
        }
        return LdrEntry;
}

PVOID NTAPI LdrpFetchAddressOfEntryPoint(IN PVOID ImageBase)
{
        PIMAGE_NT_HEADERS NtHeaders;
        ULONG_PTR EntryPoint = 0;
        NtHeaders = RtlImageNtHeader(ImageBase);
        if (NtHeaders)
        {
                EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint;
                if (EntryPoint) EntryPoint += (ULONG_PTR)ImageBase;
        }
        return (PVOID)EntryPoint;
}

VOID NTAPI LdrpInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
{
        PPEB_LDR_DATA PebData = NtCurrentPeb()->Ldr;
        ULONG i;
        i = LDR_GET_HASH_ENTRY(LdrEntry->BaseDllName.Buffer);
        InsertTailList(&LdrpHashTable, &LdrEntry->HashLinks);
        InsertTailList(&PebData->InLoadOrderModuleList, &LdrEntry->InLoadOrderLinks);
        InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderModuleList);
}

NTSTATUS NTAPI LdrpSetProtection(PVOID ViewBase,BOOLEAN Restore)
{
        PIMAGE_NT_HEADERS NtHeaders;
        PIMAGE_SECTION_HEADER Section;
        NTSTATUS Status;
        PVOID SectionBase;
        SIZE_T SectionSize;
        ULONG NewProtection, OldProtection, i;

        NtHeaders = RtlImageNtHeader(ViewBase);
        if (!NtHeaders) return STATUS_INVALID_IMAGE_FORMAT;
        Section = IMAGE_FIRST_SECTION(NtHeaders);
        for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++)
        {
                if ((Section->SizeOfRawData) && !(Section->Characteristics & IMAGE_SCN_MEM_WRITE))
                {
                        if (Restore)
                        {
                                if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
                                {
                                        NewProtection = PAGE_EXECUTE;
                                }
                                else
                                {
                                        NewProtection = PAGE_READONLY;
                                }

                                if (Section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
                                {
                                        NewProtection |= PAGE_NOCACHE;
                                }
                        }
                        else
                        {
                                NewProtection = PAGE_READWRITE;
                        }

                        SectionBase = (PVOID)((ULONG_PTR)ViewBase + Section->VirtualAddress);
                        SectionSize = Section->SizeOfRawData;
                        if (SectionSize)
                        {
                                Status = ZwProtectVirtualMemory(NtCurrentProcess(),&SectionBase,&SectionSize,NewProtection,&OldProtection);
                                if (!NT_SUCCESS(Status)) return Status;
                        }
                }
                Section++;
        }
        if (Restore) ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0);
        return STATUS_SUCCESS;
}

ULONG NTAPI LdrRelocateImageWithBias(IN PVOID BaseAddress,IN LONGLONG AdditionalBias,IN PCCHLoaderName,IN ULONG Success,IN ULONG Conflict,IN ULONG Invalid)
{
        PIMAGE_NT_HEADERS NtHeaders;
        PIMAGE_DATA_DIRECTORY RelocationDDir;
        PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
        ULONG Count;
        ULONG_PTR Address;
        PUSHORT TypeOffset;
        LONGLONG Delta;

        NtHeaders = RtlImageNtHeader(BaseAddress);
        if (NtHeaders == NULL)
                return Invalid;
        if (SWAPW(NtHeaders->FileHeader.Characteristics) & IMAGE_FILE_RELOCS_STRIPPED)
        {
                return Conflict;
        }
        RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory;
        if (SWAPD(RelocationDDir->VirtualAddress) == 0 || SWAPD(RelocationDDir->Size) == 0)
        {
                return Success;
        }
        Delta = (ULONG_PTR)BaseAddress - SWAPD(NtHeaders->OptionalHeader.ImageBase) + AdditionalBias;
        RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)BaseAddress + SWAPD(RelocationDDir->VirtualAddress));
        RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + SWAPD(RelocationDDir->Size));
        while (RelocationDir < RelocationEnd && SWAPW(RelocationDir->SizeOfBlock) > 0)
        {
                Count = (SWAPW(RelocationDir->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
                Address = (ULONG_PTR)RVA(BaseAddress, SWAPD(RelocationDir->VirtualAddress));
                TypeOffset = (PUSHORT)(RelocationDir + 1);
                RelocationDir = LdrProcessRelocationBlockLongLong(Address,Count,TypeOffset,Delta);
                if (RelocationDir == NULL)
                {
                        DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");
                        return Invalid;
                }
        }
        return Success;
}

PIMAGE_BASE_RELOCATION NTAPI LdrProcessRelocationBlockLongLong(IN ULONG_PTR Address,IN ULONG Count,IN PUSHORT TypeOffset,IN LONGLONG Delta)
{
    for (i = 0; i < Count; i++)
    {
      Offset = SWAPW(*TypeOffset) & 0xFFF;
      Type = SWAPW(*TypeOffset) >> 12;
      ShortPtr = (PUSHORT)(RVA(Address, Offset));
      /*
      if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
      (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
      {*/
      switch (Type)
      {
            /* case IMAGE_REL_BASED_SECTION : */
            /* case IMAGE_REL_BASED_REL32 : */
      case IMAGE_REL_BASED_ABSOLUTE:
            break;
      case IMAGE_REL_BASED_HIGH:
            *ShortPtr = HIWORD(MAKELONG(0, *ShortPtr) + (Delta & 0xFFFFFFFF));
            break;
      case IMAGE_REL_BASED_LOW:
            *ShortPtr = SWAPW(*ShortPtr) + LOWORD(Delta & 0xFFFF);
            break;
      case IMAGE_REL_BASED_HIGHLOW:
            LongPtr = (PULONG)RVA(Address, Offset);
            *LongPtr = SWAPD(*LongPtr) + (Delta & 0xFFFFFFFF);
            break;
      case IMAGE_REL_BASED_DIR64:
            LongLongPtr = (PUINT64)RVA(Address, Offset);
            *LongLongPtr = SWAPQ(*LongLongPtr) + Delta;
            break;
      case IMAGE_REL_BASED_HIGHADJ:
      case IMAGE_REL_BASED_MIPS_JMPADDR:
      default:
            return (PIMAGE_BASE_RELOCATION)NULL;
      }
      TypeOffset++;
    }
    return (PIMAGE_BASE_RELOCATION)TypeOffset;
}

元始天尊 发表于 2015-6-14 17:07:31

BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
{
        NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1));
        Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1));
        Status = LdrUnloadDll((PVOID)hLibModule);
}

NTSTATUS NTAPI LdrUnloadDll(IN PVOID BaseAddress)
{
        //获取ldr记录
        LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry);
        if (LdrEntry->LoadCount != 0xFFFF)
        {//降低引用计数
                LdrEntry->LoadCount--;
                if (LdrEntry->Flags & LDRP_IMAGE_DLL)
                {
                        LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_DEREFCOUNT);
                }
        }
        NextEntry = Peb->Ldr->InInitializationOrderModuleList.Blink;
        while (NextEntry != &Peb->Ldr->InInitializationOrderModuleList)
        {
                LdrEntry = CONTAINING_RECORD(NextEntry,LDR_DATA_TABLE_ENTRY,InInitializationOrderModuleList);
                NextEntry = NextEntry->Blink;
                LdrEntry->Flags &= ~LDRP_UNLOAD_IN_PROGRESS;
                if (!LdrEntry->LoadCount)
                {
                        CurrentEntry = LdrEntry;
                        RemoveEntryList(&CurrentEntry->InInitializationOrderModuleList);
                        RemoveEntryList(&CurrentEntry->InMemoryOrderModuleList);
                        RemoveEntryList(&CurrentEntry->HashLinks);
                        InsertTailList(&LdrpUnloadHead, &CurrentEntry->HashLinks);
                }
        }

        InitializeListHead(&UnloadList);
        CurrentEntry = NULL;
        NextEntry = LdrpUnloadHead.Flink;
        while (NextEntry != &LdrpUnloadHead)
        {
                LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
                CurrentEntry = LdrEntry;
                LdrpLoadedDllHandleCache = NULL;
                CurrentEntry->InMemoryOrderModuleList.Flink = NULL;
                RemoveEntryList(&CurrentEntry->HashLinks);
                InsertTailList(&UnloadList, &CurrentEntry->HashLinks);
                EntryPoint = LdrEntry->EntryPoint;
                if ((EntryPoint) && (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED))
                {
                        LdrpCallInitRoutine(LdrEntry->EntryPoint,LdrEntry->DllBase,DLL_PROCESS_DETACH,NULL);
                }
                RemoveEntryList(&CurrentEntry->InLoadOrderLinks);
                CurrentEntry = NULL;
                NextEntry = LdrpUnloadHead.Flink;
        }
        NextEntry = UnloadList.Flink;
        while (NextEntry != &UnloadList)
        {
                LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
                NextEntry = NextEntry->Flink;
                CurrentEntry = LdrEntry;
                CorImageData = RtlImageDirectoryEntryToData(LdrEntry->DllBase,TRUE,IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,&ComSectionSize);
                if (!(CurrentEntry->Flags & LDR_COR_OWNS_UNMAP))
                {
                        Status = NtUnmapViewOfSection(NtCurrentProcess(),CurrentEntry->DllBase);
                        ASSERT(NT_SUCCESS(Status));
                }
                LdrpFinalizeAndDeallocateDataTableEntry(CurrentEntry);
        }
Quickie:
        if (!LdrpInLdrInit) RtlLeaveCriticalSection(Peb->LoaderLock);
}
页: [1]
查看完整版本: LoadLibrary解析(二)