00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "CATIntercept.h"
00013 #ifdef CAT_CONFIG_WIN32
00014 #include "CATString.h"
00015
00016
00017 CATIntercept::CATIntercept()
00018 {
00019
00020 HANDLE hToken;
00021 TOKEN_PRIVILEGES tkp;
00022 if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
00023 {
00024 LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
00025 tkp.PrivilegeCount = 1;
00026 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
00027 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);
00028 CloseHandle(hToken);
00029 }
00030 }
00031
00032 CATIntercept::~CATIntercept()
00033 {
00034 RestoreAll();
00035 }
00036
00037 void CATIntercept::RestoreAll()
00038 {
00039 while (fHooks.size())
00040 {
00041 Restore(fHooks[0]);
00042 }
00043 }
00044
00045 CATResult CATIntercept::Intercept( void* target,
00046 void* hookFunc,
00047 CATUInt32 stubBytes,
00048 CATHOOK*& newHook,
00049 void* userParam)
00050 {
00051 newHook = 0;
00052 CATHOOK* hookInfo = (CATHOOK*)VirtualAlloc(0,sizeof(CATHOOK),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
00053
00054
00055 memset(hookInfo,0x90,sizeof(CATHOOK));
00056
00057 hookInfo->HookFunc = hookFunc;
00058 hookInfo->Target = target;
00059 hookInfo->OrgInstLen = stubBytes;
00060 hookInfo->UserParam = userParam;
00061 hookInfo->InterceptObj = this;
00062
00063
00064 while (*(CATUInt8*)target == 0xe9)
00065 {
00066 target = ((CATUInt8*)target + *(CATUInt32*)((CATUInt8*)target +1)) + 5;
00067 hookInfo->Target = target;
00068 }
00069
00070
00071 hookInfo->PrePushHook = 0x68;
00072 hookInfo->PrePushHookAddress = (CATUInt32)(UINT_PTR)hookInfo;
00073
00074
00075
00076
00077
00078 hookInfo->StackSwap1[0] = 0x87240487;
00079 hookInfo->StackSwap1[1] = 0x87042444;
00080 hookInfo->StackSwap2 = 0x2404;
00081
00082
00083 hookInfo->HookJmp = 0xe9;
00084 hookInfo->HookJmpLoc = ( ((CATUInt32)(UINT_PTR)hookFunc)) -
00085 (((CATUInt32)(UINT_PTR)hookInfo) + offsetof(CATHOOK,HookJmp) + 5);
00086
00087
00088
00089 hookInfo->PostPatchJump = 0xe9;
00090 hookInfo->PostPatchJumpLoc = ( ((CATUInt32)(UINT_PTR)target)) -
00091 (((CATUInt32)(UINT_PTR)hookInfo) + offsetof(CATHOOK,PostPatchJump) + 5) + stubBytes;
00092
00093
00094
00095 DWORD oldProtect;
00096 if (0 == VirtualProtectEx(GetCurrentProcess(),target,stubBytes,PAGE_EXECUTE_READWRITE,&oldProtect))
00097 return CATRESULT(CAT_ERR_HOOK_PROTECT_FAILED);
00098
00099 memcpy(hookInfo->OrgInst,target,stubBytes);
00100
00101 fHooks.push_back(hookInfo);
00102 newHook = hookInfo;
00103
00104
00105 *((CATUInt8*)target) = 0xe9;
00106 *(CATUInt32*)((CATUInt8*)target + 1) = ((CATUInt32)(UINT_PTR)hookInfo) - (((CATUInt32)(UINT_PTR)target)+5);
00107
00108 if (0 == VirtualProtectEx(GetCurrentProcess(),target,stubBytes,oldProtect,&oldProtect))
00109 return CATRESULT(CAT_ERR_HOOK_PROTECT_FAILED);
00110
00111
00112 FlushInstructionCache(GetCurrentProcess(),0,0);
00113
00114 return CAT_SUCCESS;
00115 }
00116
00117 CATResult CATIntercept::Restore(CATHOOK*& hookInfo)
00118 {
00119 if (hookInfo == 0)
00120 return CAT_ERR_INVALID_PARAM;
00121
00122
00123 DWORD oldProtect;
00124
00125 if (0 == VirtualProtectEx(GetCurrentProcess(),
00126 hookInfo->Target,
00127 hookInfo->OrgInstLen,
00128 PAGE_EXECUTE_READWRITE,
00129 &oldProtect))
00130 {
00131 return CATRESULT(CAT_ERR_HOOK_PROTECT_FAILED);
00132 }
00133
00134 memcpy(hookInfo->Target,hookInfo->OrgInst,hookInfo->OrgInstLen);
00135
00136 if (0 == VirtualProtectEx(GetCurrentProcess(),
00137 hookInfo->Target,
00138 hookInfo->OrgInstLen,
00139 oldProtect,
00140 &oldProtect))
00141 {
00142 return CATRESULT(CAT_ERR_HOOK_PROTECT_FAILED);
00143 }
00144
00145 FlushInstructionCache(GetCurrentProcess(),0,0);
00146
00147
00148 std::vector<CATHOOK*>::iterator iter = fHooks.begin();
00149 while (iter != fHooks.end())
00150 {
00151 if ( (*iter) == hookInfo )
00152 {
00153 VirtualFree(hookInfo,sizeof(CATHOOK),MEM_RELEASE);
00154 hookInfo = 0;
00155 fHooks.erase(iter);
00156 return CAT_SUCCESS;
00157 }
00158 ++iter;
00159 }
00160
00161 return CATRESULT(CAT_ERR_HOOK_NOT_FOUND);
00162 }
00163
00164 void* CATIntercept::GetFunctionFromVTable(void* objectPtr, CATUInt32 vtableIndex)
00165 {
00166 UINT_PTR* vtable = (UINT_PTR*)*(UINT_PTR*)objectPtr;
00167 void *func = 0;
00168
00169
00170 try
00171 {
00172 func = (void*)vtable[vtableIndex];
00173 }
00174 catch (...)
00175 {
00176 func = 0;
00177 }
00178
00179 return func;
00180 }
00181
00182 CATResult CATIntercept::InterceptCOMObject( void* comObject,
00183 CATINTERCEPT_COM_TABLE_ENTRY* interceptTable,
00184 void* userParam)
00185 {
00186 if (interceptTable == 0)
00187 return CATRESULT(CAT_ERR_INVALID_PARAM);
00188
00189 CATResult result = CAT_SUCCESS;
00190 while (interceptTable->VTableIndex != (CATUInt32)-1)
00191 {
00192 void* func = GetFunctionFromVTable(comObject, interceptTable->VTableIndex);
00193 if (func)
00194 {
00195 CATHOOK* tmpHook = 0;
00196 result = Intercept( func,
00197 interceptTable->HookFunction,
00198 interceptTable->StubLength,
00199 tmpHook,
00200 userParam);
00201 if (CATFAILED(result))
00202 return result;
00203 }
00204 interceptTable++;
00205 }
00206
00207 return CAT_SUCCESS;
00208 }
00209
00210
00211
00212 CATResult CATIntercept::SaveInterceptData ( const CATWChar* objectName,
00213 void* comObject,
00214 CATINTERCEPT_COM_TABLE_ENTRY* interceptTable,
00215 void* userParam)
00216 {
00217 if (interceptTable == 0)
00218 return CATRESULT(CAT_ERR_INVALID_PARAM);
00219
00220
00221 HKEY interceptKey = 0;
00222 ::RegCreateKeyEx(HKEY_CURRENT_USER,
00223 L"SOFTWARE\\GameAccessSuite\\CATIntercept",
00224 0,0,
00225 REG_OPTION_NON_VOLATILE,
00226 KEY_ALL_ACCESS,
00227 NULL,
00228 &interceptKey,
00229 0);
00230
00231 if (interceptKey == 0)
00232 return CAT_ERROR;
00233
00234 HKEY objectKey = 0;
00235 ::RegCreateKeyEx(interceptKey,objectName,0,0,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,0,&objectKey,0);
00236
00237 if (objectKey == 0)
00238 {
00239 ::RegCloseKey(interceptKey);
00240 return CAT_ERROR;
00241 }
00242
00243
00244 CATResult result = CAT_SUCCESS;
00245 while (interceptTable->VTableIndex != (CATUInt32)-1)
00246 {
00247 void* func = GetFunctionFromVTable(comObject, interceptTable->VTableIndex);
00248
00249 CATString vindex = interceptTable->VTableIndex;
00250
00251 ::RegSetValueEx(objectKey,vindex,0,REG_DWORD,(BYTE*)&func,4);
00252
00253 interceptTable++;
00254 }
00255
00256 ::RegCloseKey(objectKey);
00257 ::RegCloseKey(interceptKey);
00258 return CAT_SUCCESS;
00259 }
00260
00261
00262 CATResult CATIntercept::LoadAndHook ( const CATWChar* objectName,
00263 CATINTERCEPT_COM_TABLE_ENTRY* interceptTable,
00264 void* userParam)
00265 {
00266 if (interceptTable == 0)
00267 return CATRESULT(CAT_ERR_INVALID_PARAM);
00268
00269
00270 HKEY interceptKey = 0;
00271 ::RegCreateKeyEx(HKEY_CURRENT_USER,
00272 L"SOFTWARE\\GameAccessSuite\\CATIntercept",
00273 0,0,
00274 REG_OPTION_NON_VOLATILE,
00275 KEY_ALL_ACCESS,
00276 NULL,
00277 &interceptKey,
00278 0);
00279
00280 if (interceptKey == 0)
00281 return CAT_ERROR;
00282
00283 HKEY objectKey = 0;
00284 ::RegCreateKeyEx(interceptKey,objectName,0,0,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,0,&objectKey,0);
00285
00286 if (objectKey == 0)
00287 {
00288 ::RegCloseKey(interceptKey);
00289 return CAT_ERROR;
00290 }
00291
00292 CATINTERCEPT_COM_TABLE_ENTRY* start = interceptTable;
00293 CATResult result = CAT_SUCCESS;
00294
00295 while (interceptTable->VTableIndex != (CATUInt32)-1)
00296 {
00297 CATString vindex = interceptTable->VTableIndex;
00298 void* func = 0;
00299 DWORD type = 0;
00300 DWORD dataLen = 4;
00301 ::RegQueryValueEx(objectKey,vindex,0,&type,(BYTE*)&func,&dataLen);
00302
00303 if (func == 0)
00304 {
00305 ::RegCloseKey(objectKey);
00306 ::RegCloseKey(interceptKey);
00307 return CAT_ERROR;
00308 }
00309
00310 interceptTable++;
00311 }
00312
00313
00314 interceptTable = start;
00315 while (interceptTable->VTableIndex != (CATUInt32)-1)
00316 {
00317 CATString vindex = interceptTable->VTableIndex;
00318 void* func = 0;
00319 DWORD type = 0;
00320 DWORD dataLen = 4;
00321 ::RegQueryValueEx(objectKey,vindex,0,&type,(BYTE*)&func,&dataLen);
00322
00323 if (func)
00324 {
00325 CATHOOK* tmpHook = 0;
00326 result = Intercept( func,
00327 interceptTable->HookFunction,
00328 interceptTable->StubLength,
00329 tmpHook,
00330 userParam);
00331 if (CATFAILED(result))
00332 return result;
00333 }
00334
00335 interceptTable++;
00336 }
00337
00338 ::RegCloseKey(objectKey);
00339 ::RegCloseKey(interceptKey);
00340 return CAT_SUCCESS;
00341 }
00342
00343
00344 CATResult CATIntercept::InterceptDLL( HMODULE module,
00345 CATINTERCEPT_DLL_TABLE_ENTRY* interceptTable,
00346 void* userParam)
00347 {
00348 if (interceptTable == 0)
00349 return CATRESULT(CAT_ERR_INVALID_PARAM);
00350
00351 CATResult result = CAT_SUCCESS;
00352 while (interceptTable->FunctionName != 0)
00353 {
00354 void* func = ::GetProcAddress(module,interceptTable->FunctionName);
00355 if (func)
00356 {
00357 CATHOOK* tmpHook = 0;
00358 result = Intercept( func,
00359 interceptTable->HookFunction,
00360 interceptTable->StubLength,
00361 tmpHook,
00362 userParam);
00363 if (CATFAILED(result))
00364 return result;
00365 }
00366 interceptTable++;
00367 }
00368
00369 return CAT_SUCCESS;
00370 }
00371
00372 #endif //CAT_CONFIG_WIN32