許多年之後,面對IDA的F5,奮飛將會想起,老李老闆甩給他一本80x86彙編的那個遙遠的下午。git
那時的App的名字還叫exe、com。Asm程序員最後的榮光,就是面對黑洞洞的屏幕敲下DEBUG的那個不眠之夜。程序員
後來App更名叫pe、elf了。IDA F5一下就是C程序員的狂歡,Asm程序員只能黯淡落幕了。默默的抱起小李老闆新買的《C語言程序設計》。github
時代的車輪呼嘯而過,瑞士的同行給咱們上了一課,ollvm一下,你媽都認不出來你了。json
ollvm紀元都已經10年了,如今的混淆只有更狠,沒有最狠。api
誰來還我源代碼?還得是 IDA F5 ,當年橫空出世的時候喊人家小甜甜,如今趕上ollvm了,就喊人家牛夫人了。牛夫人也有變身的時候。緩存
是的,我知道你在用 7.5。安全
git clone https://gitlab.com/eshard/d810.git
複製代碼
把d810文件夾和D810.py文件一塊兒放到 C:\fenfei\IDAPro7_5\plugins 目錄下面。微信
而後做者強烈建議安裝 z3markdown
pip3 install z3-solver
複製代碼
打開心愛的IDA,載入樣本 blog_instruction_obfuscation_sub1.bin, 而後 File->Script File... 選中 D810.py 跑一下,最後 Ctrl-Shift-D ,神器出現了。函數
Current file loaded 中選擇配置文件 default_instruction_only.json
而後點擊 」Start「 按鈕,再 F5一下, 見證奇蹟的時刻來了。
雖然看上去還不是很帥,可是起碼他媽應該能認出他來了。
爲啥有的小夥伴即便都配置好了D810,可是F5以後仍是沒有變化?
那是由於IDA F5有緩存,你以前已經F5過了,再來一次不會走D810插件,還會走原來的緩存。
那怎麼刪除這個F5的緩存呢? 這個,我也不知道。
可是飛哥找到了一個等效的方法。
這下再F5就會從新生成,走D810的加強結果了。
完美收工……
李老闆: 奮飛呀,你就這麼結束也太水了吧。這種文章我都很差意思 轉發,嚴重影響我大佬的人設。
奮飛:老闆說的有道理,使用開源工具,不讀他的源碼是對做者的不尊重。
咱們先來聊聊 IDA Microcode, 他是一種中間語言,從反彙編出來的彙編代碼到F5生成漂亮的C代碼,中間要通過屢次的Microcode轉換。
舉個例子,生米煮成熟飯(說你呢,別想歪了),在萌新看來,就是大米 biu~~ 一下就成米飯了。可是立志成爲老鳥的小夥伴就要分析一下了, 大米加水後會膨脹,成熟度1度的時候,大米剛剛有點發白,成熟度2度的時候,大米表皮變軟,成熟度n度的時候,纔是香噴噴的米飯。
若是咱們在成熟度2度的時候,給鍋里加點葡萄乾,那麼最後出來的米飯會不會更帥?
Microcode把 ASM -> C 的過程分紅了多個成熟度,每一個成熟度提供api給你hook,你能夠本身加點料。這樣最後出來的C代碼就更可口了。
此次的新朋友是 github.com/gaasedelen/…
明明白白的查看各個成熟度的微碼,方便你夾私貨。
Microcode聊完了,咱們再聊聊D810小甜甜的原理。
D810主要作了兩步,一步是指令替換
混淆後的代碼裏面有大量這種模式的代碼,只要用點小學數學知識,咱們就能換算出
而後把對應的代碼替換掉不就好了?
在 d810/ast.py 中用 AstNode 對象來表示一個算式
好比 x+y 用 AstNode表示就是
# x+y
AstNode(m_add,
AstLeaf("x_0"),
AstLeaf("x_1"))
# (x + y) - 2 * (x & y)
AstNode(m_sub,
AstNode(m_add,
AstLeaf("x_0"),
AstLeaf("x_1")),
AstNode(m_mul,
AstConstant("2", 2),
AstNode(m_and,
AstLeaf("x_0"),
AstLeaf("x_1"))))
複製代碼
這樣抽象出來以後,你從 d810/optimizers/instructions/pattern_matching 下面就能夠翻到一堆指令替換的代碼了。
D810作的第二步,是流程重組,相似咱們以前 91fans.com.cn/post/disoll… 分析的那樣,找到 主分發器和真實塊,而後重組正確的流程。
這一步的實如今 d810/optimizers/flow 裏面
說那那麼多,咱們來動手給d810再加點料。
剛纔分析的 obfucated_full_example 還不是很帥,
while ( ((v3 | 0xFFFFFFFA) & ~(((v3 - 5) | v3 ^ 0xFFFFFFFA) & (v3 ^ (v3 - 5) ^ 5)) & 0x80000000) == 0 )
複製代碼
這行代碼看上去應該也是能夠優化的
在 \d810_logs\pattern_guess.log 的日誌裏面,他有提示咱們 (~((x_0 - 5)) | (x_0 ^ 5)) 這一步是能夠優化的。
小學數學登場
(~((x_0 - 5)) | (x_0 ^ 5)) == 1
複製代碼
飛哥,我小學數學是體育老師教的,你會不會騙我?
說好的信任呢? 來吧, 介紹一位新朋友 github.com/quarkslab/a…
專治小學數學不服
那就開始寫代碼吧
class FFRule0(PatternMatchingRule):
PATTERN = AstNode(m_or,
AstNode(m_bnot,
AstNode(m_sub,
AstLeaf('x_0'),
AstConstant('5', 5))),
AstNode(m_xor,
AstLeaf('x_0'),
AstConstant('5', 5)))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_1"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_1", 1, candidate.size)
return True
複製代碼
而後配置上咱們新的規則
再看看加強plus的結果:
歐耶,漂亮多了。
小學數學很重要。
通常狀況下做者推薦用 default_instruction_only.json ,等你搞明白了,能夠本身搭配配置,小孩子才作選擇,成年人全都要。是不行的,全部配置都加上慢的一比不說,還會增長崩潰的概率。
沒有一勞永逸直接F5就出來漂亮源碼的辦法,IDA的F5已經作了不少的工做,攻防老是在不斷升級的,武器是戰爭的重要因素,但不是決定因素,決定的因素是人不是物。
參考連接:
D810:爲 IDA Pro 建立一個可擴展的反混淆插件
若是把出類拔萃定義爲成功,那麼大多數人註定無所建樹;若是把比昨天進步一點點當成目標,那麼咱們天天都有機會宣佈本身得到了一次小勝利
TIP: 本文的目的只有一個就是學習更多的逆向技巧和思路,若是有人利用本文技術去進行非法商業獲取利益帶來的法律責任都是操做者本身承擔,和本文以及做者不要緊,本文涉及到的代碼項目能夠去 奮飛的朋友們 知識星球自取,歡迎加入知識星球一塊兒學習探討技術。有問題能夠加我wx: fenfei331 討論下。
關注微信公衆號:奮飛安全,最新技術乾貨實時推送