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?
答案 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
(这是两个call
,test
和jz
指令)。
我们还可以使跳转成为无条件的,并保持test
和call
不变。如果我们要做要执行bad_function
,这可能很方便,因为它确实会产生我们所感兴趣的某些副作用。
现在,假设bad_function
接受参数。根据调用约定,传递的参数集以及所使用的编译器和目标体系结构,在调用push
之前,我们可以得到多条bad_function
指令。这些用于将参数压入堆栈,以供调用的函数使用。同样,根据调用约定,调用者有责任在之后清理堆栈。在这种情况下,我们将需要在调用函数后删除推送指令和清除操作。
随着代码变得越来越长,我将留下一个示例供读者练习。