mirror of
https://github.com/vxcontrol/MemoryModule.git
synced 2026-07-20 21:59:45 -04:00
Support loading (and running) EXE files (fixes #7).
This commit is contained in:
+38
-12
@@ -49,20 +49,24 @@
|
||||
|
||||
#include "MemoryModule.h"
|
||||
|
||||
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;
|
||||
int initialized;
|
||||
int isDLL;
|
||||
int isRelocated;
|
||||
CustomLoadLibraryFunc loadLibrary;
|
||||
CustomGetProcAddressFunc getProcAddress;
|
||||
CustomFreeLibraryFunc freeLibrary;
|
||||
void *userdata;
|
||||
ExeEntryProc exeEntry;
|
||||
} MEMORYMODULE, *PMEMORYMODULE;
|
||||
|
||||
typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
|
||||
|
||||
#define GET_HEADER_DICTIONARY(module, idx) &(module)->headers->OptionalHeader.DataDirectory[idx]
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
@@ -202,11 +206,12 @@ ExecuteTLS(PMEMORYMODULE module)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
PerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta)
|
||||
{
|
||||
DWORD i;
|
||||
unsigned char *codeBase = module->codeBase;
|
||||
int result = 0;
|
||||
|
||||
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
|
||||
if (directory->Size > 0) {
|
||||
@@ -254,7 +259,9 @@ PerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta)
|
||||
// advance to next relocation block
|
||||
relocation = (PIMAGE_BASE_RELOCATION) (((char *) relocation) + relocation->SizeOfBlock);
|
||||
}
|
||||
result = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -355,7 +362,6 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data,
|
||||
PIMAGE_NT_HEADERS old_header;
|
||||
unsigned char *code, *headers;
|
||||
SIZE_T locationDelta;
|
||||
DllEntryProc DllEntry;
|
||||
BOOL successfull;
|
||||
|
||||
dos_header = (PIMAGE_DOS_HEADER)data;
|
||||
@@ -410,6 +416,7 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data,
|
||||
result->numModules = 0;
|
||||
result->modules = NULL;
|
||||
result->initialized = 0;
|
||||
result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0;
|
||||
result->loadLibrary = loadLibrary;
|
||||
result->getProcAddress = getProcAddress;
|
||||
result->freeLibrary = freeLibrary;
|
||||
@@ -434,7 +441,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data,
|
||||
// adjust base address of imported data
|
||||
locationDelta = (SIZE_T)(code - old_header->OptionalHeader.ImageBase);
|
||||
if (locationDelta != 0) {
|
||||
PerformBaseRelocation(result, locationDelta);
|
||||
result->isRelocated = PerformBaseRelocation(result, locationDelta);
|
||||
} else {
|
||||
result->isRelocated = 1;
|
||||
}
|
||||
|
||||
// load required dlls and adjust function table of imports
|
||||
@@ -451,14 +460,20 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data,
|
||||
|
||||
// get entry point of loaded library
|
||||
if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) {
|
||||
DllEntry = (DllEntryProc) (code + result->headers->OptionalHeader.AddressOfEntryPoint);
|
||||
// notify library about attaching to process
|
||||
successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);
|
||||
if (!successfull) {
|
||||
SetLastError(ERROR_DLL_INIT_FAILED);
|
||||
goto error;
|
||||
if (result->isDLL) {
|
||||
DllEntryProc DllEntry = (DllEntryProc) (code + result->headers->OptionalHeader.AddressOfEntryPoint);
|
||||
// notify library about attaching to process
|
||||
successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);
|
||||
if (!successfull) {
|
||||
SetLastError(ERROR_DLL_INIT_FAILED);
|
||||
goto error;
|
||||
}
|
||||
result->initialized = 1;
|
||||
} else {
|
||||
result->exeEntry = (ExeEntryProc) (code + result->headers->OptionalHeader.AddressOfEntryPoint);
|
||||
}
|
||||
result->initialized = 1;
|
||||
} else {
|
||||
result->exeEntry = NULL;
|
||||
}
|
||||
|
||||
return (HMEMORYMODULE)result;
|
||||
@@ -549,6 +564,17 @@ void MemoryFreeLibrary(HMEMORYMODULE mod)
|
||||
}
|
||||
}
|
||||
|
||||
int MemoryCallEntryPoint(HMEMORYMODULE mod)
|
||||
{
|
||||
PMEMORYMODULE module = (PMEMORYMODULE)mod;
|
||||
|
||||
if (module == NULL || module->isDLL || module->exeEntry == NULL || !module->isRelocated) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return module->exeEntry();
|
||||
}
|
||||
|
||||
#define DEFAULT_LANGUAGE MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
|
||||
|
||||
HMEMORYRSRC MemoryFindResource(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type)
|
||||
|
||||
+16
-3
@@ -44,7 +44,7 @@ typedef FARPROC (*CustomGetProcAddressFunc)(HCUSTOMMODULE, LPCSTR, void *);
|
||||
typedef void (*CustomFreeLibraryFunc)(HCUSTOMMODULE, void *);
|
||||
|
||||
/**
|
||||
* Load DLL from memory location.
|
||||
* Load EXE/DLL from memory location.
|
||||
*
|
||||
* All dependencies are resolved using default LoadLibrary/GetProcAddress
|
||||
* calls through the Windows API.
|
||||
@@ -52,7 +52,7 @@ typedef void (*CustomFreeLibraryFunc)(HCUSTOMMODULE, void *);
|
||||
HMEMORYMODULE MemoryLoadLibrary(const void *);
|
||||
|
||||
/**
|
||||
* Load DLL from memory location using custom dependency resolvers.
|
||||
* Load EXE/DLL from memory location using custom dependency resolvers.
|
||||
*
|
||||
* Dependencies will be resolved using passed callback methods.
|
||||
*/
|
||||
@@ -68,10 +68,23 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *,
|
||||
FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR);
|
||||
|
||||
/**
|
||||
* Free previously loaded DLL.
|
||||
* Free previously loaded EXE/DLL.
|
||||
*/
|
||||
void MemoryFreeLibrary(HMEMORYMODULE);
|
||||
|
||||
/**
|
||||
* Execute entry point (EXE only). The entry point can only be executed
|
||||
* if the EXE has been loaded to the correct base address or it could
|
||||
* be relocated (i.e. relocation information have not been stripped by
|
||||
* the linker).
|
||||
*
|
||||
* Important: calling this function will not return, i.e. once the loaded
|
||||
* EXE finished running, the process will terminate.
|
||||
*
|
||||
* Returns a negative value if the entry point could not be executed.
|
||||
*/
|
||||
int MemoryCallEntryPoint(HMEMORYMODULE);
|
||||
|
||||
/**
|
||||
* Find the location of a resource with the specified type and name.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "../../MemoryModule.h"
|
||||
|
||||
#define EXE_FILE TEXT("DllLoader.exe")
|
||||
|
||||
int RunFromMemory(void)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned char *data=NULL;
|
||||
size_t size;
|
||||
HMEMORYMODULE handle;
|
||||
int result = -1;
|
||||
|
||||
fp = _tfopen(EXE_FILE, _T("rb"));
|
||||
if (fp == NULL)
|
||||
{
|
||||
_tprintf(_T("Can't open executable \"%s\"."), EXE_FILE);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size = ftell(fp);
|
||||
data = (unsigned char *)malloc(size);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
fread(data, 1, size, fp);
|
||||
fclose(fp);
|
||||
|
||||
handle = MemoryLoadLibrary(data);
|
||||
if (handle == NULL)
|
||||
{
|
||||
_tprintf(_T("Can't load library from memory.\n"));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
result = MemoryCallEntryPoint(handle);
|
||||
if (result < 0) {
|
||||
_tprintf(_T("Could not execute entry point: %d\n"), result);
|
||||
}
|
||||
MemoryFreeLibrary(handle);
|
||||
|
||||
exit:
|
||||
if (data)
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
return RunFromMemory();
|
||||
}
|
||||
|
||||
@@ -22,9 +22,15 @@ CFLAGS += -DUNICODE -D_UNICODE
|
||||
endif
|
||||
|
||||
OBJ = DllLoader.o ../../MemoryModule.o
|
||||
OBJ_LOADER = DllLoaderLoader.o ../../MemoryModule.o
|
||||
|
||||
all: DllLoader.exe DllLoaderLoader.exe
|
||||
|
||||
DllLoader.exe: $(OBJ)
|
||||
$(CC) $(LDFLAGS) -o DllLoader.exe $(OBJ)
|
||||
$(CC) $(LDFLAGS) -Wl,--image-base -Wl,0x20000000 -o DllLoader.exe $(OBJ)
|
||||
|
||||
DllLoaderLoader.exe: $(OBJ_LOADER)
|
||||
$(CC) $(LDFLAGS) -Wl,--image-base -Wl,0x10000000 -o DllLoaderLoader.exe $(OBJ_LOADER)
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c $<
|
||||
@@ -33,4 +39,4 @@ DllLoader.exe: $(OBJ)
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
clean:
|
||||
$(RM) -rf $(OBJ) DllLoader.exe
|
||||
$(RM) -rf $(OBJ) $(OBJ_LOADER) DllLoader.exe DllLoaderLoader.exe
|
||||
|
||||
Reference in New Issue
Block a user