Phase 13: Tools & Protocols

التفريق الثنائي والتنفيذ الرمزي: تطابق الوظائف وحل المدخلات

تطابق بين وظائف اثنين هو مطالبة من قبل توقيع واحد مع نوعية واحدة، وإدخال حل هو نموذج واحد من حالة المسار واحد؛ هذا الدروس يبني كلا منهما ويتحقق منهما ضد radiff2، غيدرا، Angr، و z3.

Type: Build

Languages: Python, C, x86-64 assembly, Java (one Ghidra script)

Prerequisites: Phase 13 · 33 (disassembly and control flow), 34 (lifting to pseudocode), 36 (rebuild and prove equal)

Time: ~150 minutes

أهداف التعلم

  • بناء خمسة توقيعات وظيفية من كائن وإدراجها: البايتات الدقيقة، البايتات مع حقل الإنتقال مخفي، تسلسل النموم، شكل الرسم البياني التدفق، واسم الرمز.
  • قم بتشغيل مباراة طموحة في مرحلة بنديف حيث تتطابق توقيعات فقط عندما تكون فريدة من نوعها على الجانبين، وتسجيل المرحلة والجودة وراء كل مباراة.
  • قم بإعادة إنتاج الحالة التي تفشل فيها وظائف متطابقة بايتين في موازنة بايت على الصور المحملة وتجريها بعد التخفيض، مع حسابات التنظيم التي تفسر أربعة بايتات غيرة.
  • قم بإعادة إنتاج نسبة التشابه في radiff2 من مسافة ليفينشتاين و اشرح لماذا يظهر نسبة واحدة فقط عندما تستخدم المقارنة 82 بايت رادار2
  • قم بإعداد مسارات الوظيفة على IR الصغيرة، ووضع شرط لكل مسار، وحل كل ورقة للمدخلات باستخدام البحث المحدود.
  • قياس انفجار المسار على حلقة مع حدود رمزية ومقارنة العد والفئات والنماذج مع angr 10.0.3 و z3 5.1.0.

المشكلة

لقد أعدت بناءهاledger.cفي-O2وسألت وكيل ما إذا كان هناك أي شيء تغير منذ-O1العميل قام بتسجيل المواقف وبلغ عنgradeتم تعديلها، لأن بايتها تختلف في البرامج المثقلة. ثم نفذت ميزانيتها لشرح تغيير لا يوجد.gradeهي نفسها في الملفين المواد. تختلف الصور المقارنة بعد نقل، و .rodataيقع على بعد 0x70 بايت في -O2البرنامج، لذلك نزوح واحد في gradeنمت بمقدار 0x70.

نفس المساء الذي سألت فيه أي نتيجة تجعلgradeرد 4 . قرأ الوكيل الرمزية و أجاب "90". هذا هو إجابة واحدة. العامل يعود 4 لكل نتيجة من 90 إلى 109, والسؤال كان لا مقيد، لذلك كانت إجابة الوكيل عينة حيث كنت بحاجة إلى مجموعة.

كل من الفشل يأتي من نفس الفجوة. تطابق وإدخال حل كل مطالبة مع طريقة وراء ذلك. هذا الدروس يبني الطرق في مكتبة بايثون القياسية ويعمل أدوات الإنتاج بجوارها. حيث تتفق الأدوات والرقم لديك مشتقات اثنتين. حيث أنها تختلف لديك عنوان، بايت، أو مقيدة للبحث.

توقيع الوظيفة هو مطالبة ذات جودة

فليك إطار التفاوت الثنائي في عام 2004 كبناء تعزيز بين مجموعات الوظائف من اثنين من الممارسات التنفيذية المماثلة. تمدد (دولين و رولز) ذلك في عام 2005 إلى كتلة وأوامر أساسية. صفحة مفاهيم بنديف تصف الاستراتيجية التي خرجت من هذا العمل. احسب صفة واحدة لكل وظيفة على الجانبين قيمة تظهر بالضبط مرة واحدة على كل جانب هي مطابقة. قيمة تظهر أكثر من مرة غير واضحة ويتم حفرها مع الصف المقبل داخل هذه الفئة الموازية. قيمة بدون نظير تبقى غير متوازنة. بعد كل مرسلة، يشكّل المُدعو والمتسابقون من المُطابقات الجديدة مجموعات صغيرة حيث من المرجح أن تكون الصفة التالية فريدة من نوعها، ويتكرر العملية مع الصفة التالية.

كل خوارزمية مطابقة تحمل نوعية. تصنيف الصفحة مطابقة الهاش من البايتات الخام للعمل والاسم مطابقة الهاش جيدة جدا، مؤشر MD الرسم البياني التدفق والتوقيع الأساسي (كل من الممثلين الأولية الصغيرة، المنتج على الوظيفة) جيدة، مرجعات السطر كوسيط، وتعدد الحلقة أو تسلسل العناوين ضعيفة. ثقة المقابلة هي متوسط جودة الخوارزميات التي أنتجتها، وزنها بواسطة sigmoid. تشابه الوظيفة حوالي 25% متطابقة حواف الرسم البياني التدفق، 15% متطابقة كتلة الأساسية، 10% متطابقة التعليمات، و 50% الفرق في مؤشر MD الرسم البياني التدفق، مضاعفة بالثقة.

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

خمسة توقيعات من سجل واحد

يقرأ الاختلاف شيئين لكل كائن. ELF يعطي البايتز، وحجم الرمز، و .rela.*السجلاتllvm-objdump -dويعطي القائمة حدود التعليمات و الـ "منيمونيكا" ، و أثبتت الدروس 33 أن المعدل المعدل يساوي القائمة على كل تعليم لهذه الأشياء. function_record()يُحقق من أنّ بايت كل تعليمات قائمة تساوي بايتات الكائن في هذا العنوان ويُرفع بطريقة أخرى. القائمة القديمة هي إطار تغيير.

خذgradeفيledger-x86_64-O1.oالرمز يقول تعويض 0x10 والحجم 46 ، لذلك السجل يغطي 0x10 إلى 0x3e و يستبعد البايتين nopالذي يُحبط الوظيفة التالية.

توقيع البايتات الدقيقة هو SHA-256 من 46 بايت. توقيع البايتات المخدّمة تسفر كل حقل نقل أولاً. هناك حقل واحد: السجلR_X86_64_PC32 .rodata+0x10عند التداخل 0x36، أربعة بايتات على نطاق واسع، تحركات leaq (%rip), %rcxفي كائن RELA هذه البايتات الأربعة تحتوي على صفر بالفعل، لذا فإن التوقيعان تتفقان على كل وظيفة من كل كائن هنا.

التوقيع الممني يختلط تسلسل 14 ممنيونيك:

output
movslq imulq movq sarq shrq addl addl xorl cmpl ja movl leaq movl retq

توقيع شكل الرسم البياني التدفق يأتي من الكتل الأساسية والحواف المخطوطة للدرس 33، المحدودة إلى الكتل التي يمكن أن يصل إلى إدخال. gradeفي-O1يحتوي على ثلاثة كتلة و ثلاث حواف.ja 0x3dمع حافة استقطاب وحافة سقوط، يقع الكتلة 0x31 إلى 0x3d، ويعود 0x3d. يرد سلسلة الدرجات (إلى، خارج) لكل كتلة في ترتيب مرتب، لذلك تقرأ التوقيع 3b 3e [0/2,1/1,2/0]- لأجلgradeفي-O0السجل يحل القفز غير المباشر من خلال الخمسة .rela.rodataالإدخالات بالضبط كما فعل الدروس 33 ، مما يعطي ثمانية كتلة و 11 حافة مع أربعة tableالحواف

توقيع الاسم هو اسم الرمز هو أقوى حقيقة عندما يكون موجوداً و لا شيء عندما يتم نزع البناء

مزيد من الحقل يذهب إلى جانب الحالة المزروعة لاحقا. عندما يكون لدى وظيفة leaإعادة التأهيل إلى .rodata، فحص الحدود، و تحميل مؤشر،referenced_table()يقرأ الجدول بالطريقة التي فعل فيها الدروس 36:cmpl $0x4قبل ذلكjaيعطي خمس إدخالات والحمل movl (%rcx,%rax,4), %eaxيعطي أربعة بايت لكل واحد.gradeفي-O1الطاولة في .rodata+0x14يقرأ1, 2, 3, 4, 4. . .

المُتَزَادُ الطمأنوي

match_functions()يدير المراحل بالتسلسل. لكل مرحلة يجمع الوظائف التي لا تزال غير متوازنة على كل جانب من خلال توقيع تلك المرحلة ويقبل كل قيمة لها وظيفة واحدة على كل جانب. يسجل المباراة المرحلة، جودة المرحلة، كل توقيع آخر يوافق أيضا، ونسبة التشابه.

python
for stage in order:
    for signature, candidates in left_groups.items():
        partners = right_groups.get(signature, [])
        if len(candidates) != 1 or len(partners) != 1:
            continue
        a, b = candidates[0], partners[0]
        agreeing = [s.id for s in STAGES if a.signatures()[s.id] == b.signatures()[s.id]]
        matches.append(Match(a, b, stage, agreeing, radare2_ratio(a.raw, b.raw), data_equal))

يبدأ ترتيب الدروس بالمرحلة الهيكلية الأربعة أولاً والاسم في نهاية المطاف، لذلك يتم اختبار المراحل الهيكلية والاسمات تصنيفها بعد ذلك.-O1ضد-O2:

FunctionStageAgreeing signaturesSimilarity
percent_changeexact bytesall five1.000
gradeexact bytesall five1.000
totalnamename only0.171
grade_labelexact bytesall five1.000

totalنمت من 31 بايت و 13 تعليمات إلى 140 بايت و 41 تعليمة ، لأن كلانغ قد قام بتنقل الحلقة مع SSE2 و حافظ على حلقة بقية واسكالرية. صيغته انتقلت من خمسة كتلة وخمس حواف إلى عشرة كتلة وخمسين حواف. لا يوجد شيء هيكلي يبقى ، و الرمز فقط يربط الاثنين.

لأجل-O0ضد-O1نفس الترتيب ينتج مطابقة خاطئة واحدة:

Function at -O0Matched at -O1StageNames agree
percent_changegrade_labelflow-graph shapeno
gradegradenameyes
totaltotalnameyes
grade_labelunmatched

percent_changeفي-O0هو الماس من أربع كتلة: مدخل ينشأ علىbefore == 0، ذراعين، و المفصل الذي يعود. تسلسل درجاتها هو0/2, 1/1, 1/1, 2/0. .grade_labelفي-O1- نعمgradeالمخطوطة نفس الماس حول الحدود تحقق. الشكل هو فريد على كلا الجانبين والقاعدة تقبل ذلك. علامة الجودة المتوسطة هي التحذير، ومرحلة الاسم، تشغيل بعد ذلك، تتناقض معها. المقابلة الكاذبة أيضا تستهلكgrade_labelعلى اليمين، لذلك الحقيقي percent_changeوgrade_labelالأزواج لا يزالون لا مثيل لهم

ترتيب بنديف يدير مطابقة الأسماء كمرحلة ثانية عندما توجد أسماء حقيقية، و BINDIFF_ORDERفي الشفرة يفعل نفس الشيء.-O0وظائف تتطابق مع وظائفهم-O1النسخة حسب الاسم، وهو النتيجة التي يبلغ عنها غيدرا أدناه. الدرس يبقي كلا الأوامر في التجربة حتى يكون الفشل مرئيًا. شكل الرسم البياني للدفق من أربعة عقدات هو شكل كل ifوelseالذي يضم قبل العودة.

البايتات المتطابقة، والعملية المُنتقلة

تطبق Ghidra نقلات عند استيراد كائن. وبالتالي فإن موازنة البايت لها صور محملة، ودرس 36 حقل نقل مخفي لهذا السبب. load_image()يعدّد الإيراد. يمرّ القسمات المخصصة حسب الترتيب من العناوين، ويقوم بتحديد كلّ منها إلى مقالته sh_addralignو يضعها من 0x100000 ثم يطبق كل سجل:S + A - Pمكتوب كقيمة مؤكدة من 32 بت R_X86_64_PC32وR_X86_64_PLT32،S + Aكمبلغ 64 بت R_X86_64_64. . .

يوافق التخطيط مع Ghidra 12.1.4 على كل قسم يبدأ في كل من البرامج، والتي تختبر مجموعة الاختبار ضد الناتج التتبع النسخة المسجلة:

Section-O1 program-O2 program
.text0x100000, 159 bytes0x100000, 271 bytes
.rodata0x1000a00x100110
.rodata.str1.10x1000f00x100160

.textهو 112 بايت أطول في -O2، نموtotal، لذا.rodataيبدأ 0x70 بايت على بعد ذلك.gradeيجلس في 0x100010 في كلتا البرامج.leaqعند التداخل 0x33 يكون لها حقل التنقل في 0x36 وينتهي في 0x3a. إضافة التنقل 0x10 زائد 4 المعتاد يضع الجدول في .rodata+0x14. . .

في-O1الصورة: 0x1000a0 + 0x14 - 0x10003a = 0x7a = 122في-O2الصورة: 0x100110 + 0x14 - 0x10003a = 0xea = 234. البايتات في الحقل هي7a 00 00 00في صورة واحدة وea 00 00 00في المرحلة الأخرى. بايت واحد من 46 يختلف، نسبة ليفينشتاين 0.978, ومرحلة بايتات دقيقة تفشل. مرحلة بايتات مخفيات الصفر الحقل وتمر. grade_labelتحرك بنفس 0x70 مثل جدولها، لذلك ظلت تحركاتها متساوية وتتمرير بايتات دقيقة في كلا المشاهدين.

(غيدرا) أعلنت عن نفس الانقسام-O1ضد-O2, متطابقة مع المهام المحددةpercent_changeوgrade_label، إرشادات الوظيفة المُطابقة وجدت هذين الإثنين بالإضافةgradeووجد المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق المنسق

6.5.0 compare_functionsنص مزود خطوط التناقضات. على بعد الجمع يرفق الحد "تطبيع إعادة التنقل غير متوفر". الشاحنة والقناع في هذه الدروس توفر هذا التطبيع.

ما هي تدابير radiff2

6.2.4 سفنradiff2مع-ACتحلل كل من الملفات وتطبيع صف واحد لكل وظيفة: حجم اليسار والعنوان، MATCH أو UNMATCH، ونسبة، والحجم والعنوان الصحيح.

Pairpercent_changegradetotalgrade_label
-O0 vs -O1UNMATCH 0.130435UNMATCH 0.426829UNMATCH 0.106061UNMATCH 0.269841
-O1 vs -O2MATCH 1.000000MATCH 1.000000UNMATCH 0.171429MATCH 1.000000
-O1 vs -O1MATCH 1.000000MATCH 1.000000MATCH 1.000000MATCH 1.000000

النسبة في مصدر الرادار2 هي 1 - distance / max(len_a, len_b)حيث المسافة هي المسافة ليفينشتاين بين اثنين من بصمات الاصبع والصابع هو سلسلة من الكتل الأساسية للعمل في ترتيب العنوان.radare2_ratio()فيcode/main.pyيطبق نفس الصيغة على البايتات المفيدة الخام ويعيد 0.130435, 0.106061, 0.269841, و 0.171429 إلى ستة عشرات.

لا يتكاثر 0.426829gradeفي-O0على 118 بايت من الوظيفة النسبة هي 0.296610.118في العمود الحجم. بصمة أصابعها أقصر. دون عمليات نقل لا يمكن حل جدول القفز، لذلك تحليلها يصل إلى كتلة الدخول، كتلة التي تنتهي في jmpq *%rax، الحالة الافتراضية، والعودة: 82 بايت، نفس 82 التي زعمت التنزل السريع التدريجي في الدروس 33. المسافة ليفينشتاين بين تلك 82 بايت و 46 بايت في -O1هو 47، و1 - 47/82 = 0.426829مع-e bin.relocs.apply=trueيجد radare2 جميع البايت 118 ويقوم بطبع 0.288136 ، مما يساوي نسبة الدروس على الصور المتنقلة ، حيث تختلف البايتات الأربعة من حقل الصفر من الكائن. تتفق أدوات اثنتان فقط عندما يقارنان نفس البايتات ، ولا يذكر عمود الحجم أي البايتات دخلت.

-Oيقتصر بصمة الأصابع على البايتات في رمز الاختيار ويمحو التشغيلات إلى الصفر.-O0مقابل-O1ترتفع النسب إلى 0.239130, 0.512195, 0.303030, و 0.523810, و totalفي-O1مقابل-O2يرتفع إلى 0.192857 .-s(مايرز) يبلغ عن تشابه 0.956 و المسافة 162 بين الجسمين-ss(ليفينشتاين) 0.927 و 137. تلك الأرقام تشمل العناوين، جداول الرمز، وقطع التنقل ولا تقول شيئا عن الوظائف.

جيدرا نسخة تتبع المرافق

أداة تتبع النسخة Ghidra يطابق برنامج المصدر برنامج المقصود مع المرافق. المواصلات الوظيفية هي مطابقة بايتات الوظيفة الدقيقة، مطابقة تعليمات الوظيفة الدقيقة (أوبرانديات مخفية) ، مطابقة وظيفة الممثلات الدقيقة، ومطابقة تعليمات الوظيفة المكررة (1:N و N:M). المرافق البيانية هي دقيقة، مضاعفة، ومماثلة البيانات المماثلة. التواصلات الرمزية تتطابق مع الأسماء بالضبط، كمتكررات، أو من خلال التشابه. يستخدم المراجع المرجعية المقابلة المقبولة للعثور على المزيد. يجب تعريف الوظائف في برنامج الوجهة، والطول الحد الأدنى للعمل هو 10 بايت. تتبع النسخة التلقائية اسم الرمز الدقيق، البيانات الدقيقة، البايتات الوظيفة الدقيقة، تعليمات الوظيفة الدقيقة، الممنيات الوظيفة الدقيقة، تعليمات الوظيفة المكررة، ثم مُتَصَلِف مرجع، وخلق مطابقات ضمنية للمُقَبَلين. تم إضافة مُساوم BSim في 11.2.

الدرس استغرق المرافق دون رأسcapture_ghidra_vt.shيستورد كل 3 كائنات في مشروع ويتم تشغيلهListVersionTrackingMatches.java، نص قصير يمتدAbstractGhidraVersionTrackingScriptيفتح برنامج المصدر والمستهدف عن طريق المسار، ويقوم بتشغيل ستة موازين غير مرجعية في ترتيب تعقب النسخة التلقائية، ويقوم بطبع سطر واحد لكل كتلة، وظيفة، موازين، ومقابلة. كل رقم في هذا القسم يأتي من تلك الملفات النصية.

Correlator-O0 to -O1-O1 to -O2
Exact Symbol Name Match4 functions4 functions, 5 data items (labels.rel, .L.str.1 to .L.str.4)
Exact Data Match00
Exact Function Bytes Match02 (percent_change, grade_label)
Exact Function Instructions Match03 (adds grade)
Exact Function Mnemonics Match03
Duplicate Function Instructions Match00

كل وظيفة تغيرت بين-O0و-O1، لذلك فقط الأسماء مطابقة ، وهو النتيجة التي يعطي متطابق الدروس في ترتيب بنديف. كل مباراة طبعت تشابه 1.000 وثقة 10.000. وصف صفحة المساعدة المتماثلين الدقيقين على أنه تشابه 1.0 وثقة 1.0, لذلك فإن مقياس الثقة المطبوعة هو سؤال مفتوح يسجل هذا الدروس ولا يحل.

فرق البرنامج، تحت أدوات، هو شيء مختلف. يُقارن برنامجين مع نفس مساحة العناوين على البايتات، والملفات، ووحدات الشفرة، والإشارات، والعبارات، والعملات في عناوين متساوية. هو فرق محاورة بالعناوين ولا يطابق أي شيء الذي انتقل.

"ديافورا" و "نينجا ثنائي" من وثائقهم

ديافورا هو مكون إضافي IDA Pro ، أصدرت لأول مرة في عام 2015 وفي الإصدار 3.4.2 اعتبارًا من 2026-08-18. إنه AGPL-3.0 منذ 2.0 ويحتاج إلى IDAPython، لذلك فإنه يعمل في IDA Home أو IDA Pro وليس في IDA Free. إنه يصدر كل قاعدة بيانات إلى SQLite ويجري هيرستيكاته كمسائل SQL. لكل هيرستيك اسم، فئة من الأفضل، الجزئية، أو غير موثوق بها، نوع النسبة، والعلامات الاختيارية مثل SAME_CPU أو SLOW. الأسماء في المصدر الحالي تقرأ مثل مراحل هذا الدروس مع المزيد منهم: بايت هاش، نفس العنوان وممينيكونيكس، نفس الجمعية المنظفة، Mnemonics small-primes-product، نفس العقدات، الحواف، الحلقات والمكونات المتصلة بقوة، توبوولوجي نوع هاش، ولفوضى رمزية مزيفة التي تحتاج إلى Hex-Rays decompiler. تظهر ملاحظات إصدارها تاريخ ضبط: الهورستيات البطيئة تعمل فقط تحت حوالي 2000 وظيفة، ونقل "الشريط نفسه" إلى فئة غير موثوق بها. هذه الحركة هي الماس الأربعة كتلة من هذا الدروس، نظرة على المقياس.

إضافة Binary Ninja 6.0 ، التي أصدرت في 2026-09-03 ، إلى Binary Similarity كإطار مع مزودي ومحللي. يُرسل بنديف كمقدم هيكلي و WARP لمطابقات الوظائف الدقيقة التي تتسامح مع العمليات التي يمكن نقلها، ويقول دليلها لاستخدام WARP عندما تتطابق الوظائف بخلاف التعليمات التي يمكن نقلها و BinDiff عندما تبقى مرتبطة هيكليا بعد إعادة التجميع. الميزة موجودة في الطبعة النهائية فقط. لا يوجد إدارة حزم إثباطي هنا و لم يتم تشغيله، لذا هذه الفقرة تأتي من وثائقها ولا شيء آخر.

كان بنديف نفسه مفتوح المصدر منذ 2023-09-25 تحت آباشي 2.0 ، مع v8 أحدث إصدار. يحتاج إلى إزالة وملحق بن إكسفورت ، الذي يدعم IDA Pro 9.4 أو أحدث ، Binary Ninja ، و Ghidra. المسار الحر للمتعلم هو Ghidra بالإضافة إلى BinExport بالإضافة إلى خط الأوامر BinDiff. لم تشغيله الدروس ، ويقول لك معملة ممارسة العمل.

نفس الرمز، ثابت مختلف

الدرس 36 حافظ على مرشح إعادة بناء منgradeالتي يحتوي على جدول 3 كأخير مدخل لها، حيث أن الأصلي لديه 4. grade_case10_wrong.oلديه نفس 46 بايت رمزيةgradeفي-O1. يطابق المُطابقين على البايتات الدقيقة مع كل توقيع متفق.1, 2, 3, 4, 4عبر نقل واحد و1, 2, 3, 4, 3من خلال البيانات والبياناتdataEqual: falseالثلاثة الآخرين-O1المهام غير متوازنة على اليسار، لأن الكائن المرشح يحتوي على وظيفة واحدة.

هذا هو شكل التحليل المزيف. وظيفة مختلفة تتوقف عند البايتات تقول أنه لا يتغير أي شيء. تطابق بيانات دقيق غيدرا ومطابقة مرجعات السلاسل من بنديف موجودة لسبب واحد. نسخة الدروس صغيرة: لكل زوج متطابق، مقارنة البايتات نقطة نقل كل وظيفة في، مع العد من الحدود التحقق والعرض من الحمل.

الإنفاذ الرمزي: المسارات، الشروط، الحل

وصف كينغ التنفيذ الرمزي في عام 1976. تصبح المدخلات رموزًا. تقوم كل بيان بتحديث مخزن رمزي. يضيف كل فروع شرطًا إلى المسار ، ويقرر محلل ما إذا كان المسار ممكنًا وينتج مدخلًا ملموسًا يتبعه. تصبح الوظيفة ذات الأغصان شجرة المسارات ، ويعتبر الورقة عودة مع شرط مرفق.

قام بالدوني وكوبا، ديليا، ديمتريسكو، وفينوكي بإجراء مسح في عام 2018. يطلق على القسم 5 اسم انفجار المسار كتكلفة مركزية: يمكن للمفوض أن يفرك في كل فروع، لذلك يمكن أن ينمو عدد الحكومة بشكل متكامل في عدد الفروع، ويعطي حلقة تعتمد حدها على مدخل رمزي مجموعة غير محدودة من المسارات. التخفيفات التي يدرجونها هي قص المسارات غير الممكنة من خلال حل في كل فروع، وجملة للعمل والحلقات، والدمج الحالي، والقريبة القليلة. تنفيذ الكوكوليكي يدير البرنامج بشكل ملموس و رمزي في وقت واحد، ويُسجل الشروط على طول الجولة الملموسة، ويُسلب واحدة، ويطلب من المحلّل الدخول التالي. DART (2005) ، CUTE (2005) ، و SAGE (2008) هي الأنظمة المسمى.

KLEE (Cadar, Dunbar, Engler, OSDI 2008) هو آلة افتراضية رمزية على رمز بيت LLVM ، لذلك مدخلها هو clang -emit-llvmالنتائج التي تمت في البرامج التشغيلية من خلال GNU Coreutils، والتي تم إطلاقها في عام 2015، كانت تصل إلى 84.5% من التغطية على الخط، مقابل 67.7% من اختبارات المطورين، ووجدت 56 خطأ خطيرا. تم إصدار KLEE 3.2 في عام 2025-12-23 تحت رخصة NCSA، مع توصية LLVM 16.

Angr يعمل على الثنائيات. angr.Projectيحتوي على جهاز تحميل CLE الذي يقوم بتخريط الكائن وتطبيق عمليات نقل، ورفع يحول كتلة إلى VEX IR (block.vex) مع رمز البيوب كبديل، ومصنع للولايات.SimStateيحتوي على سجلات، ذاكرة، وحل.SimulationManagerخطوات مخبأة من الدول المسمىactive،deadended،found،avoidedوerroredوexplore(find=..., avoid=...)كل خطوة تعمل المحركات في ترتيب: الفشل، syscall، الرمز، الوحيد للبيانات الملموسة، و VEX كخلفية. claripy هو نهاية المحلول الأمامية على Z3، وفي Angr 10.0 هو تطبيق Rust المتاحة استيراد مثل from angr import claripy. angr 10.0.3 تم تحميله في 2026-10-10, هو BSD-2-Clause، ويحتاج إلى Python 3.12 أو أحدث. Z3 5.1.0, صدر في 2026-08-16 تحت MIT، هو الحل وراء angr، Triton، و KLEE الخلفية اختيارية.

مُجرم صغير فوق الدروس 34 IR

المُعدّم فيcode/main.pyيستخدم إشارة إير صغيرة مع شكل بيان في الدروس 34: Assign،Branch،Jump،Return، بالإضافة إلىSwitchالمختبر الممارس في الدروس 34 طلب ذلكConst،Var،Binمع عرض، Cast،Loadمن طاولة خرسانية تحمل اسمها، وNotيتم رفع وظائف الأربعة المثبتة يدوياً عند المستوى الذي يصل إليه الدروس 34 بعد تبسيطها، حيث 0x66666667المتضاعف أصبحscore / 10وكل كتلة إير قائمة بالعناوين التعليمية التي جاءت منهاcheck_ir_against_listing()يؤكد أن العناوين تغطي قائمة الوظيفة مرة واحدة بالضبط.

gradeفي-O0في تلك المعلومات:

output
0x30: local_8 = score; local_10 = score / 10 - 6; if (local_10 >u 4) goto 0x9a else 0x62
0x62: switch local_10 -> 0x91, 0x88, 0x7f, 0x76, 0x76
0x76: local_4 = 4; goto 0xa1        0x7f: local_4 = 3; goto 0xa1
0x88: local_4 = 2; goto 0xa1        0x91: local_4 = 1; goto 0xa1
0x9a: local_4 = 0                    0xa1: return local_4

أهداف التبديل تأتي منjump_table_targets()، نفس حساب الترحيل مثل الدروس 33، لذلك IR يقرأ العداد.

execute()تحتفظ قائمة عمل من حالات المسار. تتضمن الحالة الكتل الحالية، وآثر الكتل، و قائمة الحالات، و بيئة تقوم بتخريط كل متغير إلى تعبير على المدخلات. Assignيبدل البيئة في المصدر ويخزن النتيجة. Branchيبدل في الحالة، ثم يسأل المحلول مرتين: مرة مع الحالة إضافة، مرة مع سلبها. يتم إسقاط جانب لا يمكن للمحلول إرضاء، وهو الحصن الحرص الذي يصف المسح. Switchمجموعة إدخالات الجدول حسب الهدف والفراك مرة واحدة لكل هدف متميز مع تفريق المساواة الإدخال، وهذا هو كيفية Angr يعامل الهدف القفز الرمزي أيضا. Returnيُستبدل في القيمة ويغلق الورقة. يُعَرّف مسار طويل من حد الخطوة ويقفّه.

اتبع الطريق إلىreturn 4يدوياً، الإدخال يُخصصlocal_10 = score / 10 - 6- حالة الفرعlocal_10 >u 4هو غير صحيح على هذا الطريق، لذلك قائمة الحالات!(score / 10 - 6 >u 4). إدخالات المفتاح 3 و 4 كل من نقطة في 0x76, لذلك الفرق إلى 0x76 يضيف score / 10 - 6 == 3 || score / 10 - 6 == 4. كتلة 0x76 تعطيlocal_4 = 4، يقفز إلى 0xa1 ، وبدل العودة إلى 4. الورقة هي زوج من هذا الشرط و تلك القيمة

الحل هوBoundedSearch. يحمل مجالًا محدودًا لكل مدخل ، ويعد نسبة المجال ، ويقيم كل قيود باستخدام علمي C: التغليف 32-بيت ، والقسيم القصري ، والمقارنات الموقعة وغير الموقعة ، والتحركات الحسابية أو المنطقية. تقسيم صفر أو مؤشر الجدول خارج الجدول يجعل هذا التخصيص يفشل في القيود.scoreفي -200 إلى 1200 خمس مساراتgradeتكلفة 44،460 تقييم وبضع ملثانية. حل كل ورقة لمجموعة المدخلات يمنح:

LeafReturnsConditionScores in the bound
0x764!(q >u 4) && (q == 3 || q == 4)90 to 109, 20 inputs
0x7f3!(q >u 4) && q == 280 to 89, 10 inputs
0x882!(q >u 4) && q == 170 to 79, 10 inputs
0x911!(q >u 4) && q == 060 to 69, 10 inputs
0x9a0q >u 41,351 inputs, the rest of the bound

qتعنيscore / 10 - 6نفس الفصول تأتي منgradeفي-O1، حيث يكون للـ IR طريقتان، مسار الجدول يعود lookup_14[q]والمسار الافتراضي يعود 0، والسؤال يصبح قيودا على القيمة المرجعة، لأنه لا توجد حلقة الحالة التي يمكن الوصول إليها. الجدول lookup_14يقرأ من الكائن.rodataعند 0x14.

الحد هو الحد من الطريقة. البحث المحدود هو كامل داخل مجالها والصمت خارجها. في غضون -200 إلى 1200 لا تسجيل في 60 إلى 109 يعود 0 ولا تسجيل من 110 أو أكثر يعود قيمة غير الصفر. z3 يثبت كل من كل من 2^32 نقاط، والقسم التالي يظهر أين تستعيد الطرق اثنين شهود مختلفة.

تم قياس انفجار المسار

totalفي-O1هو حلقة الدروس 33: اختبار على count، جسم حلقة يضيفvalues[rdx]و الزياداتrdxوjneعودوا إلى الجسم بينماrdx != rcxفي الجوالrcxهوzext64(count)وrdxيبدأ عند 0 كل مرّة عبر الحافة الخلفيةrdx != countمعrdxثابت، لذلك الطريق لcount = cيدير الجسمcأوقات وخارجcountالمحدد إلى 0 إلى 2 يجد المنفذ 3 مسارات. مع 0 إلى 4 يجد 5 ، و مع 0 إلى 8 يجد 9. كل مسار يعود جمع مثلث من عددها: (0, 0) ، (1, 1), (2, 3) ، حتى (8, 36). angr يبلغ عن 3 ، 5 و 9 حالة محطمة والنوافذ نفسها تسعة أزواج العد والجمع في جميع مستويات التحسين الثلاثة ، بما في ذلك -O2، والتي تحتاج حلقة متجهة إلى عدد من 8 على الأقل وبالتالي لا تغير عدد المسار في هذه النطاق.

بدون قيود لا ينتهي المنفذ أبداً، لأن كل إعادة تعدد هو مسار واحد أكثر قابلية للتطبيق. حد الدروس من 24 كتلة لكل مسار، تشغيل مع countحتى 64، يعود 22 مسار، يختصر 2، ولا يبدأ أبدا 41 آخر من 65 الموجودة. تقرير يعطي هذه الأرقام الثلاثة. تكلفة الحل ينمو أيضا: 33 تقييمات في الحدود 2، 115 في 4، 531 في 8، و 6,900 للجري المحدد.

angr و z3 على نفس الأسئلة

capture_angr.pyتم إعادة التنظيم في كل شيء يمكن نقله مع الـ ELF الخلفي عند 0x400000، تم تطبيق 13 نقل لـ -O0و 8 للآخرين، و حل الرموز الأربعة.gradeمع حجة رمزية ذات 64 بت،run()انتهى مع 5 دولة في-O0و 2 في-O1و-O2، في 0.475، 0.408، و 0.318 ثانية.eax == vكل حالة معطلة وطلب من الحل للحد الأدنى والحد الأقصى الموقعة أعطى 60 إلى 69, 70 إلى 79, 80 إلى 89, و 90 إلى 109 لvمن 1 إلى 4 في كل مستوى، و -2147483648 إلى 2147483647 لل 0.

استعملت الصيغة المكتوبة على CFGFastgradeفي-O0، الذي يردد الثمانية الكتل الدروس 33 وجدت، ثم explore(find=0x400076)وجدت حالة واحدة مع ثلاثة لا تزال نشطة في 0.47 ثانية، مع الحد الأدنى 90 و أقصى 109 على الحجة ومعينة 91, 93, 94, 97 و 101.

لأجلpercent_change، دولة محطمة مع القيودbefore[31:0] != 0وbefore[31:0] == 0. تسأل عن حالة غير الصفرeax == 50أعطيتbefore = 21055744, after = 332315210في-O0،40566804, 834296877في-O1و-24484867, 993934694في-O2البحث المحدود في - 16 إلى 16 إجاباتbefore = -10, after = -15. z3 طرح نفس السؤال حول الدروس 34 قائمة، الإجابات before = -25092599, after = 305712160. مجموعة الاختبار تقيم جميع الأزواج الخمسة مع مقيّم IR وكل منهما يعطي 50. نموذج يثبت أن مدخل موجود. ليس المدخل، وأعطت ثلاثة أدوات صحيحة ثلاثة مختلفة.

capture_z3.pyالنماذج -O1قائمة gradeفي 32 بت بت متجهات بيت مع مضاعفة، والتحركات، والجدول، ويقول أربعة أسئلة أخرى.switchلبعض النتيجة 32-bit: غير موجودة في 0.068 ثانية، لذلك فإن الوظيفة المجمعة تساوي المصدر على جميع المدخلات 2^32.score / 10هو 70634653 والتحول يسقط إلى الافتراض بينما يعود العدوان 4. نفس الفرق محدودة إلى 0 إلى 109: غير مقنعة، وهذا هو السبب في شبكة الدروس 36 لم يتمكن من رؤيتها.percent_change،before == 3مع النتيجة -133 هو مقعد مع after = 1073741823، خلية الإفراط في الدروس 36، والبحث المحدود يجد شاهدًا آخر داخل مجالها،after = -1، حيث(-1 - 3) * 100 / 3يختصر إلى -133 بدون إفراط على الإطلاق

بناءها

أطلق التجربة:

bash
cd phases/13-tools-and-protocols/44-binary-diffing-and-symbolic-execution
python3 code/main.py

إنتاج هو تقرير JSON واحد. diffsيحتفظ بمطابقات الملف المفرد والصور المحملة-O0ضد-O1و-O1ضد-O2، بالإضافة إلى-O0زوج في نظام بنديفtoolComparisonيضع مرحلة الدروس بجانب حكم و نسبة radiff2 و المنسقين Ghidra لكل وظيفة. patchهل هوgrade_case10_wrong.oقضيةradare2Ratiosيعيد إعادة إنتاج أرقام radiff2gradeRelocationCaseيظهر التخطيط والتحركات الثانية، و symbolicيحتفظ بالطرق، والصفوف، والانفجارات العد.

اقرأcode/main.pyفي هذا الترتيب:

  1. ElfObjectيقرأ القسمات والرموز.rela.*السجلاتparse_listing()يقرأllvm-objdumpرسالة
  2. jump_table_targets()وbuild_cfg()إعطاء كتلة قابلة للتسجيل والحواف المخطوطة. FunctionRecord.signatures()يُبني التوقيعات الخمسة.
  3. load_image()يحدد القسمات المخصصة ويتم تطبيقها S + A - PوS + A. . .
  4. match_functions()هو المُقام الذي يُقام.levenshtein()وradare2_ratio()أعطوا التشابه
  5. parse_radiff2()وparse_ghidra_vt()اقرأ نتائج الأداة التي تم التقاطها للمقارنة.
  6. evaluate()،substitute()وBoundedSearchهي تعبيرات المفردات والحلول.
  7. execute()يُعد المساراتsolve_returns()يطلب كل ورقة مجموعة مدخلات.
  8. grade_ir_o0()،grade_ir_o1()،percent_change_ir_o1()وtotal_ir_o1()هي رفع اليدين مع عناوين تعليماتهم.

هناك ثلاثة أوامر أخرىpython3 code/main.py diff A.o B.oيختلف عن كائنات قائمتها بجوارها، و--imageيختلف الصور المحملةpython3 code/main.py paths grade O0يطبخ مسارات ودرجات وظيفة واحدة، paths total 8الحلقة مع حلقة.python3 code/main.py figure-dataيطبخ البيانات التي تضمها الرسم التفاعلي.

استخدمها

استخدم المختلف والتمريض في هذا الترتيب على اثنين من بناءات برنامجك الخاص.

  1. التقاط قائمة لكل كائن وترك function_record()التحقق من ذلك ضد البايتات، إصلاح القائمة قبل أي شيء آخر.
  2. تفصل ملفات الكائن أولاً وقرأ مرحلة كل مباراة واعتبروا مطابقات شكل الرسم التدفقية مقترحات حتى توافق توقيع ثان.
  3. تفريق الصور المحملة. وظيفة تنخفض من البايتات الدقيقة إلى البايتات المخفية تتحرك فيما يتعلق ببياناتها، وترتيب حسابية التحرك تسمى القسم الذي انتقل.
  4. لكل مطابقة، قم بمقارنة الجداول المرجعية. نفس الرمز مع ثابتات مختلفة هو وظيفة معدلة.
  5. إضافة مرحلة الأسماء ومقارنة عندما يكون في البناء رموز، إضافة ترتيب بنديف واستخدام النتيجة الهيكلية فقط لتصفية المراحل.
  6. عندما تقر أداة النسبة، اكتشف أي بايتات دخلت في ذلك قبل مقارنتها مع الخاصة بك.
  7. للعمل الذي تريد إدخاله، اكتب IR مع عنوان واحد لكل بيان، تشغيله execute()مع خط على كل مقعد حلقة رمزية، وحل كل ورقة.
  8. قم بإجراء نفس الاستفسار عبر angr أو z3 عندما تكون متاحة ومقارنة حدود الفئة.

المختبر التفاعلي

المختبر "أ": خمسة توقيعات يدوياً

منcodeالإرشادات، مفتوحة Python:

bash
cd phases/13-tools-and-protocols/44-binary-diffing-and-symbolic-execution/code
python3 -q

أركض

python
from main import *
grade = {r.name: r for r in fixture_records("ledger-x86_64-O1.o")}["grade"]
grade.raw.hex(" ")
grade.masked_bytes() == grade.raw
grade.mnemonics
grade.cfg_shape()
grade.signatures()

اكتب الأربعة بايت في تعويض 0x26 من الوظيفة قبل الطباعة grade.rawثم إشغلي نفس الخطوط علىgradeمنledger-x86_64-O0.oو أعدtableالحواف فيgrade.edges. . .

المختبر ب: شاهد الانتقال كسر البايت هاش

python
case = grade_relocation_case()
case["layout"]
case["displacements"], case["rodataShift"]
case["objectBytesEqual"], case["imageBytesEqual"], case["maskedImageBytesEqual"]

الحساب0x100110 + 0x14 - 0x10003aعلى الورق قبل أن تقرأdisplacementsثم تغيير القاعدة فيload_image()إلى 0x400000 و تأكد من عدم تغيير التنقلات، لأن كلا العمليات تتحرك معا.

المختبر (ج): التطابق الكاذب والترتيب الذي يمنعه

python
report = diff_fixtures("ledger-x86_64-O1.o", "ledger-x86_64-O2.o")
[(m.left.name, m.right.name, m.stage) for m in report.matches]
report = diff_fixtures("ledger-x86_64-O0.o", "ledger-x86_64-O1.o")
[(m.left.name, m.right.name, m.stage, m.names_agree) for m in report.matches]
report = diff_fixtures("ledger-x86_64-O0.o", "ledger-x86_64-O1.o", stages=BINDIFF_ORDER)
[(m.left.name, m.right.name, m.stage) for m in report.matches]

طباعةrecords(...)["percent_change"].cfg_shape()لـ-O0وgrade_labelلـ-O1ثم اكتب مرحلة سادسة التي تُشجّل النظرية النظرية المرتبة، لذا النظام لم يعد مهمًا، وشاهد ما إذا كان يفصلهم.

المختبر D: المسارات والحدود

python
report = grade_paths("O0")
[(p["trace"], p["condition"], p["returns"]) for p in report["paths"]]
report["returns"]["4"]
total_paths(2), total_paths(4), total_paths(8)
total_paths(64, step_limit=24)["truncated"]

التغييرSCORE_DOMAINإلىrange(0, 110)و إعادة التشغيلgrade_paths("O0"). الصف ل 0 تقلص إلى 60 مدخلات والتحققين المتقاطعين لا يزال قائما. ثم حدد النطاق إلى range(90, 100)و قراءة أي أوراق لا نموذج على الإطلاق.

مختبر التدريب

أطلق على (بينديف) على المرافق وقارنها مع النتائج الثلاثة التي لديك بالفعل

المتطلبات:

  • قم بتثبيت امتداد BinExport في Ghidra 12.1.4 واستيراد البرامج الثلاثة الكبيرة. سجل علامة إصدار BinExport والإصدار Ghidra.
  • قم بتثبيت خط الأوامر بـ " بيني ديف 8 " و قم بتحقيق-O0مقابل-O1و-O1مقابل-O2النتائج مع خيار التشابه فقط.
  • التقاط التشابه والثقة لكل وظيفة في code/fixtures/مع الأوامر الدقيقة في build_fixtures.sh. . .
  • التمديدtool_comparison()معbindiffعمود وإضافة اختبار الذي يقارن مجموعة بنديف المتناسبة على -O1مقابل-O2مع مجموعة الكلمات المُغطاة في الدروس
  • اكتب فقرة واحدة تسمي خوارزمية بنديف المستخدمةgradeو ما إذا كان مقارنة الصور المحملة.

النجاح يعني أن الديمو الطباعة أربعة أعمدة أداة لكل وظيفة والاختبار الجديد يذكر مساوية واحدة أو فرق واحد شرح.

درساً أساسياً

هذا الدروس يتضمنoutputs/skill-binary-diffing-and-symbolic-execution.md. استخدمها لتحويل اثنين من المجموعات والعمل إلى فرق مرحلي مع نوعية محددة لكل مباراة، وشرح كل وظيفة غير متطابقة أو تغير، وتقرير المسار مع مجموعة مدخلات حل لكل ورقة والحدود التي أنتجتها.

تحقق من ذلك

أطلق الظهور والجملة:

bash
cd phases/13-tools-and-protocols/44-binary-diffing-and-symbolic-execution
python3 code/main.py
python3 -m unittest discover -s code/tests -v

يجب أن تثبت التحقق:

  • الجداول الرمزية تعطي الأدوات الأربعة بحجم 46، 118، 66، 39 في -O0، 16 ، 46 ، 31 ، 63 في -O1، و 16 ، 46 ، 140 ، 63 في -O2
  • الموقع.rela.textسجلات -O1المادة تصف بأنهاllvm-objdump -rيطبعهم
  • كل تعليمات قائمة تقع في نطاق الرمز و بايتها تساوي الكائن ، و تغير بايت يرفع
  • totalفي-O1لديه خمسة كتلة، خمسة حواف، و حلقة ذاتية واحدة، وتشكل سلسلة هي تحديد
  • gradeفي-O0يسترد خمسة أهداف من طاولة القفز.rela.rodata" ولديه ثمانية كتلة و 11 حافة "
  • بدون الطاولةgradeفي-O0يصل إلى 82 بايت في أربع كتلة
  • percent_changeفي-O0وgrade_labelفي-O1لديهم نفس الشكل من أربعة كتلة
  • تتفق المفاحشات الدقيقة والتمسكة على كل وظيفة من الأشياء التي يمكن نقلها
  • -O1و-O2مشاركة البايتات لثلاث وظائف، -O0و-O1لا يشارك
  • الجدول المرجح من gradeيقرأ1, 2, 3, 4, 4و قراءة المرشح1, 2, 3, 4, 3
  • أماكن الشحن.text،.rodataو.rodata.str1.1حيث وضعهم (غيدرا) في كلا البرامج
  • R_X86_64_PC32مكتوب علىS + A - Pو يعطي الاضاحة 122 وR_X86_64_64الإدخالات في .dataتلقي عناوين سلسلة
  • gradeيتفق البايتز في الأشياء ويتفاوت في الصور بتحوّل 0x70, ويعيد التخفيض المقابلة
  • -O1مقابل-O2يطابق ثلاثة وظائف على البايتات الدقيقة و totalباسمها . نظرية الصورة تطابقgradeبواسطة البايتات المخفية ذات الشبيهة 1 - 1/46
  • ترتيب الدروس ينتج مطابقة واحدة كاذبة على شكل الرسم التدفق-O0مقابل-O1، و ترتيب بنديف يطابق كل أربعة من الاسم
  • يطابق مرشح اللمسات على البايتات ويفشل في البيانات المرجعية
  • نسبة ليفينشتاين تعيد إعادة إنتاج 0.130435, 0.106061, 0.269841, 0.171429, 0.426829 على 82 بايت، ونسبة البايتات المتنقلة radiff2 طباعة مع عمليات التنقل المطبقة
  • مجموعة MATCH radiff2 هي مساوية لمرحلة البايتات الدقيقة، و Ghidra بايت و التوصيات المتساوية هي المجموعات الدقيقة و المخفية لمشاهدة الصورة
  • غيدرا وجدت أسماء فقط على-O0مقابل-O1، مع تشابه 1.0 و 10,0 على كل مباراة
  • يغطى IR المرفوع يدويا كل تعليمات مدرجة مرة واحدة، ويستمر المقيّم في تعبيرات C
  • gradeلديه خمس مسارات في-O0مع ظروف التبديل و اثنين في -O1مع نفس الفئات
  • الفئات المحدودة 60 إلى 69، 70 إلى 79، 80 إلى 89، 90 إلى 109 مساوية للجوانب في جميع المستويات الثلاثة و z3، مع 5 و 2 حالة مقصورة، ومدى الوصول إلى حجر 90 إلى 109
  • لا يوجد نموذج في الحدود أو في angr أو في z3 ، و z3 يثبت أن القائمة تساوي مفكّل المصدر
  • كلpercent_changeالنموذج من البحث المحدود، angr، و z3 تقييم إلى القيمة المطلوبة
  • totalيعطي 3، 5، 9 مسارات مع مجموعات مثلث، نفس angr، والخطوة القفز يعود 22 ويقصر 2
  • البيانات الرقمية تحمل كل من الرؤى وأرقام التنقل وخمسة أوراق مع مجموعات المدخلات الخاصة بها، ووضع الوحدة نفس البيانات

أساليب فشل الإنتاج

FailureWhat the weak tool reportsWhat the analysis must prove
Byte hash on a loaded image"grade modified" between two builds with identical codeThe field offset, the two displacements, and the section shift; the masked hash matches
Masked hash on a relocatable object"masking made no difference"The fields were already zero; the relocation records and the referenced constants carry the change
Flow-graph shape aloneA confident pair of unrelated functionsA second signature agrees, or the names contradict and the match is dropped
Names before structure on a stripped buildNothing matchesThe structural stages with their qualities, and the unmatched list
A ratio compared across tools"radiff2 says 0.43 and the lesson says 0.30"Which bytes each side fingerprinted; 82 bytes without relocations, 118 with
Same code, different constant"exact match"The table read through the relocation and the bounds check
One model reported as the input"the score is 90"The class 90 to 109 with its count, and the bound it was found in
Bounded search reported as unsat"no input gives -133"Unsat inside the bound only; z3 finds 1073741823 outside it
Symbolic loop without a boundA timeoutThe bound or the cap, the paths returned, truncated, and never started
Closed tool described as runNumbers with no captureA capture file with the command and version, or a sentence saying documentation only

قاعدة العمليات

تطابق على توقيع واحد في وقت واحد، وقبل فقط القيم الفريدة على كلا الجانبين، والحفاظ على المرحلة ونوعيتها مع الموافقة. تفصل الأشياء والصور المحملة وتفسير كل وظيفة التي تغير المرحلة بين الاثنين. إدراج المسارات مع حلول في كل فرع، وتعادل كل حلقة رمزية، وتقديم بيان مجموعة المدخل مع حد لها. نموذج واحد بدون حد هو عينة.

المزيد من القراءة

This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.

Browse the complete course catalog or open this lesson on GitHub.