DIY之挂钩初步想法:
目前我所了解的挂钩方式为修改目标函数为首的几条指令为跳转指令,跳转到我们的挂钩函数(保存被修改的指令)挂钩函数执行完时根据需要是否需要执行被挂钩函数。这是现有的平台
支持的挂钩方式。因此,也是可以被平台发现的挂钩方式。可以被发现,也就可以防住,因此有挂钩失败,或被卸载,或被他人先挂钩。
自己想到一种DIY方式是,其实也是很简单的,继然挂钩的目的是要在执行目标函数之前,先执行我们的挂钩函数,那么,是否可以直接修改call指令的目标地址,使得对目标函数的调用
直接变成对我们挂钩函数的调用。再根据挂钩函数执行的结果判断是否需要跳到原函数执行。这样,可以保证挂钩不被第三方发现,因为这个时候已经没有使用传统的挂钩方式了,也不能用
传统的办法检测到,因为,我们是直接改的call指令调用的函数地址,没有修改原函数体的内容,天生就对传统的检测函数为首的几条指令是否被修改免疫。
好吧,直接修改call指令的目标地址,很简单的方式。但是,这个目标地址,修改成什么样呢,直接是我们的挂钩函数地址么。好像可以,但目前对挂钩理解还不是很深刻也许可以,也许
不可以,要不,这么简单的方式,当时设计目前挂钩方式机制的人怎么会想不到呢。
那么为什么这么直接的挂钩方式没有用,而是要修改函数的为首几条指令?目前对挂钩的了解还不是那么的透彻,还需要多学习才能解释,或者希望有高手能为我解答。
我之DIY也许可以使用这么直接的方式但目前没有采用我想是,如果改call,那么对目标函数的调用全部要改成挂钩函数的调用,如果有n个地方就要替换n次,效果可想而知的麻烦。 但是改
成修改函数的为首的几条指令,那么就简单了,只需要改一处,也可以实现挂钩了。这样使用的人来看,是简单了,只改一处所有地方都受用,就像是C++的抽象和多态一样!平台的挂钩接口
就是抽象基类,在基类的函数里实现挂钩及调用原函数,子类的函数执行挂钩要做的事情,就像下面这样。
class HookParent //平台实现的挂钩机制基类
{
public:
void Hook( void * pFucAddress /*被挂钩函数地址*/)
{
//1.挂钩,修改目标函数为首几条指令
....
//2.先调用挂钩函数
BOOL bCallOlder = _Hook();
//3.如果返回TRUE表示要执行原函数
if( bCallOlder )
{
//返回执行原函数内容
}
}
virtual BOOL _Hook()
{
return TRUE;
};
}
class SubHook:public HookParent //需要挂钩的人实现继承基类,只需要写自己具体的实现过程(当然只是演示,忽略函数参数的问题)
{
protected:
virtual BOOL _Hook()
{
//在挂钩函数里为所欲为
...
if( 心情好 )
{
//给原函数一个执行机会吧
return TRUE;
}
else
{
//心情不好.狠狠(猥琐的笑)
return FALSE;
}
}
}
同时,这样所有人的挂钩也就无处遁形了,因为,大家都是用的相同的方式,且是可以被检测到的方式 ,因为原函数的为首几条指令被修改了。
class BeiHookedFuc1 //将被挂钩的函数基类
{
public:
virtual Fuc1( )
{
//做我该做的事情
}
}
class HookFuc:public BeiHookedFuc1//需要挂钩的人继承被挂钩函数基类
{
protected:
virtual Fuc1()
{
//在挂钩函数里为所欲为
...
if( 心情好 )
{
//给原函数一个执行机会吧
BeiHookedFuc1::Fuc1();
}
else
{
//心情不好.狠狠(猥琐的笑)
//啥也不做了
}
}
}
都是要修改,但是前一种修改会需要平台提供支持,所以平台的Hook()函数里完成可以对挂钩函数做记录,或者挂钩函数被其他挂钩函数替换。
但是,第二种,和平台无关,不需要什么接口支持,不同人的挂钩,对其他人来说是完成透明的。
再此申明一下,目前我对挂钩原理理解还不是很深,这个我会继续学习,后续补充,或者有高手可以来指点一下。
至于,我自己的这个想法,我会实践,验证。贴出来希望有兴趣的可以和我一起来探讨,验证这个想法。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)