AgentTesla是一款源自土耳其的间谍软件,自2014年被发现以来一直保持活跃状态,主要通过钓鱼邮件进行传播。通常它被用于获取恶意软件及服务的初始访问权限,并将用户隐私数据上传到C&C服务器。黑客可以利用该恶意软件监视受害者,AgentTesla所窃密软件多达七十多种,是基于 .NET 的键盘记录器、RAT 和窃取程序,可供攻击者使用。它能记录击键和主机剪贴板的内容,提取密码和其他信息,并将其传回C2。
AgentTesla作为第一阶段恶意软件,提供对受感染系统的远程访问,并在随后用于下载更复杂的第二阶段工具,包括但不限于勒索软件。AgentTesla通常通过网络钓鱼进行传播,且使用AutoIt进行混淆,通过使用.NET的混淆技术至少需要3层解密和去混淆才可以看到实际的恶意代码。
该恶意软件通过GuLoader分发钓鱼邮件形式分发并传播恶意邮件,附件包括.zip、.gz、.cab、.msi 和 .img 文件从而破坏受害者系统。
已知使用AgentTesla的团伙包括尼日利亚黑客团伙SWEED。该团伙使用SMTP、HTTP、FTP、Discord和Telegram进行通信,目标国家有美国、中国、德国、菲律宾、伊朗、阿曼和土耳其等欧洲国家。
受害者如下表所示,可以从表中看出该组织喜欢针对互联网公司进行钓鱼:
google.com |
amazon.com |
youtube.com |
linkedin.com |
zoom.us |
mxhichina.com |
yahoo.com |
yandex.ru |
adobe.com |
twitter.com |
qq.com |
spotify.com |
facebook.com |
alibaba.com |
gsis.gr |
live.com |
instagram.android |
mail.ru |
apple.com |
dnert.com |
trendyol.com |
aliexpress.com |
aliyun.com |
expree.dhl |
booking.com |
openai.com |
b2clogin.com |
netflix.com |
gib.gov.tr |
aruba.it |
paypal.com |
microsoftonline.com |
efatura.gov.tr |
github.com |
dropbox.com |
sat.gob.mx |
coinmarket.com |
reddit.com |
.......... |
该组织常用顶级域名如下:
.mx |
.pl |
.tr |
.gr |
.it |
.cn |
.ru |
.ro |
.de |
.es |
前置知识
类似于cctor、ctor这些构造函数在main函数之前执行,他们可能会解压一些东西并将其加载到内存中调用某些东西。所以要检查他们是否会加载一些东西。
创建主窗体是在main函数之前执行的,所以必须检查创建主窗体上的内容。比如检查注册实例等。
base.MainForm = MyProject.Forms.frmEnrollments:
OnCreateMainForm()->frmEnrollments->frmEnrollments->VDObjects.Enrollment()的对象注册中隐藏了恶意代码。这里有一些命名空间类,在其中有多处添加了特殊字符,将这些特殊字符替换为其他字符,并将结果存储在数组中,此数组在执行时成为感染过程的第二阶段,随后进行字符串替换这有助于 Agent Tesla 逃避基于签名的检测。
字符串替换
base.SplashScreen = MyProject.Forms.VandelaySplashScreen:
初始化函数中调用了一个奇奇怪怪的函数A23548,并传入两个参数。但是这两个参数并未被调用,那么这个函数就很可疑。
A6879:
逐字节读取字符集
Load:系统反射程序集的加载方法,当加载任何类型的.net程序集时,load是很好的方法,因为他是动态解码和加载东西,他们将使用基本的系统反射程序集,有很多的方法除了loadfile、loadfromfile等,但是load方法是非常重要的,因为不管什么都不会写入磁盘,也不会从磁盘读取他们,具体解释如下:
在 .NET 程序中,"load 方法"通常指的是加载类、模块、组件或者资源的过程。依赖于具体的上下文,这个方法可能有不同的含义和重要性,这里有几个可能的理解:
加载程序集(Assembly Load):
在 .NET 中,一个程序集(Assembly)是编译后代码的单元,它有可能是一个 DLL 或者 EXE 文件。使用 Assembly 类的 Load 方法可以在运行时加载一个程序集。这在你需要动态加载和卸载代码的时候非常有用,比如插件系统或是运行时的编译执行。
加载资源(Resource Load):
程序运行过程中,可能需要加载各种资源,如图像、本地化字符串、配置文件等。.NET 提供了一系列不同的 Load 方法,例如 ResourceManager 类可以加载和管理资源文件中的资源。
加载窗体或控件:
在 .NET 框架的 WinForms 应用程序中,每个窗体(Form)通常都有一个 Load 事件,它在窗体首次显示前触发。这是初始化窗体数据、设置控制项属性等的绝佳时机。
加载数据:
在许多程序中,需要从数据库或其他数据源加载数据。对于 Entity Framework 这样的 ORM (对象关系映射器)来说,Load 方法用于显式地从数据库中提取数据到本地容器中。
Load 方法或事件通常是关键的,因为它们涉及到资源管理和程序状态的初始化。在编码时,确保正确使用 load 方法对于保证应用程序的运行效率和可靠性都是至关重要的。例如,如果在应用程序启动时加载的资源太多,那么将导致应用程序启动缓慢;如果加载方式不当,还可能导致内存泄漏等问题。正确的 Load 方法使用可以增强程序的模块性,减少内存占用,提高响应速度,从而提供更好的用户体验。
A6546:
Load函数这里遇到了断点不生效的问题,下断点断不下来必须要动态调试才能断下来。这与 JIT(Just-In-Time)编译器的优化有关,它可能导致断点失效。这通常发生在 Release 模式下的优化代码中。在静态调试时,尤其是在没有符号文件的情况下,可能会导致断点失效。
将改pe文件保存下来,是一个叫BeautifulUi的dll文件
dll文件无法直接调试,所以要通过下断点的方式运行
从beautiful.ui中搜索指定参数tf.dr的QV函数
在case 6中进行字符串解密,释放exe:'WJ顾Ic n城nIqMe'
使用de4dot去混淆
因为是cctor类构造函数,因此放一个断点在cctor类中
<Module>.smethod_15();这个方法中创建了一个大数组
往下查找使用数组的地方,method_8:对数组进行解码,并加载到程序集中
解密完成后是一个pe文件
这个pe文件是个dll,除了一堆待解密的资源外还有一个xml文件
xml如下,是一个关于持久化的计划任务配置文件
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2014-10-25T14:27:44.8929027</Date>
<Author>[USERID]</Author>
</RegistrationInfo>
<Triggers>
<LogonTrigger>
<Enabled>true</Enabled>
<UserId>[USERID]</UserId>
</LogonTrigger>
<RegistrationTrigger>
<Enabled>false</Enabled>
</RegistrationTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>[USERID]</UserId>
<LogonType>InteractiveToken</LogonType>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>false</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>[LOCATION]</Command>
</Exec>
</Actions>
</Task>
回来看case 3u:
<Module>.smethod_9();,其中依旧对一个大数组做了解密操作(解密出来是一些字符串)
随后来到main函数
main函数在无限的递归调用函数,使用dnspy自带的函数分析功能快速查看main函数中发生的事情:
挨个查看,当看到method_7的时候发现调用了createprocess、virtualalloc、writeprocessmemory、wow64getthreadcontent函数,猜测这里可能会有创建远程线程注入,前往createprocess查看具体内容
在method_7 createprocess和resumethread(恢复线程)处下断点
createprocess api参数如下:第六个参数是creationflags,为4u,表示挂起线程
CreateProcessA function (processthreadsapi.h) - Win32 apps | Microsoft Learn
processhacker中看到进程成功注入:
method7有三个参数,查看后发现byte_1就是注入的进程,将进程dump下来就得到了最终载荷
payload对变量进行了严重的混淆,且用A、B、C、D、a、b、c、d表示:
将字符串硬编码到数组里,程序开始运行后进行解密。
对每个字符串都进行了编码
检查741A036D-62F0-443C-B9BE-84FFF2F9A684的cctor后发现他在构造类中填充了很多字节,并且在最后会对字符串进行计算
第二个函数global::A.b.A(10, 5);中有个循环,里面多次调用sleep(1000),严重拖慢分析速度。右键编辑类,将sleep(1000)手动改成sleep(0)
使用“https://api.ipify.org"获取受害者IP;将受害者信息发送到"[email protected]"
要窃取的浏览器信息包括:
Coccoc,CentBrowser,Comodo Dragon,Elements Browser,Cool Novo, Chromium, LiebaoBrowser,Yandex Browser,Opera Browser,Sputnik,CentBrowser,Chedot,Kometa,Brave,Coowon,Iridium Browser,Citrio,Sleipnir 6,Epic Privacy, Opera Browser,7Star, Torch Browser,360 Browser,Orbitum,QIP Surf,Uran,Vivaldi,Amigo
收集ftp、vpn、浏览器等信息:
收集的信息如下表:
"C:UsersUSERAppDataRoamingCoreFTPsites.idx" "C:UsersUSERAppDataRoamingComodoIceDragon" C:UsersUSERAppDataLocalNordVPN "C:FTP NavigatorFtplist.txt" "C:UsersUSERAppDataRoamingMoonchild ProductionsPale Moon" "C:UsersUSERAppDataRoamingMozillaFirefox" "C:UsersUSERAppDataRoamingFlockBrowser" "C:UsersUSERAppDataLocalMailbirdStoreStore.db" "C:UsersUSERAppDataRoaming8pecxstudiosCyberfox" "C:UsersUSERAppDataRoamingPostbox" "C:UsersUSERAppDataRoamingApple ComputerPreferenceskeychain.plist" "C:UsersUSERAppDataRoamingeM Clientaccounts.dat" |
通过注册表自启动
AgentTesla使用以下技术反调试:
共有两种方式可以获得字符串明文,动态调试、静态分析,这里直接用静态分析,构造解密脚本进行解密
GameLoop0函数对加密字符串进行了使用空格切割和-312的操作
4.2 解密脚本
整理一下,主要解密流程如下:
1、读取字符串,对字符串进行字符替换;
2、对替换后的字符串进行分割,使用空格作为分隔符,返回一个列表。如:原始字符串是 "abcάdefg",那么经过这段代码处理后,可能得到的列表是 ["abc377", "defg"](假设 "ά" 被替换为 "377 ")。
3、对字符串base64解码
使用python脚本对字符串进行解码 如下图:
解密后的样本就是第一阶段的payload,该payload有混淆,使用de4dot去混淆后(这一步看前面的分析)用CyberChef得到干净的十六进制数据,随后将样本中的字符串进行替换,如果在内存中替换的话,去了混淆后的程序比之前的要小,内存无法完全覆盖,因此可以直接从加载之前的str字符串处下手进行替换:
由于A9283对字符串进行了base64解密操作,因此在解密完成后load的地方对字符串进行替换:
至此,第二层已经干净,导入函数清晰可见:
https://github.com/cybertechniques/site/tree/master/analysis_tools
可以将GameLoop0和A9283的方法从私有转换成公共
rule WindowsAgentTesla {
meta:
threat_name = "Windows.Trojan.AgentTesla"
reference_sample = "0cb3051a80a0515ce715b71fdf64abebfb8c71b9814903cb9abcf16c0403f62b"
severity = 100
arch_context = "x86"
scan_context = "file, memory"
license = "Elastic License v2"
os = "windows"
strings:
$a1 = "MozillaBrowserList"
$a2 = "EnableScreenLogger"
$a3 = "VaultGetItem_WIN7"
$a4 = "PublicIpAddressGrab"
$a5 = "EnableTorPanel"
$a6 = "get_GuidMasterKey"
condition:
4 of them
}
rule Windows_AgentTesla {
meta:
threat_name = "Windows.Trojan.AgentTesla"
reference_sample = "0cb3051a80a0515ce715b71fdf64abebfb8c71b9814903cb9abcf16c0403f62b"
severity = 100
arch_context = "x86"
scan_context = "file, memory"
license = "Elastic License v2"
os = "windows"
strings:
$a1 = { 00 03 08 08 10 08 10 18 09 00 04 08 18 08 10 08 10 18 0E 00 08 }
$a2 = { 00 06 17 5F 16 FE 01 16 FE 01 2A 00 03 30 03 00 B1 00 00 00 }
condition:
all of them
}
fb0db7fe3b3f1c1276b4c9240cb29ca36be79e0f193c001c33ed9784ecf6d079
后台回复:AgentTesla_2024获取相关样本
原文始发于微信公众号(黑伞安全):AgentTesla间谍软件分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论