当设置HOOK时,如何保存那些函数的起始6 个字节?当取消HOOK时,如何从保存的数据中找到某个函数的起始6个字节?解决这个问题,可以用一个结构体数组来实现,结构体中包含源函数地址、源函数起始位置的6个字节数据等内容。HOOK管理结构体设计如下。
typedef struct APIHOOKDATA_st {
DWORD dwSrcFuncAddr; /* 源函数的地址 */
DWORD dwNewFuncAddr; /* 钩子函数的地址 */
BYTE byHeaderCode[6]; /* 源函数起始6字节 */
WORD wFlag; /* 用来表示是否设置了HOOK的标志 */
} APIHOOKDATA;
typedef struct APIHOOK_st {
APIHOOKDATA *pHookData;
UINT uMaxFunctions;
} APIHOOK; APIHOOKDATA结构体用来记录单个函数的HOOK数据,APIHOOK结构体用来管理多个函数的HOOK,里面包含一个APIHOOKDATA结构体数组,uMaxFunctions是数组的长度,表示最多可以HOOK的函数个数。 1. 多个函数的HOOK管理 对多个函数的HOOK管理可以分为以下四个操作步骤。
① 初始化;
② 设置某个函数的HOOK;
③ 取消某个函数的HOOK;
④ 关闭。 下面以Windows NT系列操作系统为例来实现以上四个操作的代码。初始化操作主要是为结构体分配内存,将整个数组清零。编码如下。
/** ApiHook 模块初始化函数
@param INT nMaxHookFuncCounts——最大可设置的钩子数量
@return INT (by default) ——返回NULL 表示失败
*/
HANDLE ApiHook_Init(UINT uMaxFunctions)
{
APIHOOK * pApiHook = (APIHOOK *)malloc(sizeof(APIHOOK));
if ( pApiHook )
{
pApiHook->uMaxFunctions = uMaxFunctions;
pApiHook->pHookData =
(APIHOOKDATA *)malloc(sizeof(APIHOOKDATA) *uMaxFunctions);
if ( NULL != pApiHook->pHookData)
{
memset(pApiHook->pHookData,0,sizeof(APIHOOKDATA) *uMaxFunctions );
return (HANDLE)pApiHook;
}
free(pApiHook);
}
return NULL;
} 2. 设置HOOK操作 设置某个函数的HOOK操作主要是在数组中查找未使用的节点,将源函数相关信息保存到节点中,修改源函数起始位置的几个字节为一条跳转到钩子函数的指令。
/** 通过地址来设置某个函数的钩子函数
@param HANDLE hApiHook——由ApiHook_Init()函数生成的句柄
@param DWORD dwSrcFuncAddr——源函数地址
@param DWORD dwNewFuncAddr——钩子函数地址
@return INT (by default) ——返回-1表示失败;返回0表示在HOOK数组中的序号
*/
INT ApiHook_SetByAddr(HANDLE hApiHook,DWORD dwSrcFuncAddr,DWORD dwNewFuncAddr)
{
DWORD dwOldProtect;
DWORD dwNewProtect;
DWORD lpSrcFunc;
DWORD lppNewFunc;
UINT i;
INT nAlreadyFlag = 0;
if ( NULL == hApiHook )
{
return-1;
}
APIHOOK *pApiHook = (APIHOOK *)hApiHook;
lpSrcFunc = dwSrcFuncAddr;
/* 查找是否已设置了钩子 */
for ( i = 0; i < pApiHook->uMaxFunctions; i++ )
{
if ( pApiHook->pHookData[i].dwSrcFuncAddr == lpSrcFunc )
{
/* 如果已经设置了钩子,仅仅改变 */
nAlreadyFlag = 1;
break;
}
}
/* 如果没有设置源函数的钩子函数,在表中找出一个可供记录的位置 */
if ( i == pApiHook->uMaxFunctions )
{
for ( i = 0; i < pApiHook->uMaxFunctions; i++ )
{
if (pApiHook->pHookData[i].wFlag == 0 )
{
break;
}
}
if ( i == pApiHook->uMaxFunctions )
{
return-1;
}
}
/* 将新的钩子函数地址记录到表中 */
pApiHook->pHookData[i].dwNewFuncAddr = dwNewFuncAddr;
/* 以下这段代码将源函数头部6个字节保存到表中 */
lppNewFunc = (DWORD)(&(pApiHook->pHookData[i].dwNewFuncAddr) );
if ( !nAlreadyFlag )
{
/* 将源函数起始处6个字节保存到 byHeaderCode.中 */
memcpy( pApiHook->pHookData[i].byHeaderCode,(const void *)lpSrcFunc,6);
}
/* 以下这段代码将源函数首部6个字节改成为一条跳转到新函数地址的指令 */
if ( VirtualProtect( (LPVOID)lpSrcFunc,6, PAGE_EXECUTE_READWRITE,&dwOldProtect ) == 0 )
{
return-1;
}
*(unsigned char *)lpSrcFunc = (unsigned char)0xff;
*(((unsigned char *)lpSrcFunc)+1) = (unsigned char)0x25;
memcpy( (void *)(lpSrcFunc+2),(const void *)&lppNewFunc,4 );
if ( VirtualProtect( (LPVOID)lpSrcFunc,6,dwOldProtect, &dwNewProtect) == 0 )
{
return-1;
};
pApiHook->pHookData[i].wFlag = 1;
pApiHook->pHookData[i].dwSrcFuncAddr = lpSrcFunc;
return (INT)i;
}
3. 取消HOOK操作 取消某个函数的HOOK操作和设置操作相反,主要是在数组中查到要操作的函数的相关记录信息,将源函数起始位置处的6个字节恢复,清除数组中的对应记录信息。编码如下。 /** 取消某个函数的钩子函数设置
@param HANDLE hApiHook——由ApiHook_Init()函数生成的句柄
@param DWORD dwSrcFuncAddr——源函数地址
@return INT (by default) ——返回-1表示失败;返回0表示在HOOK数组中的序号
*/
INT ApiHook_UnSetByAddr(HANDLE hApiHook,DWORD dwSrcFuncAddr)
{
UINT i;
DWORD dwOldProtect;
DWORD dwNewProtect;
DWORD lpSrcFunc;
APIHOOK *pApiHook = (APIHOOK *)hApiHook;
if ( NULL == hApiHook )
{
return-1;
}
for ( i = 0; i < pApiHook->uMaxFunctions; i++ )
{
if ( pApiHook->pHookData[i].dwSrcFuncAddr == dwSrcFuncAddr )
{
break;
}
}
if ( i == pApiHook->uMaxFunctions )
{
return-1;
}
lpSrcFunc = pApiHook->pHookData[i].dwSrcFuncAddr;
/* 将lpSrcFunc指向的内存属性修改为可以读写的 */
if ( VirtualProtect( ( LPVOID)lpSrcFunc,6,PAGE_EXECUTE_READWRITE,&dwOldProtect ) == 0 )
{
return-1;
}
memcpy( (void *)lpSrcFunc,pApiHook->pHookData[i].byHeaderCode,6 );
/* 恢复lpSrcFunc指向的内存属性 */
if ( VirtualProtect( (LPVOID)lpSrcFunc,6,dwOldProtect,&dwNewProtect ) == 0 )
{
return-1;
}
pApiHook->pHookData[i].wFlag = 0;
if ( pApiHook->pHookData[i].pszDllName )
{
free(pApiHook->pHookData[i].pszDllName);
pApiHook->pHookData[i].pszDllName = NULL;
}
if ( pApiHook->pHookData[i].pszFuncName )
{
free( pApiHook->pHookData[i].pszFuncName );
pApiHook->pHookData[i].pszFuncName = NULL;
}
return (INT)i;
}
菜鸟一个,但是老师给布置作业要做多个函数的hook
不知道怎么写成一个DLL
还有函数具体实现什么功能也不是很清楚,能否举个例子?T T
救救我啊~~~~
typedef struct APIHOOKDATA_st {
DWORD dwSrcFuncAddr; /* 源函数的地址 */
DWORD dwNewFuncAddr; /* 钩子函数的地址 */
BYTE byHeaderCode[6]; /* 源函数起始6字节 */
WORD wFlag; /* 用来表示是否设置了HOOK的标志 */
} APIHOOKDATA;
typedef struct APIHOOK_st {
APIHOOKDATA *pHookData;
UINT uMaxFunctions;
} APIHOOK; APIHOOKDATA结构体用来记录单个函数的HOOK数据,APIHOOK结构体用来管理多个函数的HOOK,里面包含一个APIHOOKDATA结构体数组,uMaxFunctions是数组的长度,表示最多可以HOOK的函数个数。 1. 多个函数的HOOK管理 对多个函数的HOOK管理可以分为以下四个操作步骤。
① 初始化;
② 设置某个函数的HOOK;
③ 取消某个函数的HOOK;
④ 关闭。 下面以Windows NT系列操作系统为例来实现以上四个操作的代码。初始化操作主要是为结构体分配内存,将整个数组清零。编码如下。
/** ApiHook 模块初始化函数
@param INT nMaxHookFuncCounts——最大可设置的钩子数量
@return INT (by default) ——返回NULL 表示失败
*/
HANDLE ApiHook_Init(UINT uMaxFunctions)
{
APIHOOK * pApiHook = (APIHOOK *)malloc(sizeof(APIHOOK));
if ( pApiHook )
{
pApiHook->uMaxFunctions = uMaxFunctions;
pApiHook->pHookData =
(APIHOOKDATA *)malloc(sizeof(APIHOOKDATA) *uMaxFunctions);
if ( NULL != pApiHook->pHookData)
{
memset(pApiHook->pHookData,0,sizeof(APIHOOKDATA) *uMaxFunctions );
return (HANDLE)pApiHook;
}
free(pApiHook);
}
return NULL;
} 2. 设置HOOK操作 设置某个函数的HOOK操作主要是在数组中查找未使用的节点,将源函数相关信息保存到节点中,修改源函数起始位置的几个字节为一条跳转到钩子函数的指令。
/** 通过地址来设置某个函数的钩子函数
@param HANDLE hApiHook——由ApiHook_Init()函数生成的句柄
@param DWORD dwSrcFuncAddr——源函数地址
@param DWORD dwNewFuncAddr——钩子函数地址
@return INT (by default) ——返回-1表示失败;返回0表示在HOOK数组中的序号
*/
INT ApiHook_SetByAddr(HANDLE hApiHook,DWORD dwSrcFuncAddr,DWORD dwNewFuncAddr)
{
DWORD dwOldProtect;
DWORD dwNewProtect;
DWORD lpSrcFunc;
DWORD lppNewFunc;
UINT i;
INT nAlreadyFlag = 0;
if ( NULL == hApiHook )
{
return-1;
}
APIHOOK *pApiHook = (APIHOOK *)hApiHook;
lpSrcFunc = dwSrcFuncAddr;
/* 查找是否已设置了钩子 */
for ( i = 0; i < pApiHook->uMaxFunctions; i++ )
{
if ( pApiHook->pHookData[i].dwSrcFuncAddr == lpSrcFunc )
{
/* 如果已经设置了钩子,仅仅改变 */
nAlreadyFlag = 1;
break;
}
}
/* 如果没有设置源函数的钩子函数,在表中找出一个可供记录的位置 */
if ( i == pApiHook->uMaxFunctions )
{
for ( i = 0; i < pApiHook->uMaxFunctions; i++ )
{
if (pApiHook->pHookData[i].wFlag == 0 )
{
break;
}
}
if ( i == pApiHook->uMaxFunctions )
{
return-1;
}
}
/* 将新的钩子函数地址记录到表中 */
pApiHook->pHookData[i].dwNewFuncAddr = dwNewFuncAddr;
/* 以下这段代码将源函数头部6个字节保存到表中 */
lppNewFunc = (DWORD)(&(pApiHook->pHookData[i].dwNewFuncAddr) );
if ( !nAlreadyFlag )
{
/* 将源函数起始处6个字节保存到 byHeaderCode.中 */
memcpy( pApiHook->pHookData[i].byHeaderCode,(const void *)lpSrcFunc,6);
}
/* 以下这段代码将源函数首部6个字节改成为一条跳转到新函数地址的指令 */
if ( VirtualProtect( (LPVOID)lpSrcFunc,6, PAGE_EXECUTE_READWRITE,&dwOldProtect ) == 0 )
{
return-1;
}
*(unsigned char *)lpSrcFunc = (unsigned char)0xff;
*(((unsigned char *)lpSrcFunc)+1) = (unsigned char)0x25;
memcpy( (void *)(lpSrcFunc+2),(const void *)&lppNewFunc,4 );
if ( VirtualProtect( (LPVOID)lpSrcFunc,6,dwOldProtect, &dwNewProtect) == 0 )
{
return-1;
};
pApiHook->pHookData[i].wFlag = 1;
pApiHook->pHookData[i].dwSrcFuncAddr = lpSrcFunc;
return (INT)i;
}
3. 取消HOOK操作 取消某个函数的HOOK操作和设置操作相反,主要是在数组中查到要操作的函数的相关记录信息,将源函数起始位置处的6个字节恢复,清除数组中的对应记录信息。编码如下。 /** 取消某个函数的钩子函数设置
@param HANDLE hApiHook——由ApiHook_Init()函数生成的句柄
@param DWORD dwSrcFuncAddr——源函数地址
@return INT (by default) ——返回-1表示失败;返回0表示在HOOK数组中的序号
*/
INT ApiHook_UnSetByAddr(HANDLE hApiHook,DWORD dwSrcFuncAddr)
{
UINT i;
DWORD dwOldProtect;
DWORD dwNewProtect;
DWORD lpSrcFunc;
APIHOOK *pApiHook = (APIHOOK *)hApiHook;
if ( NULL == hApiHook )
{
return-1;
}
for ( i = 0; i < pApiHook->uMaxFunctions; i++ )
{
if ( pApiHook->pHookData[i].dwSrcFuncAddr == dwSrcFuncAddr )
{
break;
}
}
if ( i == pApiHook->uMaxFunctions )
{
return-1;
}
lpSrcFunc = pApiHook->pHookData[i].dwSrcFuncAddr;
/* 将lpSrcFunc指向的内存属性修改为可以读写的 */
if ( VirtualProtect( ( LPVOID)lpSrcFunc,6,PAGE_EXECUTE_READWRITE,&dwOldProtect ) == 0 )
{
return-1;
}
memcpy( (void *)lpSrcFunc,pApiHook->pHookData[i].byHeaderCode,6 );
/* 恢复lpSrcFunc指向的内存属性 */
if ( VirtualProtect( (LPVOID)lpSrcFunc,6,dwOldProtect,&dwNewProtect ) == 0 )
{
return-1;
}
pApiHook->pHookData[i].wFlag = 0;
if ( pApiHook->pHookData[i].pszDllName )
{
free(pApiHook->pHookData[i].pszDllName);
pApiHook->pHookData[i].pszDllName = NULL;
}
if ( pApiHook->pHookData[i].pszFuncName )
{
free( pApiHook->pHookData[i].pszFuncName );
pApiHook->pHookData[i].pszFuncName = NULL;
}
return (INT)i;
}
菜鸟一个,但是老师给布置作业要做多个函数的hook
不知道怎么写成一个DLL
还有函数具体实现什么功能也不是很清楚,能否举个例子?T T
救救我啊~~~~
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货