一.前言
逆向工程一直是资安界中的一个重要议题!
很多程式或许在顶层做了很多防护,但是来到了底层这些防护是否还能达到其效果?
这个答案是否定的。
故本文将介绍一些关于基础逆向知识与实作,以期待为完全没有这方面知识的朋友们
开启一扇逆向的大门。
(但开车请不要逆向=口=)
※ 如果本身已经俱备逆向能力的人大该可以跳过这篇了...
※ 受限于笔者本身的能力,这只会很浅很浅...
二.概述
1.什么是 逆向工程(Reverse Engineering)?
逆向工程是一种将程式码透过反组译使得已经被编为二进制的
机械码(Machine Code)还原回组语程式码的资安技术。
2.逆向工程的危害是什么?
I.透过反组译之后的结果,黑客可以找到一些原本隐藏于程式码中,不打算让使
用者知道的资讯。
(如:金钥,内存位置,安全漏洞,尚未公布的系统功能,etc)
II.借由其结果去修改原程式的二进码达到验证的绕过与跳过。
III.还原该程式原始程式码之后进行修改然后再贩售或分享。
3.如何进行 逆向工程?
使用一些静态或动态反组译工具(如: IDA ,Ghidra ,etc)将程式反组译(甚至
反编译)并且分析与修改。
三.原理
基本上大部份程式于机器上运行时,需要将其高阶程式借由编译器编译成组合语言,
然后再组译成机械码。
一般而言这些机械码都是二进制人类无法阅读,但是机器可以理解与执行。
在顶层的程式可以千变万化,但是机械码为了达到让"机器可以理解与执行"此时变化
就少了,也给了我们攻击的空间。
四.工具简介
这次的科普介绍所使用的工具有别于过去被广为使用贵的吓人且封闭的IDA,而是使
用 Ghidra 。
Ghidra 是由 NSA 研发并且在2019年3月6号于 RSA 大会上发布的免费的开源逆向分
析工具,俱备有反组译与反编译能力。
接口由于 Ghidra 是使用 Java 开发的,所以令人堪忧,但多戳几下会发现制作者在
制作过程中颇具巧思。
此外因为开源特性,这款工具有着无穷的进步空间且还可以使用 Java 或 Python 开
发自己的 Ghidra 插件。
Ghidra 的官方似乎没有硬性规定该如何发音这个词,不过大部分的人会念"鸡爪",
不过我私下习惯暱称他龙龙>"<
虽然该工具是在2019年公布,但是在2017年的维基解密中,就有提到 NAS 一直使用
Ghidra 做为其工具。
工具下载位置:
官网:https://ghidra-sre.org/
Github:https://github.com/NationalSecurityAgency/Ghidra
五.实作
图1:https://i.imgur.com/esc9t9C.png
图1是 Ghidra 开启后的画面,不过因为我已经有使用过并且进行过一些个人化修改
,跟刚下载下来的会略有不同...
第一步,
在 file>New Project 中开启一份逆向专案。
开启后会出现如同图1中 test1 的资料夹,此时我们就可以将我们要逆向的档案拖拉
放入 Project 中开启一份逆向专案。
这次实作使用的是 inndy 的 hackme CTF 中的 Reversing 基础题 helloworld 。
(来源位置:https://hackme.inndy.tw)
(载点:https://hackme.inndy.tw/static/helloworld)
第二步,
将 helloworld 直接拖拉或者借由 File>Import File 放入专案后,双击
helloworld 即可进行反组译。
这时 Ghidra 会问你要不要分析这份程式,请点分析。
图2:https://i.imgur.com/A1u0xcN.png
成功开启之后,画面可能会类似图2这样,不过因为 Ghidra 画面可以自己调适,所
以可能会略有不同。
不同的部份可以在 window 功能中开启,我主要使用 window>Symbol Tree ,
window>Listing , window>Bytes , window>Decompile
第三步,
图2右侧的 Symbol Tree 可以看到 Functions ,点击后依照经验优先寻找程式的进
入点 main function 。
点击 main 之后会自动跳到组语中 main 的区段,此时我们就可以察看 Decompile
中的经过反编译的程式码片段。
图3:https://i.imgur.com/RoWmkSL.png
图3中我们可以看到程式判断要不要输出FLAG的判断是在
if (local_18 == 0x12b9b0a1)
所以此时我们将 0x12b9b0a1 这个数值转回10进位发现他的数值为 314159265 。
第四步,
我们开始执行此程式,并且输入 314159265 就会得到我们要找的 FLAG 了如
图4。
图4:https://i.imgur.com/ds2tPSf.png
之后在 hackme CTF 中输入FLAG即可拿到此题分数。
一些想研究逆向的人可能会试着修改 if (local_18 == 0x12b9b0a1) 来达到绕过验
证的效果,
但是这题不行,原因是因为 Ghidra 的反编译很聪明的将 计算最后结果的程式码反
编译为如下:
*(byte *)((int)&local_35 + local_14) = *(byte *)((int)&local_35 +
local_14) ^ 0xa1;
可是事实上那个 0xa1 的结果是来至于我们的输入 local_18 这个变量最后面的
byte ,所以随意更改会造成 FLAG 无法正确解析。
如果从组语的部份我们可以更加清楚的发现这点。
图5:https://i.imgur.com/zDrPLLQ.png
图5中我们可以看到 080484f0 的位置,我们将 Array的值取出并且将最后 1 byte
存入了 EDX 。
080484f3 的位置上将 local_18 的值存入 EAX 。
在 080484f6 看到将EDX的值存入 ECX 。
最后在 080484f8 进行 XOR 运算。
因此我们可以知道反编译的结果其实只是辅助,逆向核心还是要看组语!
此外这个案例中我们也可以尝试直接由上面的资讯计算出最后的 FLAG ,相关程式如
图6。
图6:https://i.imgur.com/mWlWLXL.png
六.案例
这方面案例应该算是蛮多的,譬如网络上常看到的XXX破解版,譬如: Illustrator
破解。
七.防御方式
经过加壳或者混淆之后的程式码可以增加攻击者成功的困难度。
虽然难以避免被破解,但是可以增一些战略纵深,对于相关攻击得到一些反应时间。
在资安上我们不强求一项防御可以挡住所有攻击者,但是如果可以刷掉一部份的攻击
者,这就可以算是一种成功。
八.后话
近年来对于底层的攻击层出不穷,是至是更底层对于硬件层面的
旁路攻击(Side-channel attack)。
譬如 FBI 借由将 iPhone 上的芯片特定脚位接上通电,借此清除 iPhone 对于暴力
破解密码的记忆进行攻击。
虽然反组译并不是最底层,一些破解可能会被硬件方式阻挡,但是依旧是一门值得探
讨的问题。
一些应用也可以使用在 pwn 的 buffer overflow 上。
因此虽然我才疏学浅孤陋寡闻,但是还是希望能够抛砖引玉一下。
希望可以吸引各路大神对于这块领域做出更多的解释以及教学。
介绍 Ghidra 是因为这是一个新出来的开源软件,或许现在还不够完美,但是因为开
源的特性相信如果持续宣传,一定可以让他更加迈向完美。
望能为台湾的资讯安全贡献一份心力。
共勉之。
By st1009