如何手动编写和执行Windows .exe(使用Hex编辑器的机器代码)?

时间:2012-07-31 15:30:20

标签: windows exe executable machine-code

我想知道如何使用十六进制编辑器编写像Hello World程序一样简单的东西。我知道我可以在近机器级别使用汇编语言和汇编语言,但我只想尝试在Hello World等玩具示例中编写机器代码。

这可能是一个简单的DOS .COM文件,我可以在DOSBox上运行。但如果有人可以提供.EXE文件的示例,直接在我的Windows PC上运行它,那就太好了。

这只是纯粹的好奇心。不......我不打算直接用二进制机器代码编写程序(我甚至不编写汇编代码,我只是在大多数时候使用C / C ++作为我最低级的工具)。我只是想看看是否有可能这样做,因为可能有人必须在计算机的早期阶段就这样做。

P.S .: 我知道关于这个主题有类似的问题,但没有提供一个有效的例子。我只想要一个简单的例子,以便它可以帮助我理解编译器和汇编器如何生成可执行文件。我的意思是......在过去的第一个项目中,有人必须亲手完成。此外,对于Windows EXE格式,Microsoft必须有人编写第一个生成格式的工具以及Windows本身读取它然后执行它的方式。

6 个答案:

答案 0 :(得分:16)

corkami/wiki/PE101上有一个非常极简主义但完全正常工作(在Win7上也是)exe,它的每一个字节都在漂亮的图形中解释。您可以在十六进制编辑器中手动输入所有内容,但填充可能会使这有点单调乏味。

至于历史,是的,微软的某人发明了exe格式(旧的DOS MZ exe格式),他(或微软的其他人)为它和链接器编写了一个加载器,这是传统上转向编译器("目标文件")的输出到可执行文件中。可能(甚至可能,我会说)第一个exe程序是手工编写的,毕竟它们只是为了测试新的加载器。

后来,AT& T的COFF格式被微软扩展为PE格式,它仍然具有MZ标题并且通常(但可选地,它不在corkami示例中,它可以是任何真的)包括一个小的DOS程序只是为了打印消息"这个程序不能在DOS模式下运行"。

答案 1 :(得分:8)

1).com文件是最简单的启动位置,并且会在dosbox上运行,基本上程序从文件中的偏移0x100开始,我认为第一个0x100可以是什么,不记得了

2)虽然第一个程序通常是手工编写并组装成机器代码,但我们正在讨论当你添加两个数字时将它们保存在内存中,并且非常高兴你能休息一天。将内容打印到视频卡的“hello world”程序要复杂得多。现在你可以使用dos系统调用做一个非常简单的调用,也许这不是你感兴趣的,也许是。

3)基于2,在20世纪60年代或70年代一次比一个或几个指令更复杂的东西,甚至在编写手工组装程序时,你手工编写汇编程序,然后组装到机器码,然后加载它。首先学习汇编语言,然后学习如何为它生成机器代码,然后开始将这些字节输入到十六进制编辑器中。它不是20世纪60年代,除非你喜欢过度痛苦,通过编写asm来学习上述内容,使用汇编程序生成机器代码,然后使用反汇编程序对其进行反汇编并检查汇编语言和机器代码并进行显着改进获得工作计划所需的时间。如果您在拥有操作系统和指令集之前曾在一家芯片公司工作过,那么您仍然可以利用团队中的其他成员,芯片设计人员等来了解如何制作机器代码并进行安排。你不会以高水平的语言经验来实现这一目标,并且希望自己能够成功地完成所有这些工作。

4)x86是一个可怕的指令集,如果你不知道汇编我强烈反对你不要先学习它。拥有x86是我听过学习x86的最糟糕的借口。你已经提到了dosbox,所以我们已经计划模拟/模拟,所以使用一个好的指令集并模拟它或购买那些硬件(低于50美元甚至低于20美元将为你买一块具有更好指令集的板)。如果您选择购买,我建议首先模拟/模拟并与硬件并行。如果你真的想要教育写自己的模拟器,那就不难了。也许发明你自己的指令集。

5)这些都不会帮助您理解编译器的功能。了解汇编语言然后反汇编编译器输出是您获取该知识的最佳途径,不涉及机器代码,无需实际运行程序。编译器从较高级语言转到较低级语言(例如,C到asm或C ++到asm)。然后了解汇编程序的作用,有许多不同的解决方案,这些解决方案既有历史原因,也有其他原因。今天典型的解决方案是一个单独的编译器,汇编器和链接器(你的编译器会为你调用汇编器和链接器,除非你不告诉它,这三个步骤是隐藏的,实际上编译过程可能不止一个是运行以完成该任务)。输出二进制文件的汇编程序必须解析整个程序,输出到对象的汇编程序将在机器代码中留下漏洞,供链接器填写。例如分支或调用另一个对象中的项目,直到链接器放置它才能编码二进制中的东西,知道间距/寻址。还访问其他对象中的变量。

你可能没有看到关于十六进制编辑程序的实际例子,因为首先它是一个如此广泛的问题,没有一个简单的答案(什么操作,系统,什么系统调用或你在创建那些,什么文件格式,什么是十六进制编辑等)。另外,因为它是一个高级别的问题和问题,真正的问题是我在哪里学习汇编,在哪里我了解汇编和机器代码之间的关系,我在哪里学习系统调用(这不是汇编问题,他们与学习asm无关,你学习汇编语言本身,然后你学会用它作为执行系统调用的工具,如果你不能使用更高的语言直接执行系统调用),我在哪里学习可执行文件格式,如.com, .exe,coff,elf等。在xyz操作系统或环境中运行的什么是好的或简单的或形容词,十六进制编辑器。单独询问这些问题,您将找到答案和示例,一旦获得这些答案,您将知道如何使用十六进制编辑器输入机器代码来制作程序。一个较短的例子是,当您看到在SO上发布的程序的反汇编时,您会看到完整程序的十六进制示例,其中一些是以十六进制显示的完整程序。如果你知道文件格式,你可以直接在十六进制编辑器中输入。

答案 2 :(得分:5)

我手工创建二进制文件,但我认为它在汇编本身比简单的十六进制编辑器更容易,更新任何东西都很困难。

  • 最简单的肯定是DOS COM格式,你甚至可以type in notepad, 或者至少,即使是正常的Hello World也很容易。

  • EXE(非DOS格式)要求here不需要太多。

  • 如果您正在尝试制作PE,则可以制作TinyPE

大多数二进制文件应该以PEEXE and COM提供。

答案 3 :(得分:4)

没有发现,但本教程应该让您更好地了解程序集如何映射到机器代码(x86 ELF):http://timelessname.com/elfbin/(特别是查看页面的下半部分)

  

这个页面是关于我创建最小的x86 ELF二进制文件的尝试,该二进制文件将在Ubuntu Linux上执行说Hello World我的第一次尝试从C开始然后进展到x86程序集,最后进入hexeditor。

分析这些非常小的可执行文件非常棒,因为程序集和机器代码之间的映射更容易被发现。这也是关于这个主题的一篇非常有趣的文章(虽然与你的问题不完全相关):http://www.phreedom.org/research/tinype/(x86 PE)

答案 4 :(得分:3)

你可以进行反汇编并尝试找出你在汇编程序中使用的操作码的机器代码

例如

org 0x100
mov dx,msg
mov ah,0x09
int 0x21
ret
msg db 'hello$'

使用nasm -fbin ./a.asm -o ./a.com编译 有ndisasm a.com提供以下反汇编:

00000000  BA0801            mov dx,0x108
00000003  B409              mov ah,0x9
00000005  CD21              int 0x21
00000007  C3                ret
00000008  68656C            push word 0x6c65
0000000B  6C                insb
0000000C  6F                outsw
0000000D  24                db 0x24

00000000 to 00000007 are the instructions

所以你可以使用ba0801机器代码,使用一些十六进制编辑器,尝试将其更改为ba0901,只打印'ello',你可以使用你的十六进制编辑器来玩,并用NOP填充东西,这是机器码中的0x90,例如:

00000000:  ba 50 01 90 90 90 90 90  90 90 90 90 90 90 90 90  .@..............
00000010:  b4 09 90 90 90 90 90 90  90 90 90 90 90 90 90 90  ................
00000020:  cd 21 90 90 90 90 90 90  90 90 90 90 90 90 90 90  .!..............
00000030:  c3 90 90 90 90 90 90 90  90 90 90 90 90 90 90 90  ................
00000040:  71 77 65 72 74 79 75 69  61 73 64 66 67 68 6a 24  qwertyuiasdfghj$
00000050:  61 73 64 66 67 68 6a 6b  61 73 64 66 67 68 6a 24  asdfghjkasdfghj$
00000060:  -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- --  ----------------

如果你使用扩展名.com保存它,你可以在DosBox中运行它

答案 5 :(得分:2)

我写了一篇关于在命令提示符下使用ECHO创建可执行DOS二进制文件的文章。不需要其他第三方HEX实用程序或x86 IDE!

该技术使用键盘组合 - ALT ASCII代码将OPCODES转换为可在MSDOS下直接读取的二进制格式。输出是完全可运行的二进制* .com文件。

http://colinord.blogspot.co.uk/2015/02/extreme-programming-hand-coded.html

<强>摘录: 在DOS提示符下键入以下键命令,记​​住保持左ALT。

c:\>Echo LALT-178 LALT-36 LALT-180 LALT-2 LALT-205 LALT-33 LALT-205 LALT-32 > $.com

上面的代码实际上是描述X86汇编程序的操作码值,用于在屏幕上打印美元符号。

完成后,您的提示应如下所示。按enter键构建!

c:\>Echo ▓$┤☻═!═  > $.com

运行文件&#39; $。com&#39;你会看到屏幕上显示一个美元($)字符。

c:\>$.com
$
c:\> 

恭喜!您刚刚创建了名为$ .com的第一个手工编码的可执行文件。