Support loading (and running) EXE files (fixes #7).

This commit is contained in:
Joachim Bauch
2014-09-21 18:34:11 +02:00
parent 2d504b533e
commit 5a448ce93a
4 changed files with 119 additions and 17 deletions
+38 -12
View File
@@ -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
View File
@@ -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.
*/
+57
View File
@@ -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();
}
+8 -2
View File
@@ -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