在本系列关于 REMCOS 植入的上一篇文章中,我们分享了关于执行、持久化和防御规避机制的信息。继续本系列,我们将介绍其执行流程的后半部分,您将了解更多关于 REMCOS 录制功能及其与 C2 的通信。
启动看门狗
如果启用了 enable_watchdog_flag
(索引 0x32
),REMCOS 将激活其看门狗功能。
此功能涉及恶意软件启动一个新进程,将自身注入其中,并监视主进程。看门狗的目标是在主进程终止时重新启动它。如果看门狗终止,主进程也可以重新启动它。
看门狗注入的目标二进制文件是从硬编码列表中选择的,选择第一个进程创建和注入成功的二进制文件
svchost.exe
rmclient.exe
fsutil.exe
在此示例中,看门狗进程为 svchost.exe
。
在启动看门狗进程之前,会创建注册表值 HKCU/SOFTWARE/{MUTEX}/WD
,其中包含主进程 PID。
一旦 REMCOS 在看门狗进程中运行,它会通过验证恶意软件注册表项中是否存在 WD
值来采用“特殊”执行路径。如果存在,则删除该值,并调用监视过程函数。
值得注意的是,看门狗进程具有特殊的互斥锁,以将其与主进程互斥锁区分开来。此互斥锁字符串派生自配置(索引 0xE
),并附加 -W
。
当主进程终止时,看门狗会检测到它,并使用 ShellExecuteW
API 重新启动它,该 API 的恶意软件二进制文件路径是从 HKCU/SOFTWARE/{mutex}/exepath
注册表项中检索的。
启动录制线程
键盘记录线程
离线键盘记录器有两种操作模式
- 记录所有内容
- 当特定窗口位于前台时启用键盘记录
当配置中的 keylogger_mode
(索引 0xF
)字段设置为 1 或 2 时,REMCOS 会激活其“离线键盘记录器”功能。
键盘记录是使用具有 WH_KEYBOARD_LL
常量的 SetWindowsHookExA
API 完成的。
存储键盘记录数据的文件是使用以下配置字段构建的
keylogger_root_directory
(索引0x31
)keylogger_parent_directory
(索引0x10
)keylogger_filename
(索引0x11
)
键盘记录器文件路径为 {keylogger_root_directory}/{keylogger_parent_directory}/{keylogger_filename}
。在这种情况下,它将是 %APPDATA%/keylogger.dat
。
可以通过启用配置中的 enable_keylogger_file_encryption_flag
(索引 0x12
)标志来加密键盘记录器文件。它将使用 RC4 算法和配置密钥进行加密。
还可以通过启用配置中的 enable_keylogger_file_hiding_flag
(索引 0x13
)标志来使该文件超级隐藏。
当使用第二种键盘记录模式时,您需要使用将在当前前台窗口标题中每 5 秒搜索的字符串设置 keylogger_specific_window_names
(索引 0x2A
)字段。
匹配后,键盘记录开始。随后,每秒检查当前前台窗口,如果标题不再包含指定的字符串,则停止键盘记录器。
屏幕录制线程
当配置中启用了 enable_screenshot_flag
(索引 0x14
)时,REMCOS 将激活其屏幕录制功能。
要截取屏幕截图,REMCOS 利用 CreateCompatibleBitmap
和 BitBlt
Windows API。如果启用了 enable_screenshot_mouse_drawing_flag
(索引 0x35
)标志,则还会使用 GetCursorInfo
、GetIconInfo
和 DrawIcon
API 在位图上绘制鼠标。
存储屏幕截图的文件夹路径是使用以下配置构建的
screenshot_parent_directory
(索引0x19
)screenshot_folder
(索引0x1A
)
最终路径为 {screenshot_parent_directory}/{screenshot_folder}
。
REMCOS 利用 screenshot_interval_in_minutes
(索引 0x15
)字段,每 X 分钟捕获一次屏幕截图,并使用以下格式字符串将其保存到磁盘:time_%04i%02i%02i_%02i%02i%02i
。
与键盘记录数据类似,当启用 enable_screenshot_encryption_flag
(索引 0x1B
)时,屏幕截图将使用 RC4 加密算法和配置密钥加密保存。
在顶部,REMCOS 的屏幕录制功能与其键盘记录功能类似,都具有“特定窗口”功能。当 enable_screenshot_specific_window_names_flag
(索引 0x16
) 被设置时,会启动第二个屏幕录制线程。
这次,它会利用 screenshot_specific_window_names
(索引 0x17
) 字符串列表,当活动窗口的标题包含指定字符串之一时,就会捕获屏幕截图。屏幕截图会按照 screenshot_specific_window_names_interval_in_seconds
(索引 0x18
) 字段指定的 X 秒间隔进行拍摄。
在这种情况下,屏幕截图会使用不同的格式字符串保存在磁盘上:wnd_%04i%02i%02i_%02i%02i%02i
。下面是一个示例,使用 ["notepad"] 作为特定窗口名称列表,并将记事本进程窗口设置为活动窗口。
音频录制线程
当 enable_audio_recording_flag
(索引 0x23
) 被启用时,REMCOS 将启动其音频录制功能。
录制是使用 Windows Wave*
API 进行的。录制时长由 audio_recording_duration_in_minutes
(0x24
) 配置字段以分钟为单位指定。
录制 X 分钟后,录制文件会被保存,并开始新的录制。REMCOS 使用以下配置字段来构建录制文件夹路径
audio_record_parent_directory
(索引0x25
)audio_record_folder
(索引0x26
)
最终路径为 {audio_record_parent_directory}/{audio_record_folder}
。在本例中,它将是 C:\MicRecords
。录音会使用以下格式保存到磁盘:%Y-%m-%d %H.%M.wav
。
与 C2 的通信
初始化后,REMCOS 会启动与其 C2 的通信。它会尝试连接其 c2_list
(索引 0x0
) 中的每个域,直到其中一个响应为止。
根据之前的研究,如果为特定的 C2 启用了 TLS,则可以使用 TLS 加密通信。在这种情况下,TLS 引擎将使用 tls_raw_certificate
(索引 0x36
)、 tls_key
(索引 0x37
) 和 tls_raw_peer_certificate
(索引 0x38
) 配置字段来建立 TLS 隧道。
需要注意的是,在这种情况下,只能为多个启用了 TLS 的 C2 域提供一个对等证书。因此,有可能使用相同的证书识别其他 C2。
连接后,我们收到了第一个数据包
正如 Fortinet 深入描述的那样,协议没有改变,所有数据包都遵循相同的结构
- (橙色)
magic_number
:\x24\x04\xff\x00
- (红色)
data_size
:\x40\x03\x00\x00
- (绿色)
command_id
(数字):\0x4b\x00\x00\x00
- (蓝色)数据字段由
|\x1e\x1e\1f|
分隔
在收到来自恶意软件的第一个数据包后,我们可以使用以下函数发送我们自己的命令。
MAGIC = 0xFF0424
SEPARATOR = b"\x1e\x1e\x1f|"
def build_command_packet(command_id: int, command_data: bytes) -> bytes:
return build_packet(command_id.to_bytes(4, byteorder="little") + command_data)
def build_packet(data: bytes) -> bytes:
packet = MAGIC.to_bytes(4, byteorder="little")
packet += len(data).to_bytes(4, byteorder="little")
packet += data
return packet
在这里,我们将使用命令 0x94 更改记事本窗口的标题,并将窗口句柄 (329064) 和我们选择的文本作为参数传递。
def main() -> None:
server_0 = nclib.TCPServer(("192.168.204.1", 8080))
for client in server_0:
print(client.recv_all(5))
client.send(build_command_packet(
0x94,
b"329064" + SEPARATOR + "AM_I_A_JOKE_TO_YOU?".encode("utf-16-le")))
这是第二篇文章的结尾。第三部分将介绍 REMCOS 的配置及其 C2 命令。