【天问】DissCord:以Python软件供应链为入口的Discord窃密攻击分析

Discord是一款专为社群设计的免费网络实时通话软件与数字发行平台,主要针对游戏玩家、教育人士、朋友及商业人士,用户之间可以在软件的聊天频道通过讯息、图片、影片和音讯进行交流。这款软件可以在Microsoft Windows、macOS、Android、iOS、Linux和网页上运行[1]。由于疫情原因,2020年开始Discord成为欧美大量高校的线上教学工具,是目前美国用户增长最迅速的聊天软件。Discord的功能包括但不限于绑定银行卡用于购买会员、订阅以及第三方应用绑定,如steam、jira、paypal等。

2021年12月25日,奇安信技术研究院星图实验室自研的天问软件供应链安全分析平台Python供应链威胁监测模块全网率先捕获到一个以Discord为攻击目标的恶意Python包,并在后续两周陆续监测到10个攻击Discord的包,在发现这些恶意包之后,我们第一时间向PyPI官方反馈并移除了这些恶意包。我们将这一系列针对Discord的窃密攻击命名为DissCord。DissCord系列攻击时间轴如下。

图1:DissCord攻击时间轴

1.首次攻击分析

2021年12月25日,天问Python供应链威胁监测模块捕获到四个可疑包,它们的名字分别是discordgcspammer、discord-py-installer、aquautilitiesmanager、aquautilities。这些包会访问Discord频道的分享链接,下载一个名为pip_manager.exe的PE文件并执行。

在发现这些可疑行为后,我们迅速对这些包进行了分析[2],发现除了执行可疑文件外,这些包还存在窃取用户信息、银行卡信息等恶意行为。包作者在__init__.py 中插入恶意代码,当用户import这些包时会触发恶意行为。

值得一提的是,我们发现这些攻击Discord的恶意包代码均来自开源项目Hazard-Token-Grabber[3],其中替换index.js的相关代码来自该作者的另一个GitHub项目Injection[4]。

攻击者在__init__.py中定义了两个主要攻击函数main和HazardStealer,main函数片段如下所示。

discord_main

图2:main函数中信息窃取

攻击者将图一中窃取到的用户名、邮箱、电话、注册日期、mfa认证状态、银行卡信息保存状态等信息回传到webhook链接,如下所示。

discord_sendback
discord_webhook

图3:信息回传链接

在回传敏感信息之后,包作者通过HazardStealer函数将Discord相关的进程退出,修改启动脚本后重新启动,如下所示。

discord_hazard

图4:修改启动脚本

上图中第一个for循环遍历所有和Discord相关的进程并终止进程。第二个for循环将Discord的启动脚本index.js中的内容替换为新的自定义函数,其重新声明并覆盖了Discord原启动脚本中的函数,如下表所示。第三个for循环重新启动Discord。

函数名作用
FirstTime在用户启动Discord时,将所有缓存移除,这样可尽可能的获取全部用户信息
SendToWebhook将统计到信息回传到图三所示Discord频道
Login替换原有函数,用户登陆时将账号密码回传
ChangePassword替换原有函数,用户修改密码时将账号密码回传
ChangeEmail替换原有函数,用户修改邮箱时将新邮箱地址回传
CreditCardAdded替换原有函数,用户绑定新的信用卡时将信用卡相关信息回传

最后,该恶意包会从攻击者的私有Discord频道下载一个恶意exe文件并执行。经过天穹沙箱分析,发现该exe会通过powershell命令将自身加入Defender的排除列表,禁用计算机中的任务管理器和计算机中的安全工具,避免自己被发现。同时,该exe还会将自己设置为开机启动项,实现攻击持久化。

discord_execute

图5:执行命令行

discord_close

图6:恶意行为

discord_selfgen

图7:启动项修改

2.第二次攻击分析

2022年1月11日,天问Python供应链威胁监测模块再次捕获到一个攻击Discord的包discordproxied,在包上传的第一时间天问平台便捕获到其恶意行为并发出告警。在我们将该包的信息同步给PyPI官方后,官方于1月13日早将该包移除[5]。

攻击者于1月12日上传攻击Discord的包python7,1月15号及1月16号分别再次上传pydeveloper和discord-py-bot,经过分析我们发现这些包和discordproxied攻击手法完全相同,攻击者仅改变其中接收信息所用的webhook。

图8:discordproxied包PyPI界面

不同于第一次攻击的是,上次攻击者将恶意代码直接写在Python文件内,阅读代码可直接了解其攻击手法,并从中发现其代码来源为Rdimo的GitHub项目。此次攻击者在代码中仅留下下载两个可执行文件的指令,并将代码进行多层混淆,使其攻击更具隐蔽性。代码如下所示。

图9:混淆后的恶意代码

通过观察其对于变量名称的定义以及混淆方法的使用,我们发现其代码是通过DevelopmentTools.Net提供的python-obfuscator工具自动生成,对上述代码中的变量进行Unicode编码转换以及解码后得到如下结果。

图10:解码后的恶意代码

在对恶意包下载的package.exe进行分析后,我们得到如下信息。

图11:样本Main函数

package.exe会在Program.HideConsole()方法中使用 user32.dll模块中的ShowWindow函数隐藏窗口。我们分析样本定义的函数,整理其功能如下。

函数名作用
DetectDebug通过Debugger.IsAttached值检测调试器,达到反调试目的
DetectRegistry通过检测注册表中的特定位置键值判断是否处于沙箱运行,达到反沙箱目的
GetIP通过访问https://ip4.seeip.org获取受害机器的出口IP地址
GetIPGeo通过访问http://ip-api.com//json/接口获取用户详细地址信息
Scan定义所有将要遍历的目录
Grab读取用户Discord程序ldb类型敏感隐私文件
StealCookies获取Chrome 浏览器cookies 信息
StealPasswords获取Chrome 浏览器登录密码信息
Roblox获取Roblox 信息

此外,package.exe还包含其他如注册表中获取Windows 产品密钥,通过WMI(Win32_OperatingSystem)获取操作系统信息,通过WMI(Win32_VideoController)获取GPU信息,通过WMI(Win32_PhysicalMemory)获取内存信息,通过注册表获取CPU核心数信息,同时还获取了磁盘信息,屏幕截图,并将上述信息通过webhook回传至Discord频道内。

攻击者甚至还在攻击成功后,在用户电脑上播放了一段Circus音乐,该音乐多被用于马戏团表演中小丑出场,可见该作者的嚣张。

3.第三、四次攻击分析

2022年1月13日11时许,天问Python供应链威胁监测模块再次捕获到一个名为python5的恶意包,系统对该包的包名相似度检测及文件/网络行为检测维度上均发出告警,我们立即对该包进行了深入分析[6],并在确定其为恶意包后迅速将信息同步给了PyPI官方,官方于1月13日21点回复并删除该恶意包,而攻击者则”锲而不舍“,于当日23点再次上传了内容完全一样的恶意包python6。

1月15日,官方回复已经将python6和在第二次攻击中上传的python7一并删除,并将python8-python99这类名字列入禁止上传名单,防止攻击者再次上传。

图12:python5包PyPI界面

图13:python6包PyPI界面

上传这两个包的攻击者与第一次的攻击者使用同一个账号,然而这次他将恶意代码全部进行混淆处理,在对代码进行了反混淆后我们得到了如下结果。

图14:反混淆后的信息

我们对上面两条指令拿到的可执行文件进行了详细分析,结果如下。

3.1.样本1:Windows Defender.exe

来源链接:hxxps://uptime[.]windowstools[.]repl[.]co/controller

原始文件名:loader.exe

Hash: 08225015a1d79f95384af6b14d392912

该样本的主要功能及行为如下:

  1. 获取当前ip及硬件id,并判断当前是否包含钱包方法图15:获取钱包信息
  2. 定位当前位置并回传图16:获取地理位置信息
  3. 通过wmic读取信息图17:通过wmic读取信息
  4. 加密文件、勒索用户图18:勒索信息

3.2.样本2:KrnlBypasswer.exe

来源链接:hxxps://uptime[.]windowstools[.]repl[.]co/logger

原始文件名:Grabber.exe

Hash: 13b070b6c53ec24923e146404ed512fc

该样本经天穹沙箱分析,其行为与前两次Discord攻击方式类似,也会读取用户Discord程序ldb类型敏感隐私文件,如下图所示。

图19:天穹沙箱的Grabber.exe样本分析结果

4.代码相似度分析

4.1.攻击函数

我们将第三次攻击的PE样本反编译之后得到的函数名与第一次攻击包中的函数名进行了对比。经过分析,我们发现解析出来的部分函数名和第一次攻击包中__init__.py的相关函数名完全相同,如下表所示。

第三次攻击函数名是否在第一次攻击中出现
getuserdata
gettokens
gethwid
getip
getavatar
has_payment_methods
HazardStealer
main

此外,我们在反汇编代码中还提取到了Ridmo的Injection-clean项目的Git链接,由此可见,这次攻击者是在第一次攻击的基础上进行了一次修改,并将代码打包成exe。

图20:python5内Injection-clean信息

4.2.信息窃取对象

同时我们发现,尽管在第二次攻击中没有出现同名函数,但是其攻击函数的逻辑与第一次攻击大同小异,且窃取信息遍历的路径也完全相同。在第一次攻击的包源码中我们提取到如下的信息窃取对象路径:

图21:第一次攻击信息窃取对象

在第二次攻击的代码源码中我们提取到如下的信息窃取对象路径:

图22:第二次攻击信息窃取对象

第三次攻击中相关样本经天穹沙箱分析,得到的信息窃取对象路径如下表所示:

信息窃取对象路径
AppData\Roaming\Opera Software\Opera Stable\Local Storage\leveldb
AppData\Roaming\Opera Software\Opera GX Stable\Local Storage\leveldb
AppData\Local\BraveSoftware\Brave-Browser\User Data\Default\Local Storage\leveldb
AppData\Local\Yandex\YandexBrowser\User Data\Default\Local Storage\leveldb
AppData\Local\Microsoft\Edge\User Data\Default\Local Storage\leveldb
AppData\Local\Google\Chrome\User Data\Default\Local Storage\leveldb
AppData\Roaming\discord\Local Storage\leveldb

经过比对我们发现,第一次和第二次攻击者在窃取用户敏感信息时遍历的路径完全相同,第三次攻击则在原有的基础上加上了Microsoft Edge的路径。

5.攻击者关联分析

我们对上述几次以Discord为目标的恶意包及包上传者相关信息进行了梳理,总结如下。

攻击第一次攻击第一次攻击第二次攻击第二次攻击第三次攻击
攻击者账号illusionxDiscordSelfLithium IonLithium DevDiscordself
账号注册时间2021-12-25 15:12:492021-12-25 11:55:372019-11-22 01:16:582022-01-12 07:37:112021-12-25 11:55:37
包名femboydiscordgcspammerdiscordproxiedpython7python5
discordselfdiscord-py-installerpydeveloperpython6
autocondoaquautilitiesmanagerdiscord-py-bot
discordstreamaquautilities

在对这三次攻击进行了详细分析之后,我们认为:

  1. 第一次攻击的两个攻击者账号注册时间相同,且illusionx上传的恶意包discordself为第二个攻击者的账号名称,故此我们推测第一次攻击的两位攻击者为同一人
  2. 第三次攻击的攻击者使用的是第一次攻击者DiscordSelf账号,且他们共同使用ID为921853325899628645的Discord频道号,故此可以排除第一个包的开发者被盗号的可能,第一次和第三次攻击者为同一人
  3. 第二次攻击和第三次攻击的攻击者在代码中都下载了circus.mp3(歌曲时长1:03),这首歌是从一首时长为2:34的歌曲中截取出来,两位攻击者使用的circus.mp3的md5完全相同,且经过搜索我们并没有发现在网上有提供攻击者使用的片段circus.mp3的链接,故此我们推测第二次和第三次的攻击者为同一人
  4. 第二次攻击的攻击者及第三次攻击的攻击者,分别上传恶意包python6、python7,包名的相似性进一步的验证了我们对第二次和第三次的攻击者为同一人的猜测。

因此,我们推测三次攻击应该是同一人持不同账号进行攻击

6.总结

此次我们发现的系列攻击活动,攻击者试图以Python包为恶意代码载体,向相关包的使用者机器植入恶意代码,窃取信息,是一次典型的软件供应链安全攻击。虽然Github开源项目作者Rdimo在主页明确标注”其项目仅做学习用途“,但是通过这几起以Discord为目标的攻击事件,我们发现这些开源项目在向学习者提供便利的同时,也为攻击者提供了直接可用的武器。截止发稿,仍有至少4个Rdimo的项目处于活跃状态,其中包含第一次和第三次攻击使用的攻击代码Hazard-Token-Grabber的更新版本Hazard-Token-Grabber-V2。

此外,此类攻击在文件共享方面使用的是Discord的频道文件共享功能,在信息回传方面使用的全部都是Discord的频道webhooks方式,此类借助高可信网站传播恶意软件、回传被窃信息的方式,容易绕过部分安全防护措施,尤其需要关注。

7.参考文献

  1. Discord – 维基百科,自由的百科全书
  2. 【天问】攻击者瞄准Discord,窃取银行卡信息 [ 星图实验室 ]
  3. GitHub – Rdimo/Hazard-Token-Grabber: A discord token/password grabber thats grabs all of their tokens, passwords, credit card + alot more
  4. Injection/Injection-clean at master · Rdimo/Injection · GitHub
  5. 【天问】Discord攻击再现,多种混淆逃避安全检测 [ 星图实验室 ]
  6. 【天问】python5来了?不,是Discord攻击又来了! [ 星图实验室 ]

8.IOC

md5文件名
00f71a9eb6c801e0cc8ea3fa24ce24a4DiscordGcSpammer-0.0.1.tar.gz
1d81b581c82f54befb8a7fdbd6a6fb72discord-py-installer-0.0.1.tar.gz
a510679b0021c29ffc9fb8f69b154aa4AquaUtilitiesManager-0.0.1.tar.gz
029d821c7ac07e2ae24b27732ce667eaAquaUtilitiesManager-0.0.5.tar.gz
ab920ba8c3a254f6690bb3e1da92bd66discordproxied-0.0.1.tar.gz
7fd4ee275f86db8a0a22e5ce3bf22665pydeveloper-0.0.1.tar.gz
e7a9730983d298b56c8ef8190b377f5adiscord-py-bot-0.0.1.tar.gz
63f5884efb3c2169a80aa4706efd2ddfpython5-0.0.1.tar.gz
09c7b7e7cd4f5e9bb623c69f23f90de8python6-0.0.1.tar.gz
c5f92dac17753bf655b1c20bff9cf5dbpython7-0.0.1.tar.gz
7b9afa29f50bbb4d122ad408823041edpackage.exe
13b070b6c53ec24923e146404ed512fcGrabber.exe
08225015a1d79f95384af6b14d392912loader.exe
bfaa64f1440dd8ca74bdeaddef8b04eeCircus.mp3

========= 我 是 分 割 线 =========================================

星图实验室隶属于奇安信技术研究院,专注于软件与系统安全的核心技术研究与系统平台研发,对外输出“天穹”软件动态分析沙箱、“天问”软件供应链分析平台、“天象”软件漏洞挖掘系统等核心能力和工具系统。

我们目前正在招聘,工作地点覆盖北京、上海、南京、成都等城市,详情请参见:https://research.qianxin.com/recruitment/