文件名: xrk1_setup.exe
SHA1: 300602f268cec6dc2c8d99d0098f6cde7f4fae97

样本程序运行起来,生成了一个 InternetDownl.dll

该 dll 的文件信息如下,有Confuser壳 ,疑似黑 dll。
Confuser 1.x 是一款针对.NET应用程序的开源免费加壳工具

用ConfuserEx-Unpacker-v2.0 脱一下壳

再看一下文件信息,发现虽然脱掉了壳,但还是有混淆和反调试

再用 dnspy 看一下脱壳后的文件,可以看到很明显的恶意特征

点进 DecodeName() 查看

随便找一个在线网站对**MS5wbmc=**解码,发现是1.png

再找找样本程序运行时有没有这个文件,找到了

再看一下ExtractBase64() 函数

根据ExtractBase64() 写一个解密的 Python 脚本
先安装库,pip install Pillow,让后再运行解密脚本

看到 E9 开头,应该可以确认是一个 shellcode

然后再写一个加载这个 shellcode 的小程序
编译好后准备加载刚刚提取的 shellcode 文件**extracted_shellcode.bin****,**应该是链接到了某个 IP 地址


可以看到连接的 IP 地址是 **116.213.43.42**

VT 和微步查看该 IP 地址的相关情报,可以看到这个地址是恶意的


shellcode 执行后先是获取系统 dll 的各个 函数地址,包括 Loadlibrary()、VirtualAlloc()、VirtualFree()、RtlCaptureContext()、GetPrivateProfileStringA()。

shellcode 在搜索 "By@v<"字样,执行一个内存扫描操作,目的是在1000字节的范围内找到一个硬编码的标记 "By@v<"。成功找到该标记后,Shellcode 就能定位其配置数据,为后续建立网络连接(连接到攻击者的C2服务器)、下载并执行更复杂的恶意软件做准备,在地址 0x6071c 找到了


接着 shellcode 解密出要连接的 IP 地址116.213.43.42并准备开始连接

黑 dll 利用 powershell 创建了一个计划任务,用户在登录系统时会启动 ShellcodeLoader.exe

猜测可能是Shellcode 运行时,会首先尝试创建或检查 C:\Users\Public\Documents\SyS.ini 文件。如果文件不存在,它会创建该文件,然后继续执行后续的恶意代码,起到一个互斥体的作用

总结:该 Shellcode 首先通过 PEB(进程环境块)遍历来动态解析所需的 Windows API 函数地址(如 LoadLibraryA, VirtualAlloc, WSAStartup, connect, recv 等),然后解密出 IP 地址16.213.43.42 并连接,同时还检测是否存在杀软进程
private static T0 DecodeName<T0>()
{
return Encoding.UTF8.GetString(Convert.FromBase64String("MS5wbmc="));
}
private static T0 DecodeName<T0>()
{
return Encoding.UTF8.GetString(Convert.FromBase64String("MS5wbmc="));
}
private static T4[] ExtractBase64<T0, T1, T2, T3, T4, T5>(T5 img)
{
T0 t = Activator.CreateInstance(typeof(T0));
for (T1 t2 = 1; t2 < img.Height; t2++)
{
for (T1 t3 = 1; t3 < img.Width; t3++)
{
StringBuilder stringBuilder = t;
T2 pixel = img.GetPixel(t3, t2);
stringBuilder.Append((char)pixel.R);
}
}
return Convert.FromBase64String(t.ToString().Replace("\0", ""));
}
private static T4[] ExtractBase64<T0, T1, T2, T3, T4, T5>(T5 img)
{
T0 t = Activator.CreateInstance(typeof(T0));
for (T1 t2 = 1; t2 < img.Height; t2++)
{
for (T1 t3 = 1; t3 < img.Width; t3++)
{
StringBuilder stringBuilder = t;
T2 pixel = img.GetPixel(t3, t2);
stringBuilder.Append((char)pixel.R);
}
}
return Convert.FromBase64String(t.ToString().Replace("\0", ""));
}
import base64
from PIL import Image
def extract_data_from_image(image_path: str) -> bytes:
try:
# 打开图片文件
with Image.open(image_path) as img:
# 确保图片是RGB模式,以访问R通道
if img.mode != 'RGB':
img = img.convert('RGB')
width, height = img.size
# 用于拼接字符的列表
char_list = []
# 遍历像素 (从1,1开始,与C#代码保持一致)
for y in range(1, height):
for x in range(1, width):
# 获取(x, y)位置像素的RGB值
r, g, b = img.getpixel((x, y))
# C#代码中的 .Replace("\0", "") 相当于忽略R值为0的像素
if r != 0:
char_list.append(chr(r))
# 将字符列表拼接成Base64字符串
base64_string = "".join(char_list)
# 解码Base64字符串
# 为防止因填充错误导致解码失败,可以尝试添加等号填充
padding_needed = len(base64_string) % 4
if padding_needed:
base64_string += '=' * (4 - padding_needed)
decoded_data = base64.b64decode(base64_string)
return decoded_data
except FileNotFoundError:
print(f"错误: 文件 '{image_path}' 未找到。")
raise
except base64.binascii.Error as e:
print(f"Base64解码错误: {e}。从图片中提取的数据可能不是有效的Base64编码。")
raise
except Exception as e:
print(f"处理图片时发生未知错误: {e}")
raise
# --- 主程序 ---
if __name__ == "__main__":
IMAGE_FILE = "1.png" # 将这里替换为您的图片文件名
try:
# 调用函数提取数据
shellcode = extract_data_from_image(IMAGE_FILE)
# 将提取到的字节数据以十六进制格式打印出来
# 这种格式在分析shellcode时更常用
print(f"成功从 '{IMAGE_FILE}' 中提取数据 (shellcode):")
print(shellcode.hex())
# 如果需要将shellcode保存到文件
with open("extracted_shellcode.bin", "wb") as f:
f.write(shellcode)
print("\n已将数据保存到文件 'extracted_shellcode.bin'")
except Exception:
print("未能成功提取数据。")
import base64
from PIL import Image
def extract_data_from_image(image_path: str) -> bytes:
try:
# 打开图片文件
with Image.open(image_path) as img:
# 确保图片是RGB模式,以访问R通道
if img.mode != 'RGB':
img = img.convert('RGB')
width, height = img.size
# 用于拼接字符的列表
char_list = []
# 遍历像素 (从1,1开始,与C#代码保持一致)
for y in range(1, height):
for x in range(1, width):
# 获取(x, y)位置像素的RGB值
r, g, b = img.getpixel((x, y))
# C#代码中的 .Replace("\0", "") 相当于忽略R值为0的像素
if r != 0:
char_list.append(chr(r))
# 将字符列表拼接成Base64字符串
base64_string = "".join(char_list)
# 解码Base64字符串
# 为防止因填充错误导致解码失败,可以尝试添加等号填充
padding_needed = len(base64_string) % 4
if padding_needed:
base64_string += '=' * (4 - padding_needed)
decoded_data = base64.b64decode(base64_string)
return decoded_data
except FileNotFoundError:
print(f"错误: 文件 '{image_path}' 未找到。")
raise
except base64.binascii.Error as e:
print(f"Base64解码错误: {e}。从图片中提取的数据可能不是有效的Base64编码。")
raise
except Exception as e:
print(f"处理图片时发生未知错误: {e}")
raise
# --- 主程序 ---
if __name__ == "__main__":
IMAGE_FILE = "1.png" # 将这里替换为您的图片文件名
try:
# 调用函数提取数据
shellcode = extract_data_from_image(IMAGE_FILE)
# 将提取到的字节数据以十六进制格式打印出来
# 这种格式在分析shellcode时更常用
print(f"成功从 '{IMAGE_FILE}' 中提取数据 (shellcode):")
print(shellcode.hex())
# 如果需要将shellcode保存到文件
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2025-8-1 14:14
被ZyOrca编辑
,原因: 修正错误、调整措辞