【问题标题】:How to write and executable Windows .exe manually (machine code with Hex editor)?如何手动编写和执行 Windows .exe(使用十六进制编辑器的机器代码)?
【发布时间】:2012-07-29 10:18:04
【问题描述】:

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

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

这只是纯粹的好奇。不......我不考虑直接用二进制机器代码编写程序(我什至不经常编写汇编代码,我大多数时候只是使用 C/C++ 作为我最底层的工具)。我只是想看看是否可以这样做,因为在计算机的早期可能有人必须这样做。

附: 我知道关于这个主题有类似的问题,但没有一个提供一个有效的例子。我只想要一个简单的例子,这样它就可以帮助我理解编译器和汇编器是如何生成可执行文件的。我的意思是......过去必须有人为第一个程序手动完成此操作。此外,对于 Windows EXE 格式,肯定有人在 Microsoft 编写了第一个生成格式的工具以及 Windows 本身读取并执行它的方式。

【问题讨论】:

  • hello world 程序没有什么简单的,它是一个极其复杂和高级的话题。添加几个数字是一个简单的程序。
  • Reading/Writing machine code 的可能重复项,两者都归结为:EXE 是如何工作的?它们也太宽泛了:-)
  • @old_timer 将程序mov eax,4 ret作为机器语言写入exe文件有多复杂?它可以很容易地为 ELF 完成(使用模板),为什么不是 EXE?
  • 将一些机器代码写入任何二进制格式文件是微不足道的,您只需查找二进制格式,检查其他工具制作的一些示例以验证格式文档,然后从头开始或调整。但是带有 printf 的 hello world 程序背后有大量代码,可以看到代码出现在窗口上。是的,您可以确定一些系统调用并将其简化为带有字符串的循环
  • 如果我没记错的话,.exe 比 elf 和 elf 文件简​​单得多(简单到不需要库)。 .com 更简单...

标签: windows exe executable machine-code


【解决方案1】:

corkami/wiki/PE101 上有一个非常简约但功能齐全的(在 Win7 上也是)exe,它的每个字节都在漂亮的图形中进行了解释。您可以在十六进制编辑器中手动输入所有内容,但填充可能会让这有点乏味。

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

后来,AT&T 的 COFF 格式被 Microsoft 扩展为 PE 格式,它仍然具有 MZ 标头,并且通常(但可选,它不在 corkami 示例中,它可以是任何东西)包含一个小的 DOS 程序,只是为了打印消息“此程序无法在 DOS 模式下运行”。

【讨论】:

  • 漂亮的图形解释。像这样的东西很接近我想要的。
  • @petersaints 我添加了一些您可能感兴趣的历史记录
  • 网络主题是否存在类似的逐字节视觉解释?我知道我可以在例如查看数据包。 wireshark,但所有的视觉可能性都在一张海报中加起来。
  • @naxa 也许吧,不过我不知道在哪里可以找到它
  • 源代码和二进制文件的链接现在已断开
【解决方案2】:

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

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

3) 基于 2,在 1960 年代或 1970 年代进行测试时,任何比一次或几条指令更复杂的东西,即使在编写手工组装程序时,您也可以在汇编程序中手动编写程序,然后将其组装成机器代码,然后加载它。基本上首先学习汇编语言,然后学习如何为其生成机器代码,然后开始将这些字节输入十六进制编辑器。现在不是 1960 年代,除非你享受过度的痛苦,通过写 asm 来学习上面的内容,使用汇编程序生成机器码,然后使用反汇编程序对其进行反汇编,并将汇编语言和机器码并排检查以显着提高您获得一个工作程序所需的时间。如果你在有操作系统和指令集之前就在一家芯片公司工作,你仍然会利用团队的其他成员、芯片设计人员等来了解如何制作和安排机器码。您不会仅凭高水平的语言经验就可以完成这一切,并希望获得成功。

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

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

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

【讨论】:

  • 文件中不是从0x100开始;代码从文件的最开头开始执行。它被加载到 内存 中的地址 0100,但是,在任何被选为代码段的段中。
【解决方案3】:

我手工制作二进制文件,但我认为汇编本身比纯十六进制编辑器更容易,因为在这种编辑器中更新任何东西都会很困难。

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

  • EXE(非 DOS 格式)也不需要太多,请参阅 here

  • 如果你想创建一个 PE,你可以创建一个TinyPE

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

【讨论】:

    【解决方案4】:

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

    此页面 [...] 关于我尝试创建最小的 x86 ELF 二进制文件,该二进制文件将在 Ubuntu Linux 上执行 Hello World 我的第一次尝试从 C 开始,然后进展到 x86 汇编,最后到 hexeditor。

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

    【讨论】:

    • AFAIK,Windows 中的 PE 解析代码现在(在 Vista/7 中)更加严格,在 9x/XP 上工作的最低 PE 将无法在 Vista/7 上工作。人们应该真正研究格式规范并首先从有效的 PE 图像开始,然后才尝试修剪它。
    • 没错。我发现了一些适用于旧版本 Windows 但不适用于 Windows 7 的示例。感谢您的提示。我已经知道第一个链接(我在研究期间发现了它),但第二个是新链接(这很有趣,因为它专注于 PE 格式,而我在 Windows 上:P)
    【解决方案5】:

    我写了一篇关于在命令提示符下使用 ECHO 创建可执行 DOS 二进制文件的文章。无需其他 3rd 方 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 汇编程序以在屏幕上打印美元符号的操作码值。

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

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

    运行文件“$.com”,您将看到屏幕上显示一个美元 ($) 字符。

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

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

    【讨论】:

      【解决方案6】:

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

      例如

      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,并且只会打印“hello”,您可以使用十六进制编辑器并使用 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 中运行它

      【讨论】:

        猜你喜欢
        • 2012-02-12
        • 2012-04-15
        • 2019-07-23
        • 2012-02-14
        • 2012-07-20
        • 2012-05-07
        • 2011-10-16
        • 2011-07-13
        相关资源
        最近更新 更多