Added function hooking

Cleaned up the injector a bit and added launch-time injection
This commit is contained in:
Daniel S. 2019-03-01 01:00:50 +01:00
parent ffbcc30427
commit 7cf3ab8580
11 changed files with 166 additions and 36 deletions

View file

@ -169,7 +169,6 @@ void InjectDll(DWORD PID, bool do_resume = false)
cout << "[*] Injecting DLL " << dll_name << " into PID " << PID << endl; cout << "[*] Injecting DLL " << dll_name << " into PID " << PID << endl;
cout << "[*] Opening Process Handle" << endl; cout << "[*] Opening Process Handle" << endl;
hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, PID); hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, PID);
PID = GetProcessId(hProc);
GetFullPathNameA(dll_name, MAX_PATH, dll_full_path, 0); GetFullPathNameA(dll_name, MAX_PATH, dll_full_path, 0);
cout << "[*] Adjusting Privileges of Process" << endl; cout << "[*] Adjusting Privileges of Process" << endl;
adjustPrivs(hProc); adjustPrivs(hProc);
@ -216,23 +215,53 @@ void InjectDll(DWORD PID, bool do_resume = false)
CloseHandle(hProc); CloseHandle(hProc);
return; return;
} }
vector<HANDLE> 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[]) int main(int argc, char *argv[])
{ {
string prog; string prog;
HANDLE hProc = INVALID_HANDLE_VALUE; HANDLE hProc = INVALID_HANDLE_VALUE;
HANDLE hThread = INVALID_HANDLE_VALUE;
DWORD PID = 0; DWORD PID = 0;
GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID); if ((argc>1)&&fexists(argv[1])) {
if (PID == 0) cout << "[*] Spawning process for \"" << argv[1] << "\"" << endl;
{ vector<HANDLE> handles = spawn(argv[1]);
cout << "[*] Waiting for Scrapland to Launch..." << endl; if (handles.empty()) {
} cout << "[!] Error: " << GetLastErrorAsString() << endl;
while (PID == 0) return -1;
{ }
Sleep(100); hProc = handles[0];
hThread = handles[1];
PID = GetProcessId(hProc);
cout << "[+] Got PID: " << PID << endl;
} else {
GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID); 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); InjectDll(PID);
if (hThread != INVALID_HANDLE_VALUE) {
while (ResumeThread(hThread));
}
cout << "[*] Done!" << endl; cout << "[*] Done!" << endl;
return 0; return 0;
} }

View file

@ -160,6 +160,5 @@
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets" />
</ImportGroup>
</Project> </Project>

View file

@ -0,0 +1,50 @@
#pragma once
#include <functional>
class Hook;
map<uintptr_t, shared_ptr<Hook>> 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<uintptr_t>(detour);
uintptr_t src = reinterpret_cast<uintptr_t>(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<Hook>(this);
}
~Hook() {
cout << "Unhooking: " << this->detour << " -> " << this->orig << endl;
uintptr_t src = reinterpret_cast<uintptr_t>(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;
}
};

View file

@ -13,7 +13,7 @@ PyMethodDef *find_method_table(uintptr_t base, uintptr_t needle)
return reinterpret_cast<PyMethodDef*>(mod_addr); return reinterpret_cast<PyMethodDef*>(mod_addr);
} }
} }
return reinterpret_cast<PyMethodDef *>(0); return reinterpret_cast<PyMethodDef*>(0);
} }
map<string, Module> get_modules(uintptr_t base) map<string, Module> get_modules(uintptr_t base)
@ -27,7 +27,7 @@ map<string, Module> get_modules(uintptr_t base)
PyMethodDef *method_table = find_method_table((size_t)modules[i].init_func, reinterpret_cast<uintptr_t>(modules[i].name)); PyMethodDef *method_table = find_method_table((size_t)modules[i].init_func, reinterpret_cast<uintptr_t>(modules[i].name));
for (size_t j = 0; method_table != NULL && method_table[j].ml_name != NULL; j++) 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; Py[mod.mod->name] = mod;
} }
@ -38,7 +38,7 @@ void *get_py(const char *mod, const char *meth)
{ {
try try
{ {
return Py.at(mod).methods.at(meth).ml_meth; return Py.at(mod).methods.at(meth)->ml_meth;
} }
catch (out_of_range) catch (out_of_range)
{ {
@ -51,7 +51,7 @@ void inject(const char *mod, const char *meth, void *detour)
try try
{ {
void *orig = get_py(mod, meth); 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; cout << mod << "." << meth << ": " << orig << " -> " << detour << endl;
} }
catch (out_of_range) catch (out_of_range)

View file

@ -1,3 +1,4 @@
#define WIN32_LEAN_AND_MEAN
#include "stdafx.h" #include "stdafx.h"
#include <string> #include <string>
#include <sstream> #include <sstream>
@ -5,16 +6,19 @@
#include <map> #include <map>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <typeinfo>
#include <functional>
#include <Windows.h> #include <Windows.h>
#include <TlHelp32.h> #include <TlHelp32.h>
//#include <D3d8.h>
using namespace std; using namespace std;
#include "Scrapland.h" #include "Scrapland.h"
#include "Util.h" #include "Util.h"
#include "Structures.h" #include "Structures.h"
#include "Py_Utils.h" #include "Py_Utils.h"
#include "Hook.h"
#define SIZE 6
HMODULE hD3D8Dll = 0; HMODULE hD3D8Dll = 0;
@ -22,7 +26,6 @@ bool initialized = false;
bool running = true; bool running = true;
HMODULE mod = 0; HMODULE mod = 0;
void MainLoop(HMODULE mod) void MainLoop(HMODULE mod)
{ {
Sleep(100); Sleep(100);
@ -67,7 +70,7 @@ void MainLoop(HMODULE mod)
{ {
for (auto meth : mod.second.methods) 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); SetConsoleCtrlHandler(NULL, false);
hooks.clear();
scrap_log(0xff0000, "ScrapHacks unloaded!\n");
cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl; cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl;
;
FreeConsole(); FreeConsole();
PostQuitMessage(0);
FreeLibraryAndExitThread(mod, 0); FreeLibraryAndExitThread(mod, 0);
} }
@ -90,21 +95,53 @@ void InitConsole()
SetupConsole(me); 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> hook = hooks[P_CON_HANDLER];
t_func func= reinterpret_cast<t_func>(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<void*>(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) void DllInit(HMODULE _mod)
{ {
initialized = true; initialized = true;
mod = _mod; mod = _mod;
char mfn[1024];
InitConsole();
GetModuleFileName(0, mfn, 1024);
cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << endl;
Sleep(3000); Sleep(3000);
Py = get_modules(P_PY_MODS); cout << "[*] World: " << ptr<void>(P_WORLD, 0) << endl;
cout << "[*] Importing python dbg module" << endl; cout << "[*] Importing python dbg module" << endl;
scrap_exec("import dbg"); scrap_exec("import dbg");
cout << "[*] World: " << ptr<void>(P_WORLD,0) << endl; scrap_log(0xff0000, "ScrapHacks loaded!\n");
hD3D8Dll = GetModuleHandle("d3d8.dll");
cout << "[*] D3D8 DLL @0x"<< hD3D8Dll << endl;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainLoop, mod, 0, 0); CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainLoop, mod, 0, 0);
cout << "[*] Starting message pump" << endl; cout << "[*] Starting message pump" << endl;
MSG msg; MSG msg;

View file

@ -150,6 +150,7 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Hook.h" />
<ClInclude Include="Py_Utils.h" /> <ClInclude Include="Py_Utils.h" />
<ClInclude Include="Structures.h" /> <ClInclude Include="Structures.h" />
<ClInclude Include="Scrapland.h" /> <ClInclude Include="Scrapland.h" />

View file

@ -33,6 +33,9 @@
<ClInclude Include="Py_Utils.h"> <ClInclude Include="Py_Utils.h">
<Filter>Headerdateien</Filter> <Filter>Headerdateien</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Hook.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">

View file

@ -1,7 +1,17 @@
#pragma once #pragma once
#define P_WORLD 0x7FE944 //OFFSETS
#define P_PY_MODS 0x79C698
#define O_MONEY 0x2090 #define O_MONEY 0x2090
auto scrap_log = (int(_cdecl*)(int, const char*))0x4134C0; //POINTERS
auto scrap_exec = (void(_cdecl*)(const char*))0x5a8390; #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;

View file

@ -30,5 +30,5 @@ struct PyMod
struct Module struct Module
{ {
PyMod *mod; PyMod *mod;
map<string, PyMethodDef> methods; map<string, PyMethodDef*> methods;
}; };

View file

@ -124,7 +124,6 @@ void hexdump(void *addr, size_t count)
cout << endl; cout << endl;
} }
template<typename T> template<typename T>
T* __ptr(uintptr_t addr) T* __ptr(uintptr_t addr)
{ {
@ -156,4 +155,4 @@ template<typename T, typename... Offsets>
T* ptr(uintptr_t addr, Offsets... offsets) { T* ptr(uintptr_t addr, Offsets... offsets) {
auto ret = __ptr<T>(addr, offsets...); auto ret = __ptr<T>(addr, offsets...);
return ret; return ret;
} }

View file

@ -1,6 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#define DLL_EXPORT extern "C" __declspec(dllexport) #define DLL_EXPORT extern "C" __declspec(dllexport)
void DllInit(HMODULE); void DllInit(HMODULE);
void DllPreInit(HMODULE);
BOOL APIENTRY DllMain(HMODULE hModule, BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call, DWORD ul_reason_for_call,
@ -11,6 +12,7 @@ BOOL APIENTRY DllMain(HMODULE hModule,
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule); DisableThreadLibraryCalls(hModule);
DllPreInit(hModule);
hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, hModule, 0, 0); hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, hModule, 0, 0);
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH: