void *HookAPI(LPVOID lpFunc,LPVOID lpHandler) { void *lpRet=NULL; if (GetHookInfo(lpFunc)) UnhookAPI(lpFunc); if (NumOfHooks < MAX_HOOKS-1) { void *lpBackup=MemAlloc(JUMP_SIZE*4); ULONG_PTR *lpTable=0; #ifdef _AMD64_ lpTable=(ULONG_PTR *)MemAlloc(sizeof(ULONG_PTR)*MAX_JUMPS); LPVOID lpRelay=malloc_SomewhereAroundHere(lpFunc,sizeof(JMP_REL)); if (!lpRelay) { MemFree(lpBackup); return lpRet; } #endif SIZE_T dwBackupCodeSize=0; void *lpBridge=CreateBridge(lpFunc,lpBackup,&dwBackupCodeSize,&lpTable[1]); if (lpBridge) { EnterCriticalSection(&csHookApi); hooks[NumOfHooks].lpRealFunc=lpFunc; hooks[NumOfHooks].lpBridge=lpBridge; hooks[NumOfHooks].lpHandler=lpHandler; hooks[NumOfHooks].lpBackup=lpBackup; hooks[NumOfHooks].dwCodeSize=dwBackupCodeSize; #ifdef _AMD64_ hooks[NumOfHooks].lpRelay=lpRelay; hooks[NumOfHooks].lpTable=lpTable; WriteAbsoluteJump(lpRelay,lpHandler,lpTable); WriteRelativeJump(lpFunc,lpRelay); #else WriteRelativeJump(lpFunc,lpHandler); #endif NumOfHooks++; lpRet=lpBridge; LeaveCriticalSection(&csHookApi); } } return lpRet; }
MH_STATUS CreateHook(void* pTarget, void* const pDetour, void** ppOriginal) { CriticalSection::ScopedLock lock(*gCS); if (!gIsInitialized) { return MH_ERROR_NOT_INITIALIZED; } HOOK_ENTRY *pHook = FindHook(pTarget); if (pHook != NULL) { return MH_ERROR_ALREADY_CREATED; } if (!IsExecutableAddress(pTarget) || !IsExecutableAddress(pDetour)) { return MH_ERROR_NOT_EXECUTABLE; } { bool committed = false; RollbackIfNotCommitted scopedRollback(&committed); // トランポリン関数を作成する CREATE_TREMPOLINE_T ct = { 0 }; ct.pTarget = pTarget; if (!CreateTrampolineFunction(ct)) { return MH_ERROR_UNSUPPORTED_FUNCTION; } void* pJmpPtr = pTarget; if (ct.patchAbove) { pJmpPtr = reinterpret_cast<char*>(pJmpPtr) - sizeof(JMP_REL); } void* pTrampoline = AllocateCodeBuffer(pJmpPtr, ct.trampoline.size()); if (pTrampoline == NULL) { return MH_ERROR_MEMORY_ALLOC; } #if defined _M_X64 void* pTable = AllocateDataBuffer(pTrampoline, (ct.table.size() + 1) * sizeof(uintptr_t)); if (pTable == NULL) { return MH_ERROR_MEMORY_ALLOC; } #endif ct.pTrampoline = pTrampoline; #if defined _M_X64 ct.pTable = pTable; #endif if (!ResolveTemporaryAddresses(ct)) { return MH_ERROR_UNSUPPORTED_FUNCTION; } memcpy(pTrampoline, &ct.trampoline[ 0 ], ct.trampoline.size()); #if defined _M_X64 if (ct.table.size() != 0) { memcpy(pTable, &ct.table[ 0 ], ct.table.size() * sizeof(uintptr_t)); } #endif // ターゲット関数のバックアップをとる size_t backupSize = sizeof(JMP_REL); if (ct.patchAbove) { backupSize += sizeof(JMP_REL_SHORT); } void* pBackup = AllocateDataBuffer(NULL, backupSize); if (pBackup == NULL) { return MH_ERROR_MEMORY_ALLOC; } memcpy(pBackup, pJmpPtr, backupSize); // 中継関数を作成する #if defined _M_X64 void* pRelay = AllocateCodeBuffer(pJmpPtr, sizeof(JMP_ABS)); if (pRelay == NULL) { return MH_ERROR_MEMORY_ALLOC; } WriteAbsoluteJump(pRelay, pDetour, reinterpret_cast<uintptr_t*>(pTable) + ct.table.size()); #endif CommitBuffer(); committed = true; // フック情報の登録 HOOK_ENTRY hook = { 0 }; hook.pTarget = pTarget; hook.pDetour = pDetour; #if defined _M_X64 hook.pTable = pTable; hook.pRelay = pRelay; #endif hook.pTrampoline = pTrampoline; hook.pBackup = pBackup; hook.patchAbove = ct.patchAbove; hook.isEnabled = false; hook.queueEnable = false; hook.oldIPs = ct.oldIPs; hook.newIPs = ct.newIPs; std::vector<HOOK_ENTRY>::iterator i = std::lower_bound(gHooks.begin(), gHooks.end(), hook); i = gHooks.insert(i, hook); pHook = &(*i); } // OUT引数の処理 *ppOriginal = pHook->pTrampoline; return MH_OK; }