x86 架构是典型的CISC架构,它可以执行不同大小的存储。
Amov [ebx], 0
不明确(使用了哪个大小?),但mov byte [ebx], 0
将大小固定为 8 位。
这ptr
只是一种修饰,因此指令读起来几乎是自记录的:移动到由zero指向的字节ebx
。
这也解释了指令的语义,互联网上有很多关于 x86 寻址模式的教程。
我拿起了第一个。
1000h
是一个奇怪的地址,它可能在进程的工作集之外,它也是该.text
部分的典型 RVA(相对虚拟地址)。
这让我觉得有一个指向该指令操作数的重定位入口。
IDA free 无法调试,但x64dbg可以,尝试调试程序,看看地址是否变成BASE_ADDRESS + 1000h
.
IDA 将在加载后显示 PE 部分的静态视图,因此您可以检查全局变量的初始值,但要查看必须调试程序的内存的实时视图。
正式地,在 PE 入口点,寄存器具有未定义的值,但由于在用户模式库中开始执行,一些值泄漏,尽管这不是可靠的 ABI。
编译器和 API 使用了一些调用约定,您应该习惯这一点。
每个编译器也将有其典型的寄存器分配算法,但这可能太复杂而无法展示模式,但在非常简单的例程中。
输入值可能会在某个时候出现在某个寄存器中,但找到何时何地是最难的部分。
通过研究应用程序的行为,您可以写下一组可能的输入 API,程序将使用这些 API 并在其中的每一个上中断。
返回程序代码后,您将获得输入字符串(IO 是基于字符串的)。或者,您从一开始就对应用程序进行逆向工程,训练有素的分析师可以WinMain
很容易地找到它,如果程序没有被混淆或用非常抽象的语言编写,它会很快找到读取输入的位置。
第三种方法是使用非常接近原始技术的技术编写精简的孪生应用程序,然后分析后者。
这样你也有一个源代码来打通反汇编的迷雾。