Removing function call from application using a debugger

时间:2018-07-25 05:06:01

标签: debugging reverse-engineering

I have an application which calls a function for every iteration of the main program loop. I want to remove this function call using a debugger like OllyDBG.

I think I approximately located where the function should be based on some strings that are in it.

How would I go about doing this without breaking the program?

1 个答案:

答案 0 :(得分:0)

这实际上取决于程序如何使用该功能。而且您将需要一些基本的汇编语言来成功地做到这一点,以及可能理解不同的调用约定。

我将举几个例子,难度越来越大。

一个简单的例子

假设您要避免使用的函数具有以下原型:

void bad_function();

我们可以清楚地看到它没有参数,也不返回任何值。还可以说它不会更改任何全局变量或对该程序进行任何其他更改。在这种情况下,我们可以放心地“删除”对函数的调用,一切都会很好。

但是,我们不能仅从流中删除机器代码字节,因为存在相对和硬编码的偏移量,然后需要根据删除的字节数进行调整。幸运的是(尽管运气与之无关),有特定的指令称为nop指令,它们只是空的占位符-指示CPU不执行什么,而是继续执行下一条指令。

附注:尽管大多数指令集都定义了nop指令,但它们通常只是已经存在但没有副作用的指令约定。例如,常见的x86 nop指令是0x90,从技术上来说是xchg eax, eax。显然,与其自身交换寄存器无济于事。

简单的返回值

现在,假设函数 returns 是一个布尔值,用于确定执行是应该继续还是突然终止(例如,由于程序认为不好的事情发生了)。

该函数的原型可能如下所示:

bool bad_function();

,使用它的代码将是:

bool bad;
bad = bad_function();
if (bad)
{
    ExitProcess();
}

生成的程序集可能类似于:

    call bad_function
    test eax, eax
    jz not_bad_function
    call ExitProcess

not_bad_function:
    ... some more assembly

您会在这里注意到我们要确保执行not_bad_function下的代码(为方便阅读,我将其命名为标签。实际上,它会有一个偏移量),并且还要避免致电bad_function

我们将用nop替换不需要的指令。有时指令可能大于一个字节,我们将用几个nop指令而不是一个替换一个指令。也有多字节长的nop指令,但是我们不在这里介绍。

在以下情况下,我们将要nop淘汰所有四条指令,直到not_bad_function(这是两个calltestjz指令)。 我们还可以使跳转成为无条件的,并保持testcall不变。如果我们要做要执行bad_function,这可能很方便,因为它确实会产生我们所感兴趣的某些副作用。

“清理”堆栈

现在,假设bad_function接受参数。根据调用约定,传递的参数集以及所使用的编译器和目标体系结构,在调用push之前,我们可以得到多条bad_function指令。这些用于将参数压入堆栈,以供调用的函数使用。同样,根据调用约定,调用者有责任在之后清理堆栈。在这种情况下,我们将需要在调用函数后删除推送指令和清除操作。

随着代码变得越来越长,我将留下一个示例供读者练习。