实现自己的LoadLibrary

#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <winternl.h>
#include <Shlwapi.h>
#include <map>
#include <string>
using namespace std;

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"Shlwapi.lib")

#if defined(WIN64) || defined(_WIN64)
#pragma comment(lib,"ntdll64.lib")
#else
#pragma comment(lib,"ntdll.lib")
#endif

#if defined(UNICODE) || defined(_UNICODE)
#define GetProcAddressT GetProcAddressTW
#define LoadLibraryT LoadLibraryTW
#define FreeLibraryT FreeLibraryTW
#else
#define GetProcAddressT GetProcAddressTA
#define LoadLibraryT LoadLibraryTA
#define FreeLibraryT FreeLibraryTA
#endif

extern "C"
{
	BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(PCWSTR,PUNICODE_STRING,PCWSTR*,PVOID*);
	NTSTATUS WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,SIZE_T,const LARGE_INTEGER*,SIZE_T*,ULONG,ULONG,ULONG);
	BOOLEAN WINAPI RtlFreeHeap(PVOID,ULONG,PVOID);
	NTSTATUS WINAPI NtCreateSection(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PLARGE_INTEGER,ULONG,ULONG,HANDLE);
	NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID);
	NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE,PVOID,PSIZE_T,ULONG,PULONG);
	NTSTATUS WINAPI NtFlushInstructionCache(HANDLE,PVOID,ULONG);
};


void RtlImageDirectoryEntryToData(PIMAGE_NT_HEADERS,USHORT,ULONG*,PVOID*,PVOID) ;
ULONG NTAPI LdrRelocateImageWithBias(PVOID,PIMAGE_NT_HEADERS,LONGLONG ,PCCH,ULONG,ULONG,ULONG);
NTSTATUS NTAPI LdrpSetProtection(PVOID,PIMAGE_NT_HEADERS,BOOLEAN);

#define OBJ_CASE_INSENSITIVE    0x00000040L
#define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS)0x40000003L)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 
#define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS)0xC0000018L)
#define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007BL)
#define FILE_NON_DIRECTORY_FILE 0x00000040
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020

typedef struct _CLIENT_ID 
{
	HANDLE UniqueProcess;
	HANDLE UniqueThread;
} CLIENT_ID;

typedef struct _MTEB 
{ 
	_NT_TIB NtTib; 
	PVOID EnvironmentPointer; 
	CLIENT_ID ClientId;
	PVOID ActiveRpcHandle;
	PVOID ThreadLocalStoragePointer;
	PPEB Peb;
}MTEB,*PMTEB;

typedef struct _MPEB_LDR_DATA
{
	UINT32 Length;
	UCHAR Initialized;
	PVOID SsHandle;
	LIST_ENTRY InLoadOrderModuleList;
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList;
}MPEB_LDR_DATA,*PMPEB_LDR_DATA;

typedef struct _LDR_MODULE
{
	LIST_ENTRY InLoadOrderModuleList;
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList;
	PVOID BaseAddress;
	PVOID EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
}LDR_MODULE,*PLDR_MODULE;

typedef struct _MPEB
{
	DWORD flags;
	PVOID Mutant;
	PVOID ImageBaseAddress;
	PMPEB_LDR_DATA Ldr;
	PVOID ProcessParameters;
	PVOID SubSystemData;
	PVOID ProcessHeap;
}MPEB,*PMPEB;

struct DllStruct
{
	PVOID EntryPoint;
	PVOID ViewBase;
	SIZE_T ViewSize;
	std::map<std::wstring,FARPROC> FuncMap;//函数映射
};
std::map<std::wstring,DllStruct> DllMap;
CRITICAL_SECTION DllLock;
#define RtlGetProcessHeap() ( (PMPEB)((PMTEB)NtCurrentTeb())->Peb )->ProcessHeap
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define InitializeObjectAttributes( p, n, a, r, s ) { (p)->Length = sizeof( OBJECT_ATTRIBUTES ); (p)->RootDirectory = r; (p)->Attributes = a; (p)->ObjectName = n; (p)->SecurityDescriptor = s; (p)->SecurityQualityOfService = NULL; }
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) ((ULONG_PTR)(ntheader) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + ((ntheader))->FileHeader.SizeOfOptionalHeader ))

BOOL WINAPI LoadLibraryTA(LPCSTR DllPath);
BOOL WINAPI LoadLibraryTW(LPCWSTR DllPath);
FARPROC WINAPI GetProcAddressTA(LPCSTR DllPath,LPCSTR ProcName);
FARPROC WINAPI GetProcAddressTW(LPCWSTR DllPath,LPCWSTR ProcName);
BOOL WINAPI FreeLibraryTA(LPCSTR DllPath);
BOOL WINAPI FreeLibraryTW(LPCWSTR DllPath);

#define SWAPW(x) (x)
#define SWAPD(x) (x)
#define SWAPQ(x) (x)
#define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))

typedef BOOLEAN (WINAPI *PDLL_INIT_ROUTINE)( PVOID DllHandle,ULONG Reason,PCONTEXT Context );

void GetExportFuncs( PIMAGE_NT_HEADERS NtHeaders, PVOID ViewBase, DllStruct* ds)
{
	PIMAGE_EXPORT_DIRECTORY ExportDir = NULL;
	ULONG ExportDirSize = 0;
	if(!NtHeaders && ViewBase)
	{
		PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)ViewBase;
		NtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)DosHeader + DosHeader->e_lfanew);
	}
	if(!NtHeaders)
		return;
	RtlImageDirectoryEntryToData(NtHeaders, IMAGE_DIRECTORY_ENTRY_EXPORT, &ExportDirSize, (PVOID*)&ExportDir, ViewBase);
	PULONG NameTable = (PULONG)((ULONG_PTR)ViewBase + (ULONG_PTR)ExportDir->AddressOfNames);
	PUSHORT OrdinalTable = (PUSHORT)((ULONG_PTR)ViewBase + (ULONG_PTR)ExportDir->AddressOfNameOrdinals);
	PULONG AddressOfFunctions = (PULONG)((ULONG_PTR)ViewBase + (ULONG_PTR)ExportDir->AddressOfFunctions);
	USHORT Ordinal = -1;
	for(LONG i = 0;i < ExportDir->NumberOfNames;i++)
	{
		PCHAR FuncName = (PCHAR)((ULONG_PTR)ViewBase + NameTable[i]);
		ANSI_STRING FuncNameA;
		UNICODE_STRING FuncNameW;
		WCHAR tmp[0x1000];
		memset(tmp,0,sizeof(tmp));
		RtlInitAnsiString(&FuncNameA,FuncName);
		FuncNameW.Buffer = tmp;
		FuncNameW.MaximumLength = 0x1000;
		NTSTATUS Status = RtlAnsiStringToUnicodeString(&FuncNameW,&FuncNameA,FALSE);
		if(NT_SUCCESS(Status))
		{
			Ordinal = OrdinalTable[i];
			if(Ordinal >=0 && Ordinal < ExportDir->NumberOfFunctions)
			{
				ULONG_PTR Function = (ULONG_PTR)ViewBase + AddressOfFunctions[Ordinal];
				if(!(Function > (ULONG_PTR)ExportDir && Function < (ULONG_PTR)ExportDir + ExportDirSize))
				{
					ds->FuncMap[FuncNameW.Buffer] = (FARPROC)Function;
				}
			}
		}
	}
}

BOOL WINAPI LoadLibraryTA(LPCSTR DllPath)
{
	ANSI_STRING DllPathA;
	UNICODE_STRING DllPathW;
	NTSTATUS status;
	if(!DllPath || DllPath[0] == 0)
		return FALSE;
	WCHAR tmp[0x1000];
	memset(tmp,0,sizeof(tmp));
	RtlInitAnsiString(&DllPathA,DllPath);
	DllPathW.Buffer = tmp;
	DllPathW.MaximumLength = 0x1000;
	status = RtlAnsiStringToUnicodeString(&DllPathW,&DllPathA,FALSE);
	if(!NT_SUCCESS(status))
		return FALSE;
	return LoadLibraryTW(DllPathW.Buffer);
}

BOOL LdrpLoadImportModule(LPSTR ImportName, PVOID BaseAddress, LPWSTR pDllPath) 
{
	PVOID Address = (PVOID)LoadLibraryA(ImportName);
	Address = (PVOID)((ULONG_PTR)Address&~3);
	//遍历Ldr找到全路径
	PLIST_ENTRY ListHead = &((PMPEB)((PMTEB)NtCurrentTeb())->Peb)->Ldr->InLoadOrderModuleList;
	PLIST_ENTRY Next = ListHead->Flink;
	while(Next != ListHead)
	{
		PLDR_MODULE Cur = (PLDR_MODULE)Next;
		if(Cur->BaseAddress == Address)
		{
			memset(pDllPath,0,0x1000);
			wcsncpy(pDllPath,Cur->FullDllName.Buffer,Cur->FullDllName.Length);
			std::map<std::wstring,DllStruct>::iterator itor = DllMap.find(pDllPath);
			if(itor == DllMap.end())
			{
				DllStruct& ds= DllMap[pDllPath];
				ds.EntryPoint = Cur->EntryPoint;
				ds.ViewBase = Cur->BaseAddress;
				ds.ViewSize = Cur->SizeOfImage;
				GetExportFuncs(NULL,Address,&ds);
			}
			return TRUE;
		}
		Next = Next->Flink;
	}
	return FALSE;
}

void LdrpSnapThunk( PVOID ExportBase, PVOID ImportBase, PIMAGE_THUNK_DATA OriginalThunk, PIMAGE_THUNK_DATA Thunk, PIMAGE_EXPORT_DIRECTORY ExportEntry, ULONG ExportSize )
{
	PIMAGE_IMPORT_BY_NAME AddressOfData = (PIMAGE_IMPORT_BY_NAME)((ULONG_PTR)ImportBase + ((ULONG_PTR)OriginalThunk->u1.AddressOfData & 0xFFFFFFFF));
	LPSTR ImportName = (LPSTR)AddressOfData->Name;
	PULONG NameTable = (PULONG)((ULONG_PTR)ExportBase + (ULONG_PTR)ExportEntry->AddressOfNames);
	PUSHORT OridinalTable = (PUSHORT)((ULONG_PTR)ExportBase + (ULONG_PTR)ExportEntry->AddressOfNameOrdinals);
	USHORT Hint = AddressOfData->Hint;
	
}

void LdrpSnapIAT(PIMAGE_NT_HEADERS NtHeaders, PIMAGE_IMPORT_DESCRIPTOR IatData, PVOID ViewBase,LPCWSTR DllPathW) 
{
	NTSTATUS Status;
	PVOID Iat = NULL;
	SIZE_T ImportSize = 0;
	ULONG IatSize = 0, ExportSize = 0;
	ULONG OldProtect = 0;
	RtlImageDirectoryEntryToData(NtHeaders, IMAGE_DIRECTORY_ENTRY_IAT, &IatSize, &Iat, ViewBase);
	if(!Iat || !IatSize)
	{
		PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)(NtHeaders) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + NtHeaders->FileHeader.SizeOfOptionalHeader );
		ULONG Rva = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
		if(Rva)
		{
			for(ULONG i = 0;i < NtHeaders->FileHeader.NumberOfSections;i++)
			{
				if((Rva >= SectionHeader->VirtualAddress) && Rva < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData))
				{
					Iat = (PVOID)((ULONG_PTR)(ViewBase) + SectionHeader->VirtualAddress);
					IatSize = SectionHeader->Misc.VirtualSize;
					if(!IatSize)
						IatSize = SectionHeader->SizeOfRawData;
					break;
				}
				SectionHeader++;
			}
		}
		else
			return;
	}
	ImportSize = IatSize;

	Status = NtProtectVirtualMemory(((HANDLE)(LONG_PTR) -1), &Iat, &ImportSize, PAGE_READWRITE, &OldProtect);
	if(!NT_SUCCESS(Status))
		return;
	if(IatData->FirstThunk)
	{
		PIMAGE_THUNK_DATA OriginalThunk = NULL;
		PIMAGE_THUNK_DATA FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)ViewBase + IatData->FirstThunk);
		if((IatData->Characteristics < NtHeaders->OptionalHeader.SizeOfHeaders) || (IatData->Characteristics >= NtHeaders->OptionalHeader.SizeOfImage))
		{
			OriginalThunk = FirstThunk;
		}
		else
		{
			OriginalThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)ViewBase + IatData->OriginalFirstThunk);
		}
		LPSTR ImportName = (LPSTR)((ULONG_PTR)ViewBase + IatData->Name);
		while(OriginalThunk->u1.AddressOfData)
		{
			__try
			{
				PIMAGE_IMPORT_BY_NAME AddressOfData = (PIMAGE_IMPORT_BY_NAME)((ULONG_PTR)ViewBase + (ULONG_PTR)OriginalThunk->u1.AddressOfData & 0xFFFFFFFF);
				ImportName = (LPSTR)AddressOfData->Name;
				ANSI_STRING FuncNameA;
				WCHAR FuncName[0x1000];
				UNICODE_STRING FuncNameW;
				memset(FuncName,0,sizeof(FuncName));
				RtlInitAnsiString(&FuncNameA,ImportName);
				FuncNameW.Buffer = FuncName;
				FuncNameW.MaximumLength = sizeof(FuncName);
				RtlAnsiStringToUnicodeString(&FuncNameW,&FuncNameA,FALSE);
				FirstThunk->u1.Function = (DWORD)GetProcAddressTW(DllPathW,FuncNameW.Buffer);
				OriginalThunk++;
				FirstThunk++;
			}
			__except(1)
			{

			}
		}
	}
	NtProtectVirtualMemory(((HANDLE)(LONG_PTR) -1),&Iat,&ImportSize,OldProtect,&OldProtect);
	NtFlushInstructionCache(((HANDLE)(LONG_PTR) -1),Iat,IatSize);
}

void RtlImageDirectoryEntryToData(PIMAGE_NT_HEADERS NtHeaders, USHORT Directory, ULONG* RelocDataSize, PVOID* RelocData, PVOID ViewBase) 
{
	if(NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
	{
		PIMAGE_NT_HEADERS32 tpnh = (PIMAGE_NT_HEADERS32)NtHeaders;
		if(Directory < tpnh->OptionalHeader.NumberOfRvaAndSizes)
		{
			DWORD VA = tpnh->OptionalHeader.DataDirectory[Directory].VirtualAddress;
			if(VA)
			{
				*RelocDataSize = tpnh->OptionalHeader.DataDirectory[Directory].Size;
				*RelocData = (PVOID)((ULONG_PTR)ViewBase + VA);
			}
		}
	}
	else
	{
		PIMAGE_NT_HEADERS64 tpnh = (PIMAGE_NT_HEADERS64)NtHeaders;
		if(Directory < tpnh->OptionalHeader.NumberOfRvaAndSizes)
		{
			DWORD VA = tpnh->OptionalHeader.DataDirectory[Directory].VirtualAddress;
			if(VA)
			{
				*RelocDataSize = tpnh->OptionalHeader.DataDirectory[Directory].Size;
				*RelocData = (PVOID)((BYTE*)ViewBase + VA);
			}
		}
	}
}

BOOL WINAPI LoadLibraryTW(LPCWSTR DllPath)
{
	if(!DllPath || DllPath[0] == 0)
		return FALSE;
	BOOL result = FALSE;

	EnterCriticalSection(&DllLock);
	//查找Map,遍历导出表,更新Map
	std::map<std::wstring,DllStruct>::iterator itor = DllMap.find(DllPath);
	if(itor != DllMap.end())
	{
		result = FALSE;
		goto ENDLOAD;
	}

	UNICODE_STRING NtPathDllName;
	OBJECT_ATTRIBUTES ObjectAttributes;
	HANDLE FileHandle = NULL,SectionHandle = NULL;
	IO_STATUS_BLOCK IoStatusBlock;
	NTSTATUS Status;
	if(!RtlDosPathNameToNtPathName_U(DllPath,&NtPathDllName,NULL,NULL))
	{
		result = FALSE;
		goto ENDLOAD;
	}
	InitializeObjectAttributes(&ObjectAttributes,&NtPathDllName,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);
	}
	if(!NT_SUCCESS(Status))
	{
		result = FALSE;
		RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
		goto ENDLOAD;
	}
	Status = NtCreateSection(&SectionHandle,SECTION_MAP_READ | SECTION_MAP_EXECUTE |SECTION_MAP_WRITE | SECTION_QUERY,
		NULL,NULL,PAGE_EXECUTE,SEC_IMAGE,FileHandle);
	NtClose(FileHandle);
	if(!NT_SUCCESS(Status))
	{
		result = FALSE;
		RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
		goto ENDLOAD;
	}
	RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);

	PVOID ViewBase = NULL;
	SIZE_T ViewSize = 0;
	PIMAGE_NT_HEADERS NtHeaders = NULL;
	PIMAGE_DOS_HEADER DosHeader = NULL;
	PVOID EntryPoint = NULL;
	Status = NtMapViewOfSection(SectionHandle,((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess()*/,&ViewBase,0,0,NULL,&ViewSize,1/*ViewShare*/,0,PAGE_READWRITE);

	if(ViewBase)
	{
		DosHeader = (PIMAGE_DOS_HEADER)ViewBase;
		if(DosHeader->e_magic == IMAGE_DOS_SIGNATURE && DosHeader->e_lfanew  && DosHeader->e_lfanew < ViewSize)
		{
			NtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)DosHeader + DosHeader->e_lfanew);
			if(NtHeaders->Signature != IMAGE_NT_SIGNATURE)
				NtHeaders = NULL;
		}
		if(!NtHeaders || !(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL))
		{
			result = FALSE;
			goto ENDLOAD;
		}
		if(NtHeaders->OptionalHeader.AddressOfEntryPoint)
			EntryPoint = (PVOID)(NtHeaders->OptionalHeader.AddressOfEntryPoint + (BYTE*)ViewBase);
	}

	if(Status == STATUS_IMAGE_NOT_AT_BASE)
	{//重定位
		if(!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED))
		{
			ULONG RelocDataSize = 0;
			PVOID RelocData = NULL;
			RtlImageDirectoryEntryToData(NtHeaders, IMAGE_DIRECTORY_ENTRY_BASERELOC, &RelocDataSize, &RelocData, ViewBase);
			if(RelocData && RelocDataSize)
			{
				Status = LdrpSetProtection(ViewBase,NtHeaders,FALSE);
				if(NT_SUCCESS(Status))
				{
					Status = LdrRelocateImageWithBias(ViewBase, NtHeaders, 0LL, NULL, STATUS_SUCCESS,STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
					LdrpSetProtection(ViewBase,NtHeaders,TRUE);
					if(NT_SUCCESS(Status))
					{
						goto ENDLOAD1;
					}
				}
			}
		}
		if(!NT_SUCCESS(Status) || ViewBase)
		{
			NtUnmapViewOfSection(((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess()*/,ViewBase);
			result = FALSE;
		}
	}
	else if(!NT_SUCCESS(Status))
	{
		result = FALSE;
		goto ENDLOAD;
	}
ENDLOAD1:
	NtClose(SectionHandle);
	if(NT_SUCCESS(Status))
		result = TRUE;
	DllStruct& ds = DllMap[DllPath];
	ds.EntryPoint = EntryPoint;
	ds.ViewBase = ViewBase;
	ds.ViewSize = ViewSize;
	{
		//处理导入表
		ULONG IatDataSize = 0;
		IMAGE_IMPORT_DESCRIPTOR* IatData = NULL;
		RtlImageDirectoryEntryToData(NtHeaders, IMAGE_DIRECTORY_ENTRY_IMPORT, &IatDataSize, (PVOID *)&IatData, ViewBase);
		PVOID BaseAddress = ViewBase;
		if(IatData && IatDataSize)
		{
			while(IatData->Name && IatData->FirstThunk)
			{
				LPSTR ImportName = (LPSTR)((ULONG_PTR)BaseAddress + IatData->Name);
				PIMAGE_THUNK_DATA FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)BaseAddress + IatData->FirstThunk);
				if(FirstThunk->u1.Function)
				{
					WCHAR FuncName[0x1000];
					if(LdrpLoadImportModule(ImportName,BaseAddress,FuncName))//否则应该报错
						LdrpSnapIAT(NtHeaders, IatData, ViewBase, FuncName);
					else
					{
						MessageBoxA(NULL,ImportName,ImportName,MB_OK);
// 						LeaveCriticalSection(&DllLock);
// 						return FALSE;
					}
				}
				IatData++;
			}
		}

//		if(EntryPoint)
//			((PDLL_INIT_ROUTINE)EntryPoint)(ViewBase,DLL_PROCESS_ATTACH,NULL);
		GetExportFuncs(NtHeaders, ViewBase, &ds);
	}

ENDLOAD:
	LeaveCriticalSection(&DllLock);
	return result;
}

NTSTATUS NTAPI LdrpSetProtection(PVOID ViewBase,PIMAGE_NT_HEADERS NtHeaders,BOOLEAN Restore)
{
	NTSTATUS Status;
	PVOID SectionBase;
	SIZE_T SectionSize;
	ULONG NewProtection, OldProtection, i;
	PIMAGE_SECTION_HEADER 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 = NtProtectVirtualMemory(((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess*/,&SectionBase,&SectionSize,NewProtection,&OldProtection);
				if (!NT_SUCCESS(Status)) return Status;
			}
		}
		Section++;
	}
	if (Restore) NtFlushInstructionCache(((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess*/, NULL, 0);
	return STATUS_SUCCESS;
}

ULONG NTAPI LdrRelocateImageWithBias(PVOID BaseAddress,PIMAGE_NT_HEADERS NtHeaders,LONGLONG AdditionalBias,PCCH  LoaderName,ULONG Success,ULONG Conflict,ULONG Invalid)
{

	PIMAGE_DATA_DIRECTORY RelocationDDir;
	PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
	ULONG Count;
	ULONG_PTR Address;
	PUSHORT TypeOffset;
	LONGLONG Delta;

	if (SWAPW(NtHeaders->FileHeader.Characteristics) & IMAGE_FILE_RELOCS_STRIPPED)
	{
		return Conflict;
	}
	RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
	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)
	{
		SHORT Offset;
		USHORT Type;
		ULONG i;
		PUSHORT ShortPtr;
		PULONG LongPtr;
		PULONGLONG LongLongPtr;
		Count = (SWAPW(RelocationDir->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
		Address = (ULONG_PTR)RVA(BaseAddress,SWAPD(RelocationDir->VirtualAddress));
		TypeOffset = (PUSHORT)(RelocationDir + 1);
		for (ULONG 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)
				continue;
			switch (Type)
			{
			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:
				RelocationDir = (PIMAGE_BASE_RELOCATION)NULL;
			}
			TypeOffset++;
		}
		RelocationDir = (PIMAGE_BASE_RELOCATION)TypeOffset;
		if (RelocationDir == NULL)
		{
			return Invalid;
		}
	}
	return Success;
}

FARPROC WINAPI GetProcAddressTA(LPCSTR DllPath,LPCSTR ProcName)
{
	ANSI_STRING DllPathA,ProcNameA;
	UNICODE_STRING DllPathW,ProcNameW;
	NTSTATUS status;
	if(!DllPath || !ProcName || DllPath[0] == 0 || ProcName[0] == 0)
		return NULL;
	WCHAR tmp1[0x1000],tmp2[0x1000];
	memset(tmp1,0,sizeof(tmp1));
	memset(tmp2,0,sizeof(tmp2));
	RtlInitAnsiString(&DllPathA,DllPath);
	RtlInitAnsiString(&ProcNameA,ProcName);
	DllPathW.Buffer = tmp1;
	DllPathW.MaximumLength = 0x1000;
	ProcNameW.Buffer = tmp2;
	ProcNameW.MaximumLength = 0x1000;
	status = RtlAnsiStringToUnicodeString(&DllPathW,&DllPathA,FALSE);
	if(!NT_SUCCESS(status))
		return FALSE;
	status = RtlAnsiStringToUnicodeString(&ProcNameW,&ProcNameA,FALSE);
	if(!NT_SUCCESS(status))
		return FALSE;
	return GetProcAddressTW(DllPathW.Buffer,ProcNameW.Buffer);
}

FARPROC WINAPI GetProcAddressTW(LPCWSTR DllPath,LPCWSTR ProcName)
{
	if(!DllPath || !ProcName || DllPath[0] == 0 || ProcName[0] == 0)
		return NULL;
	FARPROC result = NULL;
	EnterCriticalSection(&DllLock);
	std::map<std::wstring,DllStruct>::iterator itor1 = DllMap.find(DllPath);
	if(itor1 != DllMap.end())
	{
		std::map<std::wstring,FARPROC>::iterator itor2 = (*itor1).second.FuncMap.find(ProcName);
		if(itor2 != (*itor1).second.FuncMap.end())
		{
			result = (*itor2).second;
		}
	}
	LeaveCriticalSection(&DllLock);
	return result;
}

BOOL WINAPI FreeLibraryTA(LPCSTR DllPath)
{
	ANSI_STRING DllPathA;
	UNICODE_STRING DllPathW;
	NTSTATUS status;
	if(!DllPath || DllPath[0] == 0)
		return FALSE;
	WCHAR tmp[0x1000];
	memset(tmp,0,sizeof(tmp));
	RtlInitAnsiString(&DllPathA,DllPath);
	DllPathW.Buffer = tmp;
	DllPathW.MaximumLength = 0x1000;
	status = RtlAnsiStringToUnicodeString(&DllPathW,&DllPathA,FALSE);
	if(!NT_SUCCESS(status))
		return FALSE;
	return FreeLibraryTW(DllPathW.Buffer);
}

BOOL WINAPI FreeLibraryTW(LPCWSTR DllPath)
{
	BOOL result = FALSE;
	if(!DllPath || DllPath[0] == 0)
		return FALSE;

	EnterCriticalSection(&DllLock);
	std::map<std::wstring,DllStruct>::iterator itor = DllMap.find(DllPath);
	if(itor == DllMap.end())
	{
		result = FALSE;
		goto ENDFREE;
	}

	NTSTATUS Status;
	PVOID BaseAddress = (*itor).second.ViewBase;
	PVOID EntryPoint = (*itor).second.EntryPoint;

	((PDLL_INIT_ROUTINE)EntryPoint)(BaseAddress,DLL_PROCESS_ATTACH,NULL);
	Status = NtUnmapViewOfSection(((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess*/, BaseAddress);
	if(NT_SUCCESS(Status))
		result = TRUE;
	DllMap.erase(itor);
ENDFREE:
	LeaveCriticalSection(&DllLock);
	return result;
}

void main()
{
	InitializeCriticalSection(&DllLock);
	LoadLibraryTA("d:\\1.dll");
	FARPROC func=GetProcAddressTA("d:\\1.dll","func");
	((void (__cdecl *)())func)();
}


你可能感兴趣的:(实现自己的LoadLibrary)