G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

admin 2024年1月20日10:15:02评论18 views1字数 2634阅读8分46秒阅读模式

第一眼看到今天介绍的这篇USENIX Security 2024论文Ahoy SAILR! There is No Need to DREAM of C: A Compiler-Aware Structuring Algorithm for Binary Decompilation,你会想到什么?如果去搜索Ahoy SAILR,搜索引擎会给你看什么呢?大家千万别试——是不是搜出来非常著名的动漫人物——《美少女战士》里面的水兵月(穿上水手服的月野兔)了?

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

言归正传,今天这篇论文算是呼应了我们半个月以前介绍的研究工作(G.O.S.S.I.P 阅读推荐 2024-01-04 反编译器的“失真度”分析)。论文讨论了这么一个问题:在二进制代码的反编译过程中,究竟要怎么才算是真正体会了源代码的精髓?

如果你刚好也是一名外国文学爱好者,那么你肯定会看过很多网上的激烈论战——关于到底哪个译者/译本更好体现了原著的精神。例如皇皇巨著《堂吉诃德》有好多不同的中文译本,关于到底哪个译者(这里面最有名的译者可能是杨绛先生)翻译得更好,在豆瓣上有很多争论,有人甚至把同一个段落的西班牙文和各个版本的中文翻译放在一起比较(https://book.douban.com/review/5722822/ 有兴趣的可以戳这里看看)。实际上本文作者也用了差不多的论述方法,不过要引出主题,首先我们要回顾一下上个世纪的一篇经典文章:

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

对,就是Dijkstra老爷子关于“goto有毒”的经典论断。这个论断不仅影响了软件开发人员,同时也影响到了二进制代码 的反编译。本文的作者分析发现,在反编译领域,有两种做法,一种做法是为了满足“不要有goto”这个洁癖,很多的反编译工具宁可让代码结构变得更复杂也要消灭一切goto,而另一种做法是坚持“原汁原味”地复原代码,结果产生了非常多的goto语句。看起来,这两种方法都不太好,可是有没有人去探索背后的原因呢?

本文坚持“实践是检验真理的唯一标准”,不忘初心,回到源代码和编译器代码优化的原始过程中去,调查了开发和编译的基本事实。基本结论包括:1)现实世界的高水平软件中确实包括很多goto(说的就是你,Linux内核!);2)编译器在编译优化过程中,会把原来没有goto的代码结构改成有goto的结构。看完这两个结论,你对第一个结论(下图给出了一个实例)可能不会有什么疑惑,但是对第二个结论是不是有一些不解?

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

我们来看这么一个例子。在下图中,左边的源代码第一个条件分支(if (a && b))实际上已经隐式地包含了第二个条件分支(if (b)),所以编译器会自作主张地把代码优化成下图右边的样子:这里面实际上包括了两类处理,首先是对代码进行复制(例如那个puts("second print")语句),其次是增加goto语句。这两类处理虽然把代码变得“丑”了一点,但是性能上会更好。

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

实际上,在反编译二进制代码的时候,我们使用的反编译器拿到的二进制代码是依照上图右边的代码生成的,那么现在问题来了,你进行反编译是要“忠实原著”(翻译出来的结构可能没那么好看)还是要根据译者的意思进行一些“艺术处理”呢?可能看到这里,你肯定会说,那显然是加工处理一下,让代码漂亮点好。且慢,让我们继续往下看另一个例子:

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

上面这个反编译结果针对的是前面我们提到的Linux内核里面的代码(Listing 1),使用的反编译器是DREAM反编译器。说到DREAM这个工具,它可有点历史了,是在2015年NDSS上第一次亮相,当时相关的研究论文题目就叫做No More Gotos: Decompilation Using Pattern-Independent Control-Flow
Structuring and Semantics-Preserving Transformations
,可见作者是有消灭一切goto的洁癖的(后来在IEEE S&P 2016上还有一个改进的工作DREAM++大家也可以了解一下)。不过,大家可以仔细品一品,在没有goto加持的情况下,是不是上面这个代码就少了一些“内核的味道”了(Linux内核开发人员默默点赞)?

在论文的第三章中,作者全面评估了编译器是如何在代码编译优化过程中引入goto的,具体的操作方法就是先去反编译那些开启了优化的代码,如果在反编译结果中发现了goto,就关闭特定的优化,再进行反编译,如果goto消失了,那就说明是这个特定的优化策略引发了反编译器生成goto这一结果。作者表示这个方法还蛮有效的,在论文的3.3章中总结了常见的会引发goto的优化策略。有了这些研究基础作为支撑,接下来就是今天的主角——SAILR反编译算法登场了。

本文的核心——SAILR反编译算法实际上是一整套特定的反编译流程,它的核心特色有两个:第一个就是依据上面讲的那些研究作为铺垫,把因为编译器优化导致反编译过程中产生的goto给消除掉;第二个是对Hex-Rays的一些特定缺点的改进(这个实际上也可以去看看我们在半个月前介绍的那篇论文)。

具体地,SAILR反编译算法会对三类结构进行处理,在反编译结果中消除goto,我们来看看下面的CFG,看你能不能理解:

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

作者把SAILR反编译算法和几个前期的研究工作(NDSS 2015的DREAM、USENIX Security 2013的Phoenix)进行了对比,在处理goto的这一点上,SAILR反编译算法明显要精确很多:

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

最后我们要额外推荐一个博客文章——30 Years of Decompilation and the Unsolved Structuring Problem(包括part 1和part 2两篇),对过去30年各类反编译工作进行了全面的总结,也包括了对今天介绍的论文的讨论,非常值得一读!!!

https://mahaloz.re/dec-history-pt1
https://mahaloz.re/dec-history-pt2

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究

论文:https://www.usenix.org/system/files/sec23winter-prepub-301-basque.pdf
Artifact:https://secartifacts.github.io/usenixsec2024/appendix-files/sec24summerae-final11.pdf

原文始发于微信公众号(安全研究GoSSIP):G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的“信达雅”研究

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月20日10:15:02
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   G.O.S.S.I.P 阅读推荐 2024-01-19 反编译的信达雅研究http://cn-sec.com/archives/2412785.html

发表评论

匿名网友 填写信息