windows-API劫持(API-HOOK)
API Hook
? ? ApiHook又叫做API劫持,也就是如果A程序調(diào)用了B.cll里面的C函數(shù),我們可以做到當(dāng)A調(diào)用C函數(shù)執(zhí)行的時(shí)候,直接執(zhí)行我們自己事先準(zhǔn)備好的函數(shù),之后我們?cè)趫?zhí)行真正的C,當(dāng)然我們可以不執(zhí)行C或者更改C的參數(shù)等等,實(shí)現(xiàn)的核心思路就是:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?mov eax, pNewAddr[/size][size=3] jmp eax
? ? 解釋下具體原理:我們首先獲取要劫持函數(shù)的地址,然后我們?cè)谧约航M裝一個(gè)數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu)的內(nèi)容是 執(zhí)行匯編:把新函數(shù)地址拷到寄存器里,然后再jmp到新函數(shù)地址位置執(zhí)行新函數(shù),然后我們把自己組裝這個(gè)數(shù)據(jù)結(jié)構(gòu)拷貝到之前獲取的需要劫持的函數(shù)地址指向的內(nèi)存的位置,這樣當(dāng)我們?cè)俅握{(diào)用該函數(shù)的時(shí)候,程序走到函數(shù)地址處發(fā)現(xiàn)是執(zhí)行我們剛剛寫好的匯編命令,直接jmp到了我們自己定義的函數(shù)地址的位置,也就相當(dāng)于直接運(yùn)行了我們自己寫好的函數(shù)地址了,當(dāng)然自己寫的函數(shù)必須要和原函數(shù)參數(shù)和返回值一樣,自己寫的函數(shù)里面也可以調(diào)用原函數(shù)(達(dá)到過濾的目的),但是前提是調(diào)用之前要先關(guān)閉劫持,也就是把我們替換的內(nèi)容給人家替換回去,執(zhí)行完之后再次替換我們的地址,如果不替換回去我們就會(huì)進(jìn)入無(wú)限遞歸了這個(gè)不解釋,當(dāng)然我們也可以修改參數(shù)什么的,給調(diào)用者進(jìn)行一個(gè)“加工”。還有就是剛開始看的時(shí)候有一個(gè)地方不理解就是:DLL注入能成功的原理是,某些系統(tǒng)DLL里面的函數(shù)所有程序調(diào)用都會(huì)執(zhí)行同一個(gè)地址,而APIHook中有一步是更改函數(shù)地址,但是如果我們更改了某些公用的函數(shù)地址,那么并不會(huì)影響其他的程序繼續(xù)調(diào)用,這個(gè)地方小糾結(jié)了一會(huì),后來弄清楚了,A加載了系統(tǒng)B.DLL獲取里面的API函數(shù)C, A2也同樣加載并且獲取了里面的API函數(shù)C2,C和C2是相等的(當(dāng)然并不是所有都相等),但是我們?cè)?/span>A程序里進(jìn)行C函數(shù)的Hook,并沒有影響A2的調(diào)用,原因是他們只是指向同一個(gè)地址不是就是同一個(gè)地址,可以理解成是中間有過度變量。我們修改的只是自己內(nèi)存那部分”本分而已”,這樣的話,我們想要Hook某個(gè)繼承的某些API的話通常可以采取DLL注入的方式,DLL注入之前我總結(jié)過并且上傳過相關(guān)的實(shí)現(xiàn)代碼。這里不解釋。然后就是在網(wǎng)上找到了一個(gè)寫的不錯(cuò)的APIHook的代碼,分享下(注意,下面代碼是方便理解的,可以通過代碼好好理解,但是實(shí)際開發(fā)不要用下面的代碼,因?yàn)橄旅鏇]考慮64位等其他問題,我平時(shí)開發(fā)常用的一個(gè)比較穩(wěn)定的代碼我上傳在:http://download.csdn.net/detail/u013761036/9603063):
AdHookApi.h #ifndef __ADHOOKAPI_H__ #define __ADHOOKAPI_H__ #include <windows.h> #include <tchar.h> #include <vector> using namespace std;// class CAdAutoHookApi class CAdHookApi; class CAdAutoHookApi { public:CAdAutoHookApi(CAdHookApi *pHookApi, void *pAddr);virtual ~CAdAutoHookApi();private:CAdHookApi *m_pHookApi;void *m_pAddr; };// class CAdAutoHook class CAdHookApi { public:CAdHookApi();virtual ~CAdHookApi();protected:struct HookMap{HANDLE hProcess;void *pOldAddr;void *pNewAddr;BYTE chOldCode[8];BYTE chNewCode[8];BOOL bHooked;DWORD dwData;}; public:HANDLE Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData = 0);HANDLE Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData = NULL, DWORD verifySize = 0, DWORD dwData = 0);BOOL Remove(HANDLE hHook);BOOL Begin(HANDLE hHook);BOOL End(HANDLE hHook);BOOL Begin2(void *pNewAddr);BOOL End2(void *pNewAddr);int BeginAll();int EndAll();int GetCount();void *OldAddr2NewAddr(void *pOldAddr);void *NewAddr2OldAddr(void *pNewAddr);public:static BOOL VerifyAddress(void *pAddr, const BYTE *verifyData, DWORD verifySize);static BOOL PatchCode(void *pAddr, const BYTE *pCode, DWORD dwCode, const BYTE *verifyData = NULL, DWORD verifySize = 0);protected:CAdHookApi::HookMap *FromNewAddr(void *pNewAddr);CAdHookApi::HookMap *FromOldAddr(void *pOldAddr);BOOL HasHook(HANDLE hHook);protected:vector<HookMap *> m_obHooks; };#endif // __ADHOOKAPI_H__AdHookApi.cpp//#include "stdafx.h" #include "AdHookApi.h" #include <stdio.h> #include <string.h> #include <assert.h> #include <Windows.h> #include "Common.h"static BOOL gUseAPI = TRUE;static BOOL WINAPI myReadMemory(HANDLE hProcess, LPVOID lpAddress, LPVOID lpBuffer, SIZE_T nSize) {BOOL bRet = FALSE;DWORD dwOldProtect = 0;bRet = VirtualProtect(lpAddress, nSize, PAGE_READONLY, &dwOldProtect);if(gUseAPI){DWORD dwRead = 0;bRet = ReadProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwRead);}else{memcpy(lpBuffer, lpAddress, nSize);}VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);assert(bRet);return bRet; }static BOOL WINAPI myWriteMemory(HANDLE hProcess, LPVOID lpAddress, LPCVOID lpBuffer, SIZE_T nSize) {BOOL bRet = FALSE;DWORD dwOldProtect = 0;bRet = VirtualProtect(lpAddress, nSize, PAGE_READWRITE, &dwOldProtect);if(gUseAPI){DWORD dwWrite = 0;bRet = WriteProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwWrite);}else{memcpy(lpAddress, lpBuffer, nSize);}VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);assert(bRet);return bRet; }// class CAdAutoHookApi CAdAutoHookApi::CAdAutoHookApi(CAdHookApi *pHookApi, void *pAddr) {m_pHookApi = pHookApi;m_pAddr = pAddr;assert(m_pHookApi != NULL);if(m_pHookApi != NULL){m_pHookApi->End2(m_pAddr);} }CAdAutoHookApi::~CAdAutoHookApi() {if(m_pHookApi != NULL){m_pHookApi->Begin2(m_pAddr);} }// class CAdHookApi CAdHookApi::CAdHookApi() { }CAdHookApi::~CAdHookApi() {EndAll(); }BOOL CAdHookApi::VerifyAddress(void *pAddr, const BYTE *verifyData, DWORD verifySize) {BOOL isPassed = FALSE;if((verifyData != NULL) && (verifySize > 0)){BYTE *addrData = new BYTE[verifySize];if(myReadMemory(GetCurrentProcess(), pAddr, addrData, verifySize)){if(memcmp(addrData, verifyData, verifySize) == 0){isPassed = TRUE;}}delete []addrData;}else{isPassed = TRUE;}return isPassed; }BOOL CAdHookApi::PatchCode(void *pAddr, const BYTE *pCode, DWORD dwCode, const BYTE *verifyData, DWORD verifySize) {if(!VerifyAddress(pAddr, verifyData, verifySize)){return FALSE;}BOOL bRet = myWriteMemory(GetCurrentProcess(), pAddr, pCode, dwCode);return bRet; }HANDLE CAdHookApi::Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData) {HMODULE hModule = LoadLibrary(lpszModule);if(hModule == NULL){return NULL;}void *pOldAddr = (void *)GetProcAddress(hModule, lpcFuncName);if(pOldAddr == NULL){return NULL;}return Add(pOldAddr, pNewAddr, NULL, 0, dwData); }HANDLE CAdHookApi::Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData, DWORD verifySize, DWORD dwData) {BOOL bRet = FALSE;HookMap *pHook = new HookMap;do{ZeroMemory(pHook, sizeof(HookMap));pHook->hProcess = GetCurrentProcess();pHook->pOldAddr = pOldAddr;if(pHook->pOldAddr == NULL){break ;}DWORD dwRead = 8;if((verifyData != NULL) && (verifySize > 0) && (verifySize > dwRead)){dwRead = verifySize;}BYTE *addrData = new BYTE[dwRead];if(!myReadMemory(pHook->hProcess, pHook->pOldAddr, addrData, dwRead)){delete []addrData;break ;}if((verifyData != NULL) && (verifySize > 0) && (memcmp(addrData, verifyData, verifySize) != 0)){delete []addrData;break ;}memcpy(pHook->chOldCode, addrData, 8);delete []addrData;DWORD dwTemp = (DWORD)pNewAddr;pHook->pNewAddr = pNewAddr;// mov eax, pNewAddr// jmp eaxpHook->chNewCode[0] = 0xB8;memcpy(pHook->chNewCode + 1, &dwTemp, sizeof(DWORD));pHook->chNewCode[5] = 0xFF;pHook->chNewCode[6] = 0xE0; pHook->bHooked = FALSE;pHook->dwData = dwData;m_obHooks.push_back(pHook);bRet = TRUE;}while(0);if(!bRet){delete pHook;pHook = NULL;}return (HANDLE)pHook; }BOOL CAdHookApi::Remove(HANDLE hHook) {BOOL bRet = FALSE;HookMap *pHook = (HookMap *)hHook;for(int i = 0; i < (int)m_obHooks.size(); i ++){HookMap *pTemp = m_obHooks[i];if(pTemp == pHook){End((HANDLE)pTemp);delete pHook;m_obHooks.erase(m_obHooks.begin() + i);bRet = TRUE;break ;}}return bRet; }BOOL CAdHookApi::Begin(HANDLE hHook) {if(!HasHook(hHook)){return FALSE;}HookMap *pHook = (HookMap *)hHook;if(pHook->bHooked){return TRUE;}DWORD dwWrite = 8; BOOL bRet = myWriteMemory(pHook->hProcess, pHook->pOldAddr, pHook->chNewCode, dwWrite);if(bRet){pHook->bHooked = TRUE;}return bRet; }BOOL CAdHookApi::End(HANDLE hHook) {if(!HasHook(hHook)){return FALSE;}HookMap *pHook = (HookMap *)hHook;if(!pHook->bHooked){return FALSE;}DWORD dwWrite = 8;BOOL bRet = myWriteMemory(pHook->hProcess, pHook->pOldAddr, pHook->chOldCode, dwWrite);if(bRet){pHook->bHooked = FALSE;}return bRet; }BOOL CAdHookApi::Begin2(void *pNewAddr) {HookMap *pHook = FromNewAddr(pNewAddr);if(pHook == NULL){return FALSE;}return Begin((HANDLE)pHook); }BOOL CAdHookApi::End2(void *pNewAddr) {HookMap *pHook = FromNewAddr(pNewAddr);if(pHook == NULL){return FALSE;}return End((HANDLE)pHook); }void *CAdHookApi::OldAddr2NewAddr(void *pOldAddr) {HookMap *pHook = FromOldAddr(pOldAddr);if(pHook == NULL){return NULL;}return pHook->pNewAddr; }void *CAdHookApi::NewAddr2OldAddr(void *pNewAddr) {HookMap *pHook = FromNewAddr(pNewAddr);if(pHook == NULL){return NULL;}return pHook->pOldAddr; }CAdHookApi::HookMap *CAdHookApi::FromNewAddr(void *pNewAddr) {HookMap *pHook = NULL;for(int i = 0; i < (int)m_obHooks.size(); i ++){HookMap *pTemp = m_obHooks[i];if(pTemp->pNewAddr == pNewAddr){pHook = pTemp;break ;}}return pHook; }CAdHookApi::HookMap *CAdHookApi::FromOldAddr(void *pOldAddr) {HookMap *pHook = NULL;for(int i = 0; i < (int)m_obHooks.size(); i ++){HookMap *pTemp = m_obHooks[i];if(pTemp->pOldAddr == pOldAddr){pHook = pTemp;break ;}}return pHook; }BOOL CAdHookApi::HasHook(HANDLE hHook) {BOOL bRet = FALSE;HookMap *pHook = (HookMap *)hHook;for(int i = 0; i < (int)m_obHooks.size(); i ++){HookMap *pTemp = m_obHooks[i];if(pTemp == pHook){bRet = TRUE;break ;}}return bRet; }int CAdHookApi::BeginAll() {int nRet = 0;for(int i = 0; i < (int)m_obHooks.size(); i ++){HookMap *pTemp = m_obHooks[i];BOOL bRet = Begin((HANDLE)pTemp);if(bRet){nRet ++;}}return nRet; }int CAdHookApi::EndAll() {int nRet = 0;for(int i = 0; i < (int)m_obHooks.size(); i ++){HookMap *pTemp = m_obHooks[i];BOOL bRet = End((HANDLE)pTemp);delete pTemp;if(bRet){nRet ++;}}m_obHooks.clear();return nRet; }int CAdHookApi::GetCount() {return (int)m_obHooks.size(); }User1 自己注入自己(測(cè)試用) #include "stdafx.h" #include "AdHookApi.h" #include <windows.h> using namespace std;static CAdHookApi AdHookApi;int WINAPI mYMessageBoxW( __in_opt HWND hWnd, __in_opt LPCWSTR lpText, __in_opt LPCWSTR lpCaption, __in UINT uType) {//如果是做過濾,記得先關(guān)閉掉當(dāng)前的劫持,然后調(diào)用原API(給調(diào)用者看,當(dāng)然這個(gè)地方也可以進(jìn)行參數(shù)修改),//然后再改成劫持的地址 也就是 end(a) do happythings begin(a)MessageBoxA(NULL ,"B" ,"B" ,MB_OK);return 0; }int main() {AdHookApi.Add(_T("User32.dll") ,"MessageBoxW" ,mYMessageBoxW);::MessageBoxW(NULL ,L"A" ,L"A" ,MB_OK);AdHookApi.BeginAll();::MessageBoxW(NULL ,L"A" ,L"A" ,MB_OK);AdHookApi.EndAll();::MessageBoxW(NULL ,L"A" ,L"A" ,MB_OK);return 0; }User2 DLL #include "stdafx.h" #include "ApiDebugger.h" #include "AdHookApi.h" #include <tlhelp32.h> #include <wincrypt.h> #include "Common.h"static const char * gCopyright = "ApiDebugger by CodeLive, email : dongfa@yeah.net"; static CAdHookApi gHooks;bool gEnableLogOutput = true;extern "C" APIDEBUGGER const char * ApiDebugger() {return gCopyright; }///BOOL WINAPI my_IsDebuggerPresent(VOID) {return FALSE; }int WINAPI my_CompareStringW(LCID Locale, DWORD dwCmpFlags, PCNZWCH lpString1, int cchCount1, PCNZWCH lpString2,int cchCount2) {CAdAutoHookApi autoHook(&gHooks, my_CompareStringW);logOutput(formatString("ApiDebugger - CompareStringW.\r\n"));int ret = CompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2);logOutput(formatString("ApiDebugger - CompareStringW(%S, %S).\r\n", lpString1, lpString2));return ret; }BOOL WINAPI my_CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR szContainer, LPCWSTR szProvider, DWORD dwProvType, DWORD dwFlags) {CAdAutoHookApi autoHook(&gHooks, my_CryptAcquireContextW);BOOL ret = CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags);logOutput(formatString("ApiDebugger - CryptAcquireContextW(0x%08X, %S, %S, 0x%08X, 0x%08X) : %S.\r\n",(int)(*phProv),(szContainer != NULL) ? szContainer : L"NULL",(szProvider != NULL) ? szProvider : L"NULL",dwProvType, dwFlags,ret ? L"TRUE" : L"FALSE"));return ret; }BOOL WINAPI my_CryptImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, HCRYPTKEY hPubKey,DWORD dwFlags, HCRYPTKEY *phKey) {CAdAutoHookApi autoHook(&gHooks, my_CryptImportKey);BOOL ret = CryptImportKey(hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);string hexData = toHexString((const char *)pbData, dwDataLen);logOutput(formatString("ApiDebugger - CryptImportKey(0x%08X, %s, 0x%08X, 0x%08X, 0x%08X) : %S.\r\n",(int)hProv, hexData.c_str(), (int)hPubKey, dwFlags, (int)(*phKey), ret ? L"TRUE" : L"FALSE"));return ret; }BOOL WINAPI my_CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash) {CAdAutoHookApi autoHook(&gHooks, my_CryptCreateHash);BOOL ret = CryptCreateHash(hProv, Algid, hKey, dwFlags, phHash);logOutput(formatString("ApiDebugger - CryptCreateHash(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X) : %S.\r\n",(int)hProv, (int)Algid, (int)hKey, dwFlags, (int)phHash,ret ? L"TRUE" : L"FALSE"));return ret; }BOOL WINAPI my_CryptHashData(HCRYPTHASH hHash, CONST BYTE *pbData, DWORD dwDataLen, DWORD dwFlags) {CAdAutoHookApi autoHook(&gHooks, my_CryptHashData);BOOL ret = CryptHashData(hHash, pbData, dwDataLen, dwFlags);string hexData = toHexString((const char *)pbData, dwDataLen);logOutput(formatString("ApiDebugger - CryptHashData(0x%08X, %s, 0x%08X) : %S.\r\n",(int)hHash, hexData.c_str(), dwFlags,ret ? L"TRUE" : L"FALSE"));return ret; }BOOL WINAPI my_CryptDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey) {CAdAutoHookApi autoHook(&gHooks, my_CryptDeriveKey);BOOL ret = CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey);logOutput(formatString("ApiDebugger - CryptDeriveKey(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X) : %S.\r\n",(int)hProv, (int)Algid, (int)hBaseData, dwFlags, (int)phKey,ret ? L"TRUE" : L"FALSE"));return ret; }BOOL WINAPI my_CryptDecrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags,BYTE *pbData, DWORD *pdwDataLen) {CAdAutoHookApi autoHook(&gHooks, my_CryptDecrypt);string hexData1 = toHexString((const char *)pbData, *pdwDataLen);writeDataToFile("CryptDec_IN.bin", pbData, *pdwDataLen);BOOL ret = CryptDecrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen);string hexData2 = toHexString((const char *)pbData, *pdwDataLen);writeDataToFile("CryptDec_OUT.bin", pbData, *pdwDataLen);logOutput(formatString("ApiDebugger - CryptDecrypt(0x%08X, 0x%08X, %S, 0x%08X, %s=>%s) : %S.\r\n",(int)hKey, (int)hHash, Final ? L"TRUE" : L"FALSE",dwFlags, hexData1.c_str(), hexData2.c_str(), ret ? L"TRUE" : L"FALSE"));return ret; }typedef int (__cdecl *sub_4026B0_func)(BYTE *pbData);// 004026B0 ; static int my_sub_4026B0(BYTE *pbData) {CAdAutoHookApi autoHook(&gHooks, my_sub_4026B0);sub_4026B0_func sub_4026B0 = (sub_4026B0_func)(0x004026B0);string hexData1 = toHexString((const char *)pbData, strlen((const char *)pbData));int ret = sub_4026B0(pbData);string hexData2 = toHexString((const char *)pbData, strlen((const char *)pbData));logOutput(formatString("ApiDebugger - sub_4026B0(%s=>%s)",hexData1.c_str(), hexData2.c_str()));return ret; }///void ApiDebugferShutdown() {gHooks.EndAll();logOutput("ApiDebugger Shutdown.\r\n"); }BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:{ // gHooks.Add(_T("KERNEL32.DLL"), "IsDebuggerPresent", my_IsDebuggerPresent); // gHooks.Add(_T("KERNEL32.DLL"), "CompareStringW", my_CompareStringW);gHooks.Add(_T("ADVAPI32.DLL"), "CryptAcquireContextW", my_CryptAcquireContextW);gHooks.Add(_T("ADVAPI32.DLL"), "CryptImportKey", my_CryptImportKey);gHooks.Add(_T("ADVAPI32.DLL"), "CryptCreateHash", my_CryptCreateHash);gHooks.Add(_T("ADVAPI32.DLL"), "CryptHashData", my_CryptHashData);gHooks.Add(_T("ADVAPI32.DLL"), "CryptDeriveKey", my_CryptDeriveKey);gHooks.Add(_T("ADVAPI32.DLL"), "CryptDecrypt", my_CryptDecrypt); /*const BYTE verifyData[] = { 0x55, 0x8B, 0xEC, 0x81, 0xEC, 0x2C, 0x01, 0x00, 0x00 };void *addr = (void *)0x004026B0;if(gHooks.Add(addr, my_sub_4026B0, verifyData, sizeof(verifyData), 0) != NULL){logOutput(formatString("ApiDebugger - hook sub_4026B0 ok.\r\n"));}else{logOutput(formatString("ApiDebugger - hook sub_4026B0 failed.\r\n"));} */gHooks.BeginAll();logOutput(formatString("ApiDebugger - %s.\r\n", gCopyright));logOutput("ApiDebugger Loaded.\r\n");}break ;case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:{}break ;case DLL_PROCESS_DETACH:{ApiDebugferShutdown();logOutput("ApiDebugger Unloaded.\r\n");}break;}return TRUE; }
總結(jié)
以上是生活随笔為你收集整理的windows-API劫持(API-HOOK)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab 介电常数,改进的基于Mat
- 下一篇: 汇编程序求助,window.inc报错