是否可以用已编译的二进制文件中的虚拟函数替换特定函数的每个实例?

2024-01-07

是否可以改变现有 x86-64 二进制文件引用和/或调用某个特定函数的方式。具体来说,是否有可能改变二进制文件而不发生任何事情(类似于nop)在该函数通常会执行的时间?

我意识到有强大的专业工具(即反编译器/反汇编器)可以完成此类任务,但我真正想知道的是可执行格式是否“足够”人类可读,能够完成此类任务只需 vim 和一个十六进制编辑器就可以了(至少在小程序上)。

某些可执行文件格式(例如 mach-o、elf、Windows 使用的任何文件等等)是否比其他格式更具可读性?难道它们全都是完全无法理解的胡言乱语吗?任何专家观点和/或良好的起点/参考文献将不胜感激。

免责声明

有人过来并很快对这个问题的初始版本投了反对票,所以我想完全清楚地表明这一点:我对禁用任何串行或安全检查或任何类似的东西不感兴趣。最初我想要一个程序停止发出真正令人恼火的噪音,但现在我只是好奇编译器和可执行文件是如何工作的。

我这样做是为了教育价值,我认为 SE 上的其他人也会对答案感兴趣。然而,我知道其他人可能不太喜欢这个话题。如果您对我所说的内容有疑问,请发表评论,我保证我会更改我的帖子。


当相关函数位于二进制文件本身并使用标准调用约定时,这很简单。例子:

void make_noise() { printf("Quack!\n"); }
int fn1() { puts("fn1"); make_noise(); return 1; }
int fn2() { puts("fn2"); make_noise(); return 2; }
int main() { puts("main"); return fn1() + fn2() - 3; }

gcc -w t.c -o a.out && ./a.out

输出(预期):

main
fn1
Quack!
fn2
Quack!

现在让我们消除噪音:

gdb -q --write ./a.out
(gdb) disas/r make_noise
Dump of assembler code for function make_noise:
  0x000000000040052d <+0>:     55      push   %rbp
  0x000000000040052e <+1>:     48 89 e5        mov    %rsp,%rbp
  0x0000000000400531 <+4>:     bf 34 06 40 00  mov    $0x400634,%edi
  0x0000000000400536 <+9>:     e8 d5 fe ff ff  callq  0x400410 <puts@plt>
  0x000000000040053b <+14>:    5d      pop    %rbp
  0x000000000040053c <+15>:    c3      retq   
End of assembler dump. 

这告诉我们一些事情:

  1. 我们想要删除的函数从地址开始0x40052d
  2. 操作码为retq指令是0xC3.

我们来打补丁retq作为第一条指令make_noise,看看会发生什么:

(gdb) set *(char*)0x40052d = 0xc3
(gdb) disas make_noise
Dump of assembler code for function make_noise:
  0x000000000040052d <+0>:     retq   
  0x000000000040052e <+1>:     mov    %rsp,%rbp
  0x0000000000400531 <+4>:     mov    $0x400634,%edi
  0x0000000000400536 <+9>:     callq  0x400410 <puts@plt>
  0x000000000040053b <+14>:    pop    %rbp
  0x000000000040053c <+15>:    retq   
End of assembler dump.

有效!

(gdb) q
Segmentation fault (core dumped)   ## This is a long-standing GDB bug

现在让我们运行修补后的二进制文件:

$ ./a.out
main
fn1
fn2

瞧!无噪音。

如果该函数位于不同的二进制文件中,LD_PRELOADFlorian Weimer 提到的技术通常比二进制修补更容易。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以用已编译的二进制文件中的虚拟函数替换特定函数的每个实例? 的相关文章

  • 在运行时访问 build-id

    我试图弄清楚如何访问链接器在运行时生成的构建 ID 从这个页面开始 https linux die net man 1 ld https linux die net man 1 ld 当我构建一个测试程序时 例如 gcc test c o
  • 静态库 (.a) 和共享库 (.so) 之间的文件格式差异?

    我知道关于共享库和静态库的用例有很多问题 这个问题与此无关 我问的是磁盘上存储的文件格式的差异 为什么问题是 两者之间有什么区别 或者它们完全相同 只是用途不同 我相信它们是不一样的 因为在共享库上运行 nm 需要 D 标志 显然它需要做一
  • 汇编程序中的重定位截断错误

    我对汇编语言完全陌生 我尝试编写简单的程序来破译凯撒密码 问题是链接后我收到以下错误 cezar o In function loop text 0xbf relocation truncated to fit R X86 64 8 aga
  • 将java代码编译为exe(例如使用Launch4Java)是否确保代码无法被逆向工程?

    经过我自己的实验 我确信 Java 代码混淆在防止逆向代码工程方面并不安全 因此 我转而使用 Launch4J 将我的核心 jar 文件之一捆绑到单个 EXE 文件中 jar 文件还包含主要的入口方法 这会再次保护代码逆向工程吗 如果计算机
  • 最小操作码大小 x86-64 strlen 实现

    我正在研究最小操作码大小x86 64 strlen我的代码高尔夫 二进制可执行文件的实现不应超过一定的大小 为简单起见 请考虑 demoscene 总体思路来自于here http www int80h org strlen 尺寸优化思路来
  • 为什么 Linux/gnu 链接器选择地址 0x400000?

    我正在 Linux x86 64 上试验 ELF 可执行文件和 gnu 工具链 我已经链接并剥离 手动 Hello World 测试 global start text start mov 1 rax 转换为 267 字节 ELF64 可执
  • 源操作数和目标操作数是否需要相同大小?

    我刚刚尝试了这个问题 要求你解释一下代码行有什么问题 movl eax rdx 解决方案表明目标操作数的大小错误 仅当从较大尺寸变为较小尺寸时才 非法 还是源操作数和目标操作数对于所有指令 或至少 mov 类类型 必须具有相同的尺寸 是的
  • 加载linux内核的基地址

    我对内核如何加载到内存有一些疑问 检查后 proc kallsyms我能够找到内核中各种符号的地址 cat proc kallsyms head n 10 00000000 t vectors start 80008240 T asm do
  • 断点改变程序流程

    我正在尝试分析和逆向我拥有的 Objective C 程序 我通过手动更改一些操作码对可执行文件进行了一些修改 然而 当我测试修改后的软件时 我得到 死亡人数 9 没关系 我想我触碰了不该触碰的东西 我当时就推出了gdb myprogram
  • 在 DNN 模块中执行 .exe

    我试图让我的 DNN 模块 6 1 3 在程序中发生特定条件时启动任何类型的可执行文件 此时我只是尝试让它运行记事本并创建一个文本文件 这就是我现在正在尝试的 ProcessStartInfo pi new ProcessStartInfo
  • 有没有 JavaScript 去混淆器(deobfuscator)之类的东西? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 这个问题正好相反哪种 JavaScript 压缩器 粉碎器 与 Google 用于其 JavaScri
  • 如何在 hash-bang 可执行文件中引用本地 ruby​​?

    我有一个 Ruby 可执行文件 它是一个捆绑器 binstub 它以 usr bin env ruby 在我的服务器上 我通过 RVM 安装了 Ruby 193 which ruby gt home dtuite rvm rubies ru
  • 如何在eclipse中生成java项目的可执行文件[重复]

    这个问题在这里已经有答案了 我正在尝试为我的 Java 应用程序创建一个可执行文件 但我不知道该怎么做 我知道如何生成可执行 jar 文件 但我想制作一个可执行应用程序 我正在使用 eclipse indigo 来制作 java 应用程序并
  • 修改编译共享库中符号的可见性

    我的项目依赖于一个第三方库 该库导出了更多应有的符号 其中一些符号被其他库和主程序无意地覆盖 如何更改已编译共享对象的函数和变量的可见性 如何更改已编译共享对象的函数和变量的可见性 您可以通过修改动态符号部分来更改符号的可见性 dynsym
  • 为什么 Visual Studio 使用 xchg ax,ax

    我正在查看程序的反汇编 因为它崩溃了 并注意到很多 xchg ax ax 我用谷歌搜索了一下 发现它本质上是一个 nop 但是为什么 Visual Studio 会执行 xchg 而不是 noop 该应用程序是一个C NET3 5 64位应
  • 为什么在强度降低乘法和循环进位加法之后,这段代码的执行速度会变慢?

    我正在读书阿格纳 雾 https en wikipedia org wiki Agner Fog s 优化手册 https en wikipedia org wiki Agner Fog Optimization 我遇到了这个例子 doub
  • 从 NASM 调用 C 函数 _printf 会导致分段错误

    我一直在尝试使用 NASM 在 Mac OS 和 Windows 上学习 64 位汇编 我的代码是 extern printf section data msg db Hello World 10 0 section text global
  • 这个反斜杠在这段汇编代码中起什么作用?

    我不确定这些推线有什么区别 修剪下来来自 Linux 的 x86 entry calling h https github com torvalds linux blob 241e39004581475b2802cd63c111fec43b
  • 在 Mac OS X 上构建 Linux 内核

    我正在做一个修改Linux内核的项目 我有一台桌面 Linux 机器 在上面构建内核没有问题 不过 我要去旅行 我想在途中工作 我只有一台 MacBook 当我尝试构建 Linux 内核时 它抱怨说elf h was not found 我
  • ELF动态符号表

    我有一个关于 ELF 动态符号表的问题 对于 FUNC 类型的符号 我注意到某些二进制文件中的值为 0 但在其他二进制文件中 它具有一些非零值 这两个二进制文件都是由 gcc 生成的 我想知道为什么会出现这种差异 有没有编译器选项来控制这个

随机推荐

  • TranslateAccelerator 和禁用的菜单项

    在我的应用程序中 我根据上下文启用 禁用菜单项 如果文本区域具有焦点 我会禁用与导航键冲突的加速器 例如 Ctrl 左 右 根据微软的文档 http msdn microsoft com en us library windows desk
  • 锚标记转到网页的错误部分

    这是问题所在的实际视频记录 我不想以任何方式做广告 https www youtube com watch v 7b38cQ0VGWI https www youtube com watch v 7b38cQ0VGWI 所以我创建一个网站只
  • 如何提高C++中merkle根计算的速度?

    我正在尝试尽可能优化默克尔根计算 到目前为止 我用 Python 实现了它 结果是这个问题 https stackoverflow com questions 67355203 how to improve the speed of mer
  • 如何防止按钮提交表单

    在下一页中 使用 Firefox 删除按钮会提交表单 但添加按钮不会提交表单 我该如何预防remove提交表单的按钮 function addItem var v form hidden last attr name var n input
  • 托管WPF插件跨进程问题

    我使用类似的方法http www codeproject com Articles 516431 Baktun Shell Hosting WPF Child Windows in Another http www codeproject
  • 检测到 HTML 文本框的拖放?

    我的网页上有一个正常的搜索框 它充满了文字 Search this website 当您单击框中输入搜索查询时 此文本将被删除 onfocus if this value Search this website this value 但是
  • 如何在Mac终端中使用SoX从文本文件中修剪特定时间的音频文件?

    我有一个文本文件 如下所示文本文件 https i stack imgur com iDm8k png 我想使用 sox 根据文本文件中的时间修剪音频文件 这样我就可以有从 0 0 到 6 16 6 16 到 13 44 13 44 到 1
  • 使用 selenium Java 或 cypress 中的 e2e 进行 Angular/SPA 应用程序的代码覆盖率

    我们想要测量 Angular 8 应用程序代码覆盖率 我们有一个用 selenium java 编写的 e2e 测试用例 它加载部署在浏览器中另一台机器上的 Angular 应用程序 并运行一些 e2e 测试用例集 问题是我如何测量 Ang
  • 字节序理论和概念

    这不是任何编程语言特有的问题 假设您在大端机器上编写了一些文件 并且您知道这一点 如果两个单字节值被连续写入 你怎么知道 Big endian 颠倒了 16 32 和 64 位值的顺序 那么您如何知道需要将其作为单个字节读取呢 例如 您写入
  • pygame中显示网格时角色移动缓慢

    我正在 pygame 中制作贪吃蛇游戏 我注意到了一件奇怪的事情 每当我显示网格时 我的角色都会缓慢运行 这是我的程序的主要功能 我刚刚开始学习pygame def main global SCREEN CLOCK pygame init
  • React 同一组件的多个实例获得相同的状态

    我有一个 React 组件 我正在创建它的 2 个副本 然而 当其中 1 个状态更新时 第 2 个状态也会更新 我不确定是什么原因造成的 这是我的代码 这是我使用两个组件的地方 this state selectedTab 0
  • 替换所有高于阈值的 RGB 值

    我有一个充满 RGB 值的 numpy 3d 数组 例如 形状 高度 宽度 3 matrix np array 0 0 5 0 6 0 9 1 2 0 如果任何值高于阈值 我必须替换 RGB 值 例如阈值 0 8 替换 2 2 2 然后 m
  • 使用 Database First 方法选择性禁用延迟加载

    我对禁用整个上下文的延迟加载不感兴趣 我只想选择性地禁用一些关键导航属性的延迟加载 随着代码优先方法 我了解如何有选择地禁用延迟加载 public virtual Person Requestor get set lazy loading
  • 隐藏 div 上的 Google Map API V3(jquery-ui 选项卡)

    我知道这个问题很古老 但我似乎找不到明确的说明 问题的要点是 当 Google 地图加载到隐藏 显示 无 div 上时 它不会完全加载 部分显示 例如jQuery 选项卡等 API V3 不再接受 checkResize left 1000
  • Elasticsearch 索引最大结果窗口配置异常

    当我将此配置添加到 etc elasticsearch elasticsearch yml在ubuntu虚拟机中 index max result window 1000000 执行此配置后 当我重新启动 Elasticsearch 时 会
  • 在 Common Lisp 中使用外部库或包的示例

    在 Common Lisp 中 quicklisp 是一种流行的库管理工具 我将使用该工具 并尝试使用 CL WHO 我使用 SBCL 1 0 57 实现 我将在下面回答我自己的问题 作为初学者 并不清楚 ASDF 和 Quicklisp
  • 调试和发布模式之间的异常堆栈跟踪差异

    下面的代码在调试和发布模式下生成不同的异常堆栈跟踪 static class ET public static void E1 throw new Exception E1 public static void E2 try E1 catc
  • Javadoc 和 RuntimeException

    我很好奇我是否应该添加throws ExceptionClass或不在方法签名之后 ExceptionClass 扩展 RuntimeException 例如 public void foo throws ExceptionClass th
  • 如何从 Perl 读取 Gmail 帐户中的邮件?

    我已经使用了该模块邮件 网页邮件 Gmail http search cpan org dist Mail Webmail Gmail阅读我的 Gmail 帐户中的新邮件 为此 我编写了以下代码 use strict use warning
  • 是否可以用已编译的二进制文件中的虚拟函数替换特定函数的每个实例?

    是否可以改变现有 x86 64 二进制文件引用和 或调用某个特定函数的方式 具体来说 是否有可能改变二进制文件而不发生任何事情 类似于nop 在该函数通常会执行的时间 我意识到有强大的专业工具 即反编译器 反汇编器 可以完成此类任务 但我真