RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS

Highlights 突出

  • The Rhadamanthys stealer is a multi-layer malware, sold on the black market, and frequently updated. Recently the author released a new major version, 0.5.0.
    Rhadamanthys 窃取程序是一种多层恶意软件,在黑市上出售,并经常更新。最近,作者发布了一个新的主要版本,0.5.0。
  • In the new version, the malware expands its stealing capabilities and also introduces some general-purpose spying functions.
    在新版本中,该恶意软件扩展了其窃取能力,还引入了一些通用的间谍功能。
  • A new plugin system makes the malware expandable for specific distributor needs.
    新的插件系统使恶意软件可以扩展以满足特定的分销商需求。
  • The custom executable formats, used for modules, are unchanged since our last publication (XS1 and XS2 formats are still in distribution).
    自上次发布以来,用于模块的自定义可执行文件格式没有变化(XS1 和 XS2 格式仍在分发中)。
  • Check Point Research (CPR) provides a comprehensive review of the agent modules, presenting their capabilities and implementation, with a focus on how the stealer components are loaded and how they work.
    Check Point Research (CPR) 对代理模块进行了全面审查,介绍了它们的功能和实现,重点介绍了窃取程序组件的加载方式及其工作方式。

Introduction 介绍

Rhadamanthys is an information stealer with a diverse set of modules and an interesting multilayered design.
Rhadamanthys 是一个信息窃取者,拥有多样化的模块和有趣的多层设计。

In our last article on Rhadamanthys [1], we focused on the custom executable formats used by this malware and their similarity to a different family, Hidden Bee, which is most likely its predecessor.
在我们上一篇关于 Rhadamanthys [ 1] 的文章中,我们重点介绍了该恶意软件使用的自定义可执行文件格式以及它们与另一个家族 Hidden Bee 的相似性,后者很可能是其前身。

In this article we do a deep dive into the functionality and cooperation between the modules. The first part of the article describes the loading chain that is used to retrieve the package with the stealer components. In the second part, we take a closer look at those components, their structure, abilities, and implementation.
在本文中,我们将深入探讨模块之间的功能和协作。本文的第一部分介绍了用于检索包含窃取程序组件的包的加载链。在第二部分中,我们将仔细研究这些组件、它们的结构、功能和实现。

Changes in version 0.5.0
版本 0.5.0 中的更改

Since we published our previous reports [1][2], Rhadamanthys keeps evolving. At the beginning of October, the author announced version 0.5.0 which comes with many changes, and interesting features.
自从我们发表了之前的报告[1][2]以来,Rhadamanthys一直在发展。10 月初,作者宣布了 0.5.0 版本,其中包含许多更改和有趣的功能。

Figure 1 - Telegram message from the author, announcing version
0.5.0.
Figure 1 – Telegram status of the author, announcing version 0.5.0.
图 1 – 作者的电报状态,宣布 0.5.0 版本。

The full list of changes, as described by the author:
完整的更改列表,如作者所述:

Figure 2 - Fragment of the changelog published on the author’s
Telegram channel (full version below).
Figure 2 – Fragment of the changelog published on the author’s Telegram channel (full version below).
图 2 – 在作者的 Telegram 频道上发布的更新日志片段(完整版本如下)。
V0.5.0 Change List V0.5.0 更新列表
01. Added observer mode 01.增加观察者模式
02. Diversify the construction of stubs and provide x86 x32 native Exe Shellcode Dotnet4 Dotnet2 to better adapt to various usage scenarios and crypt service needs.
02. 多样化存根构建,提供 x86 x32 原生 Exe Shellcode Dotnet4 Dotnet2,更好地适应各种使用场景和 crypt 服务需求。
03. The client execution process is completely rewritten, and the BUG in the syscall unhook code that caused the crash in the old version is fixed. The execution success rate is very high, and the runtime status is better.
03. 客户端执行过程完全重写,修复旧版本中syscall解钩代码中导致崩溃的BUG。执行成功率非常高,运行时状态更好。
04. Fixed the wallet upgrade support for several wallets where the cracking algorithm fails. Currently supported
04. 修复了多个钱包破解算法失败的钱包升级支持问题。目前支持
(UniSat Wallet (UniSat 钱包
Tronlink 创联
Trust 信任
Terra Station 泰拉站
TokenPocket 令牌口袋
Phantom 幽灵
Metamask 元掩码
KardiaChain 卡迪亚链
Exodus Desktop 出埃及记桌面版
Exodus Web3 出埃及记 Web3
Binance 币安
) Online real-time brute force cracking
) 在线实时暴力破解
05. Fixed Discord token acquisition, the correct encrypted token can now be decoded.
05. 修复了 Discord 令牌获取的问题,现在可以解码正确的加密令牌。
06. Break through the browser data acquisition when the browser is protected by third-party programs, and add the login data decryption algorithm of 360 Secure Browser
06.突破浏览器受第三方程序保护时浏览器数据采集,增加360安全浏览器登录数据解密算法
07. The panel search condition settings have been upgraded. You can now select conditions in batches and select categories with one click.
07. 面板搜索条件设置已升级。现在,您可以批量选择条件,并一键选择类别。
08. Add a quick setting search filter menu to directly menu the search conditions you need to check frequently.
08.添加快速设置搜索过滤器菜单,直接菜单您需要经常查看的搜索条件。
09. Modify some changes required by users in the Telegram notification module and add new templates for use
09.在Telegram通知模块中修改用户所需的一些更改,并添加新的模板以供使用
10. When building a page, the traffic source tag can directly set the previously used tag, and the URL address will be updated simultaneously.
10、在建页面时,流量来源标签可以直接设置之前使用的标签,URL地址会同步更新。
11. If permissions permit, data collection under other user accounts used on the same machine is supported.
11. 如果权限允许,则支持在同一台计算机上使用的其他用户帐户下收集数据。
12. The file collection module adds browser extension collection settings. For the Chrome kernel browser, you only need to provide the extension directory name and whether to collect Local Storage data at the same time. Firefox kernel browser can provide extension ID
12. 文件收集模块增加了浏览器扩展收集设置。对于 Chrome 内核浏览器,只需要提供扩展目录名称,以及是否同时采集本地存储数据即可。Firefox 内核浏览器可以提供扩展 ID
13. Fix the issue of using the browser to use the online password library after logging in to a Google account in Chrome, and obtaining the login password.
13. 修复在Chrome中登录Google账号后,使用浏览器使用在线密码库,并获取登录密码的问题。
14. The task module has been greatly upgraded, and a new plug-in module has been introduced to support users in secondary development of their own plug-ins.
14、任务模块大幅升级,新增插件模块,支持用户二次开发自己的插件。
Supports multiple task execution modes:
支持多种任务执行模式:
Normal execution 正常执行
In Memory LoadPE Execution
内存中 LoadPE 执行
Powershell Execution Powershell 执行
DotNet Reflection Execution
DotNet 反射执行
DotNet Extension Execution
DotNet 扩展执行
DotNet Extension with Zip Execution
具有 Zip 执行功能的 DotNet 扩展
VbScript Execution VbScript 执行
JScript Execution JScript 执行
X86 shellcode execution X86 shellcode 执行
X64 shellcode execution X64 shellcode 执行
Native Plugin Loader 原生插件加载器
15. Keylogger: supports recording all keyboard input, process details, file name, window title, supports setting process filtering, sending time, buffer size
15.键盘记录器:支持记录所有键盘输入、进程详细信息、文件名、窗口标题,支持设置进程过滤、发送时间、缓冲区大小
16. Data spy plug-in: currently supports correct login access and IP username and password for remote RDP access. The correct certificate file and password imported by the user.
16.数据间谍插件:目前支持正确的登录访问和IP用户名和密码进行远程RDP访问。用户导入的正确证书文件和密码。
17. Plug-ins and loader modules support secondary development and provide SDK support.
17. 插件和加载器模块支持二次开发,提供SDK支持。

In this blog, we present a walkthrough a sample that belongs to this release.
在此博客中,我们将演示属于此版本的示例的演练。

The initial loader 初始加载程序

The initial loader is a 32-bit Windows executable (PE). It was in large part rewritten, but still contains artifacts that make it similar to the previous edition (0.4.9).
初始加载程序是 32 位 Windows 可执行文件 (PE)。它在很大程度上被重写了,但仍然包含使其与上一版本(0.4.9)相似的工件。

The author added a check of the executable’s name. When the samples are uploaded to sandboxes for automated analysis, they are often renamed as hashes. Therefore, if the name consists of characters from a hexadeciamal charset [0-9, a-f, A-F], and its length is 16, 32, 40, or 64, the malware assumes that it is being analyzed, and exits immediately.
作者添加了对可执行文件名称的检查。当样本上传到沙盒进行自动分析时,它们通常会重命名为哈希。因此,如果名称由十六进制字符集 [0-9, a-f, A-F] 中的字符组成,并且其长度为 16、32、40 或 64,则恶意软件会假定它正在被分析,并立即退出。

Similarly as we saw in the earlier releases, the initial executable contains the configuration (embedded by the builder) as well as the package with additional modules, that constitutes the next stage. As the execution progresses, these later components are unpacked, and the configuration is passed to them.
同样,正如我们在早期版本中看到的那样,初始可执行文件包含配置(由构建器嵌入)以及包含附加模块的包,这些模块构成了下一阶段。随着执行的进行,这些后续组件将被解压缩,并将配置传递给它们。

Figure 3 - Overview of the relationship between the components used
at this stage.
Figure 3 – Overview of the relationship between the components used at this stage.
图 3 – 此阶段使用的组件之间关系的概述。

The first change that we can observe during the initial triage is a new section: .textbss. This section is empty in the raw binary (raw size = 0). However, will be filled at runtime with an unpacked content: a shellcode similar to the one used by the previous versions. The difference is that in the past versions the analogous code was loaded into a newly allocated memory region. Regardless of location, its role didn’t change: it is meant for unpacking and loading the first module from the package.
在初始分类过程中,我们可以观察到的第一个变化是一个新部分: .textbss .此部分在原始二进制文件中为空(原始大小 = 0)。但是,将在运行时填充解压缩的内容:类似于以前版本使用的 shellcode。不同之处在于,在过去的版本中,类似的代码被加载到新分配的内存区域中。无论位置如何,它的作用都没有改变:它旨在从包装中解包和加载第一个模块。

Below is a fragment of the tracelog (created with TinyTracer) that illustrates the loading of the shellcode, and the calls executed from it (v.0.5.0):
下面是跟踪日志(使用 TinyTracer 创建)的片段,它说明了 shellcode 的加载以及从中执行的调用 (v.0.5.0):

1e91;kernel32.WaitForSingleObject
1e91;内核32.WaitForSingleObject
1e99;kernel32.CloseHandle
1e99;内核32.关闭句柄
1eb7;[.text] -> [.textbss] ; <- redirection to the code that unpacks the XS module
1EB7;[.文本] -> [.文本bss] ;<- 重定向到解压缩 XS 模块的代码
27000;section: [.textbss]**
27000;部分:[.textbss]**
27311;kernel32.VirtualAlloc
27311;内核32.虚拟Alloc
270c1;kernel32.VirtualAlloc
270C1;内核32.虚拟Alloc
2726d;kernel32.VirtualFree
2726d;内核32.虚拟免费
27363;kernel32.VirtualAlloc
27363;内核32.虚拟Alloc
273bd;kernel32.VirtualProtect
273BD;内核32.虚拟保护
273f0;kernel32.VirtualFree
273F0;内核32.虚拟免费
27052;called: ?? [12081000+8a] ; <- redirection to the new module (XS)
27052;叫:??[12081000+8一] ;< – 重定向到新模块 (XS)

For comparison, this is the corresponding tracelog fragment from version 0.4.9:
为了进行比较,以下是版本 0.4.9 中的相应跟踪日志片段:

18b3a;kernel32.HeapFree 18b3a;内核32.堆免费
18b43;kernel32.HeapDestroy
18b43;内核32.堆销毁
184dc;ntdll.ZwProtectVirtualMemory
184直流;ntdll的。ZwProtectVirtualMemory
184e6;called: ?? [a7a0000+0] <- redirection to the shellcode that unpacks the XS module
184e6;叫:??[a7a0000+0] <- 重定向到解压缩 XS 模块的 shellcode
> a7a0000+2fe;kernel32.LocalAlloc
> A7A0000+2Fe;内核32.本地Alloc
> a7a0000+ba;kernel32.LocalAlloc
>A7A0000+BA;内核32.本地Alloc
> a7a0000+260;kernel32.LocalFree
>A7A0000+260;内核32.本地免费
> a7a0000+34c;kernel32.VirtualAlloc
>A7A0000+34C;内核32.虚拟Alloc
> a7a0000+3a4;kernel32.VirtualProtect
>A7A0000+3A4;内核32.虚拟保护
> a7a0000+3bb;kernel32.LocalFree
> A7A0000+3BB;内核32.本地免费
> a7a0000+52;called: ?? [10641000+88] <- redirection to the new module (XS)
> A7A0000+52;叫:??[10641000+88] <- 重定向到新模块 (XS)

The next stage, as before, is in a custom executable format. The format itself hasn’t changed since the release of 0.4.9. Once more we are dealing with XS1 (as described in our article [1]) which can be converted into a PE with the help of our tools.
与以前一样,下一阶段采用自定义可执行文件格式。自 0.4.9 发布以来,格式本身没有改变。再一次,我们正在处理 XS1(如我们的文章 [ 1] 中所述),它可以借助我们的工具转换为 PE。

The 2nd stage loader (XS1)
第二级装载机(XS1)

The component revealed (in the XS1 format) is part of the second stage of the loading process. Looking at this module we can see many similarities to the one described in [1]. Yet, clearly some parts are enhanced and improved.
显示的组件(XS1格式)是加载过程第二阶段的一部分。查看此模块,我们可以看到与 [ 1] 中描述的模块有许多相似之处。然而,显然有些部分得到了增强和改进。

One of the changes shows up in the initial triage, at the attempt to dump strings from the binary. In the past, we could obtain a lot of hints about the module functionality by dumping the strings i.e. with the help of the Flare FLOSS tool. This is no longer possible as the author decided to obfuscate them (more details in “String deobfuscation and the use of TLS”).
其中一项更改显示在初始分类中,即尝试从二进制文件中转储字符串时。过去,我们可以通过转储字符串来获得很多关于模块功能的提示,即借助 Flare FLOSS 工具。这不再可能,因为作者决定对它们进行混淆(更多细节在“字符串反混淆和TLS的使用”中)。

After converting the module to PE, and opening it in IDA, we can follow up with a more detailed assessment. Looking at the outline of the start function, we see a slightly different, refined design.
将模块转换为 PE 并在 IDA 中打开后,我们可以进行更详细的评估。从启动功能的轮廓来看,我们看到了一个略有不同的精致设计。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 4 – The main_func is now passed as a callback to the function that initializes the XS module (loads imports, allocates storage, etc)
图 4 – main_func现在作为回调传递给初始化 XS 模块(加载、导入、分配存储等)的函数

As before, the module uses the configuration passed from the previous layer. The decoded buffer starts with the !RHY marker, and contains, among others, the URL of the C2 to be contacted. This is the reconstructed structure:
和以前一样,该模块使用从上一层传递的配置。解码缓冲区从 !RHY 标记开始,其中包含要联系的 C2 的 URL。这是重建的结构:

struct rhy_config
{
DWORD magic; DWORD 魔术;
BYTE flags1; BYTE 标志 1;
DWORD flags2; DWORD 标志 2;
_BYTE iv[16];
_BYTE key[32]; _BYTE键[32];
char C2_URL[128]; 查尔C2_URL[128];
};

Just like in the previous version, the connection with the C2 is established by the netclient module which is loaded from package #1 (see Figure 3).
就像在以前的版本中一样,与 C2 的连接是由从包 #1 加载的模块建立的 netclient (参见图 3)。

In addition, the current component unpacks and uses multiple modules that are shipped in package #1. We already saw some of them in the previously described versions. The full list is below.
此外,当前组件解压缩并使用包 #1 中附带的多个模块。我们已经在前面描述的版本中看到了其中的一些。完整列表如下。

Name 名字 Format 格式 Description 描述 New in 0.5.0? 0.5.0 中的新功能?
stage.x86 阶段.x86 shellcode (32-bit) shellcode(32 位) Shellcode used in the injection of the main module of the Stage 2 into another process; responsible for accessing the named mapping, copying its content, and reloading the main module in the context of the new process
Shellcode用于将Stage 2的主模块注入另一个进程;负责访问命名映射、复制其内容以及在新进程的上下文中重新加载主模块
early.x86 早期.x86 XS Process injector (using raw syscalls)
进程注入器(使用原始系统调用)
early.x64 早期.x64 XS Process injector (using raw syscalls)
进程注入器(使用原始系统调用)
phexec.bin XS Injects from a 32-bit process into a 64-bit
从 32 位进程注入 64 位进程
prepare.bin 准备.bin shellcode (64-bit) shellcode(64 位)
unhook.bin XS Checks DLLs against hooks, and does unhooking if needed
根据挂钩检查 DLL,并在需要时取消挂钩
strategy.x86 策略.x86 XS Checks if any of the forbidden processes is running (evasion)
检查是否有任何禁止的进程正在运行(规避)
process.x 进程.x TXT List of forbidden processes (evasion)
禁止的进程列表(规避)
ua.txt TXT A list of user-agents (a random user-agent from the list will be selected and used for the internet connection)
用户代理列表(将从列表中随机选择一个用户代理并用于互联网连接)
dt.x86 XS Evasion checks based on Al-Khaser
基于 Al-Khaser 的规避检查
proto.x86 proto.x86的 shellcode 外壳代码 Encrypts and decrypts netclient module with the help of RC4 and a random key
在 RC4 和随机密钥的帮助下加密和解密 netclient 模块
netclient.x86 XS Responsible for the connection with the C2 and downloading of further modules
负责与 C2 的连接和下载其他模块

A simplified flow: 简化流程:

Figure 5 - A high-level overview of the relationships between the
components at this stage.
Figure 5 – A high-level overview of the relationships between the components at this stage.
图 5 – 此阶段组件之间关系的高级概述。

More details about the execution flow, and possible diversions from the presented path, are explained later in this report.
本报告稍后将介绍有关执行流程的更多详细信息,以及可能从所呈现路径进行的转移。

String deobfuscation and the use of TLS
字符串反混淆和 TLS 的使用

One of the new features in this release is the introduction of TLS (Thread Local Storage) for temporary buffers. They are used, among others, for decoding obfuscated strings.
此版本中的新功能之一是为临时缓冲区引入了 TLS(线程本地存储)。除其他外,它们还用于解码混淆字符串。

TLS is first allocated in the initialization function (denoted as init_xs_module in Figure 4). The value received from TlsAlloc is stored in a global variable. The malware then allocates a custom structure with a buffer and attaches it to the TLS.
TLS 首先在初始化函数中分配(如图 4 所示 init_xs_module )。接收到 TlsAlloc 的值存储在全局变量中。然后,恶意软件会分配带有缓冲区的自定义结构,并将其附加到 TLS。

Later on, that saved buffer is retrieved and used multiple times, as a workspace for deobfuscating data, such as strings.
稍后,将检索并多次使用保存的缓冲区,作为对数据(如字符串)进行反混淆的工作区。

Figure 6 - The string decoding function is applied on a hardcoded
value (pointing to the encrypted string).
Figure 6 – The string deobfuscation function is applied on a hardcoded value (pointing to the encrypted string).
图 6 – 字符串反混淆功能应用于硬编码值(指向加密字符串)。

The string decryption function is passed as a callback to the function retrieving a buffer attached to the TLS storage.
字符串解密函数作为回调传递给检索附加到 TLS 存储的缓冲区的函数。

Figure 7 - The string decryption function is set as a callback to the
function fetching the buffer from TLS.
Figure 7 – The string decryption function is set as a callback to the function fetching the buffer from TLS.
图 7 – 字符串解密函数设置为从 TLS 获取缓冲区的函数的回调。

After the string is used, the buffer is cleared (see Figure 6).
使用字符串后,缓冲区被清除(参见图 6)。

The use of TLS in the implementation of this functionality is quite atypical, and it isn’t clear what was the reason behind this design.
在实现此功能时使用 TLS 是相当不典型的,目前尚不清楚此设计背后的原因是什么。

The algorithms used for the string deobfuscation differ at different stages of the malware. In the case of the current module (XS1, Stage 2) the following algorithm is deployed:
用于字符串反混淆的算法在恶意软件的不同阶段有所不同。对于当前模块(XS1,第 2 阶段),将部署以下算法:

#!/usr/bin/env python3 #!/usr/bin/env python3
def mix_key_round(ctx, size, key3, key2, key_size):
def mix_key_round(ctx、大小、key3、key2、key_size):
if not size: return
如果不是大小:返回
for i in range(size):
对于 Range(Size) 中的 i:
pos = key_size % size
pos = key_size % 大小
key_size += 87
val = ctx[pos]
val = ctx[位置]
result = (key2 + ((val >> 5) & 0xFF)) + ctx[(val % size)] + (i * (((val + key3) >> 3) & 0xFF)) + 1
结果 = (key2 + ((val >> 5) & 0xFF)) + ctx[(val % 大小)] + (i * (((val + key3) >> 3) & 0xFF)) + 1
ctx[i] = (ctx[i] + result) & 0xFF
ctx[i] = (ctx[i] + 结果) & 0xFF
return ctx
返回 CTX
def decrypt_data(in_buf, in_size, key_buf, key_size, key2, key3):
def decrypt_data(in_buf, in_size, key_buf, key_size, key2, key3):
out_buf = [0] * in_size
ctx = [key_buf[(i % key_size)] for i in range(in_size)]
ctx = [key_buf[(i % key_size)] for i in range(in_size)]
for _ in range(4):
对于 range(4) 中的 _:
ctx = mix_key_round(ctx, in_size, key3, key2, key_size)
ctx = mix_key_round(ctx, in_size, key3, key2, key_size)
for i in range(in_size):
对于 Range(in_size) 中的 i:
out_buf[i] = (ctx[i] ^ in_buf[i]) & 0xFF
out_buf[i] = (ctx[i] ^ in_buf[i]) & 0xFF
return out_buf
返回out_buf
def decrypt_string(in_buf, key_buf):
def decrypt_string(in_buf, key_buf):
return decrypt_data(in_buf, len(in_buf), key_buf, 16, 0x3779E9B, 0)
返回 decrypt_data(in_buf, Len(in_buf), key_buf, 16, 0x3779E9B, 0)

The decryption key is stored at the beginning of the block and is always 16 bytes long. The data is terminated by 0.
解密密钥存储在块的开头,长度始终为 16 个字节。数据以 0 终止。

The IDA script for strings deobfuscation (assuming that the decrypting functions are named, appropriately: dec_cstring and dec_wstring):
用于字符串反混淆的 IDA 脚本(假设解密函数已命名,适当地: dec_cstring 和 dec_wstring ):

https://gist.github.com/hasherezade/c7701821784c436d40d1442c1a623614

The list of the deobfuscated strings for the Stage 2 loader:
第 2 阶段加载程序的反混淆字符串列表:

https://gist.github.com/hasherezade/fb91598f6de62bdecf06edf9606a54fb

Raw syscalls and Heaven’s Gate
原始系统调用和天堂之门

One of the techniques that we can observe across different Rhadamanthys modules is the use of raw syscalls for calling native API. This is a known way to evade function hooking and monitoring, and also helpful in obfuscating the names of the APIs used. This technique has a long history and occurs in multiple different variants (described, i.e. here: [3]).
我们可以在不同的 Rhadamanthys 模块中观察到的技术之一是使用原始系统调用来调用本机 API。这是规避函数挂钩和监视的已知方法,也有助于混淆所用 API 的名称。这种技术有着悠久的历史,并且以多种不同的变体出现(已描述,即此处:[ 3])。

The method relies on the fact that each native system function (implemented kernel-mode) is represented by a syscall ID. These IDs may differ depending on the Windows version. For the programmer’s convenience, Windows allows access to them via API exported by system DLLs such as NTDLL and WIN32U. NTDLL is often hooked by antimalware products, in order to watch the called APIs and detect suspicious activity.
该方法依赖于以下事实:每个本机系统函数(实现的内核模式)都由系统调用 ID 表示。这些 ID 可能因 Windows 版本而异。为了方便程序员,Windows 允许通过系统 DLL(如 NTDLL 和 WIN32U)导出的 API 访问它们。NTDLL经常被反恶意软件产品所吸引,以便监视被调用的API并检测可疑活动。

Malware tries to bypass the installed hooks by copying the numbers of syscalls directly to its own stubs, so that it won’t have to use the NTDLL. However, doing so generates another event that some monitoring tools may find suspicious, as it’s not usual to execute a syscall from a non-system module.
恶意软件试图通过将系统调用的数量直接复制到自己的存根来绕过已安装的挂钩,这样它就不必使用 NTDLL。但是,这样做会生成另一个事件,某些监视工具可能会发现该事件可疑,因为通常不会从非系统模块执行系统调用。

Looking at the implementation, we can see that the author was well aware of this problem and used a variant of the technique called indirect syscalls. The stub within the malware only prepares the syscall and its actual execution is done by returning to the NTDLL at the end of a function. In this way, the initial part of the function that contains the hook is bypassed, but the syscall is called from the NTDLL.
从实现中可以看出,作者很清楚这个问题,并使用了一种称为间接系统调用的技术变体。恶意软件中的存根仅准备系统调用,其实际执行是通过在函数结束时返回到 NTDLL 来完成的。这样,将绕过包含挂钩的函数的初始部分,但从 NTDLL 调用系统调用。

Figure 8 - Implementation of indirect syscalls used by
Rhadamanthys.
Figure 8 – Implementation of indirect syscalls used by Rhadamanthys.
图 8 – Rhadamanthys 使用的间接系统调用的实现。

The raw syscalls are used by Rhadamanthys in both 32 and 64-bit modules. As we know, a syscall can be performed only from a module that has the same bitness as the operating system. Doing a syscall from the WoW64 process (32-bit process on 64-bit Windows) requires a different approach, and using wrappers that may be different for different versions of Windows [4]. Underneath, each of those wrappers temporarily switch the process from 32-bit to 64-bit mode. The author of Rhadamanthys decided not to use existing wrappers, but instead implement his own, using the Heaven’s Gate [6] technique.
原始系统调用由 Rhadamanthys 在 32 位和 64 位模块中使用。众所周知,系统调用只能从与操作系统具有相同位数的模块执行。从 WoW64 进程(64 位 Windows 上的 32 位进程)执行系统调用需要不同的方法,并且使用不同版本的 Windows 可能不同的包装器 [ 4]。在下面,每个包装器都会暂时将进程从 32 位模式切换到 64 位模式。《Rhadamanthys》的作者决定不使用现有的包装器,而是使用天堂之门[6]技术来实现自己的包装器。

Execution flow 执行流程

The role of the modules involved in the Stage 2 hasn’t changed since the last version. They are meant to prepare and obfuscate the downloading of the actual stealers that are shipped in package #2 supplied by the C2. As we know, the download operation is performed by the netclient module. The author used several other modules to scrupulously check the environment and make it harder for an analyst or various monitoring tools to track when the download occurs.
自上一版本以来,第 2 阶段中涉及的模块的角色没有改变。它们旨在准备和混淆 C2 提供的软件包 #2 中附带的实际窃取程序的下载。众所周知,下载操作是由模块执行的 netclient 。作者使用其他几个模块来仔细检查环境,并使分析师或各种监控工具更难跟踪下载何时发生。

Depending on the settings, it is possible to load next modules into the current process, or to add an extra round by injecting the current module into a new process, and deleting the original file.
根据设置,可以将下一个模块加载到当前进程中,或者通过将当前模块注入新进程并删除原始文件来添加额外的轮次。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 9 – Overview of the main function. Different execution paths can be deployed depending on the flags set in the configuration. If the restart flag is set, on the first run the module injects itself into a new process.
图 9 – main 功能概述。根据配置中设置的标志,可以部署不同的执行路径。如果设置了重新启动标志,则在第一次运行时,模块会将自身注入到新进程中。

In the case of the analyzed sample, the restart flag was selected. This caused the main loader module to run twice, with two different paths of execution.
对于分析的样品,选择了重新启动标志。这导致主加载器模块运行两次,具有两个不同的执行路径。

On the first run, the malware injects itself into a newly created process. It is implemented in the following steps:
在第一次运行时,恶意软件会将自身注入到新创建的进程中。它通过以下步骤实现:

  1. Creates a named mapping where it places important data, such as encrypted config, the package containing later modules, the path to the original sample, checksums of functions to be used, etc.
    创建一个命名映射,用于放置重要数据,例如加密配置、包含更高模块的包、原始示例的路径、要使用的函数的校验和等。
  2. Unpacks modules implementing the process injection, 32 or 64-bit, depending on the system. These modules export several helper functions that are implemented using raw syscalls (for more about the method used see “Raw syscalls and Heaven’s Gate”). In the currently analyzed sample, the modules were named early.x86 and early.x64 . They may be different depending on the build, as since 0.5.0 distributors can customize what injection method will be used.
    解压缩实现过程注入的模块,32 位或 64 位,具体取决于系统。这些模块导出使用原始系统调用实现的多个帮助程序函数(有关所用方法的详细信息,请参阅“原始系统调用和天堂之门”)。在当前分析的样本中,模块被命名为 early.x86 和 early.x64 。它们可能因构建而异,因为从 0.5.0 开始,分发商可以自定义将使用的注入方法。
  3. The loader creates a new 32-bit process, and implants there the stage.x86 with the help of functions exported from the injector component.
    加载器创建一个新的 32 位进程,并借助从注入器组件导出的函数植入该 stage.x86 进程。
  4. The implanted shellcode is responsible for accessing the named mapping, copying its content, and reloading the Stage 2 module in the context of the new process. It then calls an alternative variant of the Stage 2 main function (main_alt in the XS1 structure [1]), to deploy the second execution path.
    植入的 shellcode 负责访问命名映射、复制其内容以及在新进程的上下文中重新加载 Stage 2 模块。然后,它调用阶段 2 main 函数的替代变体( main_alt 在 XS1 结构 [ 1] 中),以部署第二个执行路径。

The target for the injection is selected from a hardcoded list, and can be one of the following:
注入的目标从硬编码列表中选择,可以是以下目标之一:

L“%Systemroot%\\system32\\dialer.exe”
L“%系统根%\\system32\\dialer.exe”
L“%Systemroot%\\system32\\openwith.exe”
L“%系统根%\\system32\\openwith.exe”
L“%Systemroot%\\system32\\dllhost.exe”
L“%系统根%\\system32\\dllhost.exe”
L“%Systemroot%\\system32\\rundll32.exe”
L“%系统根%\\system32\\rundll32.exe”

The execution second path is deployed when the module runs inside the new process. It involves deleting the original malware file (if the relevant flag was selected in the configuration) and loading the other modules from package #1, including netclient.
当模块在新进程内运行时,将部署执行第二条路径。它涉及删除原始恶意软件文件(如果在配置中选择了相关标志)并从软件包 #1 中加载其他模块,包括 netclient .

Figure 10 - The alternative version of the main function (main_alt),
called from the injected process.
Figure 10 – The alternative version of the main function (main_alt), called from the injected process.
图 10 – main 函数 (main_alt) 的替代版本,从注入进程调用。

After performing the evasion checks, and making sure that the process is not monitored (with the help of additional modules), the malware connects to the C2 and downloads the next package (package #2 – Figure 5) with the stealer modules. Just like in the previous version, the package is shipped in a steganographic way, appended to the JPG or WAV file (for more details, refer to [1]).
在执行规避检查并确保该过程未受到监控(借助其他模块)后,恶意软件连接到 C2 并使用窃取程序模块下载下一个包(包 #2 – 图 5)。就像在以前的版本中一样,该软件包以隐写方式提供,附加到 JPG 或 WAV 文件中(有关详细信息,请参阅 [ 1])。

Retrieving Stage 3: stealer components
检索第 3 阶段:窃取组件

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 11 – Execution flow of the modules
图 11 – 模块的执行流程

Two modules are involved in downloading the payload: netclient (in XS1 format) and proto (shellcode). They are both loaded into the same memory region, and proto is copied after the netclient. First netclient is called from the main module, with the appropriate parameters: the address of the C2 copied from the configuration, and the User Agent, selected from the ua.txt list (if the list fails to load, a hardcoded User Agent is used as a backup).
下载有效负载涉及两个模块: netclient (XS1 格式)和 proto (shellcode)。它们都加载到同一个内存区域中,并在 proto netclient .首先 netclient 从主模块调用,并带有适当的参数:从配置中复制的 C2 地址,以及从 ua.txt 列表中选择的用户代理(如果列表加载失败,则使用硬编码的用户代理作为备份)。

Figure 12 - The Entry Point of the netclient module is called in the
Event callback function
Figure 12 – The Entry Point of the netclient module is called in the Event callback function
图12 – netclient模块的入口点在事件回调函数中调用

The interesting element of the flow is that at the beginning of the netclient execution, the main XS1 component gets encrypted. It is decrypted later, just before the execution returns to it. The encryption and decryption are done with the help of the proto module, which is called twice by netclient. This is yet another obfuscation step to minimize the memory artifacts.
该流程的有趣元素是,在 netclient 执行开始时,主 XS1 组件会被加密。稍后,就在执行返回之前,它被解密。加密和解密是在模块的帮助下完成的, proto 该模块由 netclient 调用两次。这是另一个混淆步骤,以最大程度地减少内存伪影。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 13 – If we try to view the code of the main module, i.e. go to the offset that called netclient, we can see that it no longer makes sense – as it was encrypted.
图 13 – 如果我们尝试查看主模块的代码,即转到调用 netclient 的偏移量,我们可以看到它不再有意义——因为它是加密的。

The netclient is responsible for connecting to the C2 and downloading the payload, then decrypting it. As before ([1]) the correctness of the resulting buffer is verified by comparing the hash calculated from the content with the expected hash that is stored in the header of the data block. In the currently analyzed case, the payload was shipped appended to a file in the WAV format.
负责 netclient 连接到 C2 并下载有效负载,然后对其进行解密。与之前 ([ 1]) 一样,通过将从内容计算出的哈希值与存储在数据块标头中的预期哈希值进行比较来验证结果缓冲区的正确性。在当前分析的案例中,有效负载被附加到 WAV 格式的文件中。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 14 – The downloaded package after decryption
图14 – 解密后下载的软件包

After the payload is downloaded, and passes the verification step, netclient module calls proto for the second time to decrypt the previously encrypted main module (XS1), using the RC4 algorithm and the key that was generated and saved at the first run.
下载有效负载并通过验证步骤后, netclient 模块会使用 RC4 算法和首次运行时生成并保存的密钥,第二次调用 proto 解密先前加密的主模块 (XS1)。

The execution goes back to the (now decrypted) main module, which first destroys the memory region where netclient and proto were loaded. It then proceeds to load the next stage from the downloaded package #2.
执行返回到(现已解密)主模块,该模块首先销毁加载和 netclient proto 加载的内存区域。然后,它继续从下载的包 #2 加载下一阶段。

Depending on whether the system is 32 or 64-bit, further execution may proceed in the current process, or in a newly created, 64-bit process, where the required elements are injected.
根据系统是 32 位还是 64 位,可以在当前进程中或在新创建的 64 位进程中继续执行,其中注入了所需的元素。

On a 64-bit system
在 64 位系统上

Most of the time we encounter a 64-bit version of Windows, which means there are several extra steps before the content from the downloaded package can be fetched and executed.
大多数情况下,我们遇到的是 64 位版本的 Windows,这意味着在获取和执行下载的包中的内容之前,还需要执行几个额外的步骤。

The malware creates a new, 64-bit process, selecting one of the paths from the hardcoded list:
恶意软件会创建一个新的 64 位进程,从硬编码列表中选择以下路径之一:

L“%Systemroot%\\system32\\credwiz.exe”
L“%系统根%\\system32\\credwiz.exe”
L“%Systemroot%\\system32\\OOBE-Maintenance.exe”
L“%系统根%\\system32\\OOBE-维护.exe”
L“%Systemroot%\\system32\\openwith.exe”
L“%系统根%\\system32\\openwith.exe”
L“%Systemroot%\\system32\\dllhost.exe”
L“%系统根%\\system32\\dllhost.exe”
L“%Systemroot%\\system32\\rundll32.exe”
L“%系统根%\\system32\\rundll32.exe”

As writing into a 64-bit process from a 32-bit one is not officially supported by the Windows API, it uses Heaven’s Gate technique [6] to do so. This time the injection functions are encapsulated in an additional module from package #1: phexec.bin.
由于 Windows API 不正式支持从 32 位进程写入 64 位进程,因此它使用 Heaven’s Gate 技术 [ 6] 来执行此操作。这一次,注入函数被封装在包 #1 中的附加模块中: phexec.bin 。

The malware now uses a 64-bit module prepare.bin, which is to be injected and used to retrieve the downloaded package #2 from inside the new process. The module prepare.bin is a shellcode containing an empty data section to be filled. The unfilled version of the section starts with the marker YHR! which is replaced with 0xDEADBEEF after it is filled.
该恶意软件现在使用一个 64位模块 ,该模块 prepare.bin 将被注入并用于从新进程内部检索下载的软件包#2。该模块 prepare.bin 是一个 shellcode,其中包含要填充的空数据部分。该部分的未填充版本以标记开头,填充 0xDEADBEEF 后替换为标记 YHR! 。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 15 – Filled in data within the prepare.bin module.
图 15 – 在 prepare.bin 模块中填写数据。

Data transmission using BaseNamedObject and the use of Exception Handlers
使用 BaseNamedObject 进行数据传输和使用异常处理程序

The loader (32-bit executable) creates a named object that is used to share the information between the current process and the infected one (64-bit). The content downloaded from the C2 is passed to this object and then received in the other process, via prepare.bin.
加载程序(32 位可执行文件)创建一个命名对象,用于在当前进程和受感染进程(64 位)之间共享信息。从 C2 下载的内容将传递到此对象,然后在另一个进程中通过 prepare.bin 接收。

During the injection, the prepare.bin is implanted into a fresh 64-bit process. The execution is redirected by patching the Entry Point of the main executable with a jump that leads to the shellcode.
在注入过程中,被 prepare.bin 植入到一个新的 64 位进程中。通过使用指向 shellcode 的跳转修补主可执行文件的入口点来重定向执行。

The shellcode (prepare.bin) contains a loop waiting for the BaseNamedObject to be filled. It sets a Vectored Exception Handler that is triggered after the data transfer from the other process is finished. The use of an exception handler is intended to be an additional obfuscation of the execution flow.
shellcode ( prepare.bin ) 包含一个等待 BaseNamedObject 填充的循环。它设置一个向量异常处理程序,该处理程序在完成来自其他进程的数据传输后触发。使用异常处理程序的目的是对执行流进行额外的模糊处理。

During its execution, the shellcode installs some more patches in the original executable of the process, and returns back to the patched code after the exception handler was registered. The overwritten code changes the memory protection and waits for the first malware process to send data over the BaseNamedObject.
在执行过程中,shellcode 会在进程的原始可执行文件中安装更多修补程序,并在注册异常处理程序后返回到修补的代码。被覆盖的代码会更改内存保护,并等待第一个恶意软件进程通过 BaseNamedObject 发送数据。

Figure 16 - The code of the infected executable overwritten during
shellcode execution, performing wait.
Figure 16 – The code of the infected executable overwritten during shellcode execution, performing wait.
图 16 – 在 shellcode 执行期间覆盖受感染可执行文件的代码,执行等待。

When the wait is over, it triggers an exception executing the int3 instruction. As a result the execution lands in the Vectored Exception Handler, that is installed by the shellcode.
等待结束后,它会触发执行指令的 int3 异常。因此,执行将落在由 shellcode 安装的向量异常处理程序中。

The exception handler is responsible for unpacking the retrieved package, fetching from it the next shellcode, and redirecting the execution. The further flow, starting from the retrieved shellcode from package #2, is analogous to the execution on a 32-bit system described below.
异常处理程序负责解压缩检索到的包,从中获取下一个 shellcode,并重定向执行。进一步的流程,从包 #2 中检索到的 shellcode 开始,类似于下面描述的在 32 位系统上的执行。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 17 – The exception handler responsible for unpacking the retrieved package, fetching from it a shellcode, and redirecting the execution.
图 17 – 异常处理程序,负责解压缩检索到的包,从中获取 shellcode 并重定向执行。

On 32-bit system 在 32 位系统上

The first element fetched from the new package is a shellcode.
从新包中获取的第一个元素是 shellcode。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 18 – Two alternative paths after the data is downloaded from the C2. If the system is 32-bit, the shellcode from the downloaded package is copied into the current process, and then run in its context. Otherwise, it is injected into a new, 64-bit process.
图 18 – 从 C2 下载数据后的两条备用路径。如果系统是 32 位的,则下载的包中的 shellcode 将复制到当前进程中,然后在其上下文中运行。否则,它将注入到新的 64 位进程中。

The shellcode decrypts and decompresses the rest of the downloaded package. It then fetches the main stealer module, which is in the XS2 format [1].
shellcode 对下载的包的其余部分进行解密和解压缩。然后,它获取 XS2 格式的主窃取器模块 [ 1]。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 19 – The module in XS2 format revealed in memory
图19 — 内存中显示的XS2格式模块

The unpacked module is loaded into a newly allocated memory region. However, the redirection contains some additional steps. Once again, the author took extra care to minimize the memory artifacts and made sure that the loading shellcode is released after use. A a small chunk of the shellcode is copied to the new memory region, just after the loaded XS2 module. After that block, other necessary data is copied, including the pointer to the package, and the Entry Point of the next module. After finishing, the loading function jumps to such a prepared stub. As the stub is in the new memory region, it can free the region containing the unpacking shellcode before the redirection to the next stage.
解压缩的模块将加载到新分配的内存区域中。但是,重定向包含一些附加步骤。再一次,作者格外小心地尽量减少内存伪影,并确保在使用后释放加载的 shellcode。一小块 shellcode 被复制到新的内存区域,就在加载的 XS2 模块之后。在该块之后,将复制其他必要的数据,包括指向包的指针和下一个模块的入口点。完成后,加载函数会跳转到这样一个准备好的存根。由于存根位于新的内存区域中,因此它可以在重定向到下一阶段之前释放包含解压缩 shellcode 的区域。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 20 – The copied stub frees the loading shellcode, and then redirects to the next module.
图 20 – 复制的存根释放加载的 shellcode,然后重定向到下一个模块。

Stage 3: coredll.bin (XS2)
第 3 阶段:coredll.bin (XS2)

After passing the full loading chain, the execution finally reaches the main stealer module: coredll.bin (in XS2 format). The module coordinates all the work, collects the results, and reports them back to the C2. It is also responsible for retrieving other modules from package #2, and using them to perform various tasks.
在通过完整的加载链后,执行最终到达主窃取模块: coredll.bin (XS2 格式)。该模块协调所有工作,收集结果,并将其报告给 C2。它还负责从包 #2 中检索其他模块,并使用它们来执行各种任务。

In the current release, the following modules are available in the package:

Module path Type Role Is new in 0.5.0?
/bin/i386/coredll.bin
/bin/amd64/coredll.bin
XS Main stealer module (analogous to the one described in this chapter)
/bin/i386/stubmod.bin
/bin/amd64/stubmod.bin
XS Prepares a .NET environment inside the process, to load other .NET modules
/bin/i386/taskcore.bin
/bin/amd64/taskcore.bin
XS Manages additional modules for the tasks supplied by the C2
/bin/i386/stubexec.bin
/bin/amd64/stubexec.bin
XS Injects into regsvr32.exe, and remaps the module into a new process
/bin/KeePassHax.dll PE (.NET) PE (.NET) Steals KeePass credentials
窃取KeePass凭据
/bin/runtime.dll PE (.NET) PE (.NET) Runs PowerShell scripts and plugins in the form of .NET assemblies
以 .NET 程序集的形式运行 PowerShell 脚本和插件
/bin/loader.dll PE (.NET) PE (.NET) General purpose .NET assemblies runner
常规用途 .NET 程序集运行程序

As seen earlier, the malware supports up to 100 LUA extensions. They are loaded from the package, retrieved by paths in the format: /extension/%08x.xs.
如前所述,该恶意软件最多支持 100 个 LUA 扩展。它们从包中加载,按以下格式的路径检索: /extension/%08x.xs 。

The coredll.bin not only coordinates the work of other modules, but also has a lot of vital functionality hardcoded. It comes with a collection of built-in stealers that can be enabled or disabled depending on the configuration.
它 coredll.bin 不仅协调其他模块的工作,而且还具有许多硬编码的重要功能。它带有一系列内置的窃取程序,可以根据配置启用或禁用这些窃取程序。

String encryption 字符串加密

In case of this module not all strings are obfuscated, so we can obtain some of them with the help of common applications such as FLOSS . Those are mainly strings from the statically linked libraries. The most important strings, relevant to the malware functionality, are encrypted and revealed just before use. Once again, TLS storage is used for the temporary buffer. This time the algorithm used for the decryption is RC4. The first 16 bytes of the input buffer is the key, followed by the encrypted data.
在此模块的情况下,并非所有字符串都经过混淆,因此我们可以借助常见应用程序(例如 FLOSS) .这些主要是来自静态链接库的字符串。与恶意软件功能相关的最重要的字符串在使用前会被加密并显示出来。同样,TLS 存储用于临时缓冲区。这次用于解密的算法是 RC4。输入缓冲区的前 16 个字节是密钥,后跟加密数据。

IDA script for deobfuscation:
用于反混淆的 IDA 脚本:

https://gist.github.com/hasherezade/51cb827b101cd31ef3061543d001b190

Deobfuscated strings from the sample:
示例中对字符串进行反混淆处理:

https://gist.github.com/hasherezade/ac63c0cbe7855276780126be006f7304

Communication between the modules
模块之间的通信

As there are multiple modules involved in the execution of various tasks, and some of them are injected into remote processes, they must communicate with the central module (coredll.bin), to coordinate the work and pass the collected results. The communication is implemented with the help of a pipe.
由于各种任务的执行涉及多个模块,其中一些模块被注入到远程进程中,因此它们必须与中心模块( coredll.bin )进行通信,以协调工作并传递收集到的结果。通信是在管道的帮助下实现的。

Figure 21 - The function creating the pipe within the main
module.
Figure 21 – The function creating the pipe within the main module.
图 21 – 在主模块中创建管道的函数。

The pipe is created by the main module, using the name Core and the current PID. This information, concatenated together, is hashed (SHA1), and the hash is used to generate the unique pipe name (following the pattern \\.\pipe\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}).
管道由主模块使用名称 Core 和当前 PID 创建。此信息连接在一起,经过哈希处理 (SHA1),哈希用于生成唯一的管道名称(遵循以下模式 \\.\pipe\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} )。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 22 – The function used to generate the pipe name.

The PID is further passed to the submodules so they can regenerate the name, following the same algorithm, and then establish the connection.

Execution flow

After the module finishes initialization, which is typical for the XS2 format [1], execution is redirected to the main function of the module. The function takes 3 arguments: the pointer to the current module, a command to be executed, and a structure, including all the data passed from the previous layers. Depending on the command argument, the module can follow one of the 4 different execution paths. In each case, the most important functionality is to load additional components, establish the connection with the C2, and deploy the built-in stealers.

Figure 23 - The overview of the main function within the Core
module.
Figure 23 – The overview of the main function within the Core module.
图 23 – 核心模块中主要功能的概述。

In some cases, the function responsible for running all the modules can be executed at the exit of the application where it is injected. It is implemented by hooking the ExitProcess function.
在某些情况下,负责运行所有模块的函数可以在注入该函数的应用程序出口处执行。它是通过挂钩函数来实现的 ExitProcess 。

Disabling the Event Tracer (and other NTDLL patches)
禁用事件跟踪器(和其他 NTDLL 修补程序)

At the beginning of the main function (Figure 23), we can see a function patching NTDLL. Its role is to disable Event Tracering (ETW), which is a built-in Windows feature allowing to collect information about the application behavior. The bypass is implemented similarly to that described in the article [5].
在 main 函数的开头(图 23),我们可以看到一个修补 NTDLL 的函数。它的作用是禁用事件跟踪 (ETW),这是一项内置的 Windows 功能,允许收集有关应用程序行为的信息。旁路的实现方式与文章[5]中描述的类似。

In the case of the WoW64 process, both the 32-bit and the 64-bit version of the NTDLL are patched. By scanning the process with PE-sieve, we can quickly dump the modified versions of NTDLLs and receive the .tag file informing about the hooks. The found patches are listed below.
对于 WoW64 进程,将修补 NTDLL 的 32 位和 64 位版本。通过使用 PE-sieve 扫描进程,我们可以快速转储 NTDLL 的修改版本并接收有关钩子的 .tag 通知文件。下面列出了找到的补丁。

In NTDLL 64-bit: 在 NTDLL 64 位中:

The installed patch is simple, it forces the EtwEventWrite function to always return 0.
安装的补丁很简单,它强制 EtwEventWrite 函数始终返回 0。

Figure 24 - The patch in the NTDLL (64-bit), disabling function
EtwEventWrite.
Figure 24 – The patch in the NTDLL (64-bit), disabling function EtwEventWrite.

The patches (NTDLL 32-bit):

Here we can see two functions patched: EtwEventWrite and NtTraceEvent – they both are forced to return immediately at the start.

Figure 25 - Multiple patches in the NTDLL (32-bit), including the
ones disabling ETW.
Figure 25 – Multiple patches in the NTDLL (32-bit), including the ones disabling ETW.

Additionally, we can see a hook inside the exception dispatcher, whose role was described in detail in our previous article on Rhadamanthys [1] (”Handling exceptions from a custom module”). In contrast to other hooks that are security bypasses, this hook is part of the XS format loading and allows to catch the exceptions thrown by the custom module.

Running the stealers

The main component of Stage 3 comes with a rich set of built-in stealers. They are stored as two distinct global lists. The first group involves stealers that rely on searching and parsing files of particular targets (i.e., profiles, local databases), which we refer to as “passive stealers”. The second set which we refer to as “active stealers” consists of more invasive components: they can interfere with running processes, inject into them, etc.

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 26 – Global lists of the passive and active stealers.
图 26 – 被动和主动窃取程序的全局列表。

Each stealer has an initialization function and a run function. They also use a top-level structure from where they fetch the data and where they report back the results. By sharing this structure, they can pass data from one to another, working as elements of the pipeline. The overview of the function responsible for running the stealers:
每个窃取程序都有一个初始化函数和一个运行函数。他们还使用顶级结构,从中获取数据并报告结果。通过共享此结构,它们可以将数据从一个传递到另一个,作为管道的元素工作。负责运行窃取程序的函数概述:

Figure 27 - Fragment of the function responsible for the deployment
of the stealers.
Figure 27 – Fragment of the function responsible for the deployment of the stealers.

First, the malware enumerates all the processes and stores their names, along with their PIDs, in a structure that will be used later. Then, all the built-in active stealers are initialized in a loop. At this point, they may reference the list of the processes to check if their targets are on the list. Some of them may also read additional information from the process, which will be passed further into the pipeline. Next, the passive stealers are initialized. The User Profile Path is retrieved and walked recursively to check if it contains some targeted directories from which the malware can steal.
首先,恶意软件枚举所有进程,并将其名称及其 PID 存储在稍后将使用的结构中。然后,所有内置的活动窃取程序都在循环中初始化。此时,他们可以参考进程列表来检查其目标是否在列表中。他们中的一些人还可能从流程中读取其他信息,这些信息将进一步传递到管道中。接下来,初始化被动窃取程序。用户配置文件路径被检索并以递归方式遍历,以检查它是否包含恶意软件可以从中窃取的一些目标目录。

After the initialization of both types of stealers is finished and information about the targets is collected, the functions performing the actual stealing activities run. First, all the initialized profile parsers are executed in a loop to collect the information from the files. Finally, the active stealers are executed.
在完成两种类型的窃取程序的初始化并收集有关目标的信息后,执行实际窃取活动的函数将运行。首先,所有初始化的配置文件解析器都在循环中执行,以从文件中收集信息。最后,执行活动的窃取者。

After all the hardcoded stealers were run, the malware initializes a built-in LUA interpreter and uses it to execute the additional set of stealers, implemented as LUA scripts (described in more detail in “The LUA scripts“).
在运行所有硬编码的窃取程序后,恶意软件会初始化一个内置的 LUA 解释器,并使用它来执行额外的一组窃取程序,这些窃取程序以 LUA 脚本的形式实现(在“LUA 脚本”中有更详细的描述)。

The results of all the executed stealers are collected in a global structure. They are posted into the queue and later uploaded to the C2.
所有已执行的窃取程序的结果都收集在一个全局结构中。它们被发布到队列中,然后上传到 C2。

The passive stealers 被动窃取者

As mentioned earlier, passive stealers rely on reading and parsing files belonging to particular applications to retrieve saved credentials.
如前所述,被动窃取者依靠读取和解析属于特定应用程序的文件来检索保存的凭据。

The passive stealers are initialized by parsing recursively all the subdirectories in %USERPROFILE% and checking the presence of targeted paths. The inner function enumerates all the directories in the %USERPROFILE%, and on each new directory found, it executes a passed callback.
被动窃取程序通过递归解析所有 %USERPROFILE% 子目录并检查目标路径的存在来初始化。内部函数枚举 %USERPROFILE% 中的所有目录,并在找到的每个新目录上执行传递的回调。

The callback then runs the full list of initialization functions (is_target) of the stealers. If the path is identified as a target, the relevant passive stealer is further initialized.
然后,回调运行窃取程序的初始化函数 ( is_target ) 的完整列表。如果路径被识别为目标,则进一步初始化相关的被动窃取程序。

Figure 28 - A loop initializing passive stealers with the directories
found recursively in the %USERDATA% directory.
Figure 28 – A loop initializing passive stealers with the directories found recursively in the %USERDATA% directory.
图 28 – 使用递归在 %USERDATA% 目录中找到的目录初始化被动窃取程序的循环。

The paths used for the target identifications (passive stealers):
用于目标识别的路径(被动窃取者):

Target 目标 Paths/extensions 路径/扩展 Is Optional 是可选的
Chrome  “Web Data”, “Web Data Ts4”
“Web 数据”、“Web 数据 Ts4”
no
Firefox 火狐浏览器 “cookies.sqlite” “饼干.sqlite” no
FileZilla “recentservers.xml” “最近服务器.xml” yes
OpenVPN OpenVPN的 “OpenVPN Connect\profiles”, “.ovpn”
“OpenVPN Connect\profiles”, “.ovpn”
yes
Telegram 电报 “configs”, “\D877F783D5D3EF8C\configs”
“配置”, “\D877F783D5D3EF8C\configs”
yes
Discord “DiscordStorage”, “discordptbStorage”, “discordcanaryStorage” yes
StickyNotes “Microsoft.MicrosoftStickyNotes”, “plum.sqlite” yes

The malware comes with a statically linked SQLite library which allows it to load and query local SQLite databases, and fetch saved data such as cookies.

The active stealers

The set of active stealers is more interesting and diverse. Some of these stealers open running processes and inject additional components. One of such components is KeePassHax.dll, injected into the KeePass process, to steal credentials from this open-source password manager (more details in: “Stealing from KeePass”). The malware may also inject its main component (core.bin) into other applications.

The set of the stealers is too big to describe each of them in detail. In summary, the following applications are targeted:

Chrome Vault WinSCP StickyNotes KeePass
Mozilla products (Thunderbird, Firefox)
and some of the Firefox-based browsers,
such as K-Meleon.exe
FoxMail Telegram Stream TeamViewer
Internet Explorer OpenVPN Discord CoreFTP 360Browser

Stealing from Chrome and Mozilla products

In some cases, the active stealer’s initialization function retrieves from the running process information about the current profile and configuration files. It is done for the following targets:

  • K-Meleon.exe (Firefox-based browser), Firefox
  • Chrome

The approach to finding the loaded profile is a bit different in each case.
在每种情况下,查找加载配置文件的方法都略有不同。

In the case of K-Meleon.exe it identifies the target files by paths retrieved from associated handles. First, the malware retrieves all object handles that are currently opened in the system, using NtQuerySystemInformation (with the argument SystemHandleInformation). It walks through obtained handles and selects the ones owned by the target process. Then, it iterates over those handles to check which names they are associated with (using NtQueryObject), and compares each name with the hardcoded one (\places.sqlite) . If the check passed, the full path is retrieved and stored for further use.
对于 K-Meleon.exe,它通过从关联句柄检索的路径来标识目标文件。首先,恶意软件使用 NtQuerySystemInformation (with the argument SystemHandleInformation ) 检索当前在系统中打开的所有对象句柄。它遍历获取的句柄,并选择目标进程拥有的句柄。然后,它会遍历这些句柄以检查它们与哪些名称相关联(使用 NtQueryObject ),并将每个名称与硬编码的名称 ( \places.sqlite ) 进行比较。如果检查通过,则检索并存储完整路径以供进一步使用。

Figure 29 - Searching for the configuration file (*places.sqlite”) by
walking through the retrieved object handles.
Figure 29 – Searching for the configuration file (“places.sqlite”) by walking through the retrieved object handles.
图 29 – 通过遍历检索到的对象句柄来搜索配置文件(“places.sqlite”)。

In the case of Chrome, the current profile is provided in the command line used to run the application. The command line of a process is stored in a dedicated field of the PEB (PEB → ProcessParameters → CommandLine), which is where the malware retrieves it from. The path to the profile is given after the —user-data-dir= command line argument, so this hardcoded string is used for the search.
对于 Chrome,当前配置文件在用于运行应用程序的命令行中提供。进程的命令行存储在 PEB ( PEB ProcessParameters → → CommandLine ) 的专用字段中,这是恶意软件检索它的位置。配置文件的路径在 —user-data-dir= 命令行参数之后给出,因此此硬编码字符串用于搜索。

As mentioned earlier, the main stealing actions are executed in the run function of each stealer. The stealers targeting Mozilla products may deploy additional processes and inject there the main module of the malware: coredll.bin. Note that although it is the same module as the one currently described, its execution path is not identical. Looking at the XS2 header [1], we can see that this format lets you provide alternative entry points of the application (denoted as entry_point – primary, and entry_point_alt – secondary). The execution of the implanted coredll.bin starts in entry_point_alt. Looking at the injection routine, we can see the corresponding address being added to the APC queue of the target’s main thread.
如前所述,主要的窃取操作在每个窃取者 run 的功能中执行。针对Mozilla产品的窃取者可能会部署其他进程,并将恶意软件的主要模块注入其中。 coredll.bin 请注意,尽管它与当前描述的模块相同,但其执行路径并不相同。查看 XS2 标头 [ 1],我们可以看到这种格式允许您提供应用程序的替代入口点(表示为 entry_point – primary 和 entry_point_alt – secondary)。植入的执行 coredll.bin 从 entry_point_alt 开始。查看注入例程,我们可以看到相应的地址被添加到目标主线程的 APC 队列中。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 30 – Fragment of the injecting function, responsible for selecting the alternative Entry Point of the module, and setting it in the APC Queue of the targeted process, for execution.

The alternative entry point leads to the execution of a minimalist main, which contain only Mozilla-specific stealers.
替代入口点导致执行极简主义的主节点,该主节点仅包含特定于 Mozilla 的窃取程序。

Depending on the given settings, the stealing functions can be executed immediately, or when the application exits. The execution at exit may be necessary in case the current process blocks some files from which the module wants to read.
根据给定的设置,窃取功能可以立即执行,也可以在应用程序退出时执行。如果当前进程阻止了模块要从中读取的某些文件,则可能需要在退出时执行。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 31 – The overview of the Alternative Entry Point of the coredll.bin. We can see that the main, stealing function, can be executed either immediately, or at the exit of the process.
图 31 – coredll.bin 的备用入口点概述。我们可以看到,主要的窃取功能可以立即执行,也可以在进程退出时执行。

There are three stealers implemented, and selected depending on the given configuration. Each of them sends the stolen content over the pipe back to the main element.
实施了三个窃取程序,并根据给定的配置进行选择。他们每个人都通过管道将被盗内容发送回主元素。

Figure 32 - The function responsible for deploying a specific,
targeted stealer attacking the Mozilla application data.
Figure 32 – The function responsible for deploying a specific, targeted stealer attacking the Mozilla application data.
图 32 – 负责部署攻击 Mozilla 应用程序数据的特定、有针对性的窃取程序的函数。

Stealing from KeePass 从KeePass偷窃

One of the modules shipped in the package is a .NET DLL named KeePassHax.dll. As the name suggests, this module targets the KeePass password manager (which is a .NET application). The DLL is injected into the target along with the assisting native module, called stubmod.bin. An interesting feature of the implementation is that it initializes the complete .NET environment of an appropriate version within the attacked KeePass process, just to deploy the stealing DLL.
软件包中附带的模块之一是名为 KeePassHax.dll 的 .NET DLL。顾名思义,该模块面向KeePass密码管理器(这是一个.NET应用程序)。DLL 与辅助本机模块一起注入到目标中,称为 stubmod.bin 。该实现的一个有趣的功能是,它在被攻击的 KeePass 进程中初始化适当版本的完整 .NET 环境,只是为了部署窃取的 DLL。

The function leading to the deployment of those components belongs to the active stealers list. As explained earlier, every stealer has two callback functions: init and run. In this case, the first function is empty, as there is nothing to initialize. The activity starts in the run function, given below. First, it searches for the keypass.exe on the previously prepared list of running processes. If the name is found, it tries to inject the malicious modules into the corresponding process.
导致部署这些组件的功能属于活动窃取者列表。如前所述,每个窃取程序都有两个回调函数: init 和 run .在这种情况下,第一个函数是空的,因为没有什么要初始化的。活动从 run 函数中开始,如下所示。首先,它会在先前准备的正在运行的进程列表中搜索。 keypass.exe 如果找到该名称,它会尝试将恶意模块注入到相应的进程中。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 33 – Fragment of the function responsible for doing an injection into the KeePass.exe. The injected payload, and the function to be executed from it, are passed as arguments.

Two modules are fetched from the package: stubmod.bin (in a 32 or 64-bit version, matching the process) and KeePassHax.dll. The stubmod.bin is an executable in the custom XS format [1], containing native code. This module is executed first, and prepares the stage for loading the DLL.

The start function of the stubmod.bin initializes the whole .NET environment inside the process where it is injected, similar to what is described in the following writeup [6].

Figure 34 - Overview of the function responsible for custom
initialization of the .NET environment within the process.
Figure 34 – Overview of the function responsible for custom initialization of the .NET environment within the process.
图 34 – 负责在进程中自定义初始化 .NET 环境的函数概述。

It then runs the KeePassHax.dll. As an argument, it passes a callback function which is responsible for sending the collected data to the main malware process, over the previously created pipe (more details in “Communication between the modules”). The way of passing the callback is a bit unusual, yet simple and effective: the pointer is first printed as a string and then given as an argument to the DllMain function of the KeePassHax.dll.
然后, KeePassHax.dll 它运行 .作为参数,它传递一个回调函数,该函数负责通过先前创建的管道将收集的数据发送到主恶意软件进程(更多详细信息请参阅“模块之间的通信”)。传递回调的方式有点不寻常,但简单而有效:指针首先打印为字符串,然后作为 函数的 DllMain 参数给出 KeePassHax.dll 。

Figure 35 - The pointer to the callback function is printed as a
string and then passed as an argument to the .NET module.
Figure 35 – The pointer to the callback function is printed as a string and then passed as an argument to the .NET module.
图 35 – 指向回调函数的指针打印为字符串,然后作为参数传递给 .NET 模块。

Looking at the DllMain function, we can see the argument being parsed and used as two combined pointers. One of the pointers, stored in the variable NativePtr, leads to the function that sends data over the pipe (that is a part of stubmod.bin). The other one stored in NativeData contains a PID of the process running the core module, which is needed to regenerate the pipe name.
查看该 DllMain 函数,我们可以看到参数被解析并用作两个组合指针。其中一个指针存储在变量 NativePtr 中,指向通过管道发送数据的函数(这是 stubmod.bin 的一部分)。另一个存储在 NativeData 中,包含运行核心模块的进程的 PID,这是重新生成管道名称所必需的。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 36 – The DllMain function of the KeePassHax.dll.
图 36 – KeePassHax.dll 的 DllMain 函数。

The main actions of dumping the credentials are done by the function KcpDump, which retrieves values of relevant fields from the main KeePass form.
转储凭据的主要操作由函数完成,该函数 KcpDump 从KeePass主表单中检索相关字段的值。

Figure 37 - The function KcpDump in the .NET module
KeePassHax.dll.
Figure 37 – The function KcpDump in the .NET module KeePassHax.dll.

The collected data is serialized and passed to the previously retrieved native function. The first supplied argument is a NativeData containing the PID passed from the caller.

Figure 38 - The KcpSendData function in the .NET module
KeePassHax.dll.
Figure 38 – The KcpSendData function in the .NET module KeePassHax.dll.

The function Program.FnSendData is implemented in the native module, which was responsible for executing the KeePassHax.dll, and has the following prototype:

int __cdecl to_read_write_to_pipe(int seed, DWORD numberOfBytesToWrite, _BYTE *data, int data_size)

The supplied seed argument is used in the generation of the pipe name, where the data is written to.

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 39 – Generating the pipe name, analogous to the function described in “Communication between modules”

This is how various components, native (in a custom format) as well as .NET modules, are blended together as one injected payload.

The LUA scripts

Although the list of stealers available by default is already very rich, the author decided to provide even more options by incorporating a LUA script runner.

The main module can load up to 100 LUA scripts. In the analyzed cases, we found approximately 60 of them are used. They implement a variety of stealers that target cryptocurrency wallets, FTP applications, e-mail agents, SSH, and more.

First, the malware loads all the available scripts from the package in a loop. They are stored in the internal structure, that is later passed to the interpreter.

Figure 40 - A LUA script fetched from the package and revealed in
memory.
Figure 40 – A LUA script fetched from the package and revealed in memory.
图 40 – 从包中获取并在内存中显示的 LUA 脚本。

Scripts work as plugins to the built-in framework.
脚本用作内置框架的插件。

Stealers are grouped by one-character identifiers:
窃取程序按单字符标识符分组:

ID Type 类型
W wallets 钱包
E e-mails 电子邮件
F FTP
N note-keeping apps 笔记保存应用程序
M messengers 使者
V VPN
2 authentication related, password managers, etc.
身份验证相关、密码管理器等。

The stealer starts with a check if the group it belongs to is enabled in the framework.
窃取程序首先检查它所属的组是否在框架中启用。

if not framework.flag_exist(“W”) then
如果不是 framework.flag_exist(“W”) 那么
return
返回

Some examples are given below.
下面给出了一些例子。

Stealer for Psi: Psi 的窃取者:

if not framework.flag_exist(“M”) then
如果不是 framework.flag_exist(“M”) 那么
return
返回
end
local filename = framework.parse_path([[%AppData%\Psi+\profiles\default\accounts.xml]])
本地文件名 = framework.parse_path([[%AppData%\Psi+\profiles\default\accounts.xml]])
if filename ~= nil and framework.file_exist(filename) then
如果 filename ~= nil 和 framework.file_exist(filename) 那么
framework.add_file(“accounts.xml”, filename)
framework.add_file(“accounts.xml”, 文件名)
framework.set_commit(“$[M]Psi+”)
framework.set_commit(“$[M]Psi+”)
end

Stealer for a DashCore wallet:
DashCore钱包的窃取者:

local file_count = 0 本地file_count = 0
if not framework.flag_exist(“W”) then
如果不是 framework.flag_exist(“W”) 那么
return
返回
end
local filenames = { 本地文件名 = {
framework.parse_path([[%AppData%\DashCore\wallets\wallet.dat]]),
framework.parse_path([[%AppData%\DashCore\wallets\wallet.dat]]),
framework.parse_path([[%LOCALAppData%\DashCore\wallets\wallet.dat]])
framework.parse_path([[%LOCALAppData%\DashCore\wallets\wallet.dat]])
}
for _, filename in ipairs(filenames) do
对于 _,ipairs(filenames) 中的文件名 do
if filename ~= nil and framework.file_exist(filename) then
如果 filename ~= nil 和 framework.file_exist(filename) 那么
if file_count > 0 then
如果file_count > 0 那么
break
end
framework.add_file(“DashCore/wallet.dat”, filename)
framework.add_file(“DashCore/wallet.dat”, 文件名)
file_count = file_count + 1
end
end
if file_count > 0 then
framework.set_commit(“!CP:DashCore”)
end

Stealer for Notezilla:

if not framework.flag_exist(“N”) then
return
end
local filename = framework.parse_path([[%AppData%\Conceptworld\Notezilla\Notes9.db]])
if filename ~= nil and framework.file_exist(filename) then
framework.add_file(“Notes9.db”, filename)
framework.set_commit(“$[N]Notezilla”)
end

List of all the targeted applications:

Armory AtomicDEX AtomicWallet Authy Desktop AzireVPN BinanceWallet
BinanceWallet BitcoinCore CheckMail Clawsmail Clawsmail CuteFTP
Cyberduck DashCore Defichain-Electrum Dogecoin Electron-Cash Electrum-SV
Electrum EMClient Exodus Frame FtpNavigator FlashFXP
FTPRush GmailNotifierPro Guarda Jaxx Litecoin-Qt Litecoin-Qt
LitecoinCore Monero MyCrypto MyMonero NordVPN Notefly
Notezilla SSH Outlook Pidgin PrivateVPN ProtonVPN
Psi+ PuTTY Qtum-Electrum Qtum RoboForm Safepay
SmartFTP Solar Wallet The Bat TokenPocket Total Commander Tox
TrulyMail WinAuth WalletWasabi WindscribeVPN Zap

Receiving commands from the C2

In addition to running the modules that were embedded in the package and sending back their results, the malware establishes a connection with the C2 to listen for additional instructions. On demand, it can drop and run additional executable files, or execute scripts via other modules.

There are 11 different supported commands that are identified by numbers.

Figure 41 - Switch-case parsing the commands from the C2 received by
the coredll.bin module.
Figure 41 – Switch-case parsing the commands from the C2 received by the coredll.bin module.
图 41 – 开关大小写解析 coredll.bin 模块接收的来自 C2 的命令。

The additional modules that can be run on demand, are taskcore.binruntime.dll, and loader.dll.
可以按需运行的其他模块是 taskcore.bin 、 runtime.dll 和 loader.dll 。

The content received from the C2 is passed in the variable denoted above as buf. Depending on the specifics of the particular command, it can be saved into a file, or into a named mapping, whose handle is passed to the other malicious module.
从 C2 接收到的内容在上面表示的变量中传递为 buf 。根据特定命令的具体情况,可以将其保存到文件中,也可以保存到命名映射中,其句柄将传递给其他恶意模块。

For example, the module received from the C2 is passed to be executed via taskcore.bin:
例如,从 C2 接收到的模块通过以下方式 taskcore.bin 传递以执行:

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 42 – Fragment of the function running the received module via taskcore.bin. The buffer received from the C2 (containing the module) is added into the mapping, whose handle is passed to the taskcore.bin module, that is run in a new process.
图 42 – 通过 taskcore.bin 运行接收模块的函数片段。从 C2(包含模块)接收的缓冲区将添加到映射中,其句柄将传递给在新进程中运行的 taskcore.bin 模块。

Running received PowerShell scripts and .NET modules
运行收到的 PowerShell 脚本和 .NET 模块

In addition to the ability to run LUA scripts, the malware allows the execution of PowerShell scripts, and since the version 0.5.0, also .NET assemblies. Unlike LUA, the scripts/assemblies to be executed are not shipped in the package but dynamically received from the C2.
除了能够运行 LUA 脚本外,该恶意软件还允许执行 PowerShell 脚本,并且从版本 0.5.0 开始,还允许执行 .NET 程序集。与 LUA 不同,要执行的脚本/程序集不是在包中附带的,而是从 C2 动态接收的。

This part of the functionality is managed by additional modules from package #2: runtme.dll (runs PowerShell scripts, and plugins) and loader.dll (a general-purpose loader of .NET assemblies).
这部分功能由包 #2 中的其他模块管理: runtme.dll (运行 PowerShell 脚本和插件)和 loader.dll (.NET 程序集的通用加载程序)。

The modules are run within a new process under the guise of AppLaunch.exe or dllhost.exe.
这些模块以 AppLaunch.exe 或 dllhost.exe 为幌子在新进程中运行。

Evolution of PowerShell runner (runtime.exe/dll)
PowerShell 运行程序的演变(运行时 .exe/dll)

In the previous versions, the PowerShell runner was implemented as runtime.exe, which is a very small executable written in .NET. The runner consisted of the Main function presented below. It takes two string arguments, which are in fact pointers in hexadecimal form. The pointers lead to the functions in the native module that loaded the current one and are used to pass the input and output. The scripts are received by calling the function sysNativeWrapper.GetScript(), then results are passed back by sysNativeWrapper.SendDumpData(data).
在以前的版本中,PowerShell 运行程序是作为 runtime.exe 实现的,这是一个非常小的可执行文件,用 .NET 编写。运行器由下面介绍的 Main 函数组成。它需要两个字符串参数,它们实际上是十六进制形式的指针。指针指向本机模块中的函数,该模块加载了当前模块,并用于传递输入和输出。通过调用函数 sysNativeWrapper.GetScript() 接收脚本,然后将 sysNativeWrapper.SendDumpData(data) 结果传回。

Figure 43 - The .NET module: “runtime.exe” (decompiled using
dnSpy)
Figure 43 – The .NET module: “runtime.exe” (decompiled using dnSpy)

The new version of the runner is a DLL, not an EXE (runtime.dll). It is fully rewritten, and much more complex. The runner exposes a new interface, to support the API of the newly introduced plugin system.

Figure 44 - List of classes on the runtime.dll (decompiled using
dnSpy).
Figure 44 – List of classes on the runtime.dll (decompiled using dnSpy).
图 44 – 运行时 .dll 上的类列表(使用 dnSpy 反编译)。

The plugins are in the form of .NET assemblies.
插件采用 .NET 程序集的形式。

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 45 – Fragment of the function executing the plugins (.NET assemblies following the defined API) – runtime.dll, decompiled using dnSpy.
图 45 – 执行插件的函数片段(遵循定义的 API 的 .NET 程序集) – 运行时 .dll,使用 dnSpy 反编译。

Simple PowerShell scripts, in the form of a string, are supported as well.
还支持字符串形式的简单 PowerShell 脚本。

Figure 46 - Fragment of the function executing PowerShell scripts -
runtime.dll, decompiled using dnSpy.
Figure 46 – Fragment of the function executing PowerShell scripts – runtime.dll, decompiled using dnSpy.
图 46 – 执行 PowerShell 脚本的函数片段 – 运行时 .dll,使用 dnSpy 反编译。

Loader of .NET assemblies (loader.dll)
.NET 程序集加载程序 (loader.dll)

The current version has yet another module, loader.dll, that is also responsible for running .NET assemblies, but in a much simpler way, and outside of the plugin system. It expects two arguments – a pointer to a byte array representing the assembly, and the array size. Then, the passed assembly is simply invoked.
当前版本还有另一个模块 loader.dll ,该模块也负责运行 .NET 程序集,但方式要简单得多,并且位于插件系统之外。它需要两个参数 – 指向表示程序集的字节数组的指针和数组大小。然后,只需调用传递的程序集。

Figure 47 - Fragment of the function executing .NET assemblies -
loader.dll, decompiled using dnSpy.
Figure 47 – Fragment of the function executing .NET assemblies – loader.dll, decompiled using dnSpy.

The “TaskCore” module

In the published changelog, the author advertises multiple changes in the task-running module:

14. The task module has been greatly upgraded, and a new plug-in module has been introduced to support users in secondary development of their own plug-ins.
Supports multiple task execution modes:
Normal execution
In Memory LoadPE Execution
Powershell Execution Powershell 执行
DotNet Reflection Execution
DotNet 反射执行
DotNet Extension Execution
DotNet 扩展执行
DotNet Extension with Zip Execution
具有 Zip 执行功能的 DotNet 扩展
VbScript Execution VbScript 执行
JScript Execution JScript 执行
X86 shellcode execution X86 shellcode 执行
X64 shellcode execution X64 shellcode 执行
Native Plugin Loader 原生插件加载器

Indeed, we can see the new module taskcore.bin which was added in this release. Depending on the specific command passed from the C2, it may be run under the guise of multiple applications, such as: AppLaunch.exedllhost.exerundll32.exeOpenWith.exenotepad.exerkeywiz.exewmpntwrk.exewmpconfig.exe.
事实上,我们可以看到此版本中添加的新模块 taskcore.bin 。根据从 C2 传递的特定命令,它可能以多个应用程序为幌子运行,例如:、、、、 notepad.exe rkeywiz.exe wmpntwrk.exe wmpconfig.exe OpenWith.exe dllhost.exe 。 rundll32.exe AppLaunch.exe

Similar to coredll.bin, it comes with RC4-encrypted strings. The list of decrypted strings (format: RVA, string) is given below:
与 coredll.bin 类似,它带有 RC4 加密的字符串。解密字符串列表(格式:RVA,字符串)如下:

As the module is in the XS2 format. The start function first finishes the initialization, then deploys the core functionality of the modules, i.e. command parsing. Each command is responsible for executing a module of a particular type.
由于该模块采用 XS2 格式。start 函数首先完成初始化,然后部署模块的核心功能,即命令解析。每个命令负责执行特定类型的模块。

Figure 48 - Switch-case parsing the commands from the C2 received by
the taskcore module.
Figure 48 – Switch-case parsing the commands from the C2 received by the taskcore module.
图 48 – Switch-case 解析 taskcore 模块接收的来自 C2 的命令。

The passed structure contains parameters filled in by the coredll.bin, and the mapping contains the buffer with a module to be executed that was received from the C2. While some of the other modules interact only with the coredll.bin, this one is also capable of establishing its own connection with the C2 and reports there directly.
传递的结构包含由 coredll.bin 填充的参数,映射包含缓冲区,该缓冲区包含从 C2 接收的要执行的模块。虽然其他一些模块仅与 coredll.bin 交互,但这个模块也能够与 C2 建立自己的连接并直接在那里报告。

As the author mentioned, the module is able to run a variety of content formats.
正如作者所提到的,该模块能够运行多种内容格式。

The simplest of them is running shellcodes.
其中最简单的是运行 shellcodes。

Figure 49 - A function within taskcore.bin, executing simple
shellcodes.
Figure 49 – A function within taskcore.bin, executing simple shellcodes.
图 49 – taskcore.bin 中的函数,用于执行简单的 shellcode。

Scripts, such as JScripts and VBScripts, are both executed by the same function:
脚本(如 JScripts 和 VBScripts)都由同一函数执行:

Figure 50 - Fragment of a function within taskcore.bin, executing
JScripts and VBScripts.
Figure 50 – Fragment of a function within taskcore.bin, executing JScripts and VBScripts.
图 50 – taskcore.bin 中执行 JScript 和 VBScript 的函数片段。

Underneath, it uses a COM interface and parses the given script with the help of a function ParseScriptText.
在下面,它使用COM接口并借助函数 ParseScriptText 解析给定的脚本。

Figure 51 - Parsing and executing scripts using the COM
interface.
Figure 51 – Parsing and executing scripts using the COM interface.
图 51 – 使用 COM 接口解析和执行脚本。

Similar to the previously mentioned stubmod.bin (”Stealing from KeePass”), the .NET environment is manually initialized. It is then it is used to run PowerShell scripts as well as plugins in the custom format (that are delivered in the form of .NET assemblies).
与前面提到的 stubmod.bin (“从 KeePass 窃取”)类似,.NET 环境是手动初始化的。然后,它用于运行 PowerShell 脚本以及自定义格式的插件(以 .NET 程序集的形式提供)。

Figure 52 - Function leading to the execution of a plugin (.NET
assembly).
Figure 52 – Function leading to the execution of a plugin (.NET assembly).
图 52 – 导致执行插件(.NET 程序集)的函数。

Before running the PowerShell scripts, the malware zeroes out the Environment Variable _PSLockdownPolicy. This modification disables the PowerShell lockdown policy, which is a security feature restricting the execution of certain actions within the PowerShell environment. As a result, this allows more freedom in execution of scripts.
在运行 PowerShell 脚本之前,恶意软件会将环境变量 _PSLockdownPolicy 归零。此修改将禁用 PowerShell 锁定策略,该策略是一项安全功能,用于限制在 PowerShell 环境中执行某些操作。因此,这允许在执行脚本时有更大的自由度。

Figure 53 - Function leading to the execution of a PowerShell
script.
Figure 53 – Function leading to the execution of a PowerShell script.
图 53 – 导致执行 PowerShell 脚本的函数。

The module also disables other security-related features: for example, it patches out AMSI checks and event tracing in NTDLL.
该模块还禁用其他与安全相关的功能:例如,它修补 NTDLL 中的 AMSI 检查和事件跟踪。

Analyzing the strings 分析字符串

The functionality of the modules is vast, but because we dumped and deobfuscated all the strings, we can get a good overview of different aspects of the modules by reviewing them. Selected artifacts described below.
模块的功能非常广泛,但由于我们转储并反混淆了所有字符串,因此我们可以通过查看模块来很好地了解模块的不同方面。下面描述的选定工件。

SQLite library SQLite 库

There are multiple strings indicating that the module comes with a statically linked SQLite library. The presence of SQLite modules in malware strongly suggests that it steals cookies, as cookies are kept in local SQLite databases. The Rhadamanthys core comes with the version string, which leads to the particular commit of the SQLite: https://www3.sqlite.org/src/info/fe7d3b75fe1bde41 (updated since the previous version of the malware, which used an earlier commit: https://www2.sqlite.org/src/info/8180e320ee4090e4)
有多个字符串表示该模块带有一个静态链接的 SQLite 库。恶意软件中存在 SQLite 模块强烈表明它窃取了 cookie,因为 cookie 保存在本地 SQLite 数据库中。Rhadamanthys 核心带有版本字符串,这会导致 SQLite: https://www3.sqlite.org/src/info/fe7d3b75fe1bde41 的特定提交(自恶意软件的先前版本以来更新,该版本使用较早的提交:https://www2.sqlite.org/src/info/8180e320ee4090e4)

SQLite format 3 SQLite 格式 3
2016-04-08 15:09:49 fe7d3b75fe1bde41511b323925af8ae1b910bc4d
2016-04-08 15:09:49 fe7d3b75fe1bde41511b323925af8ae1b910bc4d

In addition to the artifacts pointing to the library itself, we can see some queries among the decrypted strings, such as the following:
除了指向库本身的工件之外,我们还可以在解密的字符串中看到一些查询,如下所示:

SELECT title, url FROM (SELECT * FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk=moz_places.id)
选择标题,URL FROM(从moz_bookmarks.fk=moz_places.ID上的moz_bookmarks内部联接moz_places中选择*)
SELECT url FROM (SELECT * FROM moz_annos INNER JOIN moz_places ON moz_annos.place_id=moz_places.id) t GROUP BY place_id
SELECT URL FROM (SELECT * FROM moz_annos INNER JOIN moz_places ON moz_annos.place_id=moz_places.id) t GROUP BY place_id

Those queries are used for retrieving Mozilla browsing history and will be applied on the found database. They are part of the stealer described in “Stealing from Chrome and Mozilla products”.
这些查询用于检索Mozilla浏览历史记录,并将应用于找到的数据库。它们是“从 Chrome 和 Mozilla 产品中窃取”中描述的窃取程序的一部分。

Mbed-Crypto Mbed-加密

We can find multiple strings suggesting that the malware makes use of a statically linked library with Elliptic curves. Some of the strings can help uniquely identify the library and its version.
我们可以找到多个字符串,表明该恶意软件使用了带有椭圆曲线的静态链接库。某些字符串可以帮助唯一标识库及其版本。

8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D
14DEF9DEA2F79CD65812631A5CF5D3ED

It turns out to be Mbed Crypto (source), an old version of the library now renamed Mbed TLS.
原来是 Mbed Crypto(来源),该库的旧版本现在更名为 Mbed TLS。

The source file referencing the found strings can be seen on the project’s Github: [reference 1] [reference 2]. Note that the mentioned strings are not present in the new version of the library (under the new name Mbed-TLS) which suggests that the malware author used the old copy.
引用找到的字符串的源文件可以在项目的 Github 上看到:[ reference 1] [ reference 2]。请注意,上述字符串在新版本的库(新名称 Mbed-TLS)中不存在,这表明恶意软件作者使用了旧副本。

After analyzing the application, we know that this library is used to establish the TLS connection with the C2.
在分析了应用程序之后,我们知道该库用于与 C2 建立 TLS 连接。

CJSON Library CJSON图书馆

Some unencrypted strings suggest the use of JSON, implemented by the statically linked library cJSON:
一些未加密的字符串建议使用 JSON,由静态链接库 cJSON 实现:

cjson cjson的
BUG: Unable to fetch CJSON configuration
BUG:无法获取 CJSON 配置
JSON parser does not support UTF-16 or UTF-32
JSON 解析器不支持 UTF-16 或 UTF-32
‘[‘ or ‘{‘ expected 应为 ‘[‘ 或 ‘{‘
unexpected token 意外的令牌
‘}’ expected “}”应为
‘:’ expected ‘:’ 预期
string or ‘}’ expected 应为字符串或“}”
‘]’ expected  预期为 ‘]’

Looking further at the context in which those strings are used, we can see that the JSON format was applied to create reports about the stolen content, that was retrieved by the LUA scripts. We can also find relevant artifacts among the decrypted strings:
进一步查看使用这些字符串的上下文,我们可以看到 JSON 格式被应用于创建有关被盗内容的报告,这些内容由 LUA 脚本检索。我们还可以在解密的字符串中找到相关的工件:

e7bcc,'{“root”:’ e7bcc,'{“根”:’
e7bb0,’root’ e7bb0,’根’
e7d58,’profile’ e7d58,’配置文件’
e3814,’username’ e3814,“用户名”
e37f8,’password’ e37f8,“密码”
e7d40,’openvpn’ e7d40,’openvpn’

Artifacts from 360 Browser Password stealer
来自 360 浏览器密码窃取程序的伪影

Among unencrypted strings, we see the following strings that can be found in the open-source 360 Browser Password decoder.
在未加密的字符串中,我们看到以下字符串可以在开源 360 浏览器密码解码器中找到。

cf66fb58f5ca3485
(4B01F200ED01) (4B01F200ED01)

The first of the strings is an AES key that is used for decrypting the password. The second is the prefix of the encrypted password that needs to be dropped.
第一个字符串是用于解密密码的 AES 密钥。第二个是需要删除的加密密码的前缀。

A snippet from a Chinese website
来自中文网站的片段

One of the strings is quite unusual, and looks like along key or an obfuscated content:
其中一个字符串非常不寻常,看起来像是沿着键或混淆的内容:

0a{1b2c3d$4e5f6g7h_8@i9jAkBl`CmDnEo[FpGqHrI~s-JtKuLvMw%NxOyPz(Q9R8S7T6)U5V4]W3X2}Y1Z0
0a{1b2c3d$4e5f6g7h_8@i9jAkBl’CmDnEo[FpGqHrI~s-JtKuLvMw%NxOyPz(Q9R8S7T6)U5V4]W3X2}Y1Z0

However, Googling for it gives few results only, leading to a Chinese website with a simple code snippet. The snippet illustrates how to generate a random file name, and the aforementioned string is just used as a charset. The implementation used in Rhadamanthys is not identical, but has analogous functionality:
然而,谷歌搜索它只给出了很少的结果,导致一个带有简单代码片段的中文网站。该代码片段说明了如何生成随机文件名,前面提到的字符串仅用作字符集。Rhadamanthys 中使用的实现并不完全相同,但具有类似的功能:

RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS
Figure 54 – Function generating a random file name.
图 54 – 生成随机文件名的函数。

The string is referenced in the fragment of code responsible for generating names for the additional executables downloaded from the C2 that are dropped and executed.
该字符串在代码片段中引用,该代码片段负责为从 C2 下载的其他可执行文件生成名称,这些可执行文件将被删除并执行。

This piece of code is not particularly interesting, but the choice is unusual and may give a subtle hint that the author is a Chinese speaker. Hovewer, it is not enough to draw any conclusions.
这段代码不是特别有趣,但这个选择很不寻常,可能会给人一种微妙的暗示,即作者是说中文的人。哎呀,仅仅得出任何结论是不够的。

Additions in the version 0.5.1
版本 0.5.1 中的新增功能

During the writing of this article, the author already released version 0.5.1. The newest version contains additions such as a Clipper plugin, which watches a clipboard and replaces wallet addresses with attackers’ addresses. This version enables even more customization – distributors can order private stubs, prepared especially for them.
在撰写本文期间,作者已经发布了 0.5.1 版本。最新版本包含诸如 Clipper 插件之类的附加功能,该插件可以监视剪贴板并用攻击者的地址替换钱包地址。此版本可实现更多定制 – 分销商可以订购专门为他们准备的私人存根。

Figure 55 - Announcement about the version 0.5.1, published on
author’s Telegram account.
Figure 55 – Announcement about the version 0.5.1, published on author’s Telegram account.
图 55 – 关于 0.5.1 版本的公告,发布在作者的 Telegram 帐户上。

List of changes, as presented by the author:
作者提出的更改列表:

1.Added Clippers plug-in 1.新增Clippers插件
2.Telegram notification, you can now choose whether to send wallet crack and seed records in the log ZIP
2.Telegram通知,您现在可以选择是否在日志ZIP中发送钱包破解和种子记录
3.Google Account Cookie Recovery
3.Google帐户Cookie恢复
4.Default build stub cleaning for Windows Defender, including cloud protection
4.Windows Defender 的默认生成存根清理,包括云保护

We can already see that the Clipper plugin supports a rich set of targets.
我们已经可以看到 Clipper 插件支持一组丰富的目标。

Figure 56 - List of the applications attacked by the Clipper plugin
(added in version 0.5.1).
Figure 56 – List of the applications attacked by the Clipper plugin (added in version 0.5.1).

Conclusion

Rhadamanthys is a well-designed, modular stealer. In this article, we presented some details of its implementation, showing the incorporated techniques and execution flow. Although the core component comes with a lot of interesting built-in features, the power of this malware lies in its extensibility.

The currently analyzed version 0.5.0 supports multiple scripting languages, from LUA (whose interpreter is built-in to the main module) to PowerShell and other scripting languages, that are supported via an additional module.

As we can see, the author keeps enriching the set of available features, trying to make it not only a stealer but a multipurpose bot, by enabling it to load multiple extensions created by a distributor. The added features, such as a keylogger, and collecting information about the system, are also a step towards making it a general-purpose spyware.

It is evident that with the fast pace and ongoing development, Rhadamanthys is trying hard to become a big player on the malware market and is most likely here to stay.

Check Point customers remain protected from the threats described in this research.

Check Point’s Threat Emulation provides comprehensive coverage of attack tactics, file types, and operating systems and has developed and deployed a signature to detect and protect customers against threats described in this research.

Check Point’s Harmony Endpoint provides comprehensive endpoint protection at the highest security level, crucial to avoid security breaches and data compromise. Behavioral Guard protections were developed and deployed to protect customers against threats described in this research.

BG:

  • InfoStealer.Wins.Rhadamanthys.E/F

BS:

  • InfoStealer.Wins.Rhadamanthys.C/D/G

TE/Harmony Endpoint protections:

  • InfoStealer.Wins.Rhadamathys.C/D/G

IOC/Analyzed samples

ID Hash 散 列 Module type 模块类型 Format 格式
#1.1 bb8bbcc948e8dca2e5a0270c41c062a29994a2d9b51e820ed74d9b6e2a01ddcf Stage 1 (version 0.5.0) 第 1 阶段(版本 0.5.0) PE
#1.2.1 22a67f510dfb7ca822b5720b89cd81abfa5e63fefa1cdc7e266fbcbb0698db33 Stage 2: main module 第 2 阶段:主模块 XS1
#1.2.2 6ed3ac428961b350d4c8094a10d7685578ce02c6cd41cc7f98d8eeb361f0ee38 dt.x86.bin XS1
#1.2.3 4fd469d08c051d6997f0471d91ccf96c173d27c8cff5bd70c3f2c5008faa786f early.x86.bin XS1
#1.2.4 633b0fe4f3d2bfb18d4ad648ff223fe6763397daa033e9c5d79f2cae89a6c3b2 early.x64.bin XS1
#1.2.5 50b1f29ccdf727805a793a9dac61371981334c4a99f8fae85613b3ee57b186d2 phexec.bin XS1
#1.2.6 01609701a3ea751dc2323bec8018e11742714dc1b1c2dcb39282f3c4a4537c7d netclient.x86.bin XS1
#1.2.7 a905226a2486ccc158d44cf4c1728e103472825fb189e05c17d998b9f5534d63
编号:a905226a2486ccc158d44cf4c1728e103472825fb189e05c17d998b9f5534d63
proto_x86.bin shellcode 外壳代码
#1.2.8 ed713454c20844522304c49cfe25fe1490418c300e5ab0c9fca431ede1e91d7b strategy.x86.bin XS1
#1.2.9 f82ec2246dde81ca9edb69fb9c7ce3f7101f5ffcdc3bdb86fea2a5373fb026fb unhook.bin XS1
#1.3.1 ee4a487e78f23f5dffc35e73aeb9602514ebd885eb97460dd26635f67847bd16 Stage 3: main stealer component: “coredll.bin” (32-bit)
第 3 阶段:主要窃取组件:“coredll.bin”(32 位)
XS2
#1.3.2 fcb00beaa88f7827999856ba12302086cadbc1252261d64379172f2927a6760e Stage 3 submodule: “KeePassHax.dll”
第 3 阶段子模块:“KeePassHax.dll”
PE
#1.3.3 a87032195e38892b351641e08c81b92a1ea888c3c74a0c7464160e86613c4476 Stage 3 submodule: “runtime.dll”
第 3 阶段子模块:“运行时 .dll”
PE
#1.3.4 3d010e3fce1b2c9ab5b8cc125be812e63b661ddcbde40509a49118c2330ef9d0 Stage 3 submodule: “loader.dll”
第 3 阶段子模块:“加载程序 .dll”
PE
#1.3.5 ecab35dfa6b03fed96bb69ffcecd11a29113278f53c6a84adced1167b66abe62 Stage 3 submodule: “stubmod.bin” (32-bit)
第 3 阶段子模块:“stubmod.bin”(32 位)
XS2
#1.3.6 5890b47df83b992e2bd8617d0ae4d492663ca870ed63ce47bb82f00fa3b82cf9 Stage 3 submodule: “taskcore.bin” (32-bit)
第 3 阶段子模块:“taskcore.bin”(32 位)
XS2
#1.3.7 2b6faa98a7617db2bd9e70c0ce050588c8b856484d97d46b50ed3bb94bdd62f7 Stage 3 submodule: “stubexec.bin” (32-bit)
第 3 阶段子模块:“stubexec.bin”(32 位)
XS2
#1.3.8 f1f33618bbb8551b183304ddb18e0a8b8200642ec52d5b72d3c75a00cdb99fd4 Stage 3: main stealer component: “coredll.bin” (64-bit)
第 3 阶段:主要窃取组件:“coredll.bin”(64 位)
XS2

Appendix 附录

Our other writeups on Rhadamanthys:
我们关于Rhadamanthys的其他文章:

[1] “From Hidden Bee to Rhadamanthys – The Evolution of Custom Executable Formats”.
[1] “从隐藏的蜜蜂到拉达曼蒂斯——自定义可执行格式的演变”。

[2] “Rhadamanthys: The”Everything Bagel” Infostealer”
[2] “Rhadamanthys:”Everything Bagel“信息窃取者”

More about used techniques:
有关使用技术的更多信息:

[3] https://redops.at/en/blog/direct-syscalls-vs-indirect-syscalls

[4] https://media.defcon.org/DEF CON 30/DEF CON 30 presentations/Tarek Abdelmotaleb Dr. Bramwell Brizendine – Weaponizing Windows Syscalls as Modern 32-bit Shellcode – paper.pdf
[4] https://media.defcon.org/DEF CON 30/DEF CON 30 演示文稿/Tarek Abdelmotaleb Bramwell Brizendine 博士 – 将 Windows 系统调用武器化为现代 32 位 Shellcode – 论文.pdf

[5] https://whiteknightlabs.com/2021/12/11/bypassing-etw-for-fun-and-profit/

[6] https://www.malwarebytes.com/blog/news/2018/01/a-coin-miner-with-a-heavens-gate

[7] https://www.codeproject.com/Articles/11003/The-coding-gentleman-s-guide-to-detecting-the-NET

[8] https://codingvision.net/calling-a-c-method-from-c-c-native-process

[9] https://communities.bentley.com/products/programming/microstation_programming/f/archived-microstation-v8i-programming-forum/64713/write-a-com-server-in-c—call-from-vba-c-or-c-or-vb-net
[9] https://communities.bentley.com/products/programming/microstation_programming/f/archived-microstation-v8i-programming-forum/64713/write-a-com-server-in-c — 从 VBA-c-or-c-or-vb-net 调用

原文始发于cp<r>:RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS

版权声明:admin 发表于 2023年12月27日 下午3:15。
转载请注明:RHADAMANTHYS V0.5.0 – A DEEP DIVE INTO THE STEALER’S COMPONENTS | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...