[原创]:通用拦截api源代码
[来源]:黑色海岸线安全技术论坛 http://www.thysea.com/lb/cgi-bin/leobbs.cgi
[作者]:默数悲伤
[时间]:2006.5.27
经常在看到网上好多人好多帖子寻找拦截某某api的源代码,但是要想做到真正的通用拦截api的代码几乎是不可能的.因为不同的api其最关键的参数不同,地址也不相同,而且编译选项不同,拦截代码也会有一些不同.所以,这里所谓的通用只是尽量把与要拦截的api的个别因素不考虑,而只把公共部分做了出来,当然大家可以参考程序注释轻松写出自己的拦截某个api的程序出来.
该通用代码做成一个头文件的形式,使用的时候把他添加到工程即可.在需要修改的地方,代码中都会有提示.如有错误,欢迎给我留言:)
可以编译成debug或者release程序,只是需要在程序做些简单的修改.这里模拟的是拦截的connect函数,效果是每当被拦截的进程使用connect函数的时候,立即弹出一个对话框提示已经被Hook.
可能需要被修改的地方:
1:函数参数大小
2:被拦截的api的函数指针的定义
3:拦截函数中的自定义功能的函数和变量的定义
4:在拦截函数的参数中由于3的原因而需要做的响应的修改
- #include <windows.h>
- #include <tchar.h>
- #define HOOKFUCTIONSIZE 4096 //定义拦截函数体的大小,以字节为单位,且以4kb为基本单位
- #define HOOKEDAPIPARAMNUMINBYTE 12 //定义被拦截的api的函数的参数的大小,以字节为单位
- //定义拦截函数的参数
- typedef struct _RemoteParam {
- LPVOID FunAddr;
- LPVOID lpGetCurrentProcess;
- LPVOID lpWriteProcessMemory;
- unsigned char szOldCode[10];
- unsigned char szNewCode[10];
- char szCaption[8];
- char szMessage[12];
- LPVOID lpMessageBox;
- } RemoteParam, * PRemoteParam;
- typedef BOOL (__stdcall * PFN_WRITEPROCESSMEMORY)(HANDLE,LPVOID,LPCVOID,SIZE_T,SIZE_T*);
- typedef HANDLE (__stdcall * PFN_GETCURRENTPROCESS)(void);
- //这里为演示而添加的一个函数指针的声明,可以根据拦截功能的需要添加自己要使用的函数指针的定义
- typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, DWORD);
- //这里为要拦截的api的函数指针的定义
- typedef int (__stdcall * PFN_CONNECT)(SOCKET,struct sockaddr *,int);
- //实施拦截的函数体,这里以拦截connect为目标,参数个数为3,其总大小为12字节
- VOID HooKApi(LPVOID lParam)
- {
- RemoteParam* Rpm = (RemoteParam*)lParam;
- PFN_GETCURRENTPROCESS pfnGetCurrentProcess = (PFN_GETCURRENTPROCESS)Rpm->lpGetCurrentProcess;
- PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory = (PFN_WRITEPROCESSMEMORY)Rpm->lpWriteProcessMemory;
- int RetValue = 0; //定义要拦截的api的默认返回植
- DWORD NextIpAddr = 0;
- DWORD dwParamaAddr = 0;
- //保存原api的参数
- SOCKET s;
- struct sockaddr * name;
- int namelen;
- __asm
- {
- MOV EAX,[EBP+12]
- MOV [NextIpAddr], EAX
- MOV EAX,[EBP+16]
- MOV [s], EAX
- MOV EAX,[EBP+20]
- MOV [name],EAX
- MOV EAX,[EBP+24]
- MOV [namelen],EAX
- }
- //这里可以做你的事情了,比如我只想弹出一个对话框,其实也可以在让api完成之后再做些东西
- PFN_MESSAGEBOX pfnMessageBox = (PFN_MESSAGEBOX)Rpm->lpMessageBox;
- pfnMessageBox(NULL, Rpm->szMessage, Rpm->szCaption, 0);
- //现在你要做的已经完成了,让api恢复吧,完成他本来的任务
- PFN_CONNECT pfnConnect = (PFN_CONNECT)Rpm->FunAddr;
- pfnWriteProcessMemory(pfnGetCurrentProcess(),
- Rpm->FunAddr,
- (LPCVOID)Rpm->szOldCode,
- 10,
- NULL);
- //让api真正执行,这里换成你要拦截的api
- RetValue = pfnConnect(s, name, namelen);
- //再次恢复对他的拦截
- pfnWriteProcessMemory(pfnGetCurrentProcess(),
- Rpm->FunAddr,
- (LPCVOID)Rpm->szNewCode,
- 10,
- NULL);
-
- DWORD dwStackSize = 12 + HOOKEDAPIPARAMNUMINBYTE;
- //这里对拦截函数堆栈的恢复,必须放在最后
- __asm
- {
- //POP EDI //注意如果你编译生成的debug版本的程序则需要把这
- //POP ESI //三个注释去掉
- //POP EBX
- MOV ECX, [dwStackSize]
- MOV EDX, [NextIpAddr]
- MOV EAX, [RetValue]
- MOV ESP, EBP
- POP EBP
- ADD ESP, ECX //12 + HOOKEDAPIPARAMNUMINBYTE //恢复堆栈
- PUSH EDX
- RET
- }
- }
- VOID GetErrorToInfo(void)
- {
- LPVOID lpMsgBuf;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf, 0, NULL );
- MessageBox(0, (LPCTSTR)lpMsgBuf, TEXT("HOOK ERROR"), MB_OK|MB_ICONINFORMATION );
- LocalFree(lpMsgBuf);
- return;
- }
- //////////////////////////////////////////////////////////////////////////
- //************************************************************************
- //模块名字:AdjustProcessPrivileges(LPCSTR)
- //模块功能:修改调用进程的权限
- //返回数值:成功返回TRUE,失败返回FALSE
- //参数可以为下列值:
- // #define SE_BACKUP_NAME TEXT("SeBackupPrivilege")
- // #define SE_RESTORE_NAME TEXT("SeRestorePrivilege")
- // #define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege")
- // #define SE_DEBUG_NAME TEXT("SeDebugPrivilege")
- //////////////////////////////////////////////////////////////////////////
- BOOL AdjustProcessPrivileges(LPCSTR lpPrivilegesName)
- {
- HANDLE hToken;
- TOKEN_PRIVILEGES tkp;
- if(!OpenProcessToken(GetCurrentProcess(),
- TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
- {
- GetErrorToInfo();
- return FALSE;
- }
- if(!LookupPrivilegeValue(NULL,lpPrivilegesName,
- &tkp.Privileges[0].Luid))
- {
- GetErrorToInfo();
- CloseHandle(hToken);
- return FALSE;
- }
- tkp.PrivilegeCount = 1;
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(tkp),NULL,NULL))
- {
- GetErrorToInfo();
- CloseHandle(hToken);
- return FALSE;
- }
- CloseHandle(hToken);
- return TRUE;
- }
- int SetHook(DWORD dwPid, LPCTSTR lpApiName, LPCTSTR lpExportDllName, LPVOID lpHookFunAddr)
- {
- //获取要拦截的api的地址
- HMODULE hExportDll = LoadLibrary(lpExportDllName);
- if(hExportDll == NULL)
- {
- GetErrorToInfo();
- return -1;
- }
- LPVOID lpApiAddr = GetProcAddress(hExportDll, lpApiName);
- if(lpApiAddr == NULL)
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- return -1;
- }
- //打开进程句柄
- HANDLE hTargetProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
- FALSE, dwPid);
- if(hTargetProcess == NULL)
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- return -1;
- }
- //申请拦截函数内存空间
- LPVOID lpFunAddr = VirtualAllocEx(hTargetProcess, NULL, HOOKFUCTIONSIZE,
- MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
-
- if(lpFunAddr == NULL)
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- CloseHandle(hTargetProcess);
- return -1;
- }
- //申请远程参数空间
- LPVOID lpParamaAddr = VirtualAllocEx(hTargetProcess, NULL, sizeof(RemoteParam),
- MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
-
- if(lpParamaAddr == NULL)
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
- CloseHandle(hTargetProcess);
- return -1;
- }
- //把拦截函数体写入目标进程地址空间
- DWORD dwError = 0;
- if(!WriteProcessMemory(hTargetProcess, lpFunAddr, lpHookFunAddr, HOOKFUCTIONSIZE, &dwError))
- {
- MessageBox(NULL, "a", "a", 0);
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
- VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
- CloseHandle(hTargetProcess);
- return -1;
- }
- //设置远程参数,下一步要把参数写入眼要拦截的远程进程地址空间
- RemoteParam RParam;
- ZeroMemory(&RParam, sizeof(RParam));
- unsigned char oldcode[10];
- unsigned char newcode[10];
-
- if(!ReadProcessMemory(GetCurrentProcess(),
- lpApiAddr,
- oldcode,
- 10,
- &dwError))
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
- VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
- CloseHandle(hTargetProcess);
- return -1;
- }
-
- //生成跳转指令,这将覆盖要拦截的api的前十个字节
- int praadd = (int)lpParamaAddr;
- int threadadd = (int)lpFunAddr;
- newcode[4] = praadd>>24;
- newcode[3] = (praadd<<8)>>24;
- newcode[2] = (praadd<<16)>>24;
- newcode[1] = (praadd<<24)>>24;
- newcode[0] = 0x68; //PUSH lpParamaAddr
- int offsetaddr = threadadd - (int)lpApiAddr - 10 ;
- newcode[9] = offsetaddr>>24;
- newcode[8] = (offsetaddr<<8)>>24;
- newcode[7] = (offsetaddr<<16)>>24;
- newcode[6] = (offsetaddr<<24)>>24;
- newcode[5] = 0xE8; //CALL lpFunAddr
- strcat((char*)RParam.szOldCode, (char*)oldcode);
- strcat((char*)RParam.szNewCode, (char*)newcode);
- RParam.FunAddr = lpApiAddr;
- HMODULE hKernel32 = LoadLibrary("Kernel32.dll");
- if(hKernel32 == NULL)
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
- VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
- CloseHandle(hTargetProcess);
- return -1;
- }
- RParam.lpGetCurrentProcess = GetProcAddress(hKernel32, "GetCurrentProcess");
- RParam.lpWriteProcessMemory = GetProcAddress(hKernel32, "WriteProcessMemory");
- if(RParam.lpGetCurrentProcess == NULL || RParam.lpWriteProcessMemory == NULL)
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
- VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
- CloseHandle(hTargetProcess);
- FreeLibrary(hKernel32);
- return -1;
- }
- //以上皆为必须,下面可以为自己的拦截函数中所需要用的一些变量以及系统api放到参数中去
- //比如我在拦截函数中只是弹出一个对话框,标题为"HOOK",内容为"Now,hook:)",这样定义
- HMODULE hUser32 = LoadLibrary("User32.dll");
- if(hUser32 == NULL)
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
- VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
- CloseHandle(hTargetProcess);
- FreeLibrary(hKernel32);
- return -1;
- }
- RParam.lpMessageBox = GetProcAddress(hUser32, "MessageBoxA");
- if(RParam.lpMessageBox == NULL)
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
- VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
- CloseHandle(hTargetProcess);
- FreeLibrary(hKernel32);
- FreeLibrary(hUser32);
- return -1;
- }
- strcat((char*)RParam.szCaption, "HOOK\0");
- strcat((char*)RParam.szMessage, "Now,hook:)\0");
- FreeLibrary(hUser32);
- //下面为必须部分
- //把参数写入要拦截的远程进程地址空间
- if(!WriteProcessMemory(hTargetProcess, lpParamaAddr, (LPVOID)&RParam, sizeof(RParam), &dwError))
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
- VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
- CloseHandle(hTargetProcess);
- FreeLibrary(hKernel32);
- return -1;
- }
- //把新的跳转指令写入要拦截的目标进程的要拦截的api的函数的前十字节
- if(!WriteProcessMemory(hTargetProcess, lpApiAddr , (LPVOID)newcode, 10, &dwError))
- {
- GetErrorToInfo();
- FreeLibrary(hExportDll);
- VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
- VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
- CloseHandle(hTargetProcess);
- FreeLibrary(hKernel32);
- return -1;
- }
- //完成,收工,清理资源
- FreeLibrary(hExportDll);
- CloseHandle(hTargetProcess);
- FreeLibrary(hKernel32);
- return 0;
- }
复制代码 调用代码:- #include "CommonHook.h"
- int main(void)
- {
- if(!AdjustProcessPrivileges(SE_DEBUG_NAME))
- return -1;
- SetHook(832, "connect", "Ws2_32.dll", &HooKApi);
- return 0;
- }
复制代码 |