2016-11-06 295 views
0

这是一种训练任务,因为现在这些方法(我猜)不再工作了。如何在C程序中修复Hook(堆栈的恢复)

使用Win XP和MinGW编译器。没有涉及特殊的编译器选项(只是说明一个源文件的gcc)。

首先,节省地址从程序退出和跳跃到一些钩子函数:

// 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功能。我的意思是,这些线路均在钩子函数,而不是跳跃,而周期:

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

但与此变种我是从程序退出之前注册获得在ESP不正确的值(它是在更大的8个字节那么这个寄存器的值在进入这个程序之前)。所以我决定添加这8个字节(避免C程序中的任何ASM代码)。这是通过适当的退出来移入FixStack函数的目的(从堆栈中删除一些值)。

echo %ErrorLevel% 

所以我的问题非常广泛::但是,正如我所说的那样,不使用此命令返回程序执行的正确状态在调试实用工具的使用要求的一些建议开始(我仅使用OllyDbg),并以所描述的Hook实现的可能解决方案结束。

+0

@ryyker,它编译没有任何错误,并且最终版本(在回答说明)正常工作 –

+0

@ryyker,它可能不会在其他一些系统编译和使用一些其他的编译器,当然。很难让一种提供的解决方案在任何地方都可运行(因为不同的编译器最终生成不同的代码,并且我们使用一种黑客来重定向程序的执行流)。但关于这一点,我没有收到任何错误和警告。 –

回答

0

好的,我可以让我的程序工作,因为它是有意的,最后。现在我们可以启动编译(我在Win XP中使用MinGW)程序,没有任何错误和正确的返回码。

也许会有所帮助的人:

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

typedef unsigned long int DWORD; 

DWORD addr_ret; 


int FixStack() 
{ 
    DWORD m[1]; 
    m[2] = addr_ret; 

    // This line is very necessary for correct running! 
    return 0; 
} 


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

    FixStack(); 
} 


int main() 
{ 
    DWORD m[1]; 

    addr_ret = (DWORD) m[4]; 

    m[4] = (DWORD) Hook; 
} 
0

当然,你似乎已经意识到,这将只与一个非常具体的编译环境中工作。它绝对不会在64位目标上工作(因为地址不是DWORD-ish)。

是否有任何理由不使用C标准库提供的工具来执行此操作? (或者与此非常相似的东西。)

#include <stdlib.h> 

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

int main() 
{ 
    atexit(Hook); 
}