将功能插入二进制应用程序(3d party,闭源)的最佳方法是什么。
目标应用程序在OSX上,似乎是使用gcc 3+编译的。我可以看到二进制文件中实现的函数列表,并调试和隔离了一个我想远程调用的特定函数。
具体来说,我想调用这个函数 - 让我们称之为void zoomByFactor(x,y)
- 当我从复杂的HIDevice收到某些数据时。
我可以轻松地将指令修改或注入二进制文件本身(即,修补不需要仅在RAM中进行)。
你会推荐什么样的“很好”这样做?
修改
我确实需要整个申请。所以我不能抛弃它并使用库。 (对于那些需要道德解释的人:这是一个专有的CAD软件,其公司网站自2006年以来一直没有更新。我已经为这个产品付了很多钱(真的很多钱)并且有项目我不能轻易从中迁移出来的数据。该产品很适合我,但我想使用我最近得到的新HID。我已经检查了应用程序的内部,我相当自信我可以使用相关数据调用正确的函数并使其正常工作)。
到目前为止,这是我所做的,而且非常轻松。
我已经通过这个过程修改了部分应用程序:
xxd -g 0 binary > binary.hex cat binary.hex | awk 'substitute work' > modified.hex xxd -r modified.hex > newbinary chmod 777 newbinary
我正在做这种跳跃,因为二进制文件差不多100兆。
我在想的是我在主应用程序循环中的某个地方jmp,启动一个线程,然后返回到main函数。
现在,问题是:我在哪里可以插入新代码?我需要修改符号表吗?或者,我怎样才能自动加载dylib,以便我唯一需要做的“黑客攻击”是将正常加载的dylib调用插入主函数?
答案 0 :(得分:10)
对于那些对我最终做的事感兴趣的人,这是一个总结:
我看了几种可能性。它们属于运行时修补和静态二进制文件修补。
就文件修补而言,我基本上尝试了两种方法:
修改代码中的程序集 二进制文件的段(__TEXT)。
修改中的加载命令 马赫头。
第一种方法需要有可用空间或可以覆盖的方法。它还具有极差的可维护性。任何新的二进制文件都需要再次手动修补它们,特别是如果它们的源代码稍有变化。
第二种方法是尝试将LC_ LOAD_ DYLIB条目添加到mach头中。那里没有很多马赫编辑器,所以它很毛茸茸,但我实际上修改了结构,以便otool -l
可以看到我的输入。但是,这实际上并不起作用,因为在运行时有dyld: bad external relocation length
。我假设我需要使用导入表等进行处理。如果没有编辑器,这就太费力了。
第二条路径是在运行时注入代码。没有太多可以做到这一点。即使对于您可以控制的应用程序(例如,您启动的子应用程序)。也许有一种方法fork()
并启动初始化过程,但我从来没有这样做过。
有SIMBL,但这需要你的应用程序是Cocoa,因为SIMBL将构成一个系统范围的InputManager并选择性地加载bundle。我驳回了这个,因为我的应用程序不是Cocoa,而且,我不喜欢系统范围的东西。
接下来是mach_inject和mach_star项目。还有一个名为的新项目 在Google上托管的PlugSuit似乎只是一个围绕mach_inject的薄包装。
Mach_inject提供了一个API来完成名称所暗示的内容。我确实在代码中发现了一个问题。在10.5.4中,mach_inject.c文件中的mmap方法要求使用MAP_READ或MAP_READ,否则mmap将失败。
除此之外,整个事情实际上与宣传的一样。我最终使用mach_ inject_ bundle来执行我想要的事情,将DYLIB静态添加到mach头:即在模块init上启动一个新线程来执行其脏操作。
无论如何,我把它变成了维基。随意添加,更正或更新信息。在OSX上几乎没有关于此类工作的信息。信息越多越好。
答案 1 :(得分:4)
在10.5之前的MacOS X版本中,您可以使用Input Manager扩展程序执行此操作。输入管理器旨在处理诸如非罗马语言的输入之类的内容,其中扩展可以弹出窗口以输入适当的字形,然后将完成的文本传递给应用程序。该应用程序只需要确保它是Unicode干净的,并且不必担心每种语言和区域的确切细节。
输入管理器被滥用于将各种不相关的功能修补到应用程序中,并且经常破坏应用程序的稳定性。它也成为特洛伊木马的攻击载体,如“Oompa-Loompa”。 MacOS 10.5加强了对输入管理器的限制:它不会在root或wheel拥有的进程中运行它们,也不会在已修改其uid的进程中运行它们。最重要的是,10.5不会将输入管理器加载到64位进程中,并且表示即使32位使用也不受支持,将在以后的版本中删除。
因此,如果您能够遵守这些限制,则输入管理器可以执行您想要的操作。未来的MacOS版本几乎肯定会引入另一种(更安全,更有限)的方式,因为语言输入支持需要功能。
答案 2 :(得分:3)
我相信您也可以使用DYLD_INSERT_LIBRARIES method。
This post也与您尝试做的事情有关;
答案 3 :(得分:1)
我最近使用mach_star
来源对注射/覆盖进行了尝试。我最后为它写了一个教程,因为这些东西的文档总是那么粗略,而且经常过时。
http://soundly.me/osx-injection-override-tutorial-hello-world/
答案 4 :(得分:0)
有趣的问题。如果我理解正确,您可以添加远程调用正在运行的可执行文件中的函数的功能。
如果您不是真的需要整个应用程序,您可以删除主要功能并将其转换为可以链接的库文件。由您决定如何确保所有必需的初始化发生。
另一种方法可能就像病毒一样。注入一个处理远程调用的函数,可能在另一个线程中。您需要通过将一些代码注入main函数或其他任何适当的地方来启动此线程。很可能你会遇到初始化,线程安全和/或维护正确的程序状态等重大问题。
最佳选择(如果可用)是让应用程序的供应商公开插件API,以便以受支持的方式干净可靠地执行此操作。
如果你选择hack-the-binary路线,它会耗费时间和精力,但你会在这个过程中学到很多东西。
答案 5 :(得分:0)
在Windows上,这很简单,实际上做得非常广泛,称为DLL /代码注入。
OSX的商业SDK允许这样做:Application Enhancer(免费用于非商业用途)。