利用HOOKAPI拦截文件操作

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

利⽤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中的安装/卸载函数就可以实现⾃⼰的截获过程。

开发指南
⽤户需要做的就是编写⼀个替换⽼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: 宋体;
#include "stdafx.h"
#include <stdio.h>
#include "mydll.h"
#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
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
void WriteLog(char *fmt,...)
{
va_list args;
char modname[200];
char temp[5000];
HANDLE hFile;
DWORD dw;
GetModuleFileName(NULL, modname, sizeof(modname));
if((hFile =CreateFile("c:\\hookapi.log", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) <0)
{
return;
}
_llseek((HFILE)hFile, 0, SEEK_END);
wsprintf(temp, "mydll.dll:%s:", modname);
WriteFile(hFile, temp, strlen(temp), &dw, NULL);
va_start(args,fmt);
vsprintf(temp, fmt, args);
va_end(args);
WriteFile(hFile, temp, strlen(temp), &dw, NULL);
wsprintf(temp, "\r\n");
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)
{
char temp[200];
GetModuleFileName(NULL, temp, sizeof(temp));
WriteLog("%s, myCreateFileA:filename=%s", temp, lpFileName);
//MessageBox(NULL, temp, "mydll", MB_OK);
if(strstr(lpFileName, "aaa") !=NULL) return NULL;
return CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
HANDLE WINAPI myCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
//MessageBox(NULL, "myCreateFileW", "ok", MB_OK);
char temp[200];
GetModuleFileName(NULL, temp, sizeof(temp));
char fname[128];
WideCharToMultiByte( CP_ACP, 0, lpFileName, -1, fname, 128,NULL,NULL);
WriteLog("%s, myCreateFileW:filename=%s", temp, fname);
//MessageBox(NULL, temp, "mydll", MB_OK);
if(strstr(fname, "aaa.txt") !=NULL)
{
WriteLog("CreateFileW aaa found!");
return CreateFileA("c:\\temp\\bbb.txt", dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
//SetLastError(ERROR_FILE_NOT_FOUND);
//return NULL;
}
return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
BOOL WINAPI myReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
{
WriteLog("ReadFile:handle=%x", hFile);
return ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}
BOOL WINAPI myReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
WriteLog("ReadFileEx");
return ReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead,
lpOverlapped, lpCompletionRoutine);
}
BOOL WINAPI myDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
{
// struct _iobuf f;
WriteLog("DeviceIoControl=%x", hDevice);
WriteLog("dwIoControlCode=%x,lpInBuffer=%x,lpOutBuffer=%x,lpBytesReturned=%x ",lpInBuffer,dwIoControlCode,lpOutBuffer,lpBytesReturned);
// fprintf(f, "DeviceIoControl(%x, %x, ...)\n", hDevice, dwIoControlCode);
return DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned,NULL);
}
MYAPIINFO myapi_info[] =
{
{"KERNEL32.DLL", "CreateFileA", 7, "myCreateFileA"},
{"KERNEL32.DLL", "CreateFileW", 7, "myCreateFileW"},
{"KERNEL32.DLL", "ReadFile", 5, "myReadFile"},
{"KERNEL32.DLL", "ReadFileEx", 5, "myReadFileEx"},
{"KERNEL32.DLL", "DeviceIoControl", 8, "myDeviceIoControl"},
{NULL,NULL,NULL}
};
MYAPIINFO *GetMyAPIInfo()
{
return &myapi_info[0];
}
⽹友: laomms时间:2007-05-18 10:31:04调⽤程序:
#include <windows.h>
#include "resource.h"
#define MsgBox(msg) MessageBox(NULL, msg, "HookAPI - ", MB_OK)
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
typedef int (WINAPI *FuncHookOneProcess2)(HWND hwndNotify, char *exe_name);
typedef int (WINAPI *FuncUnhookOneProcess2)(char *exe_name);
typedef int (WINAPI *FuncHookAllProcess)();
typedef int (WINAPI *FuncUnhookAllProcess)();
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WriteProfileString("HookAPI", "exe_name", "HookAPI.exe");
int isNT =false;
OSVERSIONINFO VersionInfo;
VersionInfo.dwOSVersionInfoSize =sizeof(OSVERSIONINFO);
if(!GetVersionEx(&VersionInfo))
return false;
if(VersionInfo.dwPlatformId ==VER_PLATFORM_WIN32_NT)
isNT =true;
HINSTANCE hLib;
if(isNT)
hLib =LoadLibrary("HookAPINT.dll");
else
hLib =LoadLibrary("HookAPI9x.dll");
if(hLib ==NULL)
{
MessageBox(NULL, "LoadLibrary HookAPIxx.dll failed", "HookAPI.exe", MB_OK);
return false;
}
FuncHookOneProcess2 HookOneProcess2 =
(FuncHookOneProcess2)GetProcAddress(hLib, "HookOneProcess2");
FuncUnhookOneProcess2 UnhookOneProcess2 =
(FuncUnhookOneProcess2)GetProcAddress(hLib, "UnhookOneProcess2");
FuncHookAllProcess HookAllProcess =(FuncHookAllProcess)GetProcAddress(hLib, "HookAllProcess");
FuncUnhookAllProcess UnhookAllProcess =(FuncUnhookAllProcess)GetProcAddress(hLib, "UnhookAllProcess");
if(HookAllProcess ==NULL)
{
MsgBox("HookAllProcess ==NULL");
FreeLibrary(hLib);
return 0;
}
if(UnhookAllProcess ==NULL)
{
MsgBox("UnhookAllProcess ==NULL");
FreeLibrary(hLib);
return 0;
}
if(HookAllProcess() <0)
{
MsgBox("HookAllProcesses error!");
UnhookAllProcess();
FreeLibrary(hLib);
return 0;
}
// 测试只Hook⼀个正在运⾏的程序,下⾯的函数已经在1.6版本中取消,但还是很有⽤,所以以后版本中还是会提供/*
if(HookOneProcess2(NULL, "ship.exe") <0)
{
MsgBox("HookOneProcess failed!");
return 0;
}
*/
/// HookAllProcesses2是针对⽆法截获按Ctrl-Alt_Del键时运⾏的任务管理器等程序的情况使⽤的。

/*if(HookAllProcesses2(1000) <0)
{
MsgBox("HookAllProcesses error!");
return 0;
}*/
/*char temp[200], temp2[20], temp3[256];
char *p =(char *)0x7FCEDCF1;//(char *)funcSHFileOperationA;
wsprintf(temp, "func:%x", p);
wsprintf(temp2, "%x,%x,%x,%x", *p&0xFF, *(p+1)&0xFF, *(p+2), *(p+3), *(p+4));
wsprintf(temp3, "[%s], %s", temp, temp2);
MessageBox(NULL, temp3, "ok", MB_OK);*/
DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc);
UnhookAllProcess();
FreeLibrary(hLib);
return 0;
}
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, IDOK);
break;
case ID_HIDE:
ShowWindow(hDlg, SW_HIDE);
break;
}
default:
break;
}
return FALSE; }。

相关文档
最新文档