|
本帖最后由 huoronganquan 于 2025-9-27 09:45 编辑
![]()
创建COM对象代码图
首先通过IWbemLocator->ConnectServer创建指定的计算机上的 WMI 命名空间的连接得到IWbemServices指针,然后通过IWbemServices->ExecQuery执行WQL语句获取计算机敏感信息,返回的信息存储到IEnumWbemClassObject指针中, 后续通过IEnumWbemClassObject->next方法遍历返回的对象IWbemClassObject的指针,最后通过IWbemClassObject->get方法获取返回对象的属性SerialNumber,该属性值可以用于区分和识别磁盘驱动器。 通过上述代码的执行,该程序可以获取到主机的硬件信息唯一地标识该计算机。 [3] 感染载荷释放后续载荷所需文件 (1) 释放文件 接下来, 病毒开始释放后续文件。
病毒释放文件路径构建代码图
病毒首先获取用户"Documents"目录路径, 构建恶意目录名称, 将释放的恶意载体的名称并以系统+隐藏模式创建目标目录。
病毒释放文件路径构建代码图 其中, 构建得到的目录名为<随机8字节>, exe文件名称为<随机6字节>.exe, 其他文件的名称固定为"npwzwmc64.dll", "space.ico", "vdi_ipc.dat"。
病毒释放文件示意图 接着, 病毒读取自身文件, 从中寻找标志数据"QEMB8WGP", 然后读取标志文本后的4个字节作为应提取的数据大小。 寻找标志数据代码图
对应数据大小图 将数据提取后, 病毒再读入自身PE头中的时间戳数据, 将其作为异或密钥, 以8位解密提取的数据。
时间戳作为密钥解密提取数据代码图 按照规则编写解密python代码如下:
然后, 病毒读取在DllMain中被初始化的数据指针, 解引用后得到的数据, 以104为异或密钥进行8bit-xor解密, 将得到8个标志数据, 其中每个标志数据的前16字节标志着4个待提取数据的首尾字节串(<1,0>,<3,2>,<5,4>,<7,6>)。
通过标志查找到的对应数据示意图 这里可以编写Python代码对特征块进行解密:
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- key = 0x68 # 104 -> 0x68
- raw_hex = [
- # 0x545E00 + 0x545E10
- "eb ec e7 c9 d7 d0 dd d0 ca c4 91 93 89 c3 cb cb"
- " a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7",
- # 0x548B60 + 0x548B70
- "84 ac ac c0 c0 c0 c0 c0 c0 c0 c0 c0 c0 f7 92 c0"
- " 6c 00 00 00 00 00 00 00 68 e7 c9 be 00 3b 00 8e",
- # 0x546160 + 0x546170
- "eb ec e7 d4 d7 c6 c4 c2 89 ce c4 c8 a7 a7 a7 a7"
- " a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7",
- # 0x548720 + 0x548730
- "89 a3 af c0 c0 c0 c0 c0 c0 c0 c0 c0 c0 c0 e0 0e"
- " 00 00 00 00 00 00 00 00 ac e7 85 be 00 19 00 90",
- # 0x545C20 + 0x545C30
- "eb ec e7 d1 c3 ce f8 ce d7 c4 89 c3 c6 d3 a7 a7"
- " a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7",
- # 0x5489C0 + 0x5489D0
- "84 a1 b4 c0 c0 c0 c0 c0 c0 c0 c0 c0 c0 a1 a7 95"
- " 6c 00 6c 00 00 00 00 00 42 e7 d3 be 00 2e 00 88",
- # 0x546190 + 0x5461A0
- "eb ec e7 d1 ce d2 d4 c4 d3 d5 ce d1 ce c6 cb 89"
- " d4 de d4 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7",
- # 0x548440 + 0x548450
- "93 b9 b3 c0 c0 c0 c0 c0 c0 c0 c0 c0 c0 c0 ae b0"
- " 00 00 00 00 00 00 00 00 9a e7 bb be 00 02 00 88",
- ]
- # ── 解密并打印 ───────────────────────────────────────────────────
- for idx, line in enumerate(raw_hex, 1):
- # 把连续字符串转成 bytes
- cipher = bytes.fromhex(line)
- plain = bytes(b ^ key for b in cipher)
- print(f'Block #{idx}:')
- for i in range(0, len(plain), 16):
- chunk = plain[i:i+16]
- print(' ' + ' '.join(f'{b:02x}' for b in chunk))
- print()
复制代码
![]() 代码运行结果示意图
接下来编写代码对对应的数据进行提取: - import struct
- import os
-
- def encrypt_data(data):
- key = (-1775093251) & 0xFFFFFFFF
- encrypted = bytearray(data)
-
- for i in range(len(encrypted)):
- # 获取当前字节
- original_byte = encrypted[i]
-
- # 计算 XOR 密钥字节 (key >> (8 * (i % 4))) & 0xFF
- shift_amount = 8 * (i % 4)
- key_byte = (key >> shift_amount) & 0xFF
-
- # XOR 加密
- encrypted[i] = original_byte ^ key_byte
-
- key = (original_byte | (key << 8)) & 0xFFFFFFFF
-
- return bytes(encrypted)
-
- def read_and_encrypt_ranges(input_file, output_files, ranges):
- if not os.path.exists(input_file):
- print(f"错误: 找不到输入文件 {input_file}")
- return False
-
- # 获取文件大小
- file_size = os.path.getsize(input_file)
- print(f"输入文件大小: {file_size} bytes (0x{file_size:X})")
-
- try:
- with open(input_file, 'rb') as f:
- for i, (start, end, output_file) in enumerate(zip([r[0] for r in ranges],
- [r[1] for r in ranges],
- output_files)):
- # 验证范围
- if start >= file_size:
- print(f"警告: 范围 {i+1} 的起始位置 0x{start:X} 超出文件大小")
- continue
-
- if end > file_size:
- print(f"警告: 范围 {i+1} 的结束位置 0x{end:X} 超出文件大小,将调整为文件末尾")
- end = file_size
-
- # 读取数据
- f.seek(start)
- data_length = end - start
- data = f.read(data_length)
-
- if len(data) != data_length:
- print(f"警告: 范围 {i+1} 只能读取 {len(data)} bytes,预期 {data_length} bytes")
-
- print(f"处理范围 {i+1}: 0x{start:X} - 0x{end:X} ({len(data)} bytes)")
-
- # 加密数据
- encrypted_data = encrypt_data(data)
-
- # 写入输出文件
- with open(output_file, 'wb') as out_f:
- out_f.write(encrypted_data)
-
- print(f" 已写入到 {output_file}")
-
- # 显示前几个字节用于验证
- if len(data) >= 16:
- print(f" 原始数据前16字节: {data[:16].hex()}")
- print(f" 加密数据前16字节: {encrypted_data[:16].hex()}")
-
- return True
-
- except Exception as e:
- print(f"错误: {e}")
- return False
-
- def main():
- input_file = "output.bin"
- output_files = ["1.bin", "2.bin", "3.bin", "4.bin"]
-
- ranges = [
- (0x616799, 0x98B999),
- (0x9A74A9, 0x9A9567),
- (0x24, 0x616769),
- (0x9A9597, 0x9B0407)
- ]
-
- print("文件解密工具")
- print("=" * 50)
- print(f"输入文件: {input_file}")
- print(f"输出文件: {', '.join(output_files)}")
- print()
-
- print("处理范围:")
- for i, (start, end) in enumerate(ranges):
- size = end - start
- print(f" 范围 {i+1}: 0x{start:06X} - 0x{end:06X} (大小: {size} bytes, {size/1024/1024:.2f} MB)")
- print()
-
- if read_and_encrypt_ranges(input_file, output_files, ranges):
- print("\n解密完成!")
- else:
- print("\n解密过程中出现错误")
-
- if __name__ == "__main__":
- main()
复制代码
提取后, 得到对应的数据。
提取加密后的数据代码图 随后,病毒对数据进行解密处理后写入磁盘,同时会将首个exe(可执行文件)末尾的 1 字节替换为随机字节,将第二个文件末尾倒数第 4 字节替换为随机字节,将第三、四个文件的第 0xF 字节替换为随机字节,以此规避通过简单哈希值实施的检测。
病毒更改文件哈希代码图 而且此处会判断之前检测安全软件时写入的标志位, 如果检测到过有安全软件正在运行, 则不会关闭文件句柄, 使得文件一直在"占用"状态。
病毒根据是否有安全软件来决定是否关闭文件代码图 病毒将四个文件释放后, 对其目录及文件设置隐藏, 然后释放第五个文件。第五个文件被释放在目录C:\Windows\Temp下, 文件名固定为ranchserv.jpg。
将文件写到固定目录代码图
对应文件图 然后病毒读取自身文件, 在自身的文件内存中搜索"%&$6@=*"。
在自身文件内存中搜索示意图
对应数据图 将搜索到的数据前方添加32字节的随机数据, 然后一起写入到HKLM\SOFTWARE\JDBCC\data中。
对应注册项数据图 随后, 病毒首先判断 C:\Users\<用户名>\Documents\<病毒目录>\<exe文件名称>.exe C:\Users\<用户名>\Documents\<病毒目录>\<ico文件名称>.ico 两份文件是否存在, 如果不存在, 则其重启自身, 再次执行上述的全部感染载荷执行的感染步骤。如果还存在, 则开始执行持久化。
|
|