网上看到一个较新的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 idaapidef 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 stringbpw = 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/