静态信息:
样本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 idcfrom idaapi import *
import idc
def get_string(addr):out = ""while True:if Byte(addr) != 0:out += chr(Byte(addr))else:breakaddr += 1return outdef get_stringlen(addr):out = ""while True:if idc.get_wide_byte(addr)!= 0:out += chr(idc.get_wide_byte(addr))else:breakaddr += 1return addrdef 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:continueif idc.get_wide_byte(i) < 101 or v3 >106:if idc.get_wide_byte(i)<116 or v3 >121:continuev4 = v3 - 15else :v4 = v3 +15ida_bytes.patch_byte(i,v4)for i in range(stringstart,stringend):output += chr(idc.get_wide_byte(i))return outputdanger_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文件,该地址将指向文件内容