windows - Win32, How can i hook functions in compiled programs with C++? -
take instance function (viewed in ollydbg debugger)
the first push ebp instruction start void* f(int32_t n) (idk returns, guessing void*), know input parameter n @ stack, , ebp+8 pointer variable, guess int* n=(int*)(uint32_t(ebp)+0x08); /*assuming ebp void* , sizeof(ebp)==sizeof(uint32_t)==sizeof(void*) , +8 math same in c++ uint32_t , x86 assembly..*/
i want make hook, check if n above 7, or below 0, , if is, change 1. ollydbg, writing assembly code directly, can do: patch first mov ebp,esp instruction jmp short int3 instructions behind (i'll need 7 bytes), change (unused) int3's mov ebp,esp jmp long 0068bccd 0068bccd unused 0x000000000000's @ end of file
, @ 0068bccd , can write assembly codes check int pointed @ ebp+8 , , modify if necessary:
pushad cmp dword ptr ss:[ebp+8],7 ja short error cmp dword ptr ss:[ebp+8],0 jl short error jmp short finished error: pushad push offset thestring call onlink-x86.app::output add esp,4 popad mov dword ptr ss:[ebp+8],1 finished: popad jmp long 00447493 thestring: "warning: label assertion failed, (pretending 1 and) trying ignore.."+0x00
which (if didn't mess up) equivalent of
void filterintatebp_8(){ int i=*(int*)(uint32_t(ebp)+8); if(i>7 || i<0){ output("warning: label assertion failed, (pretending 1 and) trying ignore.."); *(int*)(uint32_t(ebp)+8)=1; } return; }
finally, here question: how can make hook, not ollydbg, c++ ? (i saw source code way back, mmorpg cheat program, hooking client, this, code lost me )
first, want inject dll in target process. so, can use code:
injector.h
#ifndef injector_h_included #define injector_h_included #include <windows.h> #include <string> class injector { public: /** * loads dll remote process * @return true on sucess, false on failure */ bool injectdll(dword processid, std::string dllpath); private: }; #endif // injector_h_included
injector.cpp
#include "injector.h" bool injector::injectdll(dword processid, std::string dllpath) { handle hthread, hprocess; void* plibremote = 0; // address (in remote process) szlibpath copied to; hmodule hkernel32 = getmodulehandle("kernel32"); hinstance hinst = getmodulehandle(null); char dllfullpathname[_max_path]; getfullpathname(dllpath.c_str(), _max_path, dllfullpathname, null); // process handle hprocess = openprocess(process_all_access, false, processid); // copy file path in szlibpath char szlibpath[_max_path]; strcpy_s(szlibpath, dllfullpathname); // 1. allocate memory in remote process szlibpath plibremote = virtualallocex( hprocess, null, sizeof(szlibpath), mem_commit, page_readwrite ); if (plibremote == null) { // because don't have administrator's right return false; } // 2. write szlibpath allocated memory writeprocessmemory(hprocess, plibremote, (void*)szlibpath, sizeof(szlibpath), null); // 3. force remote process load dll hthread = createremotethread(hprocess, null, 0, (lpthread_start_routine) getprocaddress(hkernel32,"loadlibrarya"), plibremote, 0, null); if (hthread == null) { return false; } return true; }
main.cpp
#include "injector.h" int main() { injector injector; dword processid = 1653; // change process id here. if (injector.injectdll(processid, "injected.dll")) { printf("good job, injected dll\n"); } else { printf("something wrong happened\n"); } while (true); }
then have make dll. gets little more complicated. first includes:
injected.dll
#include <windows.h> #include <stdio.h>
then need make function detour right location:
void detouraddress(void* funcptr, void* hook, byte* mem) { byte cmd[5] = { 0xe9, 0x00, 0x00, 0x00, 0x00 }; // jump place holder void* rvaaddr = (void*)((dword)funcptr + (dword)getmodulehandle(null)); // base + relative address // make memory readable/writable dword dwprotect; virtualprotect(rvaaddr, 5, page_execute_readwrite, &dwprotect); // read memory readprocessmemory(getcurrentprocess(), (lpvoid)rvaaddr, &mem[2], 5, null); // write jmp in cmd dword offset = ((dword)hook - (dword)rvaaddr - 5); // (dest address) - (source address) - (jmp size) memcpy(&cmd[1], &offset, 4); // write address jmp writeprocessmemory(getcurrentprocess(), (lpvoid)rvaaddr, cmd, 5, 0); // write jmp // write mem virtualprotect(mem, 13, page_execute_readwrite, &dwprotect); void* returnadress = (void*)((dword)rvaaddr + 5); memcpy(&mem[8], &returnadress, 4); // write return address mem // reprotect virtualprotect(rvaaddr, 5, dwprotect, null); }
if need remove dll @ point, need restore code:
void patchaddress(void* funcptr, byte* mem) { void* rvaaddr = (void*)((dword)funcptr + (dword)getmodulehandle(null)); // base + relative address // make memory readable/writable dword dwprotect; virtualprotect(funcptr, 5, page_execute_readwrite, &dwprotect); writeprocessmemory(getcurrentprocess(), (lpvoid)rvaaddr, &mem[2], 5, null); // write jmp virtualprotect(rvaaddr, 5, dwprotect, null); }
next, need make function out of detoured bytes in order program execute them, isn't affected our detour. add in global space:
// memory (0x5e = pop esi, 0x68 = push dword, 0xc3 = retn) byte detourmem[13] = { 0x5e, 0x5e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x00, 0x00, 0x00, 0x00, 0xc3 }; // convert bytes array function typedef void ( * pfunc)(); pfunc funcmem = (pfunc) &detourmem; // added variable example of can it. dword var = 0;
after that, need detouring function:
_declspec(naked) void detourfunction() { // need push flag , registers on stack don't modify them accident __asm { pushfd pushad // can "whatever" want here in assembly code // ex, put eax value var: mov var, eax } printf("this code executed everytime detoured function called\n"); // whatever want in c++ here if (var < 7) { // eax smaller 7 } // pop every flags , registers first pushed program continue supposed __asm { // set normal popad popfd push esi // call our funcmem mov edx, funcmem; call edx } }
finaly, here how dllmain like:
bool apientry dllmain( hmodule hmodule, dword ul_reason_for_call, lpvoid lpreserved ) { dword detouredaddress = 0x689b; // add relative address of location want detour file *stream; switch (ul_reason_for_call) { case dll_process_attach: // add if want console appears when inject dll (don't forget freeconsole when remove dll) allocconsole(); freopen_s(&stream, "conout$", "w", stdout); // if need know base address of process injected: printf("base address: 0x%x\n", (dword)getmodulehandle(null)); // our detour function detouraddress((void*)detouredaddress, (void*)&detourfunction, detourmem); break; case dll_process_detach: // restore process have before injected patchaddress((void*)detouredaddress, detourmem); freeconsole(); break; } return true; }
i understand lot @ once, if have questions don't hesitate!
Comments
Post a Comment