something i've written for w3hackit (www.gamehackers.net),
thought some of you might find this code interesting.
hijacking api is a good way to control how external dll's manipulate a program.
you can write a universal keybind feature or even a speed hack.
but this all really comes down to how much a game depends on function imports.
normally i wouldn't use the C-lib *hides*, but i wanted to write a quick sample to explain whats going on in the background.
thought some of you might find this code interesting.
hijacking api is a good way to control how external dll's manipulate a program.
you can write a universal keybind feature or even a speed hack.
but this all really comes down to how much a game depends on function imports.
normally i wouldn't use the C-lib *hides*, but i wanted to write a quick sample to explain whats going on in the background.
Code: |
#include<windows.h> #include<stdio.h> union BaseData { PBYTE pImageBase; PIMAGE_DOS_HEADER pImageHeader; }; typedef BaseData* pBaseData; typedef PIMAGE_FILE_HEADER pFileHeader; typedef PIMAGE_OPTIONAL_HEADER pExtraHeader; typedef PIMAGE_SECTION_HEADER pSectionHeader; #define InitConsts()/ m_BaseData(*pBaseData(&pImageBase)),/ m_pFileHeader(pFileHeader(DWORD(m_BaseData.pImageBase)+DWORD(m_BaseData.pImageHeader->e_lfanew)+sizeof(DWORD))),/ m_pExtraHeader(pExtraHeader(DWORD(m_pFileHeader) + sizeof(IMAGE_FILE_HEADER))),/ m_pSectionHeader(pSectionHeader(DWORD(m_pExtraHeader) + sizeof(IMAGE_OPTIONAL_HEADER))) //macro from bo2k [RVATOVA updated for our C++ class] #define RVATOVA(type,offset) ((type)((DWORD)(PBYTE(*this))+(DWORD)(offset))) class peControl { public: peControl(PBYTE pImageBase); virtual ~peControl(); //returns original. FARPROC InterceptImport(FARPROC pFuncOrigApi, FARPROC pFuncNewApi); FARPROC InterceptImport(LPCSTR pDllName, LPCSTR pApiName, FARPROC pFuncNewApi); operator PBYTE() const { return m_BaseData.pImageBase; } operator PIMAGE_FILE_HEADER() const { return m_pFileHeader; } operator PIMAGE_OPTIONAL_HEADER() const { return m_pExtraHeader; } operator PIMAGE_SECTION_HEADER() const { return m_pSectionHeader; } protected: private: const BaseData m_BaseData; const pFileHeader m_pFileHeader; const pExtraHeader m_pExtraHeader; const pSectionHeader m_pSectionHeader; }; peControl::peControl(PBYTE pImageBase) : InitConsts() { return; } peControl::~peControl() { return; } //InterceptImport concept by goldfinder FARPROC peControl::InterceptImport(FARPROC pFuncOrigApi, FARPROC pFuncNewApi) { PIMAGE_IMPORT_DESCRIPTOR pImportDesc = RVATOVA(PIMAGE_IMPORT_DESCRIPTOR, PIMAGE_OPTIONAL_HEADER(*this)->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); if(PBYTE(pImportDesc) == PBYTE(*this)) return NULL; for(;pImportDesc->Name; pImportDesc++) { for(PIMAGE_THUNK_DATA pThunk = RVATOVA(PIMAGE_THUNK_DATA, pImportDesc->FirstThunk); pThunk->u1.Function; pThunk++) { if (FARPROC(pThunk->u1.Function) == pFuncOrigApi) { DWORD dwProtect; __try { pThunk->u1.Function = DWORD(pFuncNewApi); } __except(EXCEPTION_EXECUTE_HANDLER) { if(!VirtualProtect((LPVOID)(&pThunk->u1.Function), sizeof(DWORD), PAGE_EXECUTE_READWRITE, &dwProtect)) return NULL; pThunk->u1.Function = DWORD(pFuncNewApi); } VirtualProtect((LPVOID)(&pThunk->u1.Function), sizeof(DWORD), PAGE_EXECUTE, &dwProtect); return pFuncOrigApi; } } } return NULL; } FARPROC peControl::InterceptImport(LPCSTR pDllName, LPCSTR pApiName, FARPROC pFuncNewApi) { FARPROC pCurrentApi = GetProcAddress(GetModuleHandle(pDllName), pApiName); if(pCurrentApi) { return InterceptImport(pCurrentApi, pFuncNewApi); } return NULL; } DWORD WINAPI newGetTickCount(VOID) { return 0x31337; } int main(void) { class peControl *pe = new peControl(PBYTE(GetModuleHandle(NULL))); FARPROC pOriginalGTC; printf("hijacking GetTickCount.../n"); printf("original GetTickCount address = 0x%X/n", pOriginalGTC=pe->InterceptImport("kernel32","GetTickCount", FARPROC(newGetTickCount))); printf("GetTickCount() returned 0x%X/n", GetTickCount()); printf("recalling old GetTickCount.../n"); pe->InterceptImport( FARPROC(newGetTickCount), pOriginalGTC); printf("GetTickCount() returned 0x%X/n", GetTickCount()); delete pe; return 0; } |
console output wrote: |
hijacking GetTickCount... original GetTickCount address = 0x77E7A29B GetTickCount() returned 0x31337 recalling old GetTickCount... GetTickCount() returned 0xEC9319 |