對于ollvm的恢復基本基于angr和miasm瞬测,但對于arm的恢復,支持并不理想址儒;所以便看到了另外的一框架unicorn蜒秤。
LLVM將混淆之后的程序分為以下幾個模塊:
1.函數(shù)的開始地址為序言的地址
2.序言的后繼為主分發(fā)器
3.后繼為主分發(fā)器的塊為預處理器
4.后繼為預處理器的塊為真實塊
5.無后繼的塊為retn塊
6.剩下的為無用塊
所以我們去混淆的大概思路就是按照幾個模塊找到函數(shù)地址,將真實塊留下贝咙,retn塊留下样悟,之后那些無用塊全部置為nop;關鍵就是對真實塊和虛擬塊的識別庭猩,之后再對真實塊中兩種 分支 和 順序 關系的識別窟她,使用符號執(zhí)行模擬兩者之間的關系。
unicorn的優(yōu)點
- 支持多種架構: Arm, Arm64 (Armv8), M68K, Mips, Sparc, & X86 (include X86_64).
- 對Windows和*nix系統(tǒng)(已確認包含Mac OSX, Linux, *BSD & Solaris)的原生支持
- 具有平臺獨立且簡潔易于使用的API
- 使用JIT編譯技術, 性能表現(xiàn)優(yōu)異
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple unicorn
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple capstone //使用capstone進行反匯編
這篇 只 先對unicorn熟悉了解下
官方文檔給的例子
#coding:utf-8
from unicorn import *
from unicorn.arm_const import *
ARM_CODE = b"\x37\x00\xa0\xe3\x03\x10\x42\xe0"
# mov r0, #0x37;
# sub r1, r2, r3
# Test ARM
# callback for tracing instructions
def hook_code(uc, address, size, user_data):
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" % (address, size))
def test_arm():
print("Emulate ARM code")
try:
# Initialize emulator in ARM mode
mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB) #創(chuàng)建UC對象
# map 2MB memory for this emulation 創(chuàng)建2MB的內存空間
ADDRESS = 0x10000
mu.mem_map(ADDRESS, 2 * 0x10000)
mu.mem_write(ADDRESS, ARM_CODE) #將前面定義的ARM_CODE傳入內存空間內蔼水,只支持byte
#未開機前寄存器賦值
mu.reg_write(UC_ARM_REG_R0, 0x1234)
mu.reg_write(UC_ARM_REG_R2, 0x6789)
mu.reg_write(UC_ARM_REG_R3, 0x3333)
#添加指令集Hook
# mu.hook_add(UC_HOOK_CODE, hook_code, begin=ADDRESS, end=ADDRESS)
# emulate machine code in infinite time震糖,開機
mu.emu_start(ADDRESS, ADDRESS + len(ARM_CODE))
print("已開機")
#獲取計算器結果
r0 = mu.reg_read(UC_ARM_REG_R0)
r1 = mu.reg_read(UC_ARM_REG_R1)
print(">>> R0 = 0x%x" % r0)
print(">>> R1 = 0x%x" % r1)
except UcError as e:
print("ERROR: %s" % e)
test_arm()
***************************************
結果如下:
Emulate ARM code
已開機
>>> R0 = 0x37
>>> R1 = 0x3456
通過上述腳本來了解各個函數(shù)的作用
R0 寄存器為 0x37,R1 為 0x3456
之后使用capstone 來對操作的代碼進行反匯編趴腋,查看進行了什么操作
from capstone import *
from capstone.arm import *
CODE = b"\x37\x00\xa0\xe3\x03\x10\x42\xe0"
md = Cs(CS_ARCH_ARM, CS_MODE_ARM)
for i in md.disasm(CODE, 0x1000):
print("%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str))
********************************************************************
結果:
1000: mov r0, #0x37
1004: sub r1, r2, r3