diff --git a/README.md b/README.md index 07065be..55eba2c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ An experiment to try and write a minimal, low-fuss wrapper that can run really s Don't run this on any untrusted executables, I implore you. (Or probably just don't run it at all... :p) - g++ -g -m32 -std=c++20 -lstdc++ main.cpp kernel32.cpp advapi32.cpp loader.cpp + g++ -g -m32 -std=c++20 -lstdc++ main.cpp version.cpp user32.cpp kernel32.cpp advapi32.cpp loader.cpp If you need something like this project (but more mature), you might find [taviso/loadlibrary](https://github.com/taviso/loadlibrary) more interesting. diff --git a/common.h b/common.h index aa07c6a..bdcdcec 100644 --- a/common.h +++ b/common.h @@ -3,6 +3,7 @@ #include #include #include +#include #define WIN_FUNC __attribute__((stdcall)) @@ -10,7 +11,9 @@ namespace wibo { extern uint32_t lastError; extern char *commandLine; + void *resolveVersion(const char *name); void *resolveKernel32(const char *name); + void *resolveUser32(const char *name); void *resolveAdvApi32(const char *name); void *resolveStubByName(const char *dllName, const char *funcName); void *resolveStubByOrdinal(const char *dllName, uint16_t ordinal); diff --git a/kernel32.cpp b/kernel32.cpp index 223c969..c66598a 100644 --- a/kernel32.cpp +++ b/kernel32.cpp @@ -291,6 +291,60 @@ namespace kernel32 { strcpy(lpBuffer, "C:\\Windows"); return strlen(lpBuffer); } + + unsigned int WIN_FUNC GetCurrentDirectoryA(unsigned int uSize, char *lpBuffer) { + printf("GetCurrentDirectoryA\n"); + + std::filesystem::path cwd = std::filesystem::current_path(); + std::string path = pathToWindows(cwd); + + assert(path.size() < uSize); + + strcpy(lpBuffer, path.c_str()); + return path.size(); + } + + void* WIN_FUNC GetModuleHandleA(const char* lpModuleName) { + printf("GetModuleHandleA %s\n", lpModuleName); + // wibo::lastError = 0; + return (void*)1; + } + + unsigned int WIN_FUNC GetModuleFileNameA(void* hModule, char* lpFilename, unsigned int nSize) { + printf("GetModuleFileNameA %p\n", hModule); + wibo::lastError = 0; + return 0; + } + + void* WIN_FUNC FindResourceA(void* hModule, const char* lpName, const char* lpType) { + printf("FindResourceA %p %s %s\n", hModule, lpName, lpType); + return (void*)2; + } + + void* WIN_FUNC LoadResource(void* hModule, void* res) { + printf("LoadResource %p %p\n", hModule, res); + return (void*)3; + } + + void* WIN_FUNC LockResource(void* res) { + printf("LockResource %p\n", res); + return (void*)4; + } + + unsigned int WIN_FUNC SizeofResource(void* hModule, void* res) { + printf("SizeofResource %p %p\n", hModule, res); + return 0; + } + + void* WIN_FUNC LoadLibraryA(const char* lpLibFileName) { + printf("LoadLibraryA %s\n", lpLibFileName); + return (void*)5; + } + + int WIN_FUNC FreeLibrary(void* hLibModule) { + printf("FreeLibrary %p\n", hLibModule); + return 1; + } } void *wibo::resolveKernel32(const char *name) { @@ -318,5 +372,14 @@ void *wibo::resolveKernel32(const char *name) { if (strcmp(name, "GetConsoleScreenBufferInfo") == 0) return (void *) kernel32::GetConsoleScreenBufferInfo; if (strcmp(name, "GetSystemDirectoryA") == 0) return (void *) kernel32::GetSystemDirectoryA; if (strcmp(name, "GetWindowsDirectoryA") == 0) return (void *) kernel32::GetWindowsDirectoryA; + if (strcmp(name, "GetCurrentDirectoryA") == 0) return (void *) kernel32::GetCurrentDirectoryA; + if (strcmp(name, "GetModuleHandleA") == 0) return (void *) kernel32::GetModuleHandleA; + if (strcmp(name, "GetModuleFileNameA") == 0) return (void *) kernel32::GetModuleFileNameA; + if (strcmp(name, "FindResourceA") == 0) return (void *) kernel32::FindResourceA; + if (strcmp(name, "LoadResource") == 0) return (void *) kernel32::LoadResource; + if (strcmp(name, "LockResource") == 0) return (void *) kernel32::LockResource; + if (strcmp(name, "SizeofResource") == 0) return (void *) kernel32::SizeofResource; + if (strcmp(name, "LoadLibraryA") == 0) return (void *) kernel32::LoadLibraryA; + if (strcmp(name, "FreeLibrary") == 0) return (void *) kernel32::FreeLibrary; return 0; } diff --git a/loader.cpp b/loader.cpp index 32ffabe..4e30f5d 100644 --- a/loader.cpp +++ b/loader.cpp @@ -139,7 +139,7 @@ bool wibo::Executable::loadPE(FILE *file) { printf("Image Base: %x / Size: %x\n", header32.imageBase, header32.sizeOfImage); long pageSize = sysconf(_SC_PAGE_SIZE); - printf("Page size: %x\n", pageSize); + printf("Page size: %x\n", (unsigned int)pageSize); // Build buffer imageSize = header32.sizeOfImage; diff --git a/main.cpp b/main.cpp index 3bcd930..41a75d0 100644 --- a/main.cpp +++ b/main.cpp @@ -8,13 +8,32 @@ uint32_t wibo::lastError = 0; char *wibo::commandLine; -void stub() { +static int stubIndex = 0; +static char stubDlls[0x100][0x100]; +static char stubFuncNames[0x100][0x100]; + +static void stubBase(int index) { // should go through all the functions imported by mwcceppc.exe // and create template stubs for them, at least... - printf("Unhandled function\n"); + printf("Unhandled function %s (%s)\n", stubFuncNames[index], stubDlls[index]); exit(0); } +void (*stubFuncs[0x100])(void) = { +#define DEFINE_STUB(a, b, c, d) []() { stubBase(a << 6 | b << 4 | c << 2 | d); }, +#define DEFINE_STUBS(a, b) \ + DEFINE_STUB(a, b, 0, 0) DEFINE_STUB(a, b, 0, 1) DEFINE_STUB(a, b, 0, 2) DEFINE_STUB(a, b, 0, 3) \ + DEFINE_STUB(a, b, 1, 0) DEFINE_STUB(a, b, 1, 1) DEFINE_STUB(a, b, 1, 2) DEFINE_STUB(a, b, 1, 3) \ + DEFINE_STUB(a, b, 2, 0) DEFINE_STUB(a, b, 2, 1) DEFINE_STUB(a, b, 2, 2) DEFINE_STUB(a, b, 2, 3) \ + DEFINE_STUB(a, b, 3, 0) DEFINE_STUB(a, b, 3, 1) DEFINE_STUB(a, b, 3, 2) DEFINE_STUB(a, b, 3, 3) +DEFINE_STUBS(0, 0) DEFINE_STUBS(0, 1) DEFINE_STUBS(0, 2) DEFINE_STUBS(0, 3) +DEFINE_STUBS(1, 0) DEFINE_STUBS(1, 1) DEFINE_STUBS(1, 2) DEFINE_STUBS(1, 3) +DEFINE_STUBS(2, 0) DEFINE_STUBS(2, 1) DEFINE_STUBS(2, 2) DEFINE_STUBS(2, 3) +DEFINE_STUBS(3, 0) DEFINE_STUBS(3, 1) DEFINE_STUBS(3, 2) DEFINE_STUBS(3, 3) +}; +#undef DEFINE_STUB +#undef DEFINE_STUBS + uint32_t __attribute__((stdcall)) CoInitialize(void *pvReserved) { printf("CoInitialize(...)\n"); return 0; // S_OK I think? @@ -26,21 +45,41 @@ void *wibo::resolveStubByName(const char *dllName, const char *funcName) { if (func) return func; } + if (strcmp(dllName, "USER32.dll") == 0) { + void *func = wibo::resolveUser32(funcName); + if (func) + return func; + } if (strcmp(dllName, "ADVAPI32.dll") == 0) { void *func = wibo::resolveAdvApi32(funcName); if (func) return func; } + if (strcmp(dllName, "VERSION.dll") == 0) { + void *func = wibo::resolveVersion(funcName); + if (func) + return func; + } if (strcmp(dllName, "ole32.dll") == 0) { if (strcmp(funcName, "CoInitialize") == 0) return (void *) CoInitialize; } printf("Missing function: %s (%s)\n", dllName, funcName); - return (void *) stub; + assert(stubIndex < 0x100); + assert(strlen(dllName) < 0x100); + assert(strlen(funcName) < 0x100); + strcpy(stubFuncNames[stubIndex], funcName); + strcpy(stubDlls[stubIndex], dllName); + return (void *) stubFuncs[stubIndex++]; } void *wibo::resolveStubByOrdinal(const char *dllName, uint16_t ordinal) { - return (void *) stub; + // printf("Missing function: %s (%x)\n", dllName, ordinal); + assert(stubIndex < 0x100); + assert(strlen(dllName) < 0x100); + sprintf(stubFuncNames[stubIndex], "%d", ordinal); + strcpy(stubDlls[stubIndex], dllName); + return (void *) stubFuncs[stubIndex++]; } // Windows Thread Information Block diff --git a/user32.cpp b/user32.cpp new file mode 100644 index 0000000..e4877c8 --- /dev/null +++ b/user32.cpp @@ -0,0 +1,13 @@ +#include "common.h" + +namespace user32 { + int WIN_FUNC LoadStringA(void* hInstance, unsigned int uID, char* lpBuffer, int cchBufferMax) { + printf("LoadStringA %p %d %d\n", hInstance, uID, cchBufferMax); + return 0; + } +} + +void *wibo::resolveUser32(const char *name) { + if (strcmp(name, "LoadStringA") == 0) return (void *) user32::LoadStringA; + return 0; +} diff --git a/version.cpp b/version.cpp new file mode 100644 index 0000000..1182785 --- /dev/null +++ b/version.cpp @@ -0,0 +1,16 @@ +#include "common.h" + +namespace version { + unsigned int WIN_FUNC GetFileVersionInfoSizeA(const char* lptstrFilename, unsigned int* outZero) { + printf("GetFileVersionInfoSizeA %s\n", lptstrFilename); + *outZero = 0; + // stub: signal an error + wibo::lastError = 0; + return 0; + } +} + +void *wibo::resolveVersion(const char *name) { + if (strcmp(name, "GetFileVersionInfoSizeA") == 0) return (void *) version::GetFileVersionInfoSizeA; + return 0; +}