在本系列关于 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 会激活其“离线键盘记录器”功能。
键盘记录是使用SetWindowsHookExA
API 和WH_KEYBOARD_LL
常量完成的。
存储键盘记录数据的文件使用以下配置字段构建
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
)标志来使文件超级隐藏。
使用第二种键盘记录模式时,需要使用字符串设置keylogger_specific_window_names
(索引0x2A
)字段,这些字符串将在每 5 秒钟检查当前前台窗口标题。
匹配后,键盘记录开始。随后,每秒钟检查当前前台窗口,如果标题不再包含指定的字符串,则停止键盘记录器。
屏幕录制线程
当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
)字符串列表,当前台窗口标题包含指定字符串之一时捕获屏幕截图。屏幕截图每 X 秒拍摄一次,由screenshot_specific_window_names_interval_in_seconds
(索引0x18
)字段指定。
在这种情况下,屏幕截图使用不同的格式字符串保存在磁盘上: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_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 命令。