逆向工程c程序
Posted
技术标签:
【中文标题】逆向工程c程序【英文标题】:reverse engineering c programs 【发布时间】:2011-01-17 08:56:11 【问题描述】:如果此二进制文件已分发,则每个 c 程序都将转换为机器代码。既然计算机的指令集是人尽皆知的,那有没有可能找回C原程序呢?
【问题讨论】:
能否找回C原程序? @Roger Pate,在“原始程序”末尾放一个问号,你就有问题了:|哇.... 我刚做了一个鱼汤。我能把原来的鱼拿回来吗? 两大障碍:优化和删除名称信息。在运行时代码中,编译器更喜欢删除函数和变量名称,因为它们不是必需的。编译器还可以优化代码,使其看起来与原始代码不同,但功能相同。 @stefano: if 问题是关于文本重构而不是逻辑,通常的说法是:“你可以用牛做汉堡包,但不能用汉堡包做牛” :) 【参考方案1】:您永远无法回到完全相同的源,因为没有与已编译代码一起保存的元数据。
但您可以从汇编代码中重新创建代码。
如果您对这些事情感兴趣,请查看这本书:Reversing: Secrets of Reverse Engineering。
编辑
这里有一些编译器-101,如果你用另一个词来定义一个编译器,而不是像“编译器”那样技术,它会是什么?
答案:译者
编译器将您编写的语法/短语翻译成另一种语言,C 编译器将其翻译成汇编甚至机器代码。 C# 代码被翻译成 IL 等等。
您拥有的可执行文件只是原始文本/语法的翻译,如果您想“反转它”因此“翻译回来”,您很可能不会得到与开始时相同的结构。
一个更现实的例子是,如果你从英语翻译成德语,然后从德语翻译回英语,句子结构很可能会有所不同,可能会使用其他词,但意义、上下文很可能不会变了。
如果您从 C 转到 ASM,编译器/翻译器也是如此,逻辑是相同的,只是读取方式不同(当然还有优化)。
【讨论】:
【参考方案2】:这取决于原始 C 程序的含义。诸如局部变量名称、cmets 等内容不包含在二进制文件中,因此无法获得与用于生成二进制文件的源代码完全相同的源代码。 IDA Pro 等工具可能会帮助您反汇编二进制文件。
【讨论】:
不至于变量名的级别,但至少是程序的逻辑 (程序是用 -g 编译的?)【参考方案3】:我估计一个真正熟练的黑客的转化率约为每天 1 KB 的机器代码。以西方的普通工资计算,例如,一个 100 KB 的可执行文件的价格约为 25,000 美元。在花了那么多钱之后,所获得的只是一大块 C 代码,它完全按照你的方式工作,减去了 cmets 之类的好处。它与您的版本没有任何竞争力,您将能够更快地提供更新和改进。对这些更新进行逆向工程也是一项艰巨的工作。
如果这个价格标签没有给你留下深刻印象,你可以通过添加更多代码来任意提高转化成本。请记住,可以处理此类大型程序的熟练黑客有更好的事情要做。他们编写自己的代码。
【讨论】:
快速分析几个文件发现1KB只有几百行机器码,程序越大越小。对于一个不太熟练的黑客来说,分析这么多会相对容易。但是我怀疑有人愿意为需要进一步逆向工程的原始 C 代码付费,因此程序员需要以可用的方式重写或以其他方式记录代码。如果您只是想窃取算法,或与特定的秘密 API 接口,这可能是经济高效的,但是,这听起来太贵了,无法打扰。【参考方案4】:我所知道的关于这个主题的最佳作品之一是:
Pigs from sausages? Reengineering from assembler to C via FermaT。
声称你得到了一个合理的 C 程序,即使原始的 asm 代码不是用 C 编写的!有很多注意事项。
【讨论】:
不错。我有一个警告。通过它运行我的一个程序的结果会生成一个 C 程序,但由于汇编代码假定我的非标准堆栈帧,因此生成的 C 程序无法工作。 你真的用过FermaT转换器吗? ...我希望堆栈框架布局不会有什么不同;堆栈帧只是一种“结构”,如果您可以为堆值提出合理的结构,您应该能够为堆栈帧执行此操作。能举个具体的例子吗?【参考方案5】:Hex-Rays 反编译器(IDA Pro 的扩展)可以做到这一点。它仍然是最近的和即将到来的,但显示出巨大的希望。这需要一点时间来适应,但可能会加速逆转过程。它不是“灵丹妙药”——没有 c 反编译器,但它是一项伟大的资产。
【讨论】:
反编译器如何区分for
、while
和do-while
循环,然后可以在源代码中进行不同的编码?另外,它如何获得原始函数的名称?它如何“取消优化”代码以匹配原始代码?它如何确定变量名?在 news:comp.lang.c" 中搜索 *hamburger 和 cow。
这有关系吗?如果我关心逻辑而不是形式,两者都可以【参考方案6】:
此程序的通用名称是“将汉堡包变回奶牛”。可以将二进制代码逆向工程为功能等效的 C 程序,但该 C 代码是否与原始代码非常相似是一个悬而未决的问题。
【讨论】:
【参考方案7】:使用执行此操作的工具是一项研究活动。也就是说,有可能在简单的情况下得到一些东西(例如,除非存在调试符号,否则您不会恢复局部变量名称)。对于大型程序,或者如果程序员决定让它变得困难,这在实践中几乎是不可能的。
【讨论】:
【参考方案8】:C 程序与其将生成的 ASM/机器代码之间没有 1:1 的映射关系 - 一个 C 程序可以在不同的编译器或不同的设置下编译成不同的结果),有时 C 的两个不同位可以产生相同的机器码。
您绝对可以从已编译的 EXE 生成 C 代码。您只是无法知道它在结构上与原始代码有多么相似 - 除了变量/函数名称丢失之外,我认为它不会知道代码在许多文件中拆分的原始方式。
【讨论】:
【参考方案9】:你可以试试 hex-rays.com,它有一个非常好的反编译器,可以将汇编代码反编译成 C,准确率高达 99%。
【讨论】:
以上是关于逆向工程c程序的主要内容,如果未能解决你的问题,请参考以下文章