静态信息:
样本md5:9b656f5d7e679b94e7b91fc3c4f313e4
由此可见为假的Adobe Flash Player 的攻击样本
样本分析
通过五个函数,内部调用sub_40159D函数动态获取API函数
利用IDA python解密字符串。。
完整python代码
Python> idc.get_segm_name(here())
'.text'
Python> idc.GetDisasm(here())
'call sub_405060'
Python>idc.print_insn_mnem(here())
'call'
Python>idc.print_operand(here(),0)
'sub_405060'
Python>idc.print_operand(here(),1)
''
idc.get_operand_value(ea,n)
获取操作数的值。
完整python代码
from idaapi import *
import idc
from idaapi import *
import idc
def get_string(addr):
out = ""
while True:
if Byte(addr) != 0:
out += chr(Byte(addr))
else:
break
addr += 1
return out
def get_stringlen(addr):
out = ""
while True:
if idc.get_wide_byte(addr)!= 0:
out += chr(idc.get_wide_byte(addr))
else:
break
addr += 1
return addr
def get_function_argv(addr):
for x in range(4):
addr = idc.prev_head(addr)
print("%08x" %addr)
if idc.print_insn_mnem(addr) == "push" and "offset" in idc.print_operand(addr,0):
print("GET success")
print("%08x" %addr)
return idc.get_operand_value(addr,0)
else :
print("NO")
def get_retn(addr):
for x in range(4):
addr = idc.next_head(addr)
if idc.print_insn_mnem(addr) == "mov":
print("retn success")
print("%08x" %addr)
return idc.get_operand_value(addr,0)
else :
print("NO")
def Mydecrypt(stringstart,stringend):
output = ""
for i in range(stringstart,stringend):
v3 = idc.get_wide_byte(i)
print(v3)
if idc.get_wide_byte(i)<97 or v3 > 122:
continue
if idc.get_wide_byte(i) < 101 or v3 >106:
if idc.get_wide_byte(i)<116 or v3 >121:
continue
v4 = v3 - 15
else :
v4 = v3 +15
ida_bytes.patch_byte(i,v4)
for i in range(stringstart,stringend):
output += chr(idc.get_wide_byte(i))
return output
danger_funcs = ["getapi"] # 需要寻找的函数名
for func in danger_funcs:
addr = get_name_ea_simple( func )
print("call sub_40159D:%08x" %addr)
cross_refs = CodeRefsTo( addr, 0 )
for addr in cross_refs:
print("..................")
print( "%08x" % addr)
print("get_function_argv start")
stringstart = get_function_argv(addr)
print( "%08x" %stringstart)
stringend = get_stringlen(stringstart)
result = Mydecrypt(stringstart,stringend)
print(result)
idc.set_cmt(stringstart, result, 0)
idc.set_name(stringstart, result, SN_FORCE)
print("..................")
apiaddr = get_retn(addr)
print("%08x" %apiaddr)
idc.set_name(apiaddr, result, SN_FORCE)
已经被修改,伪代码没修改过来,N -> create name anyway,这样就方便静态分析了
调用GetModuleFileName获取当前的运行进程路径并将其写入到Run注册表中以实现本地持久化,写入的注册表键值为msnconf
继续跟到sub_402811函数:
再次调用五个函数动态获取API函数地址
sub_4021EE:
打开文件成功就读取文件到dword_40B498,buffer:0040AEB0,大小0x36Eu,打开文件失败则,memset对dword_40B498地址后0x36Eu大小 区域置零,
地址布局:
从unk_40B5A2开始,每0x10填充一个02
之后将IP和端口填充到前面用02分割的内存空间中,填充的02是connect参数sockaddr结构体中的sa_family。
int main( )
{
printf("%d /n",htons(16));
return 0;
}
得到的结果是4096
解释如下,数字16的16进制表示为0x0010,数字4096的16进制表示为0x1000。 由于Intel机器是小尾端,存储数字16时实际顺序为1000,存储4096时实际顺序为0010。因此在发送网络包时为了报文中数据为0010,需要经过htons进行字节转换。
数字所占位数小于或等于一个字节(8 bits)时,不要用htons转换
sub_402E9C:根据时间因子得到随机数,加上地址,可以从5个ip中随机获取一个,建立socket连接,成功连接尝试向C2发送测试数据,成功,则将0x40B498地址处的内容发送到C2,服务器可根据该请求值判断当前攻击进行到哪一阶段,若失败则休眠60秒后 重新生成随机数再次请求,若第二次请求成功,尝试将0x40B498地址处的内容发送到C2:
成功上线后,向C2发送0x1243451,接收返回值传入Switch_case中
Switch_case:
如果有nls文件
sub_4020F6 :通过时间获得随机数
若本地存在c_126705.nls文件,该地址将指向文件内容