前言
一個肚腦蟲(Donot)APT組織的下載器樣本,樣本中的一些關鍵字符串數據需要使用指定函數進行動態解密。所以正好借此機會記錄下怎么使用IDA Python腳本來解密字符串數據。使用IDA Python腳本自動化解密字符串數據對逆向分析人員來說應該是一個比較常用的功能。
myDecode為解密函數,只要將加密的字符串數據作為參數傳入就能返回加密前的原字符串

對myDecode函數進行交叉引用,可以發現總共有34個地方調用了該函數

解密算法比較簡單,編寫解密腳本的基本思路就是通過交叉引用獲取每一個加密字符串,然后通過添加注釋的方式對解密后的原始字符串進行標注。
1 _BYTE *__cdecl myDecode(const char *a1) 2 { 3 _BYTE *v2; // [esp+10h] [ebp-8h] 4 unsigned int i; // [esp+14h] [ebp-4h] 5 6 v2 = calloc(1u, 0x1Bu); 7 for ( i = 0; i < strlen(a1); ++i ) 8 v2[i] = a1[i] ^ 3; 9 v2[i] = 0; 10 return v2; 11 }
下面是需要用到的幾個IDA Python API函數:
1 XrefsTo #獲取交叉引用地址 2 prev_head #獲取前一條指令地址 3 print_insn_mnem #獲取指令助記符 4 print_operand #獲取指令操作數 5 get_operand_value #獲取操作數地址 6 get_byte #從指定地址獲取1字節數據 7 set_cmt #添加注釋
完整腳本代碼如下:
1 import idc 2 import idaapi 3 4 def getStrAddress(addr): 5 addr = prev_head(addr) 6 if print_insn_mnem(addr) == "push" and "offset" in print_operand(addr,0): 7 return get_operand_value(addr,0) 8 else: 9 return 0 10 11 def getEncodeStr(addr): 12 out = "" 13 while(True): 14 ch = idaapi.get_byte(addr) 15 if ch != 0: 16 out += chr(ch) 17 else: 18 break 19 addr += 1 20 return out 21 22 def getDecodeStr(str): 23 i = 0 24 out = "" 25 length = len(str) 26 while i < length: 27 out += chr(ord(str[i]) ^ 3) 28 i += 1 29 return out 30 31 32 if __name__ == '__main__': 33 try: 34 for x in XrefsTo(0x6B4C4920,flags = 0): 35 addr = getStrAddress(x.frm) 36 eStr = getEncodeStr(addr) 37 dStr = getDecodeStr(eStr) 38 set_cmt(prev_head(x.frm), dStr, 0) 39 except: 40 print("Error")
看一下添加注釋后的效果:

