【问题标题】:Execute computer instructions directly in binary [closed]直接以二进制执行计算机指令[关闭]
【发布时间】:2012-04-03 10:34:01
【问题描述】:

在 C 语言中。我需要一种在程序运行时直接执行计算机指令的方法。我知道如何以二进制形式制作计算机指令的唯一方法是通过十六进制编辑器,然后将文件作为应用程序运行。我将如何使用程序编写二进制文件,然后从它们执行它,而无需创建新的执行进程。似乎他们应该是一种简单的方法来做到这一点,但无论我在哪里都找不到它。

我能想到的唯一其他方法是通过内联汇编,但在我当前的项目中,这将是一个缺点,直接使用二进制执行是最好的方法。 (这可能需要windows上的驱动程序吗?如何在linux上做?换句话说,跨平台的方法会很好)

谢谢。

【问题讨论】:

  • inlince 程序集与您的预期相比没有任何开销(这在 AFAIK 中不太可能),因为内联程序集被编译为二进制文件。
  • 所有指令在执行时都是“二进制”。你能解释一下你想要完成什么吗?
  • 故意破坏堆栈。
  • 感谢 -2 人,因为你不明白这个问题。
  • 你想做的是大多数黑客的操作方式。他们找到了一种将数据输入程序的方法,然后说服程序执行它。 E.g. a buffer overflow attack 做好准备,您的病毒扫描程序可能会将您的程序检测为病毒,或者您的硬件会阻止您执行代码 (DEP)

标签: c assembly binary


【解决方案1】:

你想做的事情有点问题,很容易让很多人问“你为什么这样做?”

假设您有一个没有内存保护的操作系统(这种情况非常罕见),您可以将一个函数指向字节数组并调用该函数。这是它的要点:

unsigned char* code_to_execute = "\xB8\x13\x00\xCD\x10";
void (*runCode)();

runCode = code_to_execute;

runCode();

但是,在做这样的事情时有很多事情要担心。您需要知道您的 C 编译器如何设置函数调用框架并在您的“二进制代码”中尊重这一点。以这种方式创建跨平台代码是不可能的。即使让它在单个平台上的多个 C 编译器中运行也很棘手。然后是内存保护。大多数现代操作系统根本不会让您随意将数据作为代码执行。您需要将内存显式标记为可执行,并且许多操作系统在没有特殊许可的情况下不允许您这样做。也没有跨平台的方式来做到这一点。

再次强调,这确实不是一个好主意。最好使用内联汇编语言。或者更好的是,根本不要使用汇编语言。也许您可以多解释一下您的项目,以及为什么直接在 C 程序中编写“二进制代码”很重要。这将帮助我们制定对您有很大帮助的答案或建议。

【讨论】:

  • 谢谢,我所说的跨平台并不是说它在每个系统上的工作方式都一样,而只是说它不是某种依赖于平台的方法,比如加载 dll 或创建设备驱动程序.这是与计算机直接连接的人工智能所必需的。计算机就是计算机,那么为什么将人工智能的语言(二进制)转换为人类可读的(汇编)只是为了直接转换回计算机可读的(二进制)。 AI 是为操作系统创建的,因此担心其他处理器如何工作并不重要。
  • 如果您很好奇,如果您可以编译 DOS COM 文件并在 DOS 中执行,那么该示例代码实际上可以工作。它将视频模式更改为 320x200、256 色。 B8 是“mov ax”,1300 是要移入 ax 的 16 位值。 CD 是“呼叫中断”,10 是 VGA 控制器的视频卡中断。
  • 现在我想知道,你不需要投射它吗?虽然我还没有真正尝试过。
  • 好吧,我明白你所说的人工智能,但是......人工智能还有很多其他问题,让“它”直接读/写到 CPU 是最少的你的问题。但是,如果您希望继续您的项目,我建议您为您的 AI 创建一个虚拟机,而不是让它直接在 CPU 上运行。您可能会学到更多东西,并且抽象可能会很有帮助。查看:en.wikibooks.org/wiki/Creating_a_Virtual_Machine/… 成功/理解您的 AI 代码后,您可以优化为纯机器代码。
  • 所以把它变成一个操作系统,这是一个想法。出现的问题是人工智能已经是一个大项目,现在我必须创建一个操作系统。所以我可能会使用 Linux 内核或其他东西,然后从那里开始。
【解决方案2】:

这个 SO 问题也许涵盖了这个主题

How to write self-modifying code in x86 assembly

不要让人们用“你为什么要做这个问题”来拖慢你的速度......

您必须对语言或操作系统或两者都有足够的了解,并在保护系统内打通或工作。然后是将要执行的二进制文件(假设您已经完成工作以使其位置独立和/或依赖于给定/找到/获取/任何地址的地址)放入内存并分支到它的问题。在 C 中,您可以声明一个函数指针,然后将地址分配给该函数作为该二进制文件的地址,然后调用该函数(如果您没有其他方法可以跳转到某个地址,我通常更喜欢编写几行 asm 和将执行分支的它们链接到我通过 asm 的任意地址)。

【讨论】:

    【解决方案3】:

    使用内存中的机器代码,将其地址转换为函数指针。当然你需要遵守 C 调用约定。

    在大多数桌面操作系统上,您需要更改内存权限以将其标记为可执行,例如在 Windows 上调用 VirtualProtect,在 Linux 上调用 mprotect

    二进制机器指令不是跨平台的。您需要为每个处理器架构生成不同的代码。

    只要代码只需要用户级权限,就不需要驱动程序。

    【讨论】:

    • 嗯,是的,我理解二进制指令不是跨平台的。我基本上只需要一种“与计算机本身对话”的方法。但是,您所说的方法听起来像是加载 dll,我该如何将二进制文件放入程序中,将其直接放入像“shell-coding”这样的字节数组中?
    • @u8sand:字节数组可以工作。像安迪这样的字符串也会在他的回答中显示出来。最好把它分配到自己的页面中,因为执行权限是按页面的,但这不是绝对要求。
    【解决方案4】:

    在运行时在应用程序中生成和运行代码是一个很好理解的问题。

    通过在网上搜索“即时编译器”或“JIT 编译”、“动态代码生成”,尤其是结合使用编程语言名称,例如“Java”。

    动态代码生成是过去十五年的热门研究课题之一。

    Java 运行时系统(称为 Java 虚拟机或 JVM)使用动态编译技术(称为 HotSpot)来显着提高(即快 10 倍以上)性能。

    Microsoft 对 C# 等 .NET 语言使用即时编译,但可能更难找到更详细的信息。

    Ian Piumarta 一直在 Viewpoints Research Institute 开发一些令人印象深刻的动态编译技术(例如 Cola),与 SmallTalk 的“父亲”Alan Kay 合作(SmallTalk 是现代窗口系统和某些类型对象的起点面向编程语言)。在 Google Summer of Code 项目中,其中一些技术用于加速 Cairo 渲染引擎(用于网络浏览器等)。

    Ian Piumarta 的工作可能是最灵活、最紧凑的,因此是一个很好的起点。请注意,伊恩非常聪明,所以如果你想使用它,请准备好认真思考。

    有一些 JIT 可以生成汇编程序,这可能正是您所需要的(但我从未使用过):

    其他可能值得一看的技术包括:

    其中,LLVM 的 JIT 和 GNU libjit 可能是最适合在其正常“主机”环境之外使用的文档。 LLVM 是 Apple 支持的技术。 LLVM 旨在从一组库中组装起来,以便用于构建其他系统。但它针对的是非常复杂、高性能的解决方案,因此可能存在相当陡峭的学习曲线。 GNU libjit 看起来更小,因此希望更容易理解。我才刚刚发现英特尔的 ORP。

    HTH

    【讨论】:

      猜你喜欢
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-01
      • 2011-07-07
      • 1970-01-01
      • 2021-03-05
      • 1970-01-01
      相关资源
      最近更新 更多