一.前言
逆向工程一直是資安界中的一個重要議題!
很多程式或許在頂層做了很多防護,但是來到了底層這些防護是否還能達到其效果?
這個答案是否定的。
故本文將介紹一些關於基礎逆向知識與實作,以期待為完全沒有這方面知識的朋友們
開啟一扇逆向的大門。
(但開車請不要逆向=口=)
※ 如果本身已經俱備逆向能力的人大該可以跳過這篇了...
※ 受限於筆者本身的能力,這只會很淺很淺...
二.概述
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