1. Add Win10 forward export support

2. Fixed some bugs
This commit is contained in:
Boring
2020-02-22 14:53:26 +08:00
parent ea135ac392
commit ed550ae6c7
15 changed files with 764 additions and 175 deletions
+61 -55
View File
@@ -4,6 +4,7 @@
#include <tchar.h>
#include "rtltype.h"
#include "ntstatus.h"
#include "Native.h"
#include <algorithm>
#if _MSC_VER
@@ -134,7 +135,7 @@ static BOOL CheckSize(size_t size, size_t expected) {
return TRUE;
}
static BOOL CopySections(const unsigned char* data, size_t size, PMEMORYMODULE module) {
static BOOL CopySections(const unsigned char* data, PMEMORYMODULE module) {
LPBYTE codeBase = module->codeBase;
LPVOID dest;
PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module);
@@ -145,7 +146,12 @@ static BOOL CopySections(const unsigned char* data, size_t size, PMEMORYMODULE m
alloc_size = headers->OptionalHeader.SectionAlignment;
cp = false;
if (section->SizeOfRawData) {
if (!CheckSize(size, static_cast<size_t>(section->PointerToRawData) + section->SizeOfRawData)) return FALSE;
__try {
ProbeForRead(data, static_cast<size_t>(section->PointerToRawData) + section->SizeOfRawData);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
alloc_size = section->SizeOfRawData;
cp = true;
}
@@ -354,15 +360,23 @@ static BOOL BuildImportTable(PMEMORYMODULE module) {
return result;
}
HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) {
//static BOOL PerformForwardExport(PMEMORYMODULE module) {
// PIMAGE_EXPORT_DIRECTORY exports;
// PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module);
// PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(headers, IMAGE_DIRECTORY_ENTRY_EXPORT);
// if (!directory->Size)return TRUE;
// return FALSE;
//
//}
HMEMORYMODULE MemoryLoadLibrary(const void* data) {
PMEMORYMODULE hMemoryModule = nullptr;
PIMAGE_DOS_HEADER dos_header, new_dos_header;
PIMAGE_NT_HEADERS old_header, new_header;
unsigned char* code;
unsigned char* base;
ptrdiff_t locationDelta;
SYSTEM_INFO sysInfo;
static SYSTEM_INFO sysInfo{};
PIMAGE_SECTION_HEADER section;
DWORD i;
size_t optionalSectionSize;
size_t lastSectionEnd = 0;
size_t alignedImageSize;
@@ -371,40 +385,36 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) {
POINTER_LIST* blockedMemory = nullptr;
#endif
if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) return nullptr;
dos_header = (PIMAGE_DOS_HEADER)data;
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
__try {
ProbeForRead(data, sizeof(IMAGE_DOS_HEADER));
dos_header = (PIMAGE_DOS_HEADER)data;
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return nullptr;
}
ProbeForRead(data, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS));
old_header = (PIMAGE_NT_HEADERS)((size_t)data + dos_header->e_lfanew);
if (old_header->Signature != IMAGE_NT_SIGNATURE ||
!ProbeForRead(data, old_header->OptionalHeader.SizeOfHeaders) ||
old_header->FileHeader.Machine != HOST_MACHINE ||
old_header->OptionalHeader.SectionAlignment & 1) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return nullptr;
}
//only dll image support
if (!(old_header->FileHeader.Characteristics & IMAGE_FILE_DLL)) {
SetLastError(ERROR_NOT_SUPPORTED);
return nullptr;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_INVALID_DATA);
return nullptr;
}
if (!CheckSize(size, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS))) return nullptr;
old_header = (PIMAGE_NT_HEADERS) & ((const unsigned char*)(data))[dos_header->e_lfanew];
if (old_header->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return nullptr;
}
if (old_header->FileHeader.Machine != HOST_MACHINE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return nullptr;
}
if (old_header->OptionalHeader.SectionAlignment & 1) {
// Only support section alignments that are a multiple of 2
SetLastError(ERROR_BAD_EXE_FORMAT);
return nullptr;
}
//only dll image support
if (!(old_header->FileHeader.Characteristics & IMAGE_FILE_DLL)) {
SetLastError(ERROR_NOT_SUPPORTED);
return nullptr;
}
section = IMAGE_FIRST_SECTION(old_header);
optionalSectionSize = old_header->OptionalHeader.SectionAlignment;
for (i = 0; i < old_header->FileHeader.NumberOfSections; i++, section++) {
for (DWORD i = 0; i < old_header->FileHeader.NumberOfSections; i++, section++) {
size_t endOfSection;
if (section->SizeOfRawData == 0) {
// Section without data in the DLL
@@ -419,7 +429,7 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) {
}
}
GetNativeSystemInfo(&sysInfo);
if (!sysInfo.dwPageSize)GetNativeSystemInfo(&sysInfo);
alignedImageSize = AlignValueUp(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize);
if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) {
SetLastError(ERROR_BAD_EXE_FORMAT);
@@ -430,12 +440,12 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) {
// reserve memory for image of library
// XXX: is it correct to commit the complete memory region at once?
// calling DllEntry raises an exception if we don't...
if (!(code = (LPBYTE)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase), alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) {
if (!(base = (LPBYTE)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase), alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) {
if (!(old_header->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return nullptr;
}
if (!(code = (LPBYTE)VirtualAlloc(nullptr, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) {
if (!(base = (LPBYTE)VirtualAlloc(nullptr, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) {
SetLastError(ERROR_OUTOFMEMORY);
return nullptr;
}
@@ -443,20 +453,20 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) {
#ifdef _WIN64
// Memory block may not span 4 GB boundaries.
while ((((uintptr_t)code) >> 32) < (((uintptr_t)(code + alignedImageSize)) >> 32)) {
while ((((uintptr_t)base) >> 32) < (((uintptr_t)(base + alignedImageSize)) >> 32)) {
POINTER_LIST* node = new POINTER_LIST;
if (!node) {
VirtualFree(code, 0, MEM_RELEASE);
VirtualFree(base, 0, MEM_RELEASE);
FreePointerList(blockedMemory);
SetLastError(ERROR_OUTOFMEMORY);
return nullptr;
}
node->next = blockedMemory;
node->address = code;
node->address = base;
blockedMemory = node;
if (!(code = (LPBYTE)VirtualAlloc(nullptr, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) {
if (!(base = (LPBYTE)VirtualAlloc(nullptr, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) {
FreePointerList(blockedMemory);
SetLastError(ERROR_OUTOFMEMORY);
return nullptr;
@@ -464,11 +474,11 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) {
}
#endif
new_dos_header = (PIMAGE_DOS_HEADER)code;
new_header = (PIMAGE_NT_HEADERS)(code + dos_header->e_lfanew);
hMemoryModule = (PMEMORYMODULE)(code + old_header->OptionalHeader.SizeOfHeaders);
new_dos_header = (PIMAGE_DOS_HEADER)base;
new_header = (PIMAGE_NT_HEADERS)(base + dos_header->e_lfanew);
hMemoryModule = (PMEMORYMODULE)(base + old_header->OptionalHeader.SizeOfHeaders);
RtlZeroMemory(hMemoryModule, sizeof(MEMORYMODULE));
hMemoryModule->codeBase = code;
hMemoryModule->codeBase = base;
hMemoryModule->pageSize = sysInfo.dwPageSize;
hMemoryModule->Signature = MEMORY_MODULE_SIGNATURE;
hMemoryModule->SizeofHeaders = old_header->OptionalHeader.SizeOfHeaders;
@@ -477,18 +487,14 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) {
hMemoryModule->blockedMemory = blockedMemory;
#endif
if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) {
goto error;
}
// copy PE header to code
memcpy(new_dos_header, dos_header, old_header->OptionalHeader.SizeOfHeaders);
new_header->OptionalHeader.SizeOfImage = (DWORD)(alignedImageSize);
new_header->OptionalHeader.ImageBase = (size_t)code;
new_header->OptionalHeader.ImageBase = (size_t)base;
new_header->OptionalHeader.BaseOfCode = headers_align;
// copy sections from DLL file block to new memory location
if (!CopySections((LPBYTE)data, size, hMemoryModule)) goto error;
if (!CopySections((LPBYTE)data, hMemoryModule)) goto error;
// adjust base address of imported data
locationDelta = (ptrdiff_t)(hMemoryModule->codeBase - old_header->OptionalHeader.ImageBase);
@@ -509,7 +515,7 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) {
if (new_header->OptionalHeader.AddressOfEntryPoint) {
__try {
// notify library about attaching to process
if (!((DllEntryProc)(code + new_header->OptionalHeader.AddressOfEntryPoint))((HINSTANCE)code, DLL_PROCESS_ATTACH, 0)) {
if (!((DllEntryProc)(base + new_header->OptionalHeader.AddressOfEntryPoint))((HINSTANCE)base, DLL_PROCESS_ATTACH, 0)) {
SetLastError(ERROR_DLL_INIT_FAILED);
goto error;
}
@@ -521,7 +527,7 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) {
hMemoryModule->initialized = TRUE;
}
return code;
return base;
error:
// cleanup
MemoryFreeLibrary(hMemoryModule);