【逆向】使用IDA Python脚本自动化解密字符串数据
前言
一个肚脑虫(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")
看一下添加注释后的效果: