如何手动读取/写入.exe机器码?

我不熟悉编译器的魔法。 对于我来说,将人类可读的代码(或不是真正可读的汇编指令)转换成机器代码的行为,对于我来说,火箭科学与魔法相结合。

我将把这个问题的主题缩小到Win32可执行文件(.exe)。 当我用专门的浏览器打开这些文件时,我可以在各个地方findstring(通常每个字符16b),其余的只是垃圾。 我认为不可读的部分(多数)是机器代码(或者可能是资源,比如图像等)。

有没有直接阅读机器代码的方法? 作为一个文件stream打开该exe文件,并逐字节读取它,如何将这些单独的字节转换为汇编? 在这些指令字节和汇编指令之间有直接的映射吗?

.exe是如何写的? 每个指令四个字节? 更多? 减? 我注意到一些应用程序可以像这样创build可执行文件:例如,在ACD中请参阅您可以将一系列图像导出为幻灯片。 但是,这不一定是一个SWF幻灯片,ACD See也能够生成EXEcutable演示文稿。 这是怎么做的?

我如何理解EXE文件里面发生了什么?

OllyDbg是一个非常棒的工具,可以将EXE拆分为可读的指令,并允许您逐一执行指令。 它还告诉你程序使用什么API函数,如果可能的话,它提供的参数(只要参数在堆栈中找到)。

一般来说,CPU指令的长度是可变的,有些是一个字节,有些则是两个,三个,四个等等。它们大多取决于指令期望的数据类型。 有些指令是通用的,比如“mov”,告诉CPU将数据从CPU寄存器移动到内存中,反之亦然。 实际上,有许多不同的“mov”指令,用于处理8位,16位,32位数据,用于移动来自不同寄存器的数据的指令等等。

您可以拿起Paul Carter博士的PC汇编语言教程 ,这是一本免费的入门级书籍,讲述汇编以及Intel 386 CPU如何运行。 它们大部分甚至适用于现代消费类英特尔CPU。

EXE格式是特定于Windows的。 入口点(即第一个可执行指令)通常在EXE文件的相同位置找到。 所有这一切都很难一次解释,但是我提供的资源应该至少可以帮助你治愈一​​些好奇心! 🙂

你需要一个反汇编器,将机器码转换成汇编语言。 这个维基百科链接描述的过程,并提供免费反汇编的链接。 当然,正如你所说的,你不懂汇编语言,这可能不是很有用的信息 – 你究竟在做什么?

您看到的可执行文件是Microsofts PE(可移植可执行文件)格式。 它本质上是一个容器,它容纳一些关于程序的特定于操作系统的数据,并且程序数据本身分成几个部分。 例如代码,资源,静态数据存储在单独的部分。

该部分的格式取决于内容。 代码部分根据可执行的目标体系结构保存机器代码。 在最常见的情况下,对于Microsoft PE二进制文件,这是Intel x86或AMD-64(与EM64T相同)。 机器代码的格式是CISC,并返回到8086及更早版本。 CISC的重要方面在于它的指令规模并不是一成不变的,你必须从正确的地方开始阅读才能获得有价值的东西。 英特尔在x86 / x64指令集上发布了很好的手册。

您可以使用反汇编程序直接查看机器代码。 结合手册你可以在大多数时间猜测源代码。

然后是MSIL EXE:持有Microsofts中间语言的.NET可执行文件,这些不包含机器特定的代码,但.NET CIL代码。 这些规格可在ECMA在线获得。

这些可以用反射器等工具查看。

可移植可执行文件中描述了EXE文件的内容。 它包含代码,数据和操作系统指导如何加载文件。

机器代码和程序集之间有1:1映射。 反汇编程序将执行反向操作。

i386上的每条指令没有固定的字节数。 有些是单字节,有些则长得多。

你可以从命令行使用调试,但这很难。

C:\WINDOWS>debug taskman.exe -u 0D69:0000 0E PUSH CS 0D69:0001 1F POP DS 0D69:0002 BA0E00 MOV DX,000E 0D69:0005 B409 MOV AH,09 0D69:0007 CD21 INT 21 0D69:0009 B8014C MOV AX,4C01 0D69:000C CD21 INT 21 0D69:000E 54 PUSH SP 0D69:000F 68 DB 68 0D69:0010 69 DB 69 0D69:0011 7320 JNB 0033 0D69:0013 7072 JO 0087 0D69:0015 6F DB 6F 0D69:0016 67 DB 67 0D69:0017 7261 JB 007A 0D69:0019 6D DB 6D 0D69:001A 206361 AND [BP+DI+61],AH 0D69:001D 6E DB 6E 0D69:001E 6E DB 6E 0D69:001F 6F DB 6F 

如果对你来说看起来很陌生,我不认为调试器或反汇编器会提供帮助 – 你需要先学习汇编程序。 研究处理器的体系结构(大量可从英特尔下载的文档)。 然后,由于大多数机器代码是由编译器生成的,因此您需要了解编译器如何生成代码 – 编写大量小程序最简单的方法,然后反汇编它们以查看C / C ++转换成的代码。

几本能帮助你理解的书:

  • 倒车
  • 黑客=开发的艺术

为了得到一个想法,在一些有趣的代码上设置一个断点,然后进入CPU窗口。

如果你对更多的东西感兴趣,用-al参数编译Free Pascal的短片段更容易。

FPC允许使用-A参数以多种汇编格式(TASM,MASM,GAS)输出生成的汇编程序,并且可以将原始的pascal代码交叉在注释中(以及更多)以便于交叉引用。

因为它是编译器生成的汇编程序,而不是从反汇编的.exe汇编程序,它更具象征性,更容易遵循。

MSDN上的Win32 exe格式

我建议采取一些Windows C源代码,并建立并开始在Visual Studio中调试它。 切换到反汇编视图并逐步执行命令。 你可以看到C代码是如何被编译成机器代码的 – 并且一步一步地观察它。

就这个问题而言,任何人都还在读CD 21这样的东西?

我记得桑德拉·布洛克在一个节目中,实际上是读一个十六进制数字屏幕,并找出程序的作用。 有点像当前版本的阅读矩阵码。

如果你读的东西像CD 21,你怎么记得不同的各种组合?

你的好奇心和你的理解水平正是我所处的地方。 我强烈推荐Code:计算机硬件和软件的隐藏语言 。 这不会回答你在这里问的所有问题,但它会揭示计算机的一些完全黑魔法方面。 这本书厚实,但可读性强。

ACD请参阅可能利用的事实,.EXE文件没有错误检查文件的长度或任何超出预期部分的文件的长度。 正因为如此,您可以创建一个.EXE文件来打开自己的文件,并将所有内容加载到给定的点上作为数据。 这很有用,因为您可以通过在适当写入的.EXE末尾添加数据来制作一个可以处理给定数据集的.EXE

(我不知道ACD See究竟是如何用一大粒盐,但我知道有一些程序是这样产生的。)

熟悉低级汇编(我的意思是低级汇编,而不是“宏”和公牛)可能是必须的。 如果你真的想直接读取原始的机器码,通常你会使用十六进制编辑器。 然而,为了理解指令的作用,大多数人会使用反汇编器将其转换成适当的汇编指令。 如果您是少数想要了解机器语言本身的人之一,我想您会想要英特尔®64和IA-32架构软件开发人员手册 。 第2卷专门介绍了关于如何读取机器代码本身以及如何与其相关的查询的指令集。