Ton*_*ony 9 windows x86 assembly parsing portable-executable
我只是在编写PE文件解析器的过程中,我已经达到了解析和解释PE文件中实际代码的程度,我假设它存储为x86操作码.
例如,DLL中的每个导出都指向函数将存储在内存中的RVAs(相对虚拟偏移),并且我编写了一个函数来将这些RVA转换为物理文件偏移.
问题是,这些是真正的操作码,还是其他的?
是否依赖于编译器/链接器关于函数如何存储在文件中,或者它们是一个还是两个字节的X86操作码.
例如,Windows 7 DLL"BWContextHandler.dll"包含四个加载到内存中的函数,使它们在系统中可用.第一个导出的函数是'DllCanUnloadNow',它位于文件中的偏移0x245D处.该数据的前四个字节是:0xA1 0x5C 0xF1 0xF2
这些一个或两个字节的操作码是这样的,还是完全不同的?
如果任何人都可以提供有关如何检查这些信息的任何信息,我们将不胜感激.
谢谢!
经过一些进一步的阅读,并通过IDA的演示版本运行文件,我认为我说第一个字节0xA1是一个单字节操作码,这意味着mov eax.我从这里得到了它:http://ref.x86asm.net/geek32.html#xA1,我认为它暂时是正确的.
但是,我对下面的字节如何构成指令的其余部分感到困惑.从我所知道的x86汇编程序来看,移动指令需要两个参数,即目标和源,因此指令是将(某些)移动到eax寄存器中,并且我假设某些内容来自以下字节.但是我不知道如何阅读这些信息:)
x86编码是复杂的多字节编码,您不能简单地在指令表中找到单行来解码它,就像在RISC(MIPS/SPARC/DLX)中一样.一条指令甚至可以有16字节编码:1-3字节操作码+几个前缀(包括多字节VEX)+几个字段用于编码立即或存储器地址,偏移,缩放(imm,ModR/M和SIB; moff).单个助记符有时会有几十个操作码.而且,对于几种情况,有两种编码可能是相同的asm行("inc eax"= 0x40和= 0xff 0xc0).
一个字节的操作码,意思是mov eax.我从这里得到了它:http://ref.x86asm.net/geek32.html#xA1,我认为它暂时是正确的.
我们来看看桌子:
po; flds; 助记符 op1; op2; grp1; grp2; 描述
A1; W; MOV; eAX; Ov; gen; 数据; 移动;
(提示:不要使用geek32表,切换到http://ref.x86asm.net/coder32.html#xA1 - 具有更少解码的字段,例如"A1 MOV eAX moffs16/32 Move")
有op1和op2列,http://ref.x86asm.net/#column_op 用于操作数.A1操作码的第一个始终是eAX,第二个(op2)是Ov.根据表http://ref.x86asm.net/#Instruction-Operand-Codes:
O/moffs原始指令没有ModR/M字节; 操作数的偏移量在指令中被编码为字,双字或四字(取决于地址大小属性).不能应用基址寄存器,索引寄存器或缩放因子(仅MOV(A0,A1,A2,A3)).
因此,在A1操作码之后,存储器偏移被编码.我认为,x86(32位模式)有32位偏移量.
PS:如果您的任务是解析PE而不是发明反汇编程序,请使用一些x86反汇编库,如libdisasm或libudis86或其他任何东西.
PPS:原始问题:
问题是,这些是真正的操作码,还是其他的?
是,"A1 5C F1 F2 05 B9 5C F1 F2 05 FF 50 0C F7 D8 1B C0 F7 D8 C3 CC CC CC CC CC"是x86机器代码.
反汇编很困难,特别是对于 Visual Studio 编译器生成的代码,尤其是 x86 程序。有几个问题:
指令是可变长度的,可以从任何偏移量开始。一些架构需要指令对齐。不是 x86。如果您从地址 0 开始读取,那么您将获得与从偏移量 1 开始读取的结果不同的结果。您必须知道有效的“起始位置”(函数入口点)是什么。
并非可执行文件的文本部分中的所有地址都是代码。有些是数据。Visual Studio 会将“跳转表”(用于实现 switch 语句的数组)放置在读取它们的过程下方的文本部分中。将数据误解为代码会导致您产生不正确的反汇编。
你不可能有完美的反汇编,它适用于所有可能的程序。程序可以自行修改。在这些情况下,您必须运行程序才能知道它的作用,而这最终会导致“停机问题”。您所能希望的最好的方法是反汇编,它适用于“大多数”程序。
通常用于尝试解决这些问题的算法称为“递归下降”反汇编。它的工作方式类似于递归下降解析器,因为它从一个已知的“入口点”(exe 的“main”方法,或 dll 的所有导出)开始,然后开始反汇编。在拆卸过程中发现了其他入口点。例如,给定“调用”指令,目标将被假定为入口点。反汇编器将反复反汇编发现的入口点,直到找不到更多入口点。
但是,该技术存在一些问题。它不会找到仅通过间接执行的代码。在 Windows 上,一个很好的例子是 SEH 异常的处理程序。分派给它们的代码实际上在操作系统内部,因此递归下降反汇编不会找到它们,也不会反汇编它们。但是,通常可以通过使用模式识别(启发式匹配)增强递归下降来检测它们。
机器学习可用于自动识别模式,但许多反汇编程序(如 IDA pro)使用手写模式取得了很大的成功。
无论如何,如果你想反汇编 x86 代码,你需要阅读Intel 手册。需要支持的场景很多。指令中的相同位模式可以根据修饰符、前缀、处理器的隐式状态等以各种不同的方式进行解释。手册中涵盖了所有这些内容。首先通读第 I 卷的前几节。这将介绍基本的执行环境。您需要的其余大部分内容都在第 II 卷中。
| 归档时间: |
|
| 查看次数: |
2128 次 |
| 最近记录: |