前言:
花指令的出現主要是防止軟件被反編譯,加大逆向分析的難度,在一些代碼中插入一些臟字節
為啥我要寫呢,因為面試的時候也碰到了,雖然我都答出來了,但是特意過來記個筆記2333
一.花指令的分類
1. 可執行的花指令
之前在西電的ctf上,就碰到一題,只是為了混淆視聽而已,實際上根本不會執行,
加大你靜態分析的難度,那題是在源碼級上搞,還有那種在匯編級上push一下
,再pop一下,這種看似沒什么用的操作同理
2. 不可執行的花指令
這里要總結幾種匯編層面上的花指令模式,很大程度是因為ida無法聯系上下文233
1.jx+jnx
這個就不用多說了吧,很常見的一種花指令了,這里jnz實際上是fake的,因為jz這個指令,讓ida
認為jz下面的是另外一個分支,所以這里去除,就是將jnz下面包括jnz 全c了,然后把loc_402669+1
的字節碼全給nop了,f5就管用了
2. call pop / add esp
這里call指令,其實本質就是jmp&push 下一條指令的地址,但是這里其實就是一個jmp指令
所以 push這條指令是多余的,需要add esp,4 調整堆棧,但是ida會默認把call 后面的那個地址
當成一個函數。
3. stx/jx
clc是清除EFlags寄存器的carry位的標志,而jnb是根據cf==0時跳轉的,然而jnb這個分支指令,ida
又將后面的部分認作成了另外的分支,interesting。
4.jmp xxx紅色
這也是一種非常常見的花指令的,其實這里很明顯就有問題,因為虛擬地址怎么可能有那么大對吧,
我們來看一下花指令源代碼,
實際是e9在搞鬼,ida會默認將e9后面的4個字節當成地址,只要nop掉就好了
5. 多重跳轉的
這里也是,仔細分析下邏輯發現其實這一大段根本沒用,就離譜,單純惡心反編譯器的,我們可以使用idapython
來進行去花,而且當花指令很多的時候,idapython的自動化會很有用
二.利用idapython去除第5點花指令
def nop(addr,endaddr): while(addr<endaddr): PatchByte(addr,0x90) addr+=1 def undefine(addr,endaddr): while addr<endaddr: MakeUnkn(addr,0) addr+=1 def dejunkcode(addr,endaddr): while addr<endaddr: MakeCode(addr) # 匹配模版 if GetMnem(addr)=='jmp' and GetOperandValue(addr,0)==addr+5 and Byte(addr+2)==0x12: next=addr+10 nop(addr,next) addr=next continue addr+=ItemSize(addr)
里面使用到的ida函數解析
MakeCode(ea) #分析代碼區,相當於ida快捷鍵C ItemSize(ea) #獲取指令或數據長度 GetMnem(ea) #得到addr地址的操作碼 GetOperandValue(ea,n) #返回指令的操作數的被解析過的值 PatchByte(ea, value) #修改程序字節 Byte(ea) #將地址解釋為Byte MakeUnkn(ea,0) #MakeCode的反過程,相當於ida快捷鍵U MakeFunction(ea,end) #將有begin到end的指令轉換成一個函數。如果end被指定為BADADDR(-1),IDA會嘗試通過定位函數的返回指令,來自動確定該函數的結束地址
idapython的參考api鏈接:
https://www.bbsmax.com/A/x9J27Lgg56/