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

时间:2009-04-16 14:26:28

标签: windows winapi operating-system exe executable

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

我将把这个问题的主题缩小到Win32可执行文件(.exe)。当我在专门的查看器中打开这些文件时,我可以找到分散在不同位置的字符串(通常每个字符16b),但其余的只是垃圾。我想不可读的部分(大多数)是机器代码(或者可能是资源,例如图像等......)。

有没有简单的方法来阅读机器代码?将exe作为文件流打开并逐字节读取,如何将这些单独的字节转换为汇编?这些指令字节与汇编指令之间是否有直接的映射?

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

我如何理解EXE文件中的内容?

13 个答案:

答案 0 :(得分:15)

OllyDbg是一个很棒的工具,可以将EXE反汇编成可读的指令,并允许您逐个执行指令。它还告诉您程序使用的API函数,如果可能的话,它会提供它提供的参数(只要参数在堆栈中找到)。

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

你可以选择Paul Carter博士的PC Assembly Language Tutorial这是一本免费的入门级书籍,讲述了装配以及英特尔386 CPU如何运作。其中大部分甚至适用于现代消费者的英特尔CPU。

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

答案 1 :(得分:6)

您需要一个反汇编程序,它将机器代码转换为汇编语言。此Wikipedia link描述了该过程并提供了免费反汇编程序的链接。当然,正如你所说,你不懂汇编语言,这可能不是很有用 - 你究竟想在这做什么?

答案 2 :(得分:5)

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

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

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

然后是MSIL EXE:.NET可执行文件持有微软中间语言,这些不包含特定于机器的代码,而是包含.NET CIL代码。其规格可在ECMA网站上获取。

可以使用Reflector等工具查看这些内容。

答案 3 :(得分:5)

EXE文件的内容在Portable Executable中描述。它包含有关如何加载文件的操作系统的代码,数据和说明。

机器代码和装配之间存在1:1的映射。反汇编程序将执行相反的操作。

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

答案 4 :(得分:4)

您可以从命令行使用debug,但这很难。

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

答案 5 :(得分:2)

如果它看起来像你一样陌生,我不认为调试器或反汇编程序会有所帮助 - 你需要先学习汇编程序编程;研究处理器的架构(可从英特尔下载大量文档)。然后,由于大多数机器代码都是由编译器生成的,因此您需要了解编译器如何生成代码 - 这是编写大量小程序的最简单方法,然后对它们进行反汇编以查看C / C ++的用途。

有几本书可以帮助您理解: -

答案 6 :(得分:2)

要了解一个想法,请在一些有趣的代码上设置断点,然后转到CPU窗口。

如果您对更多内容感兴趣,可以使用-al参数使用Free Pascal编译短片段更容易。

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

因为它是编译器生成的汇编程序,而不是来自反汇编的.exe的汇编程序,所以它更具象征性,更容易理解。

答案 7 :(得分:1)

MSDN上的

Win32 exe format

我建议使用一些Windows C源代码并在Visual Studio中构建并开始调试它。切换到反汇编视图并跳过命令。您可以看到如何将C代码编译成机器代码 - 并观察它是如何逐步运行的。

答案 8 :(得分:1)

关于这个问题,任何人都会读到类似的东西 CD 21?

我在一场演出中记得桑德拉布洛克,实际上正在阅读一些十六进制的数字并弄清楚程序的作用。有点像当前版本的阅读矩阵代码。

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

答案 9 :(得分:1)

你的好奇心和理解水平正是我在某一点上所处的位置。我高度推荐Code: The Hidden Language of Computer Hardware and Software。这不会回答你在这里提出的所有问题,但它将揭示计算机的一些完全黑魔法方面。这本书很厚,但读起来很高。

答案 10 :(得分:1)

ACD See可能正在利用.EXE文件不对文件长度进行错误检查或超出文件预期部分长度的任何事实。因此,您可以创建一个.EXE文件,该文件将打开其自身并将超出给定点的所有内容作为数据加载。这很有用,因为您可以通过在适当编写的.EXE末尾添加该数据来创建一个适用于给定数据集的.EXE

(我不知道究竟是什么ACD看到了这么多,但我知道某些程序是以这种方式生成的。)< / p>

答案 11 :(得分:1)

熟悉低级别装配(我的意思是低级装配,而不是“宏”和那个公牛)可能是必须的。如果你真的想直接读取原始机器代码本身,通常你会使用十六进制编辑器。然而,为了理解指令的作用,大多数人会使用反汇编程序将其转换为适当的汇编指令。如果你是想要了解机器语言本身的少数人之一,我想你会想要Intel® 64 and IA-32 Architectures Software Developer's Manuals第2卷专门涵盖了指令集,该指令集与您有关如何读取机器代码本身以及程序集与其相关的查询有关。

答案 12 :(得分:-1)

每条指令都以机器码形式保存在cpu内的特殊存储区中。早期的INTEL书籍提供了机器代码以供他们参考,因此应该尝试获取此类书籍,以便对此有所了解。显然,今天机器代码并不容易获得。可以将十六进制反转为机器代码的程序将是不错的选择。还是手动_ !!  乏味