目的
网上看到一个较新的Confucius APT样本,这里记录一下分析过程,主要目的是提取C&C以及分析其流量特征
初步分析
为了能够调试dll,设置x64dbg的命令行如下
"C:\Windows\SysWOW64\rundll32.exe" C:\Users\l\Desktop\d345a80e349b79c78faa9bf10922416b0d5cfb1b805e0bfb2f675d83f63c7e47\1.dll,version
跑起来直接异常了,只能先静态看看
从IDA中发现有一些加密的字符串,并且加密字符串后续的操作疑是解密过程
结合x64dbg在解密函数开头设置新的运行点可以发现解密的过程就是异或0x1D
通过IDA脚本解密出部分xor编码的字符串
import idc import idaapi def getStrAddress(addr): addr = prev_head(addr) if print_insn_mnem(addr) == "push" and "offset" in print_operand(addr,0): return get_operand_value(addr,0) else: return 0 def getEncodeStr(addr): out = "" while(True): ch = idaapi.get_byte(addr) if ch != 0: out += chr(ch) else: break addr += 1 return out def getDecodeStr(str): i = 0 out = "" length = len(str) while i < length: out += chr(ord(str[i]) ^ 0x1d) i += 1 return out if __name__ == '__main__': try: for x in XrefsTo(0x1001E410,flags = 0): addr = getStrAddress(x.frm) if addr == 0: continue eStr = getEncodeStr(addr) if eStr == "": continue dStr = getDecodeStr(eStr) set_cmt(prev_head(x.frm), dStr, 0) except: print("Error")
解密出部分字符串,发现有检测windows版本的功能,以及C&C
深入分析
二进制代码中有大量的mov操作,以及利用try catch的混淆手段扰乱着代码块,静态看起来比较复杂。
硬着头皮看了一段时间后发现样本中竟然有log函数
通过log函数我们就能很方便的梳理出样本的大致逻辑了。
大致的逻辑是获取dll name,获取计算机名,发送ping包等(在分析的过程中发现还有一些操作没有通过log函数记录,不过这也不影响我们分析其流量特征了)
为了获得流量特征定位到first ping,这里就是发送第一个数据包的地方
往上找找有一个send操作,为了方便查看流量特征,现在得想办法让dll正常跑起来,并在send下断点,查看buf的值。
由于前面动态调试的时候一直报异常,第一反应是有反调试,也的确发现了反调试API。,但下断点后发现在反调试之前就已经异常了。
通过栈回溯定位到异常产生的函数,分析发现该函数有路径字符串替换的功能,这里意识到样本的启动与路径有关。
为了搞清楚该dll启动的方式和启动路径,需要先获取上一阶段word文档中的VB宏。
对上面的VB脚本进行解密,获取到powershell脚本
import string bpw = string.ascii_lowercase gfgdfgefugwrifgr = bpw[18] + bpw[2] + bpw[17] + bpw[8] + bpw[15] + bpw[19] + bpw[8] + bpw[13] + bpw[6] + chr(46) + bpw[5] oherfuirfgrgfffwfwe = bpw[8] + bpw[11] + bpw[4] + bpw[18] + bpw[24] + bpw[18] + bpw[19] + bpw[4] + bpw[12] + bpw[14] + bpw[1] + bpw[9] + bpw[4] + bpw[2] + bpw[19] p3rhfrbbgoigrtgreg = chr(67) + chr(58) + chr(92) + "U" + bpw[18] + bpw[4] + bpw[17] + bpw[18] + chr(92) + "P" + bpw[20] + bpw[1] + bpw[11] + bpw[8] + bpw[2] + chr(92) jvpgvwfwg4tuh5yjat4rtgfrfhg = "D" + bpw[14] + bpw[22] + bpw[13] + bpw[11] + bpw[14] + bpw[0] + bpw[3] + bpw[18] + chr(92) + bpw[6] + bpw[8] + bpw[18] + bpw[19] pqwefbevfgvugrgfv = "." + bpw[19] + bpw[23] + bpw[19] jfur6yroo97ighgyte6 = bpw[18] + bpw[2] + bpw[7] + bpw[4] + bpw[3] + bpw[20] + bpw[11] + bpw[4] + "." + bpw[18] + bpw[4] + bpw[17] + bpw[21] + bpw[8] + bpw[2] + bpw[4] Path = bpw[15] + bpw[14] + bpw[22] + bpw[4] + bpw[17] + bpw[18] + bpw[7] + bpw[4] + bpw[11] + bpw[11] pbvfewi4regfergf8734 = " -" + bpw[22] + " " + bpw[7] + bpw[8] + bpw[3] + bpw[3] + bpw[4] + bpw[13] + " " + bpw[8] + bpw[4] + bpw[23] + " (([" pfjs3jdnbighgtohthhf = "S" + bpw[24] + bpw[18] + bpw[19] + bpw[4] + bpw[12] + ".T" + bpw[4] + bpw[23] + bpw[19] + ".E" + bpw[13] + bpw[2] + bpw[14] + bpw[3] + bpw[8] + bpw[13] + bpw[6] + "]::A" + "SC" + "II)." + "G" + bpw[4] pqk3ggnolhzbzgbid8rg = bpw[19] + "S" + bpw[19] + bpw[17] + bpw[8] + bpw[13] + bpw[6] + "(([" + bpw[18] + bpw[19] + bpw[17] + bpw[8] + bpw[13] + bpw[6] + "](" + bpw[6] + bpw[4] + bpw[19] + "-" + bpw[2] + bpw[14] + bpw[13] + bpw[19] + bpw[4] + bpw[13] + bpw[19] + " -p" + bpw[0] + bpw[19] + bpw[7] + " " poht95bgsf894bgiu538 = "))." + bpw[18] + bpw[15] + bpw[11] + bpw[8] + bpw[19] + "('#')))." + bpw[17] + bpw[4] + bpw[15] + bpw[11] + bpw[0] + bpw[2] + bpw[4] + "('?','')" pef = pbvfewi4regfergf8734 + pfjs3jdnbighgtohthhf + pqk3ggnolhzbzgbid8rg + p3rhfrbbgoigrtgreg + jvpgvwfwg4tuh5yjat4rtgfrfhg + pqwefbevfgvugrgfv + poht95bgsf894bgiu538 str1 = "239#......" str1 = str1.split("#") str1 = map(chr ,map(int, str1)) str1 = "".join(str1) print(str1)
在x64dbg下构造新的命令行后成功跑起来
后续的调试就相对简单了,发送的buf复用了之前的xor函数以及一个base64函数,并使用"#$#*"进行分隔,"iqaz"字符串作为结束符
至此我们就成功提取到了该样本的C&C以及流量特征
参考
http://blog.nsfocus.net/aptconfuciuspakistanibo/