jjzjj

Windows 强制执行 READ-ONLY .text 部分,即使被 ld 链接器禁用

coder 2024-06-16 原文

在下面的玩具程序中,我在 .text 部分声明了一个变量并写入它,这给出了一个段错误,因为 .text 部分被标记为只读:

Breakpoint 1, 0x00401000 in start ()
(gdb) disassemble
Dump of assembler code for function start:
=> 0x00401000 <+0>:     movl   $0x2,0x40100a
End of assembler dump.
(gdb) stepi

Program received signal SIGSEGV, Segmentation fault.
0x00401000 in start ()
(gdb)

这是 objdump 输出:

test.exe:     file format pei-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000001f  00401000  00401000  00000200  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .idata        00000014  00402000  00402000  00000400  2**2
                  CONTENTS, ALLOC, LOAD, DATA

但是,使用 --omagic 开关(禁用 READ-ONLY .text 部分)进行链接会产生以下结果:

ld --omagic -o test.exe test.obj

test.exe:     file format pei-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000001f  00401000  00401000  000001d0  2**4
                  CONTENTS, ALLOC, LOAD, CODE
  1 .idata        00000014  00402000  00402000  000003d0  2**2
                  CONTENTS, ALLOC, LOAD, DATA

但是使用 GDB 进行调试会得到以下(奇怪的)结果:

Breakpoint 1, 0x00401000 in start ()
(gdb) disassemble
Dump of assembler code for function start:
=> 0x00401000 <+0>:     dec    %ebp
   0x00401001 <+1>:     pop    %edx
   0x00401002 <+2>:     nop
   0x00401003 <+3>:     add    %al,(%ebx)
   0x00401005 <+5>:     add    %al,(%eax)
   0x00401007 <+7>:     add    %al,(%eax,%eax,1)
End of assembler dump.
(gdb) stepi
0x00401001 in start ()
(gdb) stepi
0x00401002 in start ()
(gdb) stepi
0x00401003 in start ()
(gdb) stepi
0x00401005 in start ()
(gdb) stepi

Program received signal SIGSEGV, Segmentation fault.
0x00401005 in start ()
(gdb)

首先还是报了segmentation fault,但是汇编代码也改结构了?

如何在 Windows 10 x64 上将 .text 部分链接为可写?

玩具程序:

    BITS 32

    section .text
    global _start
_start:
    mov [var], dword 2
var:    dd 0
    ret

最佳答案

出于某种原因,ld 完全更改了使用 --omagic 选项链接的 PE 可执行文件。

使用 cmp 实用程序快速比较文件显示:

 137 177 222
 141   0 320
 142   6   5
 213   0 320
 214   2   1
 217 142 205
 218 154 353
 397   0 320
 398   2   1
 437   0 320
 438   4   3
 465   0 307

...

虽然 ld 原则上应该只更改部分标题 (.text) 的部分标志,但有很多差异,即设置标志 IMAGE_SCN_MEM_WRITE

使用 HxD 手动更改标志,即将偏移量 0x19F 处的字节设置为 0xE0 可解决问题...

varret 的互换顺序试运行程序(否则程序崩溃):

Breakpoint 1, 0x00401000 in start ()
(gdb) disassemble
Dump of assembler code for function start:
=> 0x00401000 <+0>:     movl   $0x2,0x40100b
   0x0040100a <+10>:    ret
End of assembler dump.
(gdb) stepi
0x0040100a in start ()
(gdb) disassemble
Dump of assembler code for function start:
   0x00401000 <+0>:     movl   $0x2,0x40100b
=> 0x0040100a <+10>:    ret
End of assembler dump.
(gdb) x/wx var
0x40100b <var>: 0x00000002
(gdb)

我们看到事情按预期进行。

我的结论是 ld 以某种方式生成了格式错误的 PE 可执行文件,我看到 @RossRidge 对此有答案(ld 不遵守文件对齐方式部分)。

关于Windows 强制执行 READ-ONLY .text 部分,即使被 ld 链接器禁用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38913369/

有关Windows 强制执行 READ-ONLY .text 部分,即使被 ld 链接器禁用的更多相关文章

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

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

  2. 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

  3. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  4. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  5. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  6. ruby CSV : How can I read a tab-delimited file? - 2

    CSV.open(name,"r").eachdo|row|putsrowend我得到以下错误:CSV::MalformedCSVErrorUnquotedfieldsdonotallow\ror\n文件名是一个.txt制表符分隔文件。我是专门做的。我有一个.csv文件,我转到excel,并将文件保存为.txt制表符分隔的文件。所以它是制表符分隔的。CSV.open不应该能够读取制表符分隔的文件吗? 最佳答案 尝试像这样指定字段分隔符:CSV.open("name","r",{:col_sep=>"\t"}).eachdo|row|

  7. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  8. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  9. ruby - 怎么来的(a_method || :other) returns :other only when assigning to a var called a_method? - 2

    给定以下方法:defsome_method:valueend以下语句按我的预期工作:some_method||:other#=>:valuex=some_method||:other#=>:value但是下面语句的行为让我感到困惑:some_method=some_method||:other#=>:other它按预期创建了一个名为some_method的局部变量,随后对some_method的调用返回该局部变量的值。但为什么它分配:other而不是:value呢?我知道这可能不是一件明智的事情,并且可以看出它可能有多么模棱两可,但我认为应该在考虑作业之前评估作业的右侧...我已经在R

  10. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

随机推荐