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.
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