从时间上来讲,TrickBot恶意软件家族已经存在许多年了,其恶意目的主要集中在窃取受害者的网银信息上面。在最近由FortiGuard Labs捕获的众多恶意软件样本中,我们发现了一个新的TrickBot变种,它携带有一个新的模块——pwgrab,试图从多款浏览器及应用程序中窃取凭证、自动填充数据和历史记录等。我对这个pwgrab模块进行了深入的分析,并将在本文中解释它如何在受害者的系统上工作。
通过打开excel文件下载TrickBot
新的TrickBot变种通过内嵌恶意宏VBS代码的Excel文件(最初的文件名为“Sep_report.xls”)进行传播,代码会在受害者在Microsoft Excel中打开该文件时执行。我们是在2018 年10月19日捕获到这个样本的,图1展示的是在Microsoft Excel中打开的“Sep_report.xls”,它要求受害者通过单击“启用内容(Enable Content)”按钮来启用宏。
图1.在Microsoft Excel中打开的Sep_report.xls
想要查看VBA代码并不容易,因为它受到密码保护。为了分析代码,我手动修改了受保护的flag,以便能够绕过密码保护。
VBA代码以“Workbook_Open”函数开始,该函数会在打开Excel文件时自动调用。然后,它将从文字处理控件(经过编码处理的Powershell代码)读取数据。在图2中,你可以看到解码后的Powershell代码的一部分。
图2.解码的Powershell代码
最后,执行Powershell代码,从“hxxp://excel-office.com/secure.excel” 下载文件,并将其以文件名“pointer.exe”保存到本地临时文件夹中,然后运行它。在这里,你可能已经猜到,这个文件“pointer.exe”实际上就是TrickBot。
Task Schduler启动TrickBot加载pwgrab32
当“pointer.exe”首次运行时,它会创建“%AppData%VsCard”文件夹作为其主文件夹,然后将“pointer.exe”复制到其中,并将其重命名为“pointes.exe”。在我们捕获的样本中,它还更改了其模块文件夹,新的文件夹是“%AppData%VsCardData”,而不是之前的“%AppData%[随机文件夹名称]Modules”。下面的图3展示的就是新文件夹的屏幕截图。
图3.新模块文件夹“Data”的屏幕截图
与之前的版本一样,它将自身安装到系统“Task Scheduler”中,这样它就可以通过“Task Scheduler”来实现自动运行。
在“pointes.exe”运行一段时间之后,它会将带有字符串“pwgrab32”的命令“5”请求发送到C&C服务器,用于下载32位的新模块(即“pwgrab32”,或字符串“pwgrab64”,用于下载64位的新模块)。这就像下载其他模块文件一样,例如“systeminfo32”和“injectdll32”。
想要了解更多有关于命令“5”的数据包格式和用途,你可以参考我过去发布的文章。对于旧版本而言,通过命令“5”下载的所有文件都是采用AES算法加密的,而最近的版本在AES加密数据的基础上增加了一个XOR加密。因此,为了获得原始的pwgrab32模块,我们必须进行双层解密。pwgrab32模块是在2018 年10月16 日生成的,基于Borland Delphi 3.0开发。图4展示的是在PE工具中分析的pwgrab32模块。
图4.在CFF Explorer中分析的解密后的pwgrab32
通过对“pointes.exe”的分析,我发现它使用了一些反分析技术,使得第三方对它得分析变得更加困难。比如,它加密了所有的字符串信息,用于防止静态分析以及在运行期间动态加载API。
其实从“pwgrab32”这个文件命名,我们就大概可以猜出它会从受害者的系统中窃取密码信息。接下来,就让我们来继续看看它将如何做到这一点。
在下载并解密“pwgrab32”之后,“pointes.exe”将继续加载“pwgrab32”。就像加载其他模块一样,它会通过调用API“CreateProcessAsUserW”来创建一个挂起的“svchost.exe”进程。然后,它通过调用API“WriteProcessMemory”,将“pointes.exe”内存中的一段代码注入到此svchost.exe进程内存中。通过调用API“ZwQueryInformationProcess”,“pointes.exe”可以获得“svchost.exe”的ProcessBasicInformation,从中可以在其PE结构中找到“svchost.exe” 的OEP(常见程序入口点)。此外,它还会通过修改OEP中的代码来执行复制的代码段。然后,它将调用“ResumeThread”来恢复“svchost.exe”的运行。图5展示的是查找“svchost.exe”的OEP的代码段。
图5.查找svchost.exe OEP
接下来,API“WriteProcessMemory”、“SignalObjectAndWait”和“WaitForSingleObject”都将会被“pointes.exe”和“svchost.exe”多次调用,用于保持同步,以完成复制解密后的pwgrab32及相关信息。比如,复制从“pointes.exe”到“svchost.exe”的C&C服务器IP列表。最后,“pwgrab32!10006634”(pwgrab32的OEP)将由上面提到的复制的代码段调用。
从这里开始,pwgrab32将负责收集任何与密码相关的数据。
pwgrab32从受害者系统的浏览器中窃取凭凭证
首先,“pwgrab32”将解码“core-parser.dll”模块,并加载到内存中,以备后续使用。在这里,它有几个导出函数,如图6所示。
图6.core-parser.dll导出函数列表
函数“EnumDpostServer“负责返回C&C服务器IP地址。当它想要将数据发送到C&C服务器时,将由”pwgrab32“调用。
它启动了三个线程来从三种不同的浏览器中窃取凭证,它们都具有相同的线程函数,但参数不同。根据我的分析,参数1适用于Internet Explorer,参数2适用于Firefox,参数3适用于Chrome,参数4适用于Edge。但是,在我们捕获的样本中,Edge已经被禁用。
这里还需要提到一个非常庞大的函数“pwgrab32!sub_100137F8”,它负责执行从所有浏览器收集保存的凭证的操作,不同的浏览器对应不同的代码分支。在下文中,我会告诉你它是如何工作的。
在此之前,我想先讲一件我在“pwgrab32”代码中发现的很有意思的事情——它会逐个字节地加密纯文本,但稍后又会将其解密回纯文本,继而使用解密后的纯文本。难道这是Trickbot作者跟我们开的一个笑话吗?不,隐藏纯文本应该是一种反分析技术。但是,我认为在编译这个模块之前,Trickbot作者只是忘记了删除解密函数并将纯文本替换为加密文本,而这个错误在pwgrab32模块中多次出现。图7展示了它的代码片段。
图7.纯文本“IE password”首先被加密,然后又被解密
适用于Internet Explorer的线程参数1
根据Windows系统版本,针对IE有两种不同的代码分支。
如果受害者的系统版本是Windows 2000、Windows XP、Windows Vista、Windows Server 2008、Windows 7、Windows 10或Windows Server 2016,它将从系统注册表子项“HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerIntelliFormsStorage2”中读取和枚举,其中包含已保存网站主机的SHA1散列值列表以及此网站保存的凭证。图8展示的是Windows 7系统上“Storage2”子项的屏幕截图。通过调用API“FindFirstUrlCacheEntryW”和“FindNextUrlCacheEntryW”,此恶意软件可以枚举所有缓存的网站。此外,通过与子项“Storage2”中的散列值进行比较,它可以计算出每个 website host(例如“http://www.fortinet.com/”)的SHA1散列值,从而可以获取到网站的host。然后,它将解析third column数据,以获取网站的凭证。最后,它将以下面这种格式来保存收集的凭证:
“website host |登录ID|登录密码”。
图8. “Storage2”子项的屏幕截图
当受害者的系统是其他版本时,它会通过调用一些额外的API来窃取凭证。以下是窃取凭证这个过程的伪代码。
if ( VaultEnumerateVaults(0, &a4, &a5) )
return 0;
v70 = 0; a2 = 0;
if ( a4 ) { v71 = 0; a3 = 0;
while ( !VaultOpenVault(v71 + a5, 0, &vars0) && !VaultEnumerateItems(vars0, 512, &a1, &retaddr) )
{ v72 = 0;
if ( a1 ) {
v73 = lpCriticalSection;
v74 = a7;
do {
memset(&a65, 0, 0xE08u);
if ( v74 )
v75 = sub_100133F2(v72, &a65);
else
v75 = sub_1001329C(v72, &a65);
if ( v75 ) {
wnsprintfA(&String, 1024, "%S|%S|%Sn", &a66, &a67, &a68);
v76 = sub_1000CBB8(&String);
sub_1000D1AA(v73, &String, v76);
}
++v72;
}
while ( v72 < a1 );
v70 = a2; v71 = a3;
}
VaultFree(retaddr);
VaultCloseVault(vars0);
适用于Mozilla Firefox的线程参数2
此代码线程将从系统注册表读取Firefox的安装路径,然后使用安装路径调用API“SetCurrentDirectoryA”,将当前目录设置为Firefox安装路径,以便它可以轻松读取Firefox的凭证文件并加载一个dll,用于处理Firefox凭证。
“pwgrab32”将继续加载Firefox的nss3.dll,并从其AppData文件夹中读取一些Firefox文件。例如,“%AppData%MozillaFirefoxProfilese375zm7t.defaultlogins.json”。然后,用nss3.dll的API,如“PK11_GetInternalKeySlot”、“PK11_Authenticate”和“PK11SDR_Decrypt”,用于解析“logins.json”文件中保存的凭证“logins.json”。下面是“logins.json”中的一段数据。
{“id”:5,”hostname”:”https://api.twitter.com”,”httpRealm”:null,”formSubmitURL”:”https://api.twitter.com”,”usernameField”:”session[username_or_email]”,”passwordField”:”session[password]”,”encryptedUsername”:”MDoEEcPgbAAAAAA[**hide code**]ZrlGaGjQ”,”encryptedPassword”:”M1Doc8NAwcEiCH[**hide code**]jwG+/I/0+lBje8WVoEska”,”guid”:”{24146e3a-321f-5e81-95d9-ab245208835f}”
最后,它将以在上面提到的适用于IE的线程参数1的格式来保存凭证。
适用于Google Chrome的线程参数3
在创建这个线程函数之前,pwgrab32会对文件“Login Data”和“Web Data”进行两次文件备份。它们都位于“%LocalAppData%GoogleChromeUser DataDefault”文件夹中。据了解,Chrome浏览器将用户的登录凭证存储在文件“Login Data”中,并将用户保存的自动填充和信用卡信息存储在文件“Web Data”种。pwgrab32对两个文件进行备份,是为了可以从备份文件而不是原始文件中读取数据,以避免受害者在使用Chrome浏览器时发生读取冲突。这两个备份文件分别是“Login Data.bak” “和”Web Data.bak“,它们都是SQLite数据库文件。
“pwgrab32”使用了开源项目“SQLite数据库引擎(SQLite database engine)”来处理这两个SQLite文件。在图9中,你可以看到SQLite数据库引擎的数据链接在“pwgrab32”中。
图9. SQLite数据库引擎的代码
接下来,“pwgrab32”将执行一个SQL表达式,如“select origin_url, username_value, password_value, length(d_value) from logins where blacklisted_by_user = 0”,用于从“Login Data.bak”获取凭证。
稍后,“pwgrab32”将继续执行三个SQL表达式,从“Web Data.bak”获取自动填充信息、信用卡信息、电子邮箱地址、国家、公司、街道地址、全名、电话号码等。
SQL表达式从三个本地变量解密:
“SELECT name, value FROM autofill WHERE name<>”cd[Meta]”” AND name<>”cd[OpenGraph]” AND name<>”cd[Schema.org]” AND name<>”cd[DataLayer]” AND name<>”cd[buttonFeatures]” AND name<>”cd[buttonText]” AND name<>”cd[formFeatures]” ORDER BY name; “
“SELECT expiration_month, expiration_year, card_number_encrypted, use_date, origin FROM credit_cards ORDER BY origin;”
“SELECT profiles.origin, profiles.company_name, profiles.street_address, profiles.city, profiles.state, profiles.zipcode, profiles.country_code ,profiles.language_code, emails.email, names.first_name, names.middle_name, names.last_name, names.full_name, phones.number FROM autofill_profiles AS profiles INNER JOIN autofill_profile_emails AS emails ON(profiles.guid = emails.guid) INNER JOIN autofill_profile_names AS names ON(profiles.guid = names.guid) INNER JOIN autofill_profile_phones AS phones ON(profiles.guid = phones.guid); “
在完成对凭证和自动填充信息的窃取之后,这些信息会立即被发送到C&C服务器。
在后面的“凭证上传”章节中,我将讨论数据包的格式以及它们是如何被发送到C&C服务器的。
pwgrab32从某些客户端收集凭证
在上述所有三个线程都完成之后,“pwgrab32”将窃取来自三个客户端软件的凭证:“Outlook”、“FileZilla”和“WinSCP”。在图10中,你可以看到窃取凭证所需调用的函数。
图10.用于从Outlook、FileZilla和WinSCP窃取凭证的函数
“Outlook”的配置文件存储在系统注册表中。根据不同的版本,其注册表路径可能是“HKCUSoftwareMicrosoftWindows NTCurrentVersionWindows Messaging SubsystemProfilesOutlook”、“ HKCUSoftwareMicrosoftOffice15.0OutlookProfilesOutlook ”或“ HKCUSoftwareMicrosoftOffice16.0OutlookProfilesOutlook”。
然后,“pwgrab32”将遍历所有项,读取并解析值,以获取凭证。
图11展示了由“pwgrab32”从我的测试系统中抓取到的Outlook凭证,其格式为“host |帐户名|密码”。
图11. 从Outlook中抓取到的凭证
FileZilla是一种FTP客户端软件,它将其历史记录以纯文本形式存储在文件“%APPDATA%\filezilla\recentservers.xml”中,并将其登录数据以纯文本形式存储在文件“%APPDATA%\filezilla\sitemanager.xml”中。“pwgrab32”可以通过解析这两个XML文件来轻松获取其历史记录和凭证。
WinSCP是另一种FTP客户端软件,它的凭证存储在注册表路径“HKCUSoftwareMartin PrikrylWinSCP 2Sessions”下。“pwgrab32”可以通过枚举所有子项并读出它们的值“HostName”、“PortNumber”、“UserName”、“Password”和“FSProtocol”来获取其凭证。
凭证上传
Trickbot有许多C&C命令。我在过去的文章已经对它们进行过详细的介绍。
然而,在模块“pwgrab32”中,我发现它具有两个新的命令编号:81和83。
l 命令81用于上传从浏览器、FTP客户端和Outlook窃取的凭证;
l 命令83用于上传来自Google浏览器窃取的表单自动填充信息。
它使用HTTP POST方法将纯文本凭证上传给C&C服务器。
POST URI格式如下:
POST /[group tag]/[Client_ID]/[命令编号]/
主体部分是窃取的凭证或纯文本形式的自动填充信息。
其中,“group tag”是“auto1”, Client_ID是用计算机名、Windows版本和随机字符串生成的。
图12展示的是使用命令81上传“chrome密码”。
图13展示的是使用命令83上传“chrome自动填充信息”。
图12.从Chrome窃取的凭证数据
图13.从Chrome窃取的自动填充数据
下面是用于处理凭证数据的C&C服务器的IP列表。IP列表由“pointes.exe”从文件“ dpost”解密,并通过调用API WriteProcessMemory传递给“pwgrab32”。通过调用core-parser.dll 的API EnumDpostServer(fun_index),我们可以通过使用fun_index获取其中的一个IP。
<dpost>
<handler>http://173.171.132.82:8082</handler>
<handler>http://66.181.167.72:8082</handler>
<handler>http://46.146.252.178:8082</handler>
<handler>http://97.88.100.152:8082</handler>
<handler>http://174.105.232.193:8082</handler>
<handler>http://23.142.128.34:80</handler>
<handler>http://177.0.69.68:80</handler>
<handler>http://5.228.72.17:80</handler>
<handler>http://174.105.232.193:80</handler>
<handler>http://177.0.69.68:80</handler>
<handler>http://23.226.138.220:443</handler>
<handler>http://23.226.138.196:443</handler>
<handler>http://23.226.138.221:443</handler>
<handler>http://92.38.135.151:443</handler>
<handler>http://198.23.252.204:443</handler>
</dpost>
如何删除此恶意软件
1)打开Task Scheduler,进入Task Scheduler(Local) -> Task Scheduler Library ;
2)选择名为“Msnetcs”的项,按Delete键,然后单击“Yes”;
3)重新启动系统,并删除“%AppData%VsCard”整个文件夹。
IoC
URL
“hxxp://excel-office.com/secure.excel “
样本SHA256
[Sep_report.xls]
41288C8A4E58078DC2E905C07505E8C317D6CC60E2539BFA4DF5D557E874CDEC
[secure.excel] or [pointer.exe] or [pointes.exe]
D5CADEF60EDD2C4DE115FFD69328921D9438ACD76FB42F3FEC50BDAAB225620D
参考资料
https://www.fortinet.com/blog/threat-research/deep-analysis-of-the-online-banking-botnet-trickbot.html
https://www.fortinet.com/blog/threat-research/new-trickbot-plugin-harvests-email-addresses-from-sql-servers-screenlocker-module-not-for-ransom.html
https://blog.malwarebytes.com/threat-analysis/2017/08/trickbot-comes-with-new-tricks-attacking-outlook-and-browsing-data/
https://www.webroot.com/blog/2018/03/21/trickbot-banking-trojan-adapts-new-module/
https://blog.trendmicro.com/trendlabs-security-intelligence/trickbot-shows-off-new-trick-password-grabber-module/
文章原文链接:https://www.anquanke.com/post/id/163972