草庐IT

windows - 为什么 NASM 和 dumpbin.exe 对同一个可执行文件的反汇编输出不同?

coder 2024-06-09 原文

这是我遵循的步骤。

1) 我从 Kip Irvine 的《x86 处理器的汇编语言》一书中获取了三个不同小程序的汇编语言代码。

2) 我组装、链接以生成有效的可执行文件,在每种情况下都没有错误。

3) 对于每个可执行文件,我使用 NASM 生成反汇编

ndisasm -u -p intel add3.exe > add3_ndisasm.txt

4) 在每种情况下,我都使用 dumpbin.exe 获得了反汇编输出

dumpbin /disasm add3.exe > add3_dumpbin_disasm.txt

令人惊讶的是,我在第 4 步得到的反汇编与第 3 步完全不同。

这是我使用的汇编代码(在 3 种情况之一中)。

; This program adds and subtracts 32-bit integers.
.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD
DumpRegs PROTO
.code
main PROC
mov eax,10000h ; EAX = 10000h
add eax,40000h ; EAX = 50000h
sub eax,20000h ; EAX = 30000h
call DumpRegs
INVOKE ExitProcess,0
main ENDP
END main

这是第 3 步 (NDISASM) 的反汇编示例

00000000  4D                dec ebp

00000001  5A                pop edx

00000002  90                nop

00000003  0003              add [ebx],al

00000005  0000              add [eax],al

00000007  000400            add [eax+eax],al

0000000A  0000              add [eax],al

0000000C  FF                db 0xff

0000000D  FF00              inc dword [eax]

这是来自第 4 步 (dumpbin.exe)

Microsoft (R) COFF/PE Dumper Version 14.11.25508.2
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file add3.exe

File Type: EXECUTABLE IMAGE

  00401000: 50                 push        eax

  00401001: E8 EF 0F 00 00     call        00401FF5

  00401006: C3                 ret

  00401007: 55                 push        ebp

  00401008: 8B EC              mov         ebp,esp

  0040100A: 83 C4 E8           add         esp,0FFFFFFE8h

  0040100D: 60                 pushad

  0040100E: 80 3D 00 40 40 00  cmp         byte ptr ds:[00404000h],0
            00

  00401015: 75 05              jne         0040101C

我从第 3 步的输出中提取了一些指令代码,并试图在第 4 步的反汇编列表中搜索它们,但找不到它们。

5) 然后我对可执行文件进行了十六进制转储(使用 frhed)并将其中的字节值与两个步骤中的输出进行比较。

0000  4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 b8 00 00 00 00 00 00 00 40 00 00  MZ..........ÿÿ..¸.......@..

001b  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ...........................

0036  00 00 00 00 00 00 d8 00 00 00 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 73  ......Ø.....º..´.Í!¸.LÍ!Ths

0051  69 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f 74 20 62 65 20 72 75 6e 20 69 6e 20  i program cannot be run in 

006c  44 4f 53 20 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 5b 39 0b f3 1f 58 65  DOS mode....$.......[9.ó.Xe

我在第 5 步中看到的字节值与第 3 步中的字节值匹配,但与第 4 步中的字节值不匹配。

如何解释这些差异? 我一定是在某处遗漏了一些简单的小细节,那是什么?

最佳答案

简答: .exe.com

提示:注意 MZ 签名作为第 5 步输出中的前两个字节 :-P

长答案:

Microsoft 的可执行.exe 格式不仅仅包含代码。首先,它以一个特殊的签名(格式创建者的首字母缩写)开头,然后是描述代码组织的大量信息。

相比之下,.com 文件只是一个代码,这意味着它的第一个字节是文件加载到内存后执行的内容。

你得到的第一个反汇编是错误的(是的,第一个是错误的,不是第二个!)因为它试图从第一个字节开始解析而不是跳到实际代码。

dumpbin 足够智能,可以正确解析 .exe 文件的 header 并开始实际代码的反汇编。

解决方案

如果您想比较反汇编输出,您要么必须确保您的 NASM 知道文件类型并正确解析其 header ,要么...简化您的生活并转换 .exe.com 中,在这种情况下,两个反汇编操作应该产生相同的输出(当然,除了潜在的错误)

我上次将 .exe 文件转换为 .com 是多年前使用名为 exe2bin 的实用程序。在线快速搜索显示这是在 Windows XP 时代,操作系统不再附带。如果你从某个地方下载它,我认为没有理由不工作。

关于windows - 为什么 NASM 和 dumpbin.exe 对同一个可执行文件的反汇编输出不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48473521/

有关windows - 为什么 NASM 和 dumpbin.exe 对同一个可执行文件的反汇编输出不同?的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  3. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  4. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  5. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  6. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  7. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  8. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  9. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  10. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

随机推荐