通过DLL劫持技术HookAPI

DLL劫持技术当一个可执行文件运行时,Windows加载器将可执行模块映射到进程的地址空间中,加载器分析可执行模块的输入表,并设法找出任何需要的DLL,并将它们映射到进程的地址空间中。

由于输入表中只包含DLL名而没有它的路径名,因此加载程序必须在磁盘上搜索DLL文件。

首先会尝试从当前程序所在的目录加载DLL,如果没找到,则在Windows系统目录中查找,最后是在环境变量中列出的各个目录下查找。

利用这个特点,先伪造一个系统同名的DLL,提供同样的输出表,每个输出函数转向真正的系统DLL。

程序调用系统DLL时会先调用当前目录下伪造的DLL,完成相关功能后,再跳到系统DLL同名函数里执行,如图18.3所示。

这个过程用个形象的词来描述就是系统DLL被劫持(hijack)了。

图18.3 DLL劫持技术演示利用这种方法取得控制权后,可以对主程序进行补丁。

此种方法只对除kernel32.dll、ntdll.dll等核心系统库以外的DLL有效,如网络应用程序的ws2_32.dll、游戏程序中的d3d8.dll,还有大部分应用程序都调用的lpk.dll,这些DLL都可被劫持。

利用第5章5.6.2节提供的CrackMeNet.exe来演示一下如何利用劫持技术制作补丁,目标文件用Themida v1.9.2.0加壳保护。

1.补丁地址去除这个CrackMe网络验证方法参考第5章5.6.2节,将相关补丁代码存放到函数PatchProcess()里。

例如将401496h改成:00401496 EB 29 jmp short 004014C1补丁编程实现就是:unsigned char p401496[2] = {0xEB, 0x29};WriteProcessMemory(hProcess,(LPVOID)0x401496, p401496, 2, NULL);p401496这个数组的数据格式,可以用OllyDbg插件获得,或十六进制工具转换。

例如Hex Workshop打开文件,执行菜单“Edit/Copy As/Source”即可得到相应的代码格式。

2.构建输出函数查看实例CrackMeNet.exe输入表,会发现名称为“ws2_32.dll”的DLL,因此构造一个同名的DLL来完成补丁任务。

伪造的ws2_32.dll 有着真实ws2_32.dll一样的输出函数,完整源码见光盘映像文件。

实现时,可以利用DLL模块中的函数转发器来实现这个目标,其会将对一个函数的调用转至另一个DLL中的另一个函数。

可以这样使用一个pragma指令:#pragma comment(linker, "/EXPORT:SomeFunc=DllWork.someOtherFunc")这个pragma告诉链接程序,被编译的DLL应该输出一个名叫SomeFunc的函数。

但是SomeFunc函数的实现实际上位于另一个名叫SomeOtherFunc的函数中,该函数包含在称为DllWork. dll的模块中。

如果要达到劫持DLL的目的,生成的DLL输出函数必须与目标DLL输出函数名一样。

本例可以这样构造pragma指令:#pragma comment(linker, "/EXPORT:WSAStartup=_MemCode_WSAStartup,@115") 编译后的DLL,会有与ws2_32.dll同名的一个输出函数WSAStartup,实际操作时,必须为想要转发的每个函数创建一个单独的pragma代码行,读者可以用工具AheadLib或用其他办法,将ws2_32.dll输出函数转换成相应的pragma指令。

当应用程序调用伪装ws2_32.dll的输出函数时,必须将其转到系统ws2_32.dll中,这部分的代码自己实现。

例如,WSAStartup输出函数构造如下:ALCDECL MemCode_WSAStartup(void){GetAddress("WSAStartup");__asm JMP EAX;//转到系统ws2_32.dll的WSAStartup输出函数}其中,GetAddress()函数的代码如下:// MemCode 命名空间namespace MemCode{HMODULE m_hModule = NULL; //原始模块句柄DWORD m_dwReturn[500] = {0}; //原始函数返回地址// 加载原始模块inline BOOL WINAPI Load(){TCHAR tzPath[MAX_PATH]={0};TCHAR tzTemp[MAX_PATH]={0};GetSystemDirectory(tzPath, sizeof(tzPath));strcat(tzPath,"\\ws2_32.dll");m_hModule = LoadLibrary(tzPath);//加载系统系统目录下ws2_32.dllif (m_hModule == NULL){wsprintf(tzTemp, TEXT("无法加载 %s,程序无法正常运行。

"), tzPath);MessageBox(NULL, tzTemp, TEXT("MemCode"), MB_ICONSTOP); }return (m_hModule != NULL);}// 释放原始模块inline VOID WINAPI Free(){if (m_hModule)FreeLibrary(m_hModule);}// 获取原始函数地址FARPROC WINAPI GetAddress(PCSTR pszProcName){FARPROC fpAddress;TCHAR szProcName[16]={0};TCHAR tzTemp[MAX_PATH]={0};if (m_hModule == NULL){if (Load() == FALSE)ExitProcess(-1);}fpAddress = GetProcAddress(m_hModule, pszProcName);if (fpAddress == NULL){if (HIWORD(pszProcName) == 0){wsprintf(szProcName, "%d", pszProcName);pszProcName = szProcName;}wsprintf(tzTemp, TEXT("无法找到函数 %hs,程序无法正常运行。

"), pszProcName);MessageBox(NULL, tzTemp, TEXT("MemCode"), MB_ICONSTOP); ExitProcess(-2);}return fpAddress;}}using namespace MemCode;编译后,用LordPE查看伪造的ws2_32.dll输出函数,和真实ws2_32.dll完全一样,如图18.4所示。

(点击查看大图)图18.4 伪造ws2_32.dll的输出表查看伪造的ws2_32.dll中任意一个输出函数,例如WSACleanup:.text:10001CC0 ; int __stdcall WSACleanup().text:10001CC0 WSACleanup proc near.text:10001CC0 push offsetaWsacleanup ;"WSACleanup".text:10001CC5 call sub_10001000 ;GetAddress(WSA Cleanup).text:10001CCA jmp eax.text:10001CCA WSACleanup endp会发现输出函数WSACleanup()首先调用GetAddress(WSACleanup),获得真实ws2_32.dll中WSACleanup的地址,然后跳过去执行,也就是说,ws2_32.dll各输出函数被Hook了。

3.劫持输出函数ws2_32.dll有许多输出函数,经分析,程序发包或接包时,WSAStartup输出函数调用的比较早,因此在这个输出函数放上补丁的代码。

代码如下:ALCDECL MemCode_WSAStartup(void){hijack();GetAddress("WSAStartup");__asm JMP EAX;}hijack()函数主要是判断是不是目标程序,如果是就调用PatchProcess()进行补丁。

void hijack(){if (isTarget(GetCurrentProcess())) //判断主程序是不是目标程序,是则补丁之{PatchProcess(GetCurrentProcess());}}伪造的ws2_32.dll制作好后,放到程序当前目录下,这样当原程序调用WSASTartup函数时就调用了伪造的ws2_32.dll的WSASTartup 函数,此时hijack()函数负责核对目标程序校验,并将相关数据补丁好,处理完毕后,转到系统目录下的ws2_32.dll执行。

这种补丁技术,对加壳保护的软件很有效,选择挂接的函数最好是在壳中没有被调用的,当挂接函数被执行时,相关的代码已被解压,可以直接补丁了。

在有些情况下,必须用计数器统计挂接的函数的调用次数来接近OEP。

此方法巧妙地绕过了壳的复杂检测,很适合加壳程序的补丁制作。

一些木马或病毒也会利用DLL劫持技术搞破坏,因此当在应用程序目录下发现系统一些DLL文件存在时,如lpk.dll,应引起注意。

合集下载

利用HOOKAPI拦截文件操作

利用HOOKAPI拦截文件操作

利⽤HOOKAPI拦截⽂件操作先读下HookAPI 使⽤⽂档:功能简介HookAPI 是⼀个截获Windows 32位API函数的开发包,它可以在Windows调⽤某个API函数的时候,先调⽤⾃⼰编写的函数,从⽽实现特殊的功能。

HookAPI同样也适⽤于截获⽤户⾃⼰编写的DLL⽂件中的输出函数。

1.5系统特点:1)⾃⼰编写的替代函数的参数形式和原API函数完全⼀样,⽅便了Delphi和VB⽤户的使⽤。

2)实时截获所有新建⽴的进程,即进程建⽴后马上安装钩⼦,⽽不是采⽤定时扫描进程的⽅法3)由于不采⽤定时扫描进程的⽅法,所以系统资源消耗少,基本上看不到消耗CPU资源。

4)新建⽴的InstDLL动态库,减少了⽤户调⽤HookAPI的代码。

运⾏和开发平台为Windows NT/2000/9x/XP包含的⽂件列表:【EXE⽬录】:调⽤InstHook.dll来安装HookAPI的执⾏程序【InstHook⽬录】:安装HookAPI的DLL程序【dll⽬录】:NT/2000/XP/XP下截获32位API函数的DLL程序【HOOKAPI9x.dll】:Win9x下截获32位API函数的DLL程序【EXE⽬录】:HookAPI.exe的源码【HOOKSOCKET⽬录】:截获Socket函数的mydll例⼦【HOOKREG⽬录】:截获注册表函数的mydll例⼦【HOOKFILE⽬录】:截获⽂件存取的mydll例⼦【HOOKFILE9x⽬录】:win9x下的截获⽂件存取的mydll_9x例⼦【HookFile_Delphi⽬录】:截获⽂件存取的Delphi下的mydll的例⼦【HookSocket_Delphi⽬录】:截取Socket函数的Delphi下的mydll的例⼦使⽤:⽤户编写要截获的API函数相对应的⾃⼰的实现函数,编译成mydll.dll,同时在⾃⼰的程序中调⽤InstHook.dll中的安装/卸载函数就可以实现⾃⼰的截获过程。

APIHOOK的实现原理

APIHOOK的实现原理

APIHOOK的实现原理API Hooking(API挂钩)是一种常见的软件技术,用于修改或者扩展应用程序的行为,它通过“操纵”应用程序的API调用过程来实现这一目标。

API Hooking通常用于各种目的,例如:监视应用程序的行为、修复漏洞、收集数据等。

本文将介绍API Hook的实现原理及其相关概念。

1. API Hook概述API Hooking通过劫持和修改应用程序对动态链接库(DLL)中导出函数的调用来实现目标功能。

在Windows操作系统中,每个可执行文件都会使用一些API函数,这些函数由系统提供并存储在动态链接库中。

当应用程序调用这些函数时,操作系统会在库文件中查找并执行相应的函数代码。

API Hooking就是在应用程序和DLL之间插入一个中间层,通过改变函数调用的目标,来控制和改变应用程序的行为。

API Hooking的实现原理可以归纳为以下几个步骤:(1)定位目标函数:首先,需要确定要Hook的目标函数。

可以通过静态分析程序源代码、反汇编可执行文件、监视应用程序行为等方法来获取目标函数的地址或名称。

(2)获取目标函数的原始地址:通过动态链接库(DLL)中的导入表,可以获取到目标函数的原始地址。

导入表中保存了DLL中导出函数地址的引用。

(3)Hook目标函数:Hook目标函数的方式有多种,这里介绍两种常见的方式。

a. 钩子函数(Hook Function):通过将Hook函数替换为目标函数的调用,可以劫持目标函数的执行。

Hook函数在执行之前、中间或者之后可以执行额外的逻辑操作,并返回结果给应用程序。

b. IAT Hooking(Import Address Table Hooking):IAT是动态链接库中的导入表,包含了动态链接库中导出函数的地址。

通过修改IAT中目标函数的地址,将其指向Hook函数,即可实现Hook效果。

(4)重定向函数调用:Hook目标函数后,需要将应用程序中对目标函数的调用重定向到Hook函数。

windows-API劫持(API-HOOK)

windows-API劫持(API-HOOK)

windows-API劫持(API-HOOK)API HookApiHook⼜叫做API劫持,也就是如果A程序调⽤了B.cll⾥⾯的C函数,我们可以做到当A调⽤C函数执⾏的时候,直接执⾏我们⾃⼰事先准备好的函数,之后我们在执⾏真正的C,当然我们可以不执⾏C或者更改C的参数等等,实现的核⼼思路就是:mov eax, pNewAddr[/size][size=3] jmp eaxAdHookApi.h#ifndef __ADHOOKAPI_H__#define __ADHOOKAPI_H__#include <windows.h>#include <tchar.h>#include <vector>using namespace std;// class CAdAutoHookApiclass CAdHookApi;class CAdAutoHookApi{public:CAdAutoHookApi(CAdHookApi *pHookApi, void *pAddr);virtual ~CAdAutoHookApi();private:CAdHookApi *m_pHookApi;void *m_pAddr;};// class CAdAutoHookclass 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;};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 CAdAutoHookApiCAdAutoHookApi::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 CAdHookApiCAdHookApi::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);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){}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;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 ⾃⼰注⼊⾃⼰(测试⽤)#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) {//如果是做过滤,记得先关闭掉当前的劫持,然后调⽤原API(给调⽤者看,当然这个地⽅也可以进⾏参数修改),//然后再改成劫持的地址也就是 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 <tlhelp32.h>#include <wincrypt.h>#include "Common.h"static const char * gCopyright = "ApiDebugger by CodeLive, email : dongfa@";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"));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;}。

hook技术原理

hook技术原理

Hook技术是一种用于拦截API函数调用的技术,它通过修改系统API函数的内存地址,从而拦截系统函数的调用,实现对系统API函数的拦截和修改。

Hook技术的基本原理是将系统API函数的内存地址指向一个用户定义的函数,而不是指向实际的API函数。

当调用系统API函数时,系统将调用用户定义的函数,而不是原来的函数。

这样就可以实现对系统API函数的拦截和修改。

Hook技术的实现步骤如下:
1、首先,程序员需要查找和定位需要拦截的API函数的内存地址。

2、然后,程序员需要编写用户定义的函数,用来拦截和修改系统API函数的调用。

3、接着,程序员需要将系统API函数的内存地址指向用户定义的函数,从而实现API函数的拦截。

4、最后,程序员需要将系统API函数的原始内存地址保存起来,以便在不再需要拦截时,可以恢复原来的API函数调用行为。

Hook技术是一种强大的技术,可以用来实现各种功能,比如拦截软件的调用,拦截软件的输入输出,拦截系统函数的调用等。

Hook技术也可以用来实现防病毒,反垃圾邮件,防恶意程序,实现软件保护以及实现自定义控件等功能。

hook api

hook api

实现HOOK API两种方法
改引入表式 陷阱式
用改引入表式方法来实现,这种方法易 于实现,但要求你熟悉PE文件结构。主 要是定位到Kernel32.dll模块的 OpenProcess函数地址,并用 WriteProcessMemory函数改写函数地址。
进程的定义
通常被定义为一个正在运行的程序的实 例,是一个程序在其自身的地址空间中 的一次执行活动。 的一次执行活动。
Hook的应用模式 的应用模式
观察模式 最为常用,像Windows提供的SetWindowHook 就是典型地为这类应用准备的。而且这也是最 普遍的用法。 这个模式的特点是,在事情发生 的时候,发出一个通知信息。观察者只可以查 看过程中的信息,根据自己关心的内容处理自 己的业务,但是不可以更改原来的流程。 如全 局钩子中,经常使用的鼠标消息、键盘消息的 监视等应用。金山词霸屏幕取词的功能是一个 典型的应用
HOOKAPI的原则
被HOOK的API的原有功能不能受到任何 影响。就像医生救人,如果把病人身体里 的病毒杀死了,病人也死了,那么这个 “救人”就没有任何意义了。如果你 HOOK API之后,你的目的达到了,但 API的原有功能失效了,这样不是HOOK, 而是REPLACE,操作系统的正常功能就 会受到影响,甚至会崩溃。
HOOK API
Hook API是一种拦截应用程序API函 数调用的通用机制,通过建立API Hook 可以监视和改变应用程序的行为。 HookAPI 技术常用于屏幕取词、网络防 火墙、病毒木马等领域。
Hook就是钩子的意思,而API是指 Windows开放给程序员的编程接口,使 得在用户级别下可以对操作系统进行控 制,也就是一般的应用程序都需要调用 API来完成某些功能,Hook API就是在这 些应用程序调用真正的系统API前可以先 被截获,从而进行一些处理再调用真正 的API来完成功能。

DLL劫持技术

DLL劫持技术

AheadLib 2.2.150--------------------------------------------------------------------------------一、简介AheadLib 是用来生成一个特洛伊DLL的工具,用于分析DLL中的函数参数调用(比如记录Socket send 了什么等等)、更改函数功能(随心所欲了:)、更改界面功能(比如在Hook里面生成一个按钮,截获事件等等)。

二、使用1.用AheadLib 打开要模拟的DLL,生成一个CPP 文件。

2.用Visual Studio 6.0/.NET 建立一个DLL 工程,把这个CPP 文件加入到项目中。

3.使用Release 方式编译,生成的DLL 将和原来的DLL 具有一模一样的导出函数,并且能顺利把这些函数转发到原来的函数中。

4.AheadLib 还可以生成Hook 代码,用于截取当前进程的所有消息,这样就可以随心所欲地处理各种消息了(修改第三方程序界面功能的好助手)。

三、备注1.如果导出函数过多,在Visual Studio 6.0 中,如果出现编译错误,请在项目属性关闭与编译头功能。

2.如果是C++ 、C __stdcall、C __fastcall 的方式导出的话,生成的函数声明将会还原成原代码级别(可能需要修改才能编译,比如导出C++类的情况)。

此时使用__declspec(dllexport) 导出——不能指定导出序号。

3.如果是NONAME 或者C _CDECL 方式导出(比如DEF 导出,大多数Windows DLL都是这种情况,比如WS2_32等等),则使用#pragma comment(linker, "/EXPORT:...)导出,且指定导出序号。

4.如果系统中没有DbgHelp.dll,将无法识别C++ 模式的导出。

DLL劫持技术说明我是从CoDe_Inject帮助下才了解这个DLL劫持技术(或称HOOK),利用这个制作内存补丁非常的好用。

HOOK的原理


这种DLL注入方式有两个优点: 这种机制在Win 9x/Me和Win NT/2K中都是得到支持的,预计在以后的版本中也将得到支持;钩子DLL可以在不需要的时候,可由我们主动的调用 UnHookWindowsHookEx来卸载,比起使用注册表的机制来说方便了许多。尽管这是一种相当简洁明了的方法,但它也有一些显而易见的缺点:首先值得我们注意的是,Windows钩子将会降低整个系统的性能,因为它额外增加了系统在消息处理方面的时间;其次,只有当目标进程准备接受某种消息时,钩子所在的DLL才会被系统映射到该进程的地址空间中,钩子才能真正开始发挥作用,因此如果我们要对某些进程的整个生命周期内的API调用情况进行监控,用这种方法显然会遗漏某些API的调用 。
通常可采用的几种注入方式:
1.利用注册表
如果我们准备拦截的进程连接了User32.dll,也就是使用了User32.dll中的API(一般图形界面的应用程序都是符合这个条件),那么就可以简单把你的钩子驱动器DLL的名字作为值添加在下面注册表的键下: HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\Windows\AppInit_DLLs 值的形式可以为单个DLL的文件名,或者是一组DLL的文件名,相邻的名称之间用逗号或空格间隔。所有由该值标识的DLL将在符合条件的应用程序启动的时候装载。这是一个操作系统内建的机制,相对其他方式来说危险性较小,但它也有一些比较明显的缺点:该方法仅适用于NT/2K操作系统,显然看看键的名称就可以明白;如果需要激活或停止钩子的注入,只有重新启动Windows,这个就似乎太不方便了;最后一点也很显然,不能用此方法向没有使用User32.dll的应用程序注入DLL,例如控制台应用程序等。另外,不管是否为你所希望,钩子DLL将注入每一个GUI应用程序,这将导致整个系统性能的下降!

hook api几种方法


:71A21B72 8B4508 mov eax, dword ptr [ebp+08]
:71A21B75 5F pop edi
:71A21B76 5E pop esi
:71A21B77 C9 leave
:71A21B78 C21000 ret 0010
下面用4种方法来HOOK这个API:
:71A21B62 8BD8 mov ebx, eax
:71A21B64 E8C7F6FFFF call 71A21230 //将被HOOK的机器码(第3种方法)
:71A21B69 3BDF cmp ebx, edi
:71A21B6B 5B pop ebx
:71A21B6C 0F855F940000 jne 71A2AFD1
假设我们的HOOK代码在71A20400处,那么我们把71A21B64处的CALL指令改为CALL 71A20400(原指令是这样的:CALL 71A21230)
而71A20400处的HOOK代码是这样的:
71A20400:
pushad
//在这里做你想做的事情
:71A21B42 57 push edi
:71A21B43 57 push edi
:71A21B44 FF7514 push [ebp+14]
:71A21B47 8945F0 mov dword ptr [ebp-10], eax
:71A21B4A 8B450C mov eax, dword ptr [ebp+0C]
4,上下文的问题,有些HOOK代码不能执行某些操作,否则会破坏原API的上下文,原API就失效了;
5,同步问题,在HOOK代码里尽量不使用全局变量,而使用局部变量,这样也是模块化程序的需要;

Windows中Hook API技术

Windows下Hook API技术 inline hook分类: WINDOWS什么叫Hook API?所谓Hook就是钩子的意思,而API是指 Windows开放给程序员的编程接口,使得在用户级别下可以对操作系统进行控制,也就是一般的应用程序都需要调用API来完成某些功能, Hook API的意思就是在这些应用程序调用真正的系统API前可以先被截获,从而进行一些处理再调用真正的API来完成功能。

在讲Hook API之前先来看一下如何Hook消息,例如Hook全局键盘消息,从而可以知道用户按了哪些键,这种Hook消息的功能可以由以下函数来完成,该函数将一个新的 Hook加入到原来的Hook链中,当某一消息到达后会依次经过它的Hook链再交给应用程序。

HHOOK SetWindowsHookEx(int idHook, //Hook类型,例如WH_KEYBOARD,WH_MOUSEHOOKPROC lpfn, //Hook处理过程函数的地址HINSTANCE hMod, //包含Hook处理过程函数的dll句柄(若在本进程可以为NULL)DWORD dwThreadId, //要Hook的线程ID,若为0,表示全局Hook所有);这里需要提一下的就是如果是Hook全局的而不是某个特定的进程则需要将Hook过程编写为一个DLL,以便让任何程序都可以加载它来获取Hook过程函数。

而对于Hook API微软并没有提供直接的接口函数,也许它并不想让我们这样做,不过有2种方法可以完成该功能。

第一种,修改可执行文件的IAT表(即输入表),因为在该表中记录了所有调用API的函数地址,则只需将这些地址改为自己函数的地址即可,但是这样有一个局限,因为有的程序会加壳,这样会隐藏真实的IAT表,从而使该方法失效。

第二种方法是直接跳转,改变API函数的头几个字节,使程序跳转到自己的函数,然后恢复API开头的几个字节,在调用AP完成功能后再改回来又能继续Hook了,但是这种方法也有一个问题就是同步的问题,当然这是可以克服的,并且该方法不受程序加壳的限制。

HOOKAPI(一)——HOOK基础+一个鼠标钩子实例

HOOKAPI(⼀)——HOOK基础+⼀个⿏标钩⼦实例HOOK API (⼀)——HOOK基础+⼀个⿏标钩⼦实例code: https:///hfl15/windows_kernel_development/tree/master/demo_source_code/MouseHook0x00 起因最近在做毕业设计,有⼀个功能是需要实现对剪切板的监控和进程的防终⽌保护。

原本想从内核层实现,但没有头绪。

最后决定从调⽤层⼊⼿,即采⽤HOOK API的技术来挂钩相应的API,从⽽实现预期的功能。

在这样的需求下,就开始学习了HOOK API。

0x01什么是HOOK APIHOOK(钩⼦,挂钩)是⼀种实现Windows平台下类似于中断的机制。

HOOK机制允许应⽤程序拦截并处理Windows消息或指定事件,当指定的消息发出后,HOOK程序就可以在消息到达⽬标窗⼝之前将其捕获,从⽽得到对消息的控制权,进⽽可以对该消息进⾏处理或修改,加⼊我们所需的功能。

钩⼦按使⽤范围分,可分为线程钩⼦和系统钩⼦,其中,系统钩⼦具有相当⼤的功能,⼏乎可以实现对所有Windows消息的拦截、处理和监控。

这项技术涉及到两个重要的API,⼀个是SetWindowsHookEx,安装钩⼦;另⼀个是UnHookWindowsHookEx,卸载钩⼦。

本⽂使⽤的HOOK API技术,是指截获系统或进程对某个API函数的调⽤,使得API的执⾏流程转向我们指定的代码段,从⽽实现我们所需的功能。

Windows下的每个进程均拥有⾃⼰的地址空间,并且进程只能调⽤其地址空间内的函数,因此HOOK API尤为关键的⼀步是,设法将⾃⼰的代码段注⼊到⽬标进程中,才能进⼀步实现对该进程调⽤的API进⾏拦截。

然⽽微软并没有提供HOOK API的调⽤接⼝,这就需要开发者⾃⼰编程实现,⼤家所熟知的防毒软件、防⽕墙软件等均采⽤HOOK API实现。

⼀般来说,HOOK API由两个组成部分,即实现HOOK API的DLL⽂件,和启动注⼊的主调程序。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档