assembly - 很少的汇编语法问题和反汇编代码的解释
问题描述
我正在尝试在某些练习/挑战中对可执行文件进行逆向工程。
我在 IDA64 反汇编程序中打开了该文件。大多数代码是隐藏的,但三个子例程是可见的(包括开始)。我在组装方面的主要经验是在学校使用 MIPS - 所以我几乎没有什么让我感到困惑的事情:
这条线是什么意思?ebx 地址的值是 0 还是只是它的第一个字节?
mov byte ptr [ebx], 0
当我看到这两行代码时,地址'1000h'是什么?含义 - 我在哪里可以找到它,里面有什么?IDA 中的所有代码都从 401000 开始。
mov ebx, 1000h xor [ebx], eax
是否有任何关于 eax、ebx 和 esi 寄存器的约定,我应该假设它们在代码开头有什么?可执行文件要求用户输入 - 我可以假设这个输入在任何特定的寄存器中吗?
解决方案
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
很容易地找到它,如果程序没有被混淆或用非常抽象的语言编写,它会很快找到读取输入的位置。
第三种方法是使用非常接近原始技术的技术编写精简的孪生应用程序,然后分析后者。
这样你也有一个源代码来打通反汇编的迷雾。
推荐阅读
- c++ - 如何正确提示用户?
- android - 如何以编程方式获取应用程序的旧(非自适应)图标?
- ruby - 随着时间的推移意外打开与后台处理器的多个连接
- git - 获取 git repo,然后应用补丁。提交补丁而不是基础仓库
- c++ - 如何在没有#include的情况下生成所有内联代码的单个文件?
- haskell - Haskell 中的通用模式
- python - 如何在 Dash Plotly 中为各个类指定样式?
- javascript - 如何获得以前选择的 OOP Javascript 记住按钮?
- powershell - Powershell Exchange 列出具有大小的文件夹中的所有主题
- sql - Oracle - 内部查询需要时间