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;
}
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]