标题:
[原创]通用拦截api源代码
[打印本页]
作者:
默数悲伤
时间:
2006-5-27 01:11
标题:
[原创]通用拦截api源代码
[原创]:通用拦截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;
}
复制代码
欢迎光临 黑色海岸线论坛 (http://bbs.thysea.com/)
Powered by Discuz! 7.2