实现自己的LoadLibrary
决定实现自己的loadlibrary,已经实现大部分,然而在模拟执行dllmain时却发生异常,查找发现加载的dll导入表没有初始化。不明白这段代码在哪里实现的,正在研究中,功亏一篑啊
该代码完全独立于ldr结构,并用map结构一次映射所有函数,不需要getproc一个个进行查找,LoadLibary只需要传入完整dll路径
GetProcAddress只需要dll路径以及函数名即可获得函数地址,这部分功能测试正常,500行代码
而输出表部分,很奇怪,懂得高人指点一下:
#include <windows.h>
#include <winternl.h>
#include <map>
#include <string>
using namespace std;
#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);
};
ULONG NTAPI LdrRelocateImageWithBias(PVOID,PIMAGE_NT_HEADERS,LONGLONG ,PCCH,ULONG,ULONG,ULONG);
NTSTATUS NTAPI LdrpSetProtection(PVOID,PIMAGE_NT_HEADERS,BOOLEAN);
#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)
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
{
DWORD flags;
PVOID Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS 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
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);
BOOL WINAPI LoadLibraryTA(LPCSTR DllPath)
{
ANSI_STRING DllPathA;
UNICODE_STRING DllPathW;
NTSTATUS status;
if(!DllPath || DllPath == 0)
return FALSE;
WCHAR tmp;
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 WINAPI LoadLibraryTW(LPCWSTR DllPath)
{
if(!DllPath || DllPath == 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)-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->OptionalHeader.AddressOfEntryPoint == NULL || !(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL))
{
result = FALSE;
goto ENDLOAD;
}
EntryPoint = (PVOID)(NtHeaders->OptionalHeader.AddressOfEntryPoint + (BYTE*)ViewBase);
}
if(Status == STATUS_IMAGE_NOT_AT_BASE)
{//重定位
if(!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED))
{
USHORT Directory = IMAGE_DIRECTORY_ENTRY_BASERELOC;
ULONG RelocDataSize = 0;
PVOID RelocData = NULL;
if(NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
{
PIMAGE_NT_HEADERS32 tpnh = (PIMAGE_NT_HEADERS32)NtHeaders;
if(Directory >= tpnh->OptionalHeader.NumberOfRvaAndSizes)
return NULL;
DWORD VA = tpnh->OptionalHeader.DataDirectory.VirtualAddress;
if(VA == NULL)
return NULL;
RelocDataSize = tpnh->OptionalHeader.DataDirectory.Size;
RelocData = (PVOID)((BYTE*)ViewBase + VA);
}
else
{
PIMAGE_NT_HEADERS64 tpnh = (PIMAGE_NT_HEADERS64)NtHeaders;
if(Directory >= tpnh->OptionalHeader.NumberOfRvaAndSizes)
return NULL;
DWORD VA = tpnh->OptionalHeader.DataDirectory.VirtualAddress;
if(VA == NULL)
return NULL;
RelocDataSize = tpnh->OptionalHeader.DataDirectory.Size;
RelocData = (PVOID)((BYTE*)ViewBase + VA);
}
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)-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;
ds.EntryPoint = EntryPoint;
ds.ViewBase = ViewBase;
ds.ViewSize = ViewSize;
{
typedef BOOLEAN (WINAPI *PDLL_INIT_ROUTINE)( PVOID DllHandle,ULONG Reason,PCONTEXT Context );
// ((PDLL_INIT_ROUTINE)EntryPoint)(ViewBase,DLL_PROCESS_ATTACH,NULL);
PVOID BaseAddress = ViewBase;
USHORT Directory = IMAGE_DIRECTORY_ENTRY_EXPORT;
PIMAGE_EXPORT_DIRECTORY ExportDir = NULL;
ULONG ExportDirSize = 0;
if(NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
{
PIMAGE_NT_HEADERS32 tpnh = (PIMAGE_NT_HEADERS32)NtHeaders;
if(Directory >= tpnh->OptionalHeader.NumberOfRvaAndSizes)
return NULL;
DWORD VA = tpnh->OptionalHeader.DataDirectory.VirtualAddress;
if(VA == NULL)
return NULL;
ExportDirSize = tpnh->OptionalHeader.DataDirectory.Size;
ExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)ViewBase + VA);
}
else
{
PIMAGE_NT_HEADERS64 tpnh = (PIMAGE_NT_HEADERS64)NtHeaders;
if(Directory >= tpnh->OptionalHeader.NumberOfRvaAndSizes)
return NULL;
DWORD VA = tpnh->OptionalHeader.DataDirectory.VirtualAddress;
if(VA == NULL)
return NULL;
ExportDirSize = tpnh->OptionalHeader.DataDirectory.Size;
ExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)ViewBase + VA);
}
PULONG NameTable = (PULONG)((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNames);
PUSHORT OrdinalTable = (PUSHORT)((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNameOrdinals);
PULONG AddressOfFunctions = (PULONG)((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfFunctions);
USHORT Ordinal = -1;
for(LONG i = 0;i < ExportDir->NumberOfNames;i++)
{
PCHAR FuncName = (PCHAR)((ULONG_PTR)BaseAddress + NameTable);
ANSI_STRING FuncNameA;
UNICODE_STRING FuncNameW;
WCHAR tmp;
memset(tmp,0,sizeof(tmp));
RtlInitAnsiString(&FuncNameA,FuncName);
FuncNameW.Buffer = tmp;
FuncNameW.MaximumLength = 0x1000;
Status = RtlAnsiStringToUnicodeString(&FuncNameW,&FuncNameA,FALSE);
if(NT_SUCCESS(Status))
{
Ordinal = OrdinalTable;
if(Ordinal >=0 && Ordinal < ExportDir->NumberOfFunctions)
{
ULONG_PTR Function = (ULONG_PTR)BaseAddress + AddressOfFunctions;
if(!(Function > (ULONG_PTR)ExportDir && Function < (ULONG_PTR)ExportDir + ExportDirSize))
{
ds.FuncMap = (FARPROC)Function;
}
}
}
}
}
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;
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) ((ULONG_PTR)(ntheader) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + ((ntheader))->FileHeader.SizeOfOptionalHeader ))
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)-1,&SectionBase,&SectionSize,NewProtection,&OldProtection);
if (!NT_SUCCESS(Status)) return Status;
}
}
Section++;
}
if (Restore) NtFlushInstructionCache((HANDLE)-1, NULL, 0);
return STATUS_SUCCESS;
}
ULONG NTAPI LdrRelocateImageWithBias(PVOID BaseAddress,PIMAGE_NT_HEADERS NtHeaders,LONGLONG AdditionalBias,PCCHLoaderName,ULONG Success,ULONG Conflict,ULONG Invalid)
{
#define SWAPW(x) (x)
#define SWAPD(x) (x)
#define SWAPQ(x) (x)
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;
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)(RelocationDir->VirtualAddress);
TypeOffset = (PUSHORT)(RelocationDir + 1);
for (ULONG i = 0; i < Count; i++)
{
Offset = SWAPW(*TypeOffset) & 0xFFF;
Type = SWAPW(*TypeOffset) >> 12;
ShortPtr = (PUSHORT)Offset;
if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir || (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
continue;
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)Offset;
*LongPtr = SWAPD(*LongPtr) + (Delta & 0xFFFFFFFF);
break;
case IMAGE_REL_BASED_DIR64:
LongLongPtr = (PUINT64)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 || ProcName == 0)
return NULL;
WCHAR tmp1,tmp2;
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 || ProcName == 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)
return FALSE;
WCHAR tmp;
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)
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;
typedef BOOLEAN (WINAPI *PDLL_INIT_ROUTINE)( PVOID DllHandle,ULONG Reason,PCONTEXT Context );
((PDLL_INIT_ROUTINE)EntryPoint)(BaseAddress,DLL_PROCESS_ATTACH,NULL);
Status = NtUnmapViewOfSection((HANDLE)-1, BaseAddress);
if(NT_SUCCESS(Status))
result = TRUE;
ENDFREE:
LeaveCriticalSection(&DllLock);
return result;
}
void main()
{
InitializeCriticalSection(&DllLock);
LoadLibraryTA("d:\\1.dll");
FARPROC func=GetProcAddressTA("d:\\1.dll","func");
((void (__cdecl *)())func)();
}
完善后的代码,,可以弹出MessageBox
#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);
ANSI_STRING FuncNameA;
UNICODE_STRING FuncNameW;
WCHAR tmp;
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;
if(Ordinal >=0 && Ordinal < ExportDir->NumberOfFunctions)
{
ULONG_PTR Function = (ULONG_PTR)ViewBase + AddressOfFunctions;
if(!(Function > (ULONG_PTR)ExportDir && Function < (ULONG_PTR)ExportDir + ExportDirSize))
{
ds->FuncMap = (FARPROC)Function;
}
}
}
}
}
BOOL WINAPI LoadLibraryTA(LPCSTR DllPath)
{
ANSI_STRING DllPathA;
UNICODE_STRING DllPathW;
NTSTATUS status;
if(!DllPath || DllPath == 0)
return FALSE;
WCHAR tmp;
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;
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.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;
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.VirtualAddress;
if(VA)
{
*RelocDataSize = tpnh->OptionalHeader.DataDirectory.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.VirtualAddress;
if(VA)
{
*RelocDataSize = tpnh->OptionalHeader.DataDirectory.Size;
*RelocData = (PVOID)((BYTE*)ViewBase + VA);
}
}
}
}
BOOL WINAPI LoadLibraryTW(LPCWSTR DllPath)
{
if(!DllPath || DllPath == 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;
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;
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,PCCHLoaderName,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;
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 || ProcName == 0)
return NULL;
WCHAR tmp1,tmp2;
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 || ProcName == 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)
return FALSE;
WCHAR tmp;
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)
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)();
} 你可以去看看memorymodule
页:
[1]