如何修复C程序中的Hook(堆栈的恢复)

时间:2016-11-06 21:50:59

标签: c windows debugging stack hook

这是一种训练任务,因为现在这些方法(我猜)不再适用了。

使用Win XP和MinGW编译器。不涉及特殊的编译器选项(仅包含说明一个源文件的gcc)。

首先,保存一个地址以退出程序并跳转到某个Hook函数:

// Our system uses 4 bytes for addresses.
typedef unsigned long int DWORD;

// To save an address of the exit from the program.
DWORD addr_ret;

// An entry point.
int main()
{
   // To make a direct access to next instructions.
   DWORD m[1];

   // Saving an address of the exit from the program.
   addr_ret = (DWORD) m[4];

   // Replacing the exit from the program with a jump to some Hook function.
   m[4] = (DWORD) Hook;

   // Status code of the program's execution.
   return 0;
}       

此代码的目标是获取对系统特权级别的访问权限,因为当我们返回(应该返回)系统时,我们只是将程序重定向到我们的一些方法。这种方法的代码:

// Label's declaration to make a jump.
jmp_buf label;

void Hook()
{
   printf ("Test\n");

   // Trying to restore the stack using direct launch (without stack's preparation) of the function (we'll wee it later).
   longjmp(label, 1);

   // Just to make sure that we won't return here after jump's (from above) finish, because we are not getting stuck in the infinite loop.
   while(1) {}
}

最后我会陈述一个函数(在我看来)应该修复堆栈指针 - ESP寄存器:

void FixStack()
{
   // A label to make a jump to here.
   setjmp(label);

   // A replacement of the exit from this function with an exit from the whole program.
   DWORD m[1];
   m[2] = addr_ret;
}

当然,我们应该将这些包含用于所述程序:

#include <stdio.h>
#include <setjmp.h>

程序的整个逻辑在我的系统中正常工作,但我无法恢复堆栈(ESP),因此程序返回错误的返回码。

在上述解决方案之前,我没有使用跳转和FixStack功能。我的意思是这些线在Hook函数中而不是跳跃和循环:

DWORD m[1];
m[2] = addr_ret;

但是对于这个变体,我在退出程序之前在ESP寄存器中得到了一个不正确的值(它比在该程序中输入之前的寄存器值大8个字节)。所以我决定以某种方式添加这8个字节(避免在C程序中的任何ASM代码)。它的目的是跳转到FixStack函数并从中适当退出(从堆栈中删除一些值)。但是,正如我所说,它不会使用此命令返回程序执行的正确状态:

echo %ErrorLevel%

所以我的问题非常广泛:从使用调试实用程序(我只使用OllyDbg)中提出一些建议开始,并结束所描述的Hook实现的可能解决方案。

2 个答案:

答案 0 :(得分:0)

好的,我最终可以按照预期的方式使我的程序正常工作。现在我们可以启动编译(我在Win XP中使用MinGW)程序,没有任何错误和正确的返回代码。

也许对某人有帮助:

foreign key (rm_id) references roomate.rm_id,

答案 1 :(得分:0)

当然,您似乎已经意识到这只适用于非常具体的构建环境。它绝对不会在64位目标上工作(因为地址不是DWORD-ish)。

您是否有任何理由不想使用C标准库提供的功能来完成此操作? (或者与此非常相似的东西。)

#include <stdlib.h>

void Hook()
{
    printf("Test\n");
}

int main()
{
    atexit(Hook);
}