火绒剑监控
执行监控
创建schtasks.exe文件
参数: “C:WindowsSystem32schtasks.exe” /Create /TN “UpdatesvsqbOQbkJjh” /XML “C:UsersxxxAppDataLocalTemptmpC0FD.tmp”‘
创建了自己
文件监控
创建C:UsersxxxAppDataRoamingvsqbOQbkJjh.exe文件 并写入数据
在临时文件夹下创建tmpC0FD.tmp 写入数据
注册表监控
删除注册表
网络监控
发送数据 数据未加密
进程监控
创建挂起进程 写入数据 恢复进程
创建自己 写入数据 读内存修改属性 设置线程上下文 最后恢复进程
行为监控
自我复制C:UsersxxxAppDataRoamingvsqbOQbkJjh.exe
恶意代码分析
代码第一层-字符串资源解密
资源字符串 为第二层要执行的代码(未解密)
解密函数
通过base64解码 得到下一层PE文件
Dump出来以后是一个dll文件
第二层-图片资源解密
获取图片资源
解密得到第三层
第三层
拷贝自己到C:UsersxxxxAppDataRoaming文件夹 文件名称为vsqbOQbkJjh.exe
创建计划任务
任务名称:vsqbOQbJjh
创建者:WIN-U8DNL3N3GKJpc
触发信息:登录WIN-U8DNL3N3GKJpc时
操作:启动程序C:UserspcAppDataRoamingvsqbOQbkJjh.exe
创建自己
获取线程上下文
像新创建的进程写入PE文件 设置新的eip
并激活线程
第四层开始运行
第四层
程序所需字符串硬编码到数组里
程序开始运行会调用此方法解密字符串
程序会通过下标和大小返回自身所需的字符串 共有772条
关闭自身重复进程
创建http请求 url: http://nSfkEw.com
最后运行此文件
复制自身 通过注册表自启动
重命名tmpG769.tmp 将自己拷贝到C:UsersxxxxAppDataLocalTemp 实现自我删除
要窃取的浏览器客户端
Chedot,Kometa,Brave,Coowon,Cool Novo,Iridium Browser,Citrio,Sputnik,Opera Browser,7Star, Yandex Browser,Liebao Browser,Chromium,Torch Browser,360 Browser,Sleipnir 6,Epic Privacy, Orbitum,QIP Surf,Uran,Vivaldi,Amigo,CentBrowser,Coccoc,Elements Browser,Elements Browser
屏幕截图
创建计时器 获取屏幕截图
将此图像以指定的格式保存到指定的流中
通过http发送到服务器
键盘记录
记录被感染者的键盘信息
创建计时器 发送记录的键值
通过电子邮件发送用户信息
发件邮箱:[email protected]
发件邮箱密码:Gdn4ford@2016
主机地址:mail.focuzauto.com
端口:587
回传邮箱地址:[email protected]
邮件主题:”PW_xxxx/WIN-UL8QQFCU9CJ”
邮件正文:
“Time: 07/07/2022 10:54:16<br>User Name: xxxx<br>Computer Name: WIN-UxxxxFCU9CJ<br>OSFullName: Microsoft Windows 7 专业版 <br>CPU: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz<br>RAM: 2703.49 MB<br><hr>”
创建FTP请求
发送内容 以xml文件格式发送
PW_xxxx-WIN-UL8QQFCU9CJ_2022_07_07_13_34_10.html
“<html>Time: 07/07/2022 13:34:10<br>User Name: xxxx<br>Computer Name: WIN-UxxxxU9CJ<br>OSFullName: Microsoft Windows 7 专业版 <br>CPU: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz<br>RAM: 2703.49 MB<br><hr></html>”
创建http请求
以表单的形式 传输数据
下载tor客户端
网址:
https://www.theonionrouter.com/dist.torproject.org/torbrowser/9.5.3/tor-win32-0.4.3.6.zip
下载到:
C:UsersxxxxAppDataRoamingTortor.zip
匿名传输数据
Ioc
MD5 | URL | |
---|---|---|
39F524C1AB0EB76DFD79B2852E5E8C39 | [email protected] | http://nSfkEw.com |
8A171A85D778196517E737D9EF23D3DB | mail.focuzauto.com | |
81F86EFD54CA768968830299ABE776FA |
配置提取工具:
import re
import pathlib
import os
import shutil
from collections import deque
#from matplotlib.style
class AgentTeslaAnalysis():
version = '1.0.0'
def __init__(self, folder):
self.folder = folder
self.code = None
self.property_dict1 = {}
self.property_dict = {}
self.property_map = {
'.Host =': self._extract_email_host,
'NetworkCredential': self._extract_email_u_p,
'NameValueCollection': self._extract_Http_host,
'WebRequest.Create' : self._extract_Tor_host
}
self.config = {}
def process(self):
for _ in pathlib.Path(self.folder).rglob("*"):
if not os.path.isfile(str(_)): continue
with open(str(_), 'r') as fp:
file_stream = fp.read()
if re.search(r'(public static [dw]+ [dw]+ = .*?;[nt ]+){1,}',file_stream):
self.code = file_stream
self.create_mapping()
for _ in pathlib.Path(self.folder).rglob("*"):
if not os.path.isfile(str(_)): continue
with open(str(_), 'r') as fp:
file_stream = fp.read()
if re.search(
r'internal static byte[] {1,}= {1,}new byte[d+].*?{([tnd ]+,{0,1}){500,}[nt]+}',
file_stream, re.DOTALL):
self.code = file_stream
self.config_extract()
return
def create_mapping(self):
if re.search(r'public static string [dw]+ = .*?.[dw]+()',self.code):
for _ in re.findall(r'public static string [dw]+ = .*?.[dw]+()',self.code):
_list =re.findall(r'public static string ([dw]+) = .*?.([dw]+)()',_)
self.property_dict1[_list[0][0]] = _list[0][1]
_list.clear()
def config_extract(self):
iter_bytes = re.search(
r'internal static byte[] {1,}= {1,}new byte[d+].*?{([tnd ]+,{0,1}){500,}[nt]+}',
self.code, re.DOTALL).group()
enc_bytes = []
for _ in re.findall(r'[nt ]+(d{1,3})', iter_bytes):
enc_bytes.append(int(_))
xor_key = re.search(r'^ i) ^ (0x[A-Fa-f0-9]{2})u', self.code)
if xor_key:
xor_key = int(re.findall(r'0x([a-fA-F0-9]{2})', xor_key.group())[0], 16)
def decrypt(key, enc_array):
res = []
for index, _ in enumerate(enc_array):
res.append(((_ ^ index) ^ xor_key) & 0xFF)
return res
dec_bytes = decrypt(xor_key, enc_bytes)
for _ in re.findall(
r'public static string ([dw]+)().*?{.*?return .*?.[d+] ?? (d+, (d+), (d+));.*?}',
self.code, re.DOTALL):
self.property_dict[_[0]] = ''.join([chr(c) for c in dec_bytes[int(_[1]): int(_[1]) + int(_[2])]])
for _ in pathlib.Path(self.folder).rglob("*"):
if not os.path.isfile(str(_)): continue
reback_code = deque(maxlen=3)
with open(str(_), 'r') as fp:
for code_line in fp.readlines():
reback_code.append(code_line)
for k, v in self.property_map.items():
if code_line.find(k) >= 0:
v(list(reback_code))
def _extract_Tor_host(self, code_line):
if re.search(r'HttpWebRequest .*? = (HttpWebRequest)WebRequest.Create(.*?)',code_line[-1]):
if re.search(r'string .*? = .*?.[dw]+()',code_line[-2]):
[http_TorProxy_host] = re.findall(r'string .*? = .*?.([dw]+)()',code_line[-2])
self.config["http_TorProxy_host"] = self.property_dict.get(http_TorProxy_host,'')
#邮箱的host完成
def _extract_email_host(self, code_line):
code_line = code_line[-1]
value_data = code_line.split('=')[1]
if re.search(r'.[dw]+()', value_data):
key = re.findall(r'.([dw]+)()', value_data)[0]
if key in self.property_dict:
self.config['EmailHost'] = self.property_dict[key]
elif re.search(r'global::.......',value_data):
key = re.findall(r'global::......(.)', value_data)[0]
self.config['EmailHost'] = self.property_dict[self.property_dict1[key[0]]]
def _extract_Http_host(self,code_line):
if re.search(r'global::........*?, {1,}.*?, {1,}.*?, {1,}.*?.[dw]+(), {1,}.*?, {1,}(NameValueCollection).*?)', code_line[-1]):
[httpHost] = re.findall(
r'global::......(.).*?, {1,}.*?, {1,}.*?, {1,}.*?.[dw]+(), {1,}.*?, {1,}(NameValueCollection).*?)',
code_line[-1])
self.config['httpHost'] = self.property_dict.get(httpHost[0], '')
if re.search(r'.*?(.*?.[dw]+(), {1,}.*?, {1,}.*?, {1,}.*?.[dw]+(), {1,}.*?, {1,}(NameValueCollection).*?)', code_line[-1]):
[httpHost] = re.findall(r'.*?(.*?.([dw]+)(), {1,}.*?, {1,}.*?, {1,}.*?.[dw]+(), {1,}.*?, {1,}(NameValueCollection).*?)', code_line[-1])
self.config['httpHost'] = self.property_dict.get(httpHost, '')
#邮箱和ftp
def _extract_email_u_p(self, code_line):
mode = 'Email'
for _ in code_line:
if _.find("WebRequest.Create") >= 0:
if re.search(r'WebRequest.Create([dw_-]+.[dw]+() + .*?)', code_line[1]):
[FtpHost] =re.findall(r'WebRequest.Create(.*?.([dw]+)() + .*?)', code_line[1])
self.config['FtpHost'] = self.property_dict.get(FtpHost, '')
elif re.search(r'WebRequest.Create(global::....... .*?)', code_line[1]):
key = re.findall(r'WebRequest.Create(global::......(.) .*?)', code_line[1])
FtpHost = self.property_dict1[key[0]]
self.config['FtpHost'] = self.property_dict.get(FtpHost, '')
if _.find("ftp") != -1 and _.find("NetworkCredential") != -1 :
mode = 'Ftp'
break
if re.search(r'NetworkCredential([dw_-]+.[dw]+(), {1,}[dw_-]+.[dw]+())', code_line[2]):
[user, password] =
re.findall(r'NetworkCredential([dw_-]+.([dw]+)(), {1,}[dw_-]+.([dw]+)())', code_line[2])[0]
if user and password and (user in self.property_dict or password in self.property_dict):
self.config[f'{mode}UserName'] = self.property_dict.get(user, '')
self.config[f'{mode}Password'] = self.property_dict.get(password, '')
if re.search(r'NetworkCredential(global::......., global::.......)', code_line[2]):
key = re.findall(r'NetworkCredential(global::......(.), global::......(.))', code_line[2])
self.config[f'{mode}UserName'] = self.property_dict.get(self.property_dict1[key[0][0]], '')
self.config[f'{mode}Password'] = self.property_dict.get(self.property_dict1[key[0][1]], '')
key.clear()
if __name__ == '__main__':
if os.path.exists(".\file"):
shutil.rmtree(".\file")
os.system(".\ilspycmd\ilspycmd.exe -p -o .\file " + input("文件路径: "))
A = AgentTeslaAnalysis(".\file")
A.process()
print(A.config)
原文始发于微信公众号(红队蓝军):AgentTesla分析报告