From 7cf3ab8580b03315c3c8d1546b64b13510d788d7 Mon Sep 17 00:00:00 2001 From: Daniel Seiller Date: Fri, 1 Mar 2019 01:00:50 +0100 Subject: [PATCH] Added function hooking Cleaned up the injector a bit and added launch-time injection --- ScrapHacks/Injector/Injector/Injector.cpp | 49 ++++++++++++--- ScrapHacks/Injector/Injector/Injector.vcxproj | 3 +- ScrapHacks/ScrapHack/Hook.h | 50 +++++++++++++++ ScrapHacks/ScrapHack/Py_Utils.h | 8 +-- ScrapHacks/ScrapHack/ScrapHack.cpp | 63 +++++++++++++++---- ScrapHacks/ScrapHack/ScrapHack.vcxproj | 1 + .../ScrapHack/ScrapHack.vcxproj.filters | 3 + ScrapHacks/ScrapHack/Scrapland.h | 18 ++++-- ScrapHacks/ScrapHack/Structures.h | 2 +- ScrapHacks/ScrapHack/Util.h | 3 +- ScrapHacks/ScrapHack/dllmain.cpp | 2 + 11 files changed, 166 insertions(+), 36 deletions(-) create mode 100644 ScrapHacks/ScrapHack/Hook.h diff --git a/ScrapHacks/Injector/Injector/Injector.cpp b/ScrapHacks/Injector/Injector/Injector.cpp index 6f97ca8..f235d2c 100644 --- a/ScrapHacks/Injector/Injector/Injector.cpp +++ b/ScrapHacks/Injector/Injector/Injector.cpp @@ -169,7 +169,6 @@ void InjectDll(DWORD PID, bool do_resume = false) cout << "[*] Injecting DLL " << dll_name << " into PID " << PID << endl; cout << "[*] Opening Process Handle" << endl; hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, PID); - PID = GetProcessId(hProc); GetFullPathNameA(dll_name, MAX_PATH, dll_full_path, 0); cout << "[*] Adjusting Privileges of Process" << endl; adjustPrivs(hProc); @@ -216,23 +215,53 @@ void InjectDll(DWORD PID, bool do_resume = false) CloseHandle(hProc); return; } + +vector spawn(char* binary) { + STARTUPINFO startupinfo; + PROCESS_INFORMATION processinfo; + ZeroMemory(&startupinfo, sizeof(startupinfo)); + ZeroMemory(&processinfo, sizeof(processinfo)); + startupinfo.cb = sizeof(startupinfo); + if (!CreateProcessA(NULL, binary, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupinfo, &processinfo)) { + return {}; + } + return { processinfo.hProcess,processinfo.hThread }; +} + int main(int argc, char *argv[]) { string prog; HANDLE hProc = INVALID_HANDLE_VALUE; + HANDLE hThread = INVALID_HANDLE_VALUE; DWORD PID = 0; - GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID); - if (PID == 0) - { - cout << "[*] Waiting for Scrapland to Launch..." << endl; - } - while (PID == 0) - { - Sleep(100); + if ((argc>1)&&fexists(argv[1])) { + cout << "[*] Spawning process for \"" << argv[1] << "\"" << endl; + vector handles = spawn(argv[1]); + if (handles.empty()) { + cout << "[!] Error: " << GetLastErrorAsString() << endl; + return -1; + } + hProc = handles[0]; + hThread = handles[1]; + PID = GetProcessId(hProc); + cout << "[+] Got PID: " << PID << endl; + } else { GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID); + if (PID == 0) + { + cout << "[*] Waiting for Scrapland to Launch..." << endl; + } + while (PID == 0) + { + Sleep(100); + GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID); + } + cout << "[+] Found PID: " << PID << endl; } - cout << "[+] Found PID: " << PID << endl; InjectDll(PID); + if (hThread != INVALID_HANDLE_VALUE) { + while (ResumeThread(hThread)); + } cout << "[*] Done!" << endl; return 0; } diff --git a/ScrapHacks/Injector/Injector/Injector.vcxproj b/ScrapHacks/Injector/Injector/Injector.vcxproj index 0262f32..15a021c 100644 --- a/ScrapHacks/Injector/Injector/Injector.vcxproj +++ b/ScrapHacks/Injector/Injector/Injector.vcxproj @@ -160,6 +160,5 @@ - - + \ No newline at end of file diff --git a/ScrapHacks/ScrapHack/Hook.h b/ScrapHacks/ScrapHack/Hook.h new file mode 100644 index 0000000..8c33603 --- /dev/null +++ b/ScrapHacks/ScrapHack/Hook.h @@ -0,0 +1,50 @@ +#pragma once +#include +class Hook; + +map> hooks; + +class Hook { +private: + DWORD protect; + void* orig; + void* detour; + uint8_t orig_bytes[6]; + uint8_t jmp_bytes[6]; +public: + Hook(void* func, void* detour) { + cout << "Hooking: " << func << " -> " << detour << endl; + uintptr_t dest = reinterpret_cast(detour); + uintptr_t src = reinterpret_cast(func); + this->orig = func; + this->detour = detour; + this->jmp_bytes[0] = 0x68; // push + this->jmp_bytes[1] = (dest >> 0) & 0xff; + this->jmp_bytes[2] = (dest >> 8) & 0xff; + this->jmp_bytes[3] = (dest >> 16) & 0xff; + this->jmp_bytes[4] = (dest >> 24) & 0xff; + this->jmp_bytes[5] = 0xC3; // ret + VirtualProtect(func, 16, PAGE_EXECUTE_READWRITE, &(this->protect)); + memcpy(this->orig_bytes, this->orig, 1 + 4 + 1); + memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); + hooks[src]=shared_ptr(this); + } + + ~Hook() { + cout << "Unhooking: " << this->detour << " -> " << this->orig << endl; + uintptr_t src = reinterpret_cast(this->orig); + memcpy(this->orig, this->orig_bytes, 1 + 4 + 1); + } + + void disable() { + memcpy(this->orig, this->orig_bytes, 1 + 4 + 1); + } + void enable() { + memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); + } + + void* func() { + return this->orig; + } + +}; diff --git a/ScrapHacks/ScrapHack/Py_Utils.h b/ScrapHacks/ScrapHack/Py_Utils.h index e78e4d0..d6624af 100644 --- a/ScrapHacks/ScrapHack/Py_Utils.h +++ b/ScrapHacks/ScrapHack/Py_Utils.h @@ -13,7 +13,7 @@ PyMethodDef *find_method_table(uintptr_t base, uintptr_t needle) return reinterpret_cast(mod_addr); } } - return reinterpret_cast(0); + return reinterpret_cast(0); } map get_modules(uintptr_t base) @@ -27,7 +27,7 @@ map get_modules(uintptr_t base) PyMethodDef *method_table = find_method_table((size_t)modules[i].init_func, reinterpret_cast(modules[i].name)); for (size_t j = 0; method_table != NULL && method_table[j].ml_name != NULL; j++) { - mod.methods[method_table[j].ml_name] = method_table[j]; + mod.methods[method_table[j].ml_name] = &method_table[j]; } Py[mod.mod->name] = mod; } @@ -38,7 +38,7 @@ void *get_py(const char *mod, const char *meth) { try { - return Py.at(mod).methods.at(meth).ml_meth; + return Py.at(mod).methods.at(meth)->ml_meth; } catch (out_of_range) { @@ -51,7 +51,7 @@ void inject(const char *mod, const char *meth, void *detour) try { void *orig = get_py(mod, meth); - Py.at(mod).methods.at(meth).ml_meth = detour; + Py.at(mod).methods.at(meth)->ml_meth = detour; cout << mod << "." << meth << ": " << orig << " -> " << detour << endl; } catch (out_of_range) diff --git a/ScrapHacks/ScrapHack/ScrapHack.cpp b/ScrapHacks/ScrapHack/ScrapHack.cpp index 79d66be..9312b66 100644 --- a/ScrapHacks/ScrapHack/ScrapHack.cpp +++ b/ScrapHacks/ScrapHack/ScrapHack.cpp @@ -1,3 +1,4 @@ +#define WIN32_LEAN_AND_MEAN #include "stdafx.h" #include #include @@ -5,16 +6,19 @@ #include #include #include +#include +#include #include #include -//#include - using namespace std; #include "Scrapland.h" #include "Util.h" #include "Structures.h" #include "Py_Utils.h" +#include "Hook.h" + +#define SIZE 6 HMODULE hD3D8Dll = 0; @@ -22,7 +26,6 @@ bool initialized = false; bool running = true; HMODULE mod = 0; - void MainLoop(HMODULE mod) { Sleep(100); @@ -67,7 +70,7 @@ void MainLoop(HMODULE mod) { for (auto meth : mod.second.methods) { - cout << mod.first << "." << meth.first << " @ " << meth.second.ml_meth << endl; + cout << mod.first << "." << meth.first << " @ " << meth.second->ml_meth << endl; } } } @@ -77,9 +80,11 @@ void MainLoop(HMODULE mod) } } SetConsoleCtrlHandler(NULL, false); + hooks.clear(); + scrap_log(0xff0000, "ScrapHacks unloaded!\n"); cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl; - ; FreeConsole(); + PostQuitMessage(0); FreeLibraryAndExitThread(mod, 0); } @@ -90,21 +95,53 @@ void InitConsole() SetupConsole(me); } +void handle_command(const char* cmd) { + cout << "CMD: " << cmd << endl; + scrap_log(0x00ff00, "HAXX: "); + scrap_log(0x00ff00,cmd); + scrap_log(0x00ff00,"\n"); + return; +} + +int my_console(const char* cmd) { + typedef int(_cdecl *t_func)(const char*); + shared_ptr hook = hooks[P_CON_HANDLER]; + t_func func= reinterpret_cast(hook->func()); + if (cmd[0] == '$') { + handle_command(++cmd); + return 0; + } + hook->disable(); + int ret=func(cmd); + hook->enable(); + return ret; +} + +void hook_console() { + new Hook(reinterpret_cast(P_CON_HANDLER) , my_console); +} + + +void DllPreInit(HMODULE _mod) { + char mfn[1024]; + InitConsole(); + GetModuleFileName(0, mfn, 1024); + Py = get_modules(P_PY_MODS); + hD3D8Dll = GetModuleHandle("d3d8.dll"); + cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << endl; + cout << "[*] D3D8 DLL @0x" << hD3D8Dll << endl; + hook_console(); +} + void DllInit(HMODULE _mod) { initialized = true; mod = _mod; - char mfn[1024]; - InitConsole(); - GetModuleFileName(0, mfn, 1024); - cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << endl; Sleep(3000); - Py = get_modules(P_PY_MODS); + cout << "[*] World: " << ptr(P_WORLD, 0) << endl; cout << "[*] Importing python dbg module" << endl; scrap_exec("import dbg"); - cout << "[*] World: " << ptr(P_WORLD,0) << endl; - hD3D8Dll = GetModuleHandle("d3d8.dll"); - cout << "[*] D3D8 DLL @0x"<< hD3D8Dll << endl; + scrap_log(0xff0000, "ScrapHacks loaded!\n"); CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainLoop, mod, 0, 0); cout << "[*] Starting message pump" << endl; MSG msg; diff --git a/ScrapHacks/ScrapHack/ScrapHack.vcxproj b/ScrapHacks/ScrapHack/ScrapHack.vcxproj index 1e6763f..c3d1781 100644 --- a/ScrapHacks/ScrapHack/ScrapHack.vcxproj +++ b/ScrapHacks/ScrapHack/ScrapHack.vcxproj @@ -150,6 +150,7 @@ + diff --git a/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters b/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters index 4b1cc35..f3af96c 100644 --- a/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters +++ b/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters @@ -33,6 +33,9 @@ Headerdateien + + Headerdateien + diff --git a/ScrapHacks/ScrapHack/Scrapland.h b/ScrapHacks/ScrapHack/Scrapland.h index 9e2c0f9..e9a4024 100644 --- a/ScrapHacks/ScrapHack/Scrapland.h +++ b/ScrapHacks/ScrapHack/Scrapland.h @@ -1,7 +1,17 @@ #pragma once -#define P_WORLD 0x7FE944 -#define P_PY_MODS 0x79C698 +//OFFSETS #define O_MONEY 0x2090 -auto scrap_log = (int(_cdecl*)(int, const char*))0x4134C0; -auto scrap_exec = (void(_cdecl*)(const char*))0x5a8390; +//POINTERS +#define P_WORLD 0x7FE944 +#define P_PY_MODS 0x79C698 +#define P_CON_HANDLER 0x402190 +#define P_SCRAP_LOG 0x4134C0 +#define P_SCRAP_EXEC 0x5a8390 + +//FUNCTION TYPES +#define T_SCRAP_LOG int(_cdecl*)(unsigned int, const char*) +#define T_SCRAP_EXEC int(_cdecl*)(const char*) + +auto scrap_log = (T_SCRAP_LOG)P_SCRAP_LOG; +auto scrap_exec = (T_SCRAP_EXEC)P_SCRAP_EXEC; diff --git a/ScrapHacks/ScrapHack/Structures.h b/ScrapHacks/ScrapHack/Structures.h index d9721c9..850f63b 100644 --- a/ScrapHacks/ScrapHack/Structures.h +++ b/ScrapHacks/ScrapHack/Structures.h @@ -30,5 +30,5 @@ struct PyMod struct Module { PyMod *mod; - map methods; + map methods; }; diff --git a/ScrapHacks/ScrapHack/Util.h b/ScrapHacks/ScrapHack/Util.h index bfde2ed..ae6b14f 100644 --- a/ScrapHacks/ScrapHack/Util.h +++ b/ScrapHacks/ScrapHack/Util.h @@ -124,7 +124,6 @@ void hexdump(void *addr, size_t count) cout << endl; } - template T* __ptr(uintptr_t addr) { @@ -156,4 +155,4 @@ template T* ptr(uintptr_t addr, Offsets... offsets) { auto ret = __ptr(addr, offsets...); return ret; -} \ No newline at end of file +} diff --git a/ScrapHacks/ScrapHack/dllmain.cpp b/ScrapHacks/ScrapHack/dllmain.cpp index 4b3aa25..6fab88b 100644 --- a/ScrapHacks/ScrapHack/dllmain.cpp +++ b/ScrapHacks/ScrapHack/dllmain.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #define DLL_EXPORT extern "C" __declspec(dllexport) void DllInit(HMODULE); +void DllPreInit(HMODULE); BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, @@ -11,6 +12,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hModule); + DllPreInit(hModule); hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, hModule, 0, 0); break; case DLL_PROCESS_DETACH: