先读下
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中的安装/卸载函数就可以实现自己的截获过程。
开发指南
用户需要做的就是编写一个替换老API函数的mydll.dll,并在自己的程序中调用InstHook.dll中的安装/卸载函数就行了。 Mydll文件的编写:1) 建立生成DLL的工程文件mydll 2) 如果工程名称不是mydll,则如果是win9x,则在工程文件的设置中修改生成的目标输出文件为mydll_9x.dll,其他操作系统(NT/2K/XP)输出文件为mydll.dll 3) 编写含有自己的调用过程的mydll.cpp程序和DLL输出函数说明文件mydll.def 4) 编译生成mydll.dll/mydll_9x.dll
mydll.cpp文件的编写从三个例子程序可以看出,mydll.cpp文件其实非常简单,它包含如下内容 1) 包含mydll.h文件,此文件中只有一个MYAPIINFO结构说明: typedef struct { char *module_name; char *function_name; char *myfunc_name; }MYAPIINFO; module_name是要截获的DLL或其他模块文件的名称,如kernel32.dll function_name是要截获的API或用户DLL文件中函数的名称和参数,类似C中的说明格式,如connect函数为:connect(SOCKET, struct sockaddr *, INT) myfunc_name为自己编写的替代函数的名称,如自己编写了myconnect函数,则myfunc为”myconnect”
2) 为生成win9x下的dll文件(mydll_9x.dll)加入下列编译选项 #ifdef WIN95 #pragma code_seg("_INIT") #pragma comment(linker,"/SECTION:.bss,RWS /SECTION:.data,RWS /SECTION:.rdata,RWS /SECTION:.text,RWS /SECTION:_INIT,RWS ") #pragma comment(linker,"/BASE:0xBFF70000") #endif 如果是生成的win9x下的dll文件(mydll_9x.dll),那么编译选项里要先定义WIN95
3) 包含一个MYAPIINFO myapi_info[]结构数组定义并赋值,最后必须包含一个NULL项。此结构数组就是要截获的函数信息,如: MYAPIINFO myapi_info[] = { {"WSOCK32.DLL", "socket(INT, INT, INT)", “mysocket”}, {"WSOCK32.DLL", "connect(SOCKET, struct sockaddr *, INT)", “myconnect”}, {"WSOCK32.DLL", "recv(INT, char *, INT, INT)", “myrecv”}, {"WSOCK32.DLL", "send(INT, char *, INT, INT)", “mysend”}, {"ADVAPI32.DLL", "RegOpenKeyA(HKEY, LPCSTR, PHKEY)", “myRegOpenKeyA”}, {NULL,NULL,NULL} //最后必须包含此项 }; 4) 必须包含函数GetMyAPIInfo,如下: MYAPIINFO *GetMyAPIInfo() { return &myapi_info[0]; } 5) 编写替换函数,替换函数格式为: DWORD _cdecl MyFuncName(type1 param1, type2, param2, …) 其中函数必须为WINAPI调用方式(Delphi下为stdcall),函数的参数声明必须和原api函数中的参数相对应,如: int WINAPI myconnect(SOCKET s, struct sockaddr *name, int namelen) { struct sockaddr_in *paddr =(struct sockaddr_in *)name;
char *ip =inet_ntoa(paddr->sin_addr); int port =ntohs(paddr->sin_port); int ret =connect(s, name, namelen); int err=WSAGetLastError(); WriteLog("connect: ip=%s, port=%d, ret=%d\n", ip, port, ret); // check filter WSASetLastError(err); return ret; } 在此例子中,有保存和恢复错误码的代码,因为在编写自己的处理过程时,错误码可能会被修改,而原调用程序很可能根据错误码来判断进一步的动作;即使在myconnect中不调用原函数connect,那么在myconnect返回时,也要使用WSASetLastError或SetLastError来正确设置错误码。其他替换函数也应该这样做。 另外,在win9x下,最好在mydll中调用一下任意一个原先的api函数,以便mydll能调用原先的dll模块,否则就要在hookapi.exe中调用mydll前使用LoadLibrary调用一下原先的dll文件;否则将Hook不成功。
mydll.def文件的编写mydll.def中包含GetMyAPIInfo和自己编写的替换函数的输出说明,如下: EXPORTS GetMyAPIInfo @1 MyFunc1 @2 MyFunc2 @3
InstallHook.dll文件的使用InstHook.dll中的内容很简单,只有四个函数(参见InstHook.h): 1) int WINAPI InitHookAPI(); 此函数初始化HookAPI 2) int WINAPI HookAllProcesses(); 此函数实现截获和替换mydll中定义的API 3) int WINAPI UnhookAllProcesses(); 此函数恢复原先系统的mydll中定义的API 4) int WINAPI NTHookProcess(DWORD process_id); 此函数在NT下截获和替换某个特定的进程中的mydll中定义的API,进程必须已经存在 5) int WINAPI NTUnhookProcess(DWORD process_id); 此函数在NT下恢复某个特定的进程中的mydll中定义的API,进程必须已经存在 6) int WINAPI NTHookProcess2(char *mod_name); 此函数在NT下Hook某个文件或模块名为mod_name的进程,进程必须已经存在 7) int WINAPI NTUnhookProcess2(char *mod_name); 此函数在NT下Unhook此函数在NT下截获和替换某个文件或模块名为mod_name的进程,进程必须已经存在
例子说明API中实现了三个例子,每个例子都是截获函数调用,并写日志到c:\hookapi.log,并未进行其他的操作 截获Socket函数的例子本例子中演示了截获Windows 32位Socket API函数,截获的DLL文件为WSOCK32.dll,截获的函数有socket,connect,recv,send。 mysocket函数:只是写日志。用户可以不调用socket()函数而直接返回一个socket值,从而在所有的socket函数调用中实现虚假的网络调用,欺骗应用程序。 myconnect函数:写日志。用户可以在此如下修改myconnect函数:不调用connect()而直接返回成功,欺骗应用程序;connect另外一个主机地址;connect另外一个端口。 myrecv函数:写日志。用户可以在此如下修改myrecv函数:不调用recv()函数而直接填充自己的buf,欺骗应用程序;调用recv,记录分析接收的数据包;调用recv,解密数据包;调用recv,使用send和另一端再次通讯;等等。 mysend函数:写日志。用户可以在此如下修改mysend函数:不调用send()函数而直接返回成功,欺骗应用程序;记录分析要发送的数据包;加密数据包(使用另一个buffer),然后调用send将加密包发送出去;等等。 但截获标准Socket API并不能获取所有系统对网络存取的内容,如驱动程序对网络的存取,如果要截获所有网络存取情况,可以看ipfilter等相关的源码,在编程沙龙上有很多。 截获注册表函数的例子通过截获注册表函数和注册表的值,可以记录分析程序使用和创建了哪些注册表项,用于去除日期限制等应用。但截获标准注册表API并不能获取所有系统对文件存取的内容,如驱动程序对注册表的存取,如果要截获所有注册表存取情况,可以看regmon的源码,在编程沙龙上有。 截获文件存取的例子通过截获文件存取,用户可以分析某个程序的文件存取情况等,但截获标准文件API并不能获取所有系统对文件存取的内容,如驱动程序对文件的存取,如果要截获所有文件存取情况,可以看filemon的源码,在编程沙龙上有。
根据上述例子,用户可以编写自己感兴趣的mydll,截获系统API或某些应用程序附带的dll中的函数的使用情况,来实现自己的特殊功能,如通过截获CreateProcessW来限制用户只能执行特定的应用程序或打开特定的文件。
编译和运行将例子编译成mydll.dll/mydll_9x.dll,将mydll.dll、mydll_9x.dll、injlib.dll、HookAPINT.dll、HookAPI9x.dll、InstHook.dll放到和调用InstHook.dll的应用程序(如HookAPI.exe)相同的目录下。然后运行调用InstHook.dll<SPAN style="FONT-FAMILY: 宋体;
#ifdef WIN95 BOOL APIENTRY DllMain( HANDLE hModule, void WriteLog(char *fmt,...) GetModuleFileName(NULL, modname, sizeof(modname)); WriteFile(hFile, temp, strlen(temp), &dw, NULL); _lclose((HFILE)hFile); HANDLE WINAPI myCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) HANDLE WINAPI myCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) WriteLog("%s, myCreateFileW:filename=%s", temp, fname); return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
return ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); BOOL WINAPI myReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, return ReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead, BOOL WINAPI myDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) // struct _iobuf f; MYAPIINFO myapi_info[] = MYAPIINFO *GetMyAPIInfo()
|
利用HOOKAPI拦截文件操作
最新推荐文章于 2024-07-23 17:40:00 发布