除了函数的开头,我该如何挂接?我试图将功能添加到第三方可执行文件中,并且我需要它完全执行其代码,然后将其数据传递到我的函数中。我不太清楚该怎么做。

有简单的方法吗?我找不到实现此功能的任何挂钩引擎。我在任何地方都找不到任何信息。

我看到有人说您可以添加一个非法操作码然后捕获异常,但是我不知道该怎么做。

示例(伪代码):

int moveCharacter(int x, int y) {
    x += 5;
    y += 5;
    return 0;
}


说我想直接在return 0之前进行钩子,并将新的xy变量传递给我自己的函数(在将变量写入日志文件的注入的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;
}


评论


我的印象是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

#3 楼

一种更简单的方法是确定代码实际生成所需数据的时间点。找到该位置后,将后几个字节替换为对自己的代码的调用或远端调用。请仔细记录您要覆盖的字节。 (顺便说一句,我建议使用调用或远距离调用而不是jmp,这样我就不必担心代码重定位;我可以引用原始位置从堆栈中返回,而不必担心在哪里我相对于原始代码。)

您的代码应该做的第一件事就是保留状态。也许是pusha / pushf?现在处理。代码的最后几个字节应该执行以下操作,而不是执行返回操作:


将标志和寄存器
从先前的原始代码的字节中复制覆盖
,通过调整SP来解决堆栈问题,以适应当前SP下方的IP或CS:IP的呼叫或远端呼叫
jmp或far jmp

实际上是传统恶意软件“钩”入您的代码的主要方式。您正在绕道而行。