我想了解可执行文件的工作方式。我希望能够详细地理解一个非常具体的示例,使我能够这样做。我的最终目标(也许是过于雄心勃勃的)是获取hello-world .exe文件(使用C编译器编译并链接),并详细了解如何将其加载到内存中并由x86处理器执行。如果我成功完成了此事,我想写一篇文章和/或制作一个有关它的视频,因为我没有在互联网上找到类似的东西。
我要问的特定问题以粗体标出。当然,我们欢迎任何其他类似建议的建议和消息来源。提前非常感谢您的帮助!
Answer概述了C代码直到作为程序进入物理内存之前所经历的过程。我还不确定我要研究C代码的编译方式。 是否有一种方法可以在组装之前查看C编译器生成的汇编代码?我可能认为值得花些力气来理解加载和链接的过程。同时,我需要了解的最重要的部分是
我对PA格式有非常基本的了解(这种了解将在“到目前为止我学到的内容”部分中概述),我认为给出的资料应该足够了,我只需要对其进行进一步研究即可。直到我足够了解基本的Hello-World程序。 当然欢迎您提供有关此主题的其他来源
对于x86,将字节码转换为汇编代码(反汇编)似乎非常困难。尽管如此,我还是想了解更多。您将如何拆卸一个短字节代码段?
我仍在寻找一种查看进程内存(分配给它的虚拟内存)内容的方法。我已经研究过诸如ReadProcessMemory
之类的windows-kernel32.dll函数,但无法使其正常工作。同样令我感到奇怪的是,似乎没有(免费)工具可用于此。加上对加载的理解,我也许就能了解如何从RAM运行进程。另外,我还在寻找用于汇编程序员的调试工具,这些工具可以查看整个过程虚拟内存内容。我当前搜索的起点是question。您是否对我如何查看和了解RAM的加载和进程执行?
此StackOverflow问题的其余部分详细介绍了我到目前为止所学的内容,并提供了各种资料。它旨在具有可复制性,并可以帮助任何试图理解这一点的人。但是,对于到目前为止我看到的示例,我仍然有一些疑问。
在Windows中,可执行文件遵循PA格式
。 official documentation和this article很好地概述了格式。该格式描述了.exe文件中各个字节的含义。开头是一个我不会担心的DOS程序(出于遗留原因而包括在内)。然后是一堆标题,这些标题提供了有关可执行文件的信息。实际的文件内容分为具有名称的部分,例如“ .rdata”。在文件头之后,还有节头,它们告诉您文件的哪个部分是哪个节以及每个节的功能(例如,如果其中包含可执行代码)。标题和节可以使用诸如dumpbin(用于查看二进制文件的Microsoft工具)之类的工具进行解析。为了与dumpbin输出进行比较,可以使用十六进制编辑器甚至使用Powershell(命令Format-Hex -Path <Path to file>
)直接查看文件的十六进制代码。
我为一个非常简单的程序执行了这些步骤,但是什么也不做。这是代码:
?然后我看了转储输出:; NASM assembler programm. Does nothing. Stores string in code section. ; Adapted from stackoverflow.com/a/1029093/9988487 global _main section .text _main: hlt db 'Hello, World'
我用NASM组装了它(命令
,这似乎很长,让我认为可能有一些错误nasm -fwin32 filename.asm
),并将其与VS2019附带的链接器(link /subsystem:console /nodefaultlib /entry:main test.obj
)链接起来。改编自this answer,该文档演示了如何使用WinAPI调用为Windows制作hello-world程序。该程序在Windows 10上运行,并以无输出终止。它花费了[[大约2秒钟才能运行
D:\ASM>dumpbin test.exe /ALL
Microsoft (R) COFF/PE Dumper Version 14.22.27905.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file test.exe
PE signature found
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (x86)
2 number of sections
5E96C000 time date stamp Wed Apr 15 10:04:16 2020
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
102 characteristics
Executable
32 bit word machine
OPTIONAL HEADER VALUES
10B magic # (PE32)
14.22 linker version
200 size of code
200 size of initialized data
0 size of uninitialized data
1000 entry point (00401000)
1000 base of code
2000 base of data
400000 image base (00400000 to 00402FFF)
1000 section alignment
200 file alignment
<further header values omitted ...>
SECTION HEADER #1
.text name
E virtual size
1000 virtual address (00401000 to 0040100D)
200 size of raw data
200 file pointer to raw data (00000200 to 000003FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
Execute Read
RAW DATA #1
00401000: F4 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 0A ôHello, World.
SECTION HEADER #2
.rdata name
58 virtual size
2000 virtual address (00402000 to 00402057)
200 size of raw data
400 file pointer to raw data (00000400 to 000005FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
Read Only
RAW DATA #2
00402000: 00 00 00 00 00 C0 96 5E 00 00 00 00 0D 00 00 00 .....À.^........
00402010: 3C 00 00 00 1C 20 00 00 1C 04 00 00 00 00 00 00 <.... ..........
00402020: 00 10 00 00 0E 00 00 00 2E 74 65 78 74 00 00 00 .........text...
00402030: 00 20 00 00 1C 00 00 00 2E 72 64 61 74 61 00 00 . .......rdata..
00402040: 1C 20 00 00 3C 00 00 00 2E 72 64 61 74 61 24 7A . ..<....rdata$z
00402050: 7A 7A 64 62 67 00 00 00 zzdbg...
Debug Directories
Time Type Size RVA Pointer
-------- ------- -------- -------- --------
5E96C000 coffgrp 3C 0000201C 41C
Summary
1000 .rdata
1000 .text
文件头字段“特征”是标志的组合。特别是102h = 1 0000 0010b
和两个设置标志(根据PE格式doc)是IMAGE_FILE_EXECUTABLE_IMAGE
和IMAGE_FILE_BYTES_REVERSED_HI
。后者有描述IMAGE_FILE_BYTES_REVERSED_HI:大字节序:内存中的MSB优先于LSB。此标志已弃用,应为零。
我问自己:
为什么现代的汇编程序和现代的链接程序产生不推荐使用的标志?
文件中有2个部分。.text
节是在汇编代码中定义的(并且是唯一包含可执行代码的部分,如其标题中所指定)。 我不知道第二部分'.rdata'(名称似乎指的是“可读数据”)。
为什么创建它?我怎么能找到?拆卸dumpbin test.exe /DISASM
)。它得到正确的hlt
,即“ Hello,World”。字符串(可能很不幸)被解释为可执行命令。我猜这几乎不能归咎于反汇编程序。但是,如果我理解正确(我没有汇编程序设计的实际经验),那么将数据放入代码段并不是闻所未闻的(这是我在研究汇编程序时发现的几个示例中完成的)。 是否有更好的方法可以对此进行取消配置,从而可以更好地重现我的汇编代码
?另外,编译器有时会以这种方式将数据放入代码段中吗?目标,我想了解可执行文件的工作方式。我希望能够详细地理解一个非常具体的示例,使我能够这样做。我的最终目标(也许是雄心勃勃的)是打个招呼-...[不,编译器不会将数据放在代码段中(如果我错了,请纠正我)。有.data节(用于初始化的数据)和.bss节(用于未初始化的数据)。