有简单的方法吗?我找不到实现此功能的任何挂钩引擎。我在任何地方都找不到任何信息。
我看到有人说您可以添加一个非法操作码然后捕获异常,但是我不知道该怎么做。
示例(伪代码):
int moveCharacter(int x, int y) {
x += 5;
y += 5;
return 0;
}
说我想直接在
return 0
之前进行钩子,并将新的x
和y
变量传递给我自己的函数(在将变量写入日志文件的注入的DLL或代码腔)。在执行完函数之后,我想返回到原始函数,以便它可以像正常一样返回。#1 楼
之所以没有引擎来钩住函数的结尾,是因为很难确定它的位置,甚至很难确定它的存在。函数具有单个入口点,但它可以具有多个出口点,根本不包含任何出口点(考虑exit())。出口点也可以具有多种类型-return,throw(),longjmp() ,C ++ EH等。
函数完成后挂接的一般想法是绕开调用者,但是对于您所需要的来说为时已晚。
无论如何,这是这样做的:首先,绕开感兴趣的功能,这钩住了执行的开始。当您收到控制权时,请先解除函数的挂钩,然后从堆栈中读取返回地址(假设函数实际上将返回)。
接下来,绕开返回地址(调用方),然后让原始函数执行。当您再次收到控制权时,该功能已完成其执行。您可以取消钩住返回地址,执行其他操作,然后继续执行。
不幸的是,您将无法访问局部变量(根据您的描述,这似乎是您想要的)。
一种方法要避免该问题,请通过安装Vectored Exception Handler接收单步异常来单步执行该功能。这样一来,您就可以检查下一条将要执行的指令(因为在执行前一条指令之后会发生异常),并且如果它是返回指令,则可以记录这些值。
如果使用异常方法,则需要安装向量异常处理程序以指向您的代码,然后在感兴趣的地方放置一个断点指令。同样,问题是要确定该位置在哪里。
#2 楼
Microsoft Detours使此操作非常容易。您将有效地编写以下代码(为安全起见,您还希望进行其他调用,例如DetourUpdateThread()
):DetourTransactionBegin();
DetourAttach(&(PVOID&)OriginalFunction, Function);
DetourTransactionCommit();
,然后编写这样的代码如下所示:
int Function(int x)
{
int r = OriginalFunction(x);
// Handle r here
return r;
}
#3 楼
一种更简单的方法是确定代码实际生成所需数据的时间点。找到该位置后,将后几个字节替换为对自己的代码的调用或远端调用。请仔细记录您要覆盖的字节。 (顺便说一句,我建议使用调用或远距离调用而不是jmp,这样我就不必担心代码重定位;我可以引用原始位置从堆栈中返回,而不必担心在哪里我相对于原始代码。)您的代码应该做的第一件事就是保留状态。也许是pusha / pushf?现在处理。代码的最后几个字节应该执行以下操作,而不是执行返回操作:
将标志和寄存器
从先前的原始代码的字节中复制覆盖
,通过调整SP来解决堆栈问题,以适应当前SP下方的IP或CS:IP的呼叫或远端呼叫
jmp或far jmp
实际上是传统恶意软件“钩”入您的代码的主要方式。您正在绕道而行。
评论
我的印象是Detours只能用于执行其他功能之前。除了使OriginalFunction成为函数的开始之外,我还能做任何事情吗?我在主要帖子中添加了一个示例,以尝试解释我想要做什么。
– Sean Heiss
13年7月14日在0:53
嗯,您需要访问本地堆栈变量。在这种情况下,只需将目标函数的ret指令用jmp修补到您的钩子函数即可。
–詹森·格夫纳(Jason Geffner)
13年7月14日在0:58
不过,Detours具有非常严格的EULA。不适合很多目的。
– 0xC0000022L♦
13年8月31日在1:34