[How2DEOBF] #2 控制流混淆
序
? ? ? ? 在前一篇專欄中,我們已經(jīng)簡單了解了關(guān)于反混淆的一些內(nèi)容。在本篇專欄中,我們將針對控制流混淆進行簡單的分析。控制流是指按一定的順序排列程序元素來決定程序執(zhí)行的順序,在大部分混淆器中,為了使目標(biāo)程序的執(zhí)行邏輯更加難懂,會進行控制流混淆。
? ? ? ? 控制流混淆的方法有很多,可有Exception?Jump,F(xiàn)LA,Bogus Jump乃至GEN3(Skidfuscator)之類,后又會有實現(xiàn)細(xì)節(jié)上的偏差,可能有些甚至叫法都不固定(比如存在JunkJump這種稱呼),比較雜亂。? ? ? ? ??
? ? ? ? 但人的腦袋總歸是有限的,很多控制流混淆都有共通的解法。這里,我們將對一個簡單的控制流混淆進行反混淆,從而初步展現(xiàn)一種解決思路。
分析
? ? ? ? 還是以這個目標(biāo)程序為例,這次我們使用Caesium混淆器為程序添加了一個控制流混淆。

? ? ? ??

? ? ? ? 對比之后我們發(fā)現(xiàn),原來的GOTO竟然變成了這一段奇怪的東西。
? ? ? ? 由于沒有使用Renamer,這個Getstatic指令所獲取的field顯然是混淆器生成的(1362525270),那么這到底是什么呢?
? ? ? ? 為了搞清楚,讓我們查看一下它。

? ? ? ? 看起來,它似乎被指定了初始值。對整個程序查驗之后,也沒有發(fā)現(xiàn)對它的修改指令。這樣,我們可以確定它是一個不變的量,那么上面那一段的執(zhí)行結(jié)果也就確定了:1? 0,所以會跳轉(zhuǎn)到Label 8的位置,也就與混淆前的GOTO執(zhí)行效果一致了。
? ? ? ? 好,這樣我們也就進行反混淆了——那當(dāng)然沒那么簡單。
? ? ? ? 讓我們看看類似的混淆還在哪些地方被運用了——

? ? ? ? 先前的情況是IFNE,而這里則是IFEQ,如果我們像剛才那樣想當(dāng)然認(rèn)定只有一種情況,那反混淆的結(jié)果就是不完全的,因此,在分析時,應(yīng)當(dāng)考慮可能的多種情況。雖說我們可以等反混淆一次之后再分析查驗,不過這實在是不夠優(yōu)雅(強迫癥)。
? ? ? ? 保持著謹(jǐn)慎的態(tài)度,我們繼續(xù)分析,果然又有新的發(fā)現(xiàn)。

? ? ? ? 仿照對于最初的那種情況的思路,我們也發(fā)現(xiàn),這個IFGE執(zhí)行結(jié)果也是依賴于一個固定的int類型的field。
? ? ? ? 這下不好,是否還存在其他可能的跳轉(zhuǎn)呢?
? ? ? ? 于是,偷懶的我們悄悄看了一下混淆器的源碼。

? ? ? ? 看來我們分析的確實比較到位,四種情況里考察到了三種(事實上示例程序確實不存在第四種情況)。
? ? ? ? 現(xiàn)在我們可以掌握思路了,這個控制流混淆實質(zhì)上就是把GOTO拆成4個效果等價的instructions,其中前兩個負(fù)責(zé)跳轉(zhuǎn),后兩個則是異常處理。我們只要對所有這種形式的跳轉(zhuǎn)分析并修改為初始的跳轉(zhuǎn)語句,就可以完成反混淆。
實現(xiàn)
? ? ? ? 說了這么多,總算進入正題了,這次我們?nèi)匀皇褂门c上一篇專欄同款的反混淆器編寫Transformer。
? ? ? ? 遍歷所有class的method,并匹配這種跳轉(zhuǎn)。

? ? ? ? 我們知道這些跳轉(zhuǎn)實質(zhì)上都是GOTO,所以全部替換成GOTO就完事了。

? ? ? ? 等等,我們似乎少了什么。
? ? ? ? 沒錯,還有那些混淆器生成的field需要去除,雖然這些東西對最后反混淆的結(jié)果幾乎沒有影響了,但是誰叫我們是強迫癥呢。
? ? ? ? 讓我們記錄下這些跳轉(zhuǎn)時使用的field,然后最后再清除它們。
? ? ? ? 最后完整的代碼差不多是這樣:

? ? ? ? 運行之后,成功去除了控制流混淆。
后記
? ? ? ? 以上便是一個簡單的控制流混淆的處理流程。在處理這種混淆時,尤其要留心觀察,考慮多種情況,而且不能暴躁(那就更難想到好的處理策略了)。要想提升分析能力,只能夠多多實踐,可以自行尋找一些樣本或是混淆器進行嘗試。
? ? ? ? 下載示例程序:https://wwcx.lanzoum.com/b032jht7i(5080)