Phase 13: Tools & Protocols

الاتصالات والإطارات المتعددة: النظام V و Windows x64 و AArch64

يظهر التفكيك الذي يقرأه المرجسمه. فقط ABI يقول ما تعنيه تلك السجلات، و ABI يتم اختيارها من قبل عنوان الموضوع، لذلك هذا الدروس يقرأ الرأس أولا ثم يفتقد كل سجل ضد القاعدة التي وضعته هناك.

Type: Build

Languages: Python, C, x86-64 and AArch64 assembly

Prerequisites: Phase 13 · 32 (ELF from scratch), Phase 13 · 33 (disassembly and control flow)

Time: ~140 minutes

أهداف التعلم

  • اختر الاتفاقية المكالمة من عنوان الموضوع: ELF x86-64 هو نظام V psABI، COFF AMD64 هو مايكروسوفت x64, ELF AArch64 هو AAPCS64, Mach-O arm64 هو تغير أبل.
  • قم بتفكيك خط البداية لـ"بايت" من وظيفة واحدة ب"بايت" لكل ABI ووضع كل سجل مدفوع وعنوان العودة ومؤشر الإطار في عكسها من مؤشر كومة الدخول.
  • إدخال سجلات المعلمات للعمل من السجلات التي تقرأها قبل أن تكتبها، وفرق الحجج الكبيرة من الحملات فوق مؤشر الكبيرة الدخول.
  • أخبر تسلسلات السجل المستقل للنظام V من فتحات الموقف من مايكروسوفت x64، وكلاهما من معدادات NGRN و NSRN من AAPCS64.
  • تحقق من كل استنتاج ضد توقيع المصدر والقاعدة في المواصفات، والمدمج الخاص بيانات التسريح في .pdata،.xdataو.eh_frame. . .
  • مقارنة كيفية Ghidra، IDA، Binary Ninja، radare2، rizin، و Angr اسم واسترداد نفس الحقائق، وتسجيل حيث انتاجها لا يوافق مع المصدر.

المشكلة

لقد قمت بتجميعهاconvention.cلـ لينكس x86-64 في -O2وطلب من radare2 6.2.4eight_argsلقد أجاب بسبعة:rdi،rsi،rdx،r8،r9،rsp+0x8وrsp+0x10المصدر C لديه ثمانية معايير.%rcxمرة واحدة بالضبط، فيleaq (%rdx,%rcx), %rax، والحصول على المتغيرات في الأداة لم يحسب سجل يظهر فقط داخل عنوان.

ثم قمت بفتح نسخة Windows لنفس الملف في rizin 0.9.1.amd64ووجدتr8،rcx،rdxو ثلاث فتحات كومة. الكائن هو COFF، لذلك الاتفاقية هي مايكروسوفت x64, الحجة الرابعة السجل هو r9هناك أربعة فتحات في كومة، ويتفوت الأدوات في نفس المصدر

قائمة هي سلسلة من التعليمات. اتفاقية الدعوة هو عقد يعيش خارج القائمة: التي تسجل الحملات الحجج التي يجب أن يحفظها المدعو، حيث العنوان العائدة وحجج كومة الجلسة، وما يجب أن يترك المدعو فوق مؤشر كومة. أربع وثائق تحدد العقود التي تهم هنا. النظام V AMD64 psABI (إصدار 1.0 ، بناء بتاريخ 12 مارس 2025) القواعد 3.2.1 إلى 3.2.3. مؤتمر مكالمة Microsoft x64 ، واستخدام كومة ، وصفحات المبادئ والإبيلوج (تاريخ الصفحة من 2018-12-17 إلى 2025-03-19). إصدار Arm AAPCS64 2025Q4 (23 يناير 2026) القواعد 6.1 إلى 6.9. أوراق منصة أبل arm64 هذا الدروس يقرأ تلك القواعد، يطبقها على ملف واحد C مرتبة ثلاث طرق، ويعمل على بناء المحلل الذي يحول قائمة إلى قائمة معقولة من مواقع المعلمات، سجلات مدخنة، وتعويضات الإطار.

واحد من الرؤساء يختار كتاب القواعد

convention.cلديه اثني عشر وظيفة: leaf_add،eight_args،mixed،by_value،big_ret،sum_varargs،keeps، وخمسة من المُتصلينexternتعمل بنفس الأشكال.long long، لأنlongهو 4 بايت على هدف MSVC و 8 بايت على الآخرين، وهياكل تغير تغييرات الحجم الاتفاقية.-target x86_64-unknown-linux-gnu،x86_64-pc-windows-msvcوaarch64-unknown-linux-gnuفي-O0و-O2وarm64-apple-macosفي-O2لا يوجد عناوين لينكس أو ويندوز مثبتة، لذلك يعلن الملف ما يحتاجه ويشمل فقط كلانغ الخاص stdarg.hوstddef.h. . .

describe_object()فيcode/main.pyيقرأ الرقم السحري البايت 4 وحقل آلة واحدة ويعد العقد:

HeaderFieldValueRulebook
7f 45 4c 46 ELFe_machine at offset 0x1262System V AMD64 psABI
64 86 COFFMachine at offset 00x8664Microsoft x64
7f 45 4c 46 ELFe_machine183AAPCS64
cf fa ed fe Mach-O 64cputype at offset 40x0100000cAAPCS64 with Apple differences

العقود الثلاثة تختلف على كل سطر تقريبا من الجدول التالي. يتم اقتباس كل قيمة من الوثيقة المذكورة في سطر العنوان، ويتم التحقق من كل واحدة من خلال اختبار ضد العلامات.

RuleSystem V psABIMicrosoft x64AAPCS64
Integer arguments%rdi %rsi %rdx %rcx %r8 %r9, next free registerRCX RDX R8 R9, by positionx0 to x7, by NGRN
Floating-point arguments%xmm0 to %xmm7, next free registerXMM0 to XMM3, by positionv0 to v7, by NSRN
Integer result%rax, then %rdxRAXx0, then x1
Floating-point result%xmm0, then %xmm1XMM0v0
Result too large for registersaddress passed in %rdi "as if it were the first argument", returned in %raxpointer in RCX, arguments shifted right, returned in RAXaddress in x8, x0 to x7 untouched
Callee-saved%rbp %rbx %r12 to %r15RBX RBP RDI RSI RSP R12 to R15, XMM6 to XMM15r19 to r29, SP, low 64 bits of v8 to v15
First stack argument on entry8(%rsp)40(%rsp), above a 32-byte shadow store0(sp)
Below the stack pointer128-byte red zone"considered volatile"no red zone (Apple: 128 bytes)
Alignment at the call(%rsp + 8) multiple of 16 on entry16-byte aligned outside prolog and epilogSP mod 16 = 0
Variadic marker%al holds an upper bound on vector registers usedfloats duplicated in the integer registernone in registers; Apple uses 8-byte stack slots

النظام V: تسلسلين مستقلين من السجلات ومناطق حمراء

صABI 3.2.3 تصنف كل ثمانية بايت من كل حججة INTEGER أو SSE أو MEMORY ثم تعيين السجلات من قائمتين لا تتفاعل. "INTEGER" تأخذ "السجل المتاحة التالية من التسلسل %rdi، %rsi، %rdx، %rcx، %r8 و %r9". SSE تأخذ %xmm0إلى%xmm7. "إذا لم يكن هناك سجلات متاحة لأي ثمانية بايت من الحجج، يتم نقل الحجة بأكملها على كومة" و "يتم دفع الحجج الذاكرة على كومة في ترتيب معاكس (من اليمين إلى اليسار).

eight_args(a, b, c, d, e, f, g, h)في-O2هو 27 بايت:

text      10: 48 01 fe                     	addq	%rdi, %rsi
      13: 48 8d 04 0a                  	leaq	(%rdx,%rcx), %rax
      17: 48 01 f0                     	addq	%rsi, %rax
      1a: 4c 01 c0                     	addq	%r8, %rax
      1d: 4c 01 c8                     	addq	%r9, %rax
      20: 48 03 44 24 08               	addq	0x8(%rsp), %rax
      25: 48 03 44 24 10               	addq	0x10(%rsp), %rax
      2a: c3                           	retq

ستة سجلات، ثم حمولتين في8(%rsp)و16(%rsp). الشكل 3.3 من psABI يضع "حجة الذاكرة 8byte 0" في 16(%rbp)متى%rbpهو قاعدة الإطار، والتي هي 8(%rsp)عند دخول قبل أي إضغطgهو في الثامنةhفي 16

mixed(int i, double d, long long l, float f)يظهر القائمة الثانية.%ediو%rsi، أول و ثانيا INTEGER سجلات.%xmm0و%xmm1، السجلات الأولى والثانية SSE.cvtsi2sd %edi, %xmm2و%xmm2هو سجل الخدش الذي يكتبه الوظيفة قبل قراءته. تحليل يعالج وجهة cvtsi2sdكما يختلق القراءة حجة نقطة عائمة ثالثة.mixedكـ(double arg1, double arg2, double arg3)فيxmm0،xmm1،xmm2. . .

by_value(struct pair p)يمر على 16 بايت من الهيكل كـ 2 INTEGER 8 بايت في %rdiو%rsi، ويعيدها بنفس الطريقة:leaq 0x1(%rdi), %rax; leaq -0x1(%rsi), %rdx; retq. .big_ret(long long seed)يعود 32 بايت، وهو ذاكرة الفئة، ويقول psABI "المدعو يوفر مساحة لقيمة العودة ويمر عنوان هذا التخزين في %rdi كما لو كان الحجة الأولى". seedيتحرك إلى%rsi، وبدأت الوظيفة بـmovq %rdi, %raxلأن " عند العودة %rax سوف تحتوي على العنوان الذي تم إدخاله من قبل المتصل في %rdi".

المنطقة الحمراء هي التوقيع الآخر للنظام V. psABI 3.2.2: "منطقة 128 بايت خارج الموقع الذي يشير إليه %rsp تعتبر محجوزة ولا يمكن تعديلها بواسطة معالجات الإشارة أو المقاطعة".-O0،eight_argsهوpushq %rbp; movq %rsp, %rbpثم ستة متاجر إلى-0x8(%rbp)من خلال-0x30(%rbp)بدون أيsubqالمتاجر تقع بـ 48 بايت تحت مؤشر الكمبيوتر-O2بناءsum_varargsيخصص 88 بايت مع subq $0x58, %rspثم يكتب مساحة حفظ السجل في -0x58(%rsp)إلى-0x80(%rsp)128 بايت تحت مؤشر كومة، المنطقة الحمراء بأكملها.-mno-red-zoneوleaf_addيكتسبpushq %raxوaddq $0x8, %rspليحافظ على 8 بايت من السكان المحليين فوق المؤشر

إضافة مسجل واحد. "%al يستخدم كحجة مخفية لتحديد عدد السجلات المتجهة المستخدمة"، الحدود العليا من 0 إلى 8. call_varargsيضعها معxorl %eax, %eaxفي-O2وmovb $0x0, %alفي-O0. .sum_varargsيقرأها أولاً: testb %al, %al; jeيقفز الثامنmovaps %xmmNيحتفظ عندما لم يتم استخدام سجل المتجه.

مايكروسوفت x64: المواقف، متجر الظل، و لا منطقة حمراء

قواعد مايكروسوفت هي موضعية. "تتم تمرير الحجج الكاملة في السجلات RCX ، RDX ، R8 ، و R9 . يتم تمرير حجج النقطة العائمة في XMM0L ، XMM1L ، XMM2L ، و XMM3L. " و" يتم تمرير أي حجج النقطة العائمة والدقة المزدوجة في المعلمات الأربعة الأولى في XMM0 - XMM3 ، اعتمادا على الموقع. "mixedيصل كـ%ecx،%xmm1،%r8،%xmm3: الفراغ 0 هو int، لذلك RCX؛ فتحة 1 هي مزدوجة ، لذلك XMM1السباق 3 هو عائم، لذلكXMM3. .XMM0وXMM2إبق فارغًا

يجب على المتصل أيضاً مغادرة الغرفة. "يجب على المتصل دائمًا تخصيص مساحة كافية لتخزين أربعة ملامح السجل، حتى لو لم يأخذ المتصل العديد من الملامح". الصفحات تدعوها متجر الظل أو عناوين المنزل، والحظير الأربعة "مملوكة بشكل فعال للعمل المطلوب". عند الدخول 0(%rsp)هو عنوان العودة8(%rsp)إلى39(%rsp)هذه هي المنازل الأربعة، والحجة الأولى على كومة هي في40(%rsp). .eight_argsفي-O2يقرأ0x28(%rsp)،0x30(%rsp)،0x38(%rsp)،0x40(%rsp): 40، 48، 56، 64

الجانب المكالم يظهر الحسابcall8في-O2هوsubq $0x48, %rspثم متجر من 5، 6، 7، 8 في 0x20(%rsp)إلى0x38(%rsp)قبل ذلكmovl $1, %ecxو الأصدقاء. 72 بايت هو 32 لتخزين الظل، 32 لأربعة حجج كومة، و 8 حتى عنوان العودة هو على حدود 16 بايت. call_varargsلا يزال يكتب الحجج و لا يزال يخصصsubq $0x28, %rsp: 32 للمخزن الظل و 8 للمواءمةkeepsيدفع ثلاثة سجلات غير متطايرة (24 بايت) ثم subq $0x20, %rsp، لذلكextيجد مخزن الظل الـ32 بايت تحت عنوان العودة

تتبع القواعد الخاصة بها. "أي حججة لا تناسب 8 بايت، أو ليست 1، 2، 4 أو 8 بايت، يجب أن تمر عبر مرجع". و "الحجج 16 بايت يتم مرجعها". by_valueلذلك يتلقى مؤشراً لنسخة في %rdx، بعد مؤشر النتيجة المخفية في %rcx: "يجب على المدعو تخصيص الذاكرة لقيمة العودة وإرسال مؤشر لها كحجة أولى. يتم تحويل الحجج المتبقية بعد ذلك إلى الحجة الواحدة إلى اليمين". call_pairيُبني النسخة في 0x20(%rsp)معmovaps، يمرleaq 0x20(%rsp), %rdx، يمر بمضخة النتيجةleaq 0x38(%rsp), %rcx، ويقرأ.bعودتي من0x40(%rsp). . .

لا توجد منطقة حمراء. "يعتبر كل الذاكرة خارج عنوان RSP الحالي متقلبة: قد يقوم نظام التشغيل أو جهاز إزالة الحذاء بإعادة كتابة هذه الذاكرة خلال جلسة إزالة الحذاء المستخدم أو معالج إزالة الحذاء".-O0 leaf_addيحتاج 8 بايت من المحليين و يحصل عليهم مع pushq %raxعند دخول وpopq %rcxقبل ذلكretq، إرشادات واحدة بدلاً منsubqوaddq. صفحة الاستخدامات المتعددة تعريف الورقة التي يمكن أن تفعل هذا: "عمل الورقة هو واحد لا يتطلب إدخال جدول الوظائف. لا يمكن أن تجري تغييرات على أي سجلات غير متطايرة، بما في ذلك RSP".

يطلق Variadic على سجلاتهم. "للمهام المتغيرة أو غير النموذجية، يجب أن يتم نقل أي قيم نقطة عائمة في السجل العام المقابلة". sum_varargsفي-O2المتاجر%rdx،%r8،%r9إلى0x18(%rsp)،0x20(%rsp)،0x28(%rsp)بعد واحدpushq %rax، وهو تعويضات الدخول 16، 24، 32: المنازل في المعلمات السجل الثاني، الثالث، والرابع.va_listهوleaq 0x18(%rsp), %rax، منزل%rdx، أول حجة غير مسموح بها

AAPCS64، وما تغيره Apple

AAPCS64 6.8.2 يمر قائمة القواعد مع مقاسين. C.9: يتم نسخ الحجة التكاملية "إلى الأجزاء الأقل أهمية في x[NGRN]" وزيادات NGRN. C.1 يفعل الشيء نفسه للحجج في النقاط العائمة مع NSRN. C.12: مركبة من أقصى حد 8 - NGRNيتم "نسخ الكلمات المزدوجة في سجلات ذات الغرض العام متتالية". يحدد C.13 "تعيين NGRN إلى 8" بمجرد أن يذهب الحجج إلى كومة، لذلك لا يعود أي شيء إلى السجلات بعد ذلك. eight_argsاستخداماتx0إلىx7و لا يلمس أبداً الكتلةmixedهوw0،d0،x1،s1. .by_valueهوx0وx1في الداخل والخارج

6.9 يقول نتيجة التي سوف يتم إرسالها في السجلات "يتم إرجاعها في نفس السجلات"، وإلا "يجب إرسال عنوان كتلة الذاكرة كحجة إضافية للعمل في x8". big_retيكتبstr x0, [x8]،stur q0, [x8, #0x8]،str x9, [x8, #0x18]و لا يكتب أبداًx0. .call_bigالمجموعاتmov x8, spوseedيبقى فيx0، لأن 6.9 يضيف "لا يوجد شرط على الجهاز للحفاظ على القيمة المخزنة في x8" و x8ليس أحد سجلات الحجج.

6.1.1: "يجب على دعوة فرعية الروتين الحفاظ على محتويات السجلات r19-r29 و SP. " 6.4.5.2: في واجهة عامة "SP mod 16 = 0". الدرجة التدريجية هي كاملة التنزيل و "لا يسمح لأي خيط بالوصول (للوصول إلى القراءة أو الكتابة) للمنطقة غير النشطة" أسفلها، لذلك لينكس -O0 leaf_addالإصداراتsub sp, sp, #0x10لـ 8 بايت من السكان المحليين حيث استخدم النظام V المنطقة الحمراء

6.4.6 تعريف سجل الإطار: "سجل الإطار من قيمين 64 بت على كومة ... يجب أن تشير أدنى كلمة مضاعفة معلقة إلى سجل الإطار السابق والأكبر كلمة مضاعفة معلقة يجب أن تحتوي على القيمة التي تم تمريرها في LR عند دخول الوظيفة الحالية. " و" موقع سجل الإطار داخل إطار كومة غير محدد. " تشير المزج المواقع في هذا الملف الواحد. keepsفي-O2على لينكس يضع السجل في الأسفل مع stp x29, x30, [sp, #-0x30]!; mov x29, spنفس الوظيفة في-O0يضعها في القمة مع sub sp, sp, #0x20; stp x29, x30, [sp, #0x10]; add x29, sp, #0x10. . .

يحتفظ مذكرات Apple arm64 بالسجلات والمواءمة وتغيير الإطار والمنطقة الحمراء والدعوات المتغيرة. "يجب على سجل مؤشر الإطار (x29) دائمًا معالجة سجل الإطار الصالح. قد تختار بعض الوظائف ، مثل وظائف الورق أو دعوات الذيل ، عدم إنشاء إدخال في هذه القائمة".keepsيوفّرx22, x21, x20, x19أولاً و يضع القائمة على القائمة:stp x29, x30, [sp, #0x20]; add x29, sp, #0x20. "المسجلات الاحتياطية للمنظمات x18. لا تستخدم هذا السجل. " "المنطقة الحمراء ARM64 تتكون من 128 بايت مباشرة تحت مؤشر كومة" ، والصوت لا يزال ينبعث sub sp, sp, #0x10للـ-O0ورقة، لذلك لا يستخدمها المجمع بشكل افتراضي. يتم تعيين الحجج المتعددة "لعدد المناسب من فتحات كومة 8 بايت" و "أنواع va_list هو اسم مستعار ل char*". call_varargsفي متاجر " آبل " من 10، 20، 30 إلى [sp]،[sp, #8]،[sp, #0x10]و يمر فقطw0؛ تمرير إعداد لينكس w1،w2،w3و التصويتات التالية معb extvaالتفاحsum_varargsيقرأadd x8, sp, #0x10، مؤشر مكالمة المتصل ، كما هو va_list؛ لينكس sum_varargsيوفّرx1إلىx7وq0إلىq7في إطار 224 بايت ويقوم بتبديل حقل الهيكل __gr_offsإلى -56 و __vr_offsإلى -128 مع واحد mov x8, #-0x38; movk x8, #0xff80, lsl #32. . .

الرموز تختلف أيضاً. ماخ-او يُسجل كل رمز في "سي"_، لذا الإدراج يظهر_keepsوالعمل الأول يظهر تحت العلامة الخاصةltmp0. المحلل يُعيد تسمية العلامات عبر جدول الرمز

فك المخططات الأولى يدوياً ثلاث مرات

keeps(int n)مكالماتext(i)في حلقة ويحافظn،iوaccعلى طول المكالمة، لذلك كل ABI يجب أن حفظ السجلات. اقرأ أول البايتات من-O2بناء لكل هدف

النظام V، 4 بايت:

  1. 55هوpush r64مع السجل في القطع الثلاثة السفلية: 50 + 5،%rbpعمق 8%rbpتم حفظها عند تعويض الدخول -8.
  2. 41 56: 41هل REX مع Bالمجموعة56هو50 + 6. REX.B تمتد من 6 إلى 14: pushq %r14في -16.
  3. 53هو50 + 3: pushq %rbxفي -24.

ثلاث دفعات هي 24 بايت. عنوان العودة يضيف 8 و 32 هو مضاعف 16 ، لذلك callq extداخل الحلقة متوافقة بدون subqلا يوجدmovq %rsp, %rbpلذا هذه البناء لا تملك مؤشر الإطار%rbpكمسجلة الوصول إلى الجهازacc(xorl %ebp, %ebp،addl %eax, %ebpالمشهد هو المرآة5b 41 5e 5d c3. . .

مايكروسوفت x64، 7 بايت:

  1. 56هوpushq %rsiعند -857هوpushq %rdiفي -16.53هوpushq %rbxفي -24. كل ثلاثة غير متطايرة هنا، وRDIوRSIكانت سجلات الحجج تحت النظام V.
  2. 48 83 ec 20: REX.W، opcode 83 /5مع 8 بتات فورية، ModRM ecهو11 101 100: subq $0x20, %rspعمق 56

56 + عنوان العودة هو 64 ، متوافق. 32 بايت هو مخزن الظل الذيextيسمح صفحة البيانات المختلفة فقط "إضافة RSP، ثابتة أو RSP، ثابتة [FPReg] ، تليها سلسلة من الصفر أو أكثر من 8 بايتات تسجيل الظهور والعودة أو jmp" ، والبايتات هي 48 83 c4 20 5b 5f 5e c3. . .

أرك 64، 16 بايت في أربع كلمات،

  1. a9bd7bfdهوstpمع مؤشر مسبق.10إختار سجلات 64 بت، بت 25:23 011إختار المؤشر المسبق، بت 22 هو 0 للمخزن. imm7 في بت 21:15 هو 1111010، وهو -6 ، مقياس 8: -48. Rt2 عند 14:10 هو 30، Rn عند 9:5 هو 31 (sp), Rt عند 4: 0 هو 29. stp x29, x30, [sp, #-0x30]!: مؤشر الدرج يسقط 48x29يذهب إلى -48 و x30إلى -40.
  2. f9000bf5هوstrمع تعويض غير مؤلف من 12 بت مقياس 8: imm12 في 21:10 هو 2 ، Rn هو sp، ريت هو 21 str x21, [sp, #0x10]، تعويض دخول -32.
  3. 910003fdهوaddفوري: imm12 هو 0، Rn هو sp، ردي هو 29mov x29, sp: مؤشر الإطار يشار إلى -48
  4. a9024ff4هوstpمع تعويض مؤلف: imm7 هو 4 ، مقياس إلى 32. Rt2 هو 19 ، Rt هو 20. stp x20, x19, [sp, #0x20]: x20في -16, x19عند -8

الإطار 48 بايت:x29عند 0x30في الثامنةx21عند 16، 8 بايت من التشغيل عند 24، x20في 32x19في 40، أقل كلمة في السجل تشير إلى السجل السابق والكلمة التالية تحتوي على LR، كما يتطلب 6.4.6. cmp w0, #0x1يقع بين المخزن الأول والثاني، قام المخطط بتحويله إلى المخطط، ويحمل المحلل مقارنة أو تعليمات حسابية بين عمليات كومة.

كتب المجمّع نفس الحقائق مرتين

تحليل المبتكر هو مشتق واحد. يقوم المُجمّع بإصدار آخر لـ (المتخفّف) ، ويجب أن يوافق الاثنان.

على ويندوز النتيجة الثانية هي.pdataو.xdata. بناء-O2كائن بدون-fno-asynchronous-unwind-tablesوllvm-objdump -hتظهر.xdataمن 0x34 بايت و .pdataمن 0x48 بايت. 0x48 هو 72, ست RUNTIME_FUNCTIONإدخالات من 12 بايت مع ثلاثة IMAGE_REL_AMD64_ADDR32NBكلّ منكم يُنقلsum_varargs،keeps،call8،call_varargs،call_pairوcall_big. وظائف الستة الأخرى هي الأوراق، ويقول صفحة التعامل مع الاستثناء "إذا لم يجد البحث إدخال جدول الوظائف، يفترض أن يكون الرمز جزءًا من وظيفة الأوراق، و RSP يُعطي إشارة العودة مباشرةً".

  • نعم.xdataالبايتاتkeepsهل هي01 07 04 00 07 32 03 30 02 70 01 60. .UNWIND_INFOيبدأ مع النسخة في 3 بتات و العلامات في 5 بتات: النسخة 1 ، لا العلامات. حجمProlog هو 7 ، CountOfCodes هو 4 ، FrameRegister و FrameOffset هي 0. كل UNWIND_CODEهو تعويض في المنتج الأول والبايت من رمز الخيارات والمعرفة. 07 32: في التسعير 7 ، والعمل 2 هو UWOP_ALLOC_SMALL، المعلومات 3 يعني3 * 8 + 8 = 32البايتات03 30: op 0 هو UWOP_PUSH_NONVOL, السجل 3 هوrbx. .02 70: rdi. .01 60: rsiيتم تخزين الرموز في ترتيب معاكس من التنفيذ، وتحوي نفس الأطراف الثلاثة وتوزيع 32 بايت كما البايت 56 57 53 48 83 ec 20- المُؤمنونsum_varargsالدخول هو01 01 01 00 01 02 00 00: إضافة 1 بايت مع رمز واحد،UWOP_ALLOC_SMALLمن 8 بايت. هكذا يرى المتحركpushq %rax: تخصيص، لأن %raxهو متطاير ولا يتم حفظ أي شيء.

على لينكس النتيجة الثانية هي.eh_frame، التي تعرّفها المادة 4.2.4 وترمز في القسم 6.4 من DWARF 5. llvm-dwarfdump --eh-frameعلى الكائن الذي يمكن نقله يطبخ FDE واحد لكل وظيفة ويحلR_X86_64_PC32التنقلات، حتى تكون النطاقات قابلة للاستخدام.keeps:

text  DW_CFA_def_cfa_offset: +16
  DW_CFA_def_cfa_offset: +24
  DW_CFA_def_cfa_offset: +32
  DW_CFA_offset: RBX -32
  DW_CFA_offset: R14 -24
  DW_CFA_offset: RBP -16

CFA هو مؤشر كومة قبل الدعوة، 8 فوق مؤشر كومة دخول، لذلك RBP -16هو تعويض الدخول -8، R14 -24هو -16, RBX -32هو -24, وأعمق تعويض CFA من 32 هو الإطار 24 بايت زائد عنوان العودة.keepsيقولDW_CFA_def_cfa: W29 +48معW29 -48،W30 -40،W21 -32،W20 -16،W19 -8هناك CFA هو مؤشر كومة الدخول نفسه، لذلك تعتبر التداعيات هي التداعيات الإطارية دون تحويل، ويتم تعريف CFA من x29بينما سجل الإطار على الهواءeh_frame_cross_check()يقدم هذا المقارنة لجميع 12 FDE من كلا الكائنات.call8تحت النظام V يدفع اثنين من الحجج الخارجة في منتصف الجسم، لذلك أعمق تعويض CFA هو 32 بينما إطار البروج هو 8، والتحقق يقارن أعمق مؤشر كومة الجسم يصل، 24 زائد 8.

ما الذي تسميه الأدوات هذا

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

Ghidra 12.1.4 (Apache-2.0).القواعد تعيش في ملفات مواصفات المُجمّع،.cspec، بجانب لغة "سليغ"x86-64-gcc.cspecيعلن عن<default_proto>اسمها__stdcall، "مستمد من نظام V التطبيقات واجهة ثنائية AMD64 معمليات المعالجة الهندسة المعمارية أبريل 2016"، مع <pentry>القوائم لـXMM0_QaإلىXMM7_QaوRDI, RSI, RDX, RCX, R8, R9, دخول كومة في التسويق 8 , a join_dual_classالقاعدة للأنواع التي تصل إلى 16 بايت، المخرجات XMM0_Qa, XMM1_Qa, RAX, RDXوhidden_returnللبقيةx86-64-win.cspecيعلن__fastcallمع أربعة<group>العناصر التي تتزامنXMM0_QaمعRCX،XMM1_QaمعRDX، وهكذا، والتي هي القاعدة الموضعية، مدخل كومة في التكفيف 40، convert_to_ptrبالنسبة لخطوط ذات 3، 5، 6 أو 7 بايت مع تعليق "يمكن إغلاق خطوط ذات حجم 8,16,32,64 بيت فقط للتسجيل"unaffectedالإدراجRBX RBP RDI RSI RSP R12إلىR15وXMM6إلىXMM15وlocalrangeمن كومة 8 إلى 39، وهو متجر الظل. AARCH64.cspecيعلن__cdeclوالذي يُدخل أولاًx8معstorage="hiddenret"، ثمq0إلىq7وx0إلىx7،convert_to_ptrلخطوط ذات 17 بايت أو أكثر، و killedbycallبما في ذلكx8مع تعليق "سجل الموقع غير المباشر للنتيجة ، والذي لا يعكس في قائمة المنتج". تدعى المرحلة النهائية لتحميل "مثيل عمل إقامة" ؛ المحللين "مثيل الاتفاقية الدعوة" و "مثيل إشارة التحميل". اختيار البرنامج "تقييم النمط" يختار النموذج الافتراضي.

IDA Pro and IDA Free (Hex-Rays, commercial; current release 9.4, build 9.4.260714).نوع الوظيفة هو إعلان C المحدد من خلال SetType، و "سوف يستخدم IDA معلومات النوع للتعليق على التفكيك مع المعلومات حول حجج الوظيفة". يتم كتابة المواقع التي لا تنتجها أي اتفاقية قياسية في اتفاقية IDA الخاصة: int __usercall func@<ebx>(int x, int y@<esi>)يضع النتيجة فيEBXوyفيESIو@<^12.4>أسماء موقع كومة حسب التداخل والحجم. __userpurgeنفس الشيء مع تنظيف كومة الكاليه نفس الصفحة قائمة__spoilsللكتلة المزججة__hidden،__return_ptrو__struct_ptrللحقائق الضمنية هذه الدروس تسترد يدويا. عمل "Decompile as call" من المتحلل يقبل __usercallالنموذج الأول للتعليمات الواحدة. IDA Free يدعم x86 و x86-64 فقط.

Binary Ninja 6.0 "Krypton" (Vector 35, commercial, with a Free edition that decompiles x86, x86_64, ARMv7, and AArch64).أPlatform"يحتوي على كل المعلومات المتعلقة بيئة تنفيذ الثنائي، وخاصة الاتفاقيات الدعوة المستخدمة، والنظام التشغيلي، والهندسة المعمارية" ويتضمن القائمة linux-x86_64،windows-x86_64،linux-aarch64وmac-aarch64، كل واحد مع default_calling_convention.CallingConvention- نعمint_arg_regs،float_arg_regs،callee_saved_regs،caller_saved_regs،int_return_reg،high_int_return_reg،float_return_reg، و 2 أعلام تشفر الاختلافات في هذا الدروس مباشرة:arg_regs_share_index"عندما يكون True، فإن الحجة Nth تستغرق فتحة Nth من كل من القوائم الإعدادية والسجلات العائمة بغض النظر عن نوعها" ، و stack_reserved_for_arg_regs، "مساحة الظل / المنزل المستخدمة من قبل Windows x64 الاتفاقية الدعوة". eligible_for_heuristics،required_arg_regsوrequired_clobbered_regsتحديد المواقف السرية. أنواع المنصات هي أصول C تحت types/platform/واحد لكل اسم منصة

radare2 6.2.4 (LGPL-3.0, run here). afclيردد الاتفاقيات التي يعرفها مكونات المكونات: amd64 amd64syscall dlang golang golang_abi0 ms p9 reg swiftلـ x86-64 و arm64 dlang golang p9 reg swiftلـ (أرك64). afcتقرير عن اتفاقية الوظيفة الحاليةafcrبصماتcc.amd64.arg0: rdiمن خلالarg5: r9وret0: rax، والملفات الشخصية هي ملفات SDB تسمىcc-ARCH-BITS.sdb. رادار2 اخترتamd64لـ (الـ) كائن ELF وmsلـ كائن COFF، وهو الانقسام الصحيح. afvقائمة بالحقائق والمتغيرات، و afsيطبخ توقيعاً على لينكس-O2الموضوعafvوجدت سبعة حجج لeight_argsو سقطتrcxعلى جسم ويندوز الذي وجدتهrcx, rdx, r8و أربعة فتحات و سقطتr9كلا السجلين المفقودين يظهرون فقط داخلlea. علىmixedلقد أبلغتdouble arg1 @ xmm0, arg2 @ xmm1, arg3 @ xmm2على لينكس ولا توجد حجج على الإطلاق على ويندوز. على AArch64 وجدتx0إلىx7لـeight_argsوبالنسبةbig_retلقد تم سردهاx0وdouble arg2 @ d1حيث يقرأ الوظيفةx8و تحميل ثابتة في q1كلّ شخصafsالتوقيع يبدأ بـvoidلأن نوع العودة لا يتم استنتاجها-O0حيث يتم تخزين كل حججة في الإطارafvوجدت جميع الحجج الثمانيةeight_argsمعrbp+0x10وrbp+0x18للزوجين

rizin 0.9.1 (LGPL-3.0, run here) and Cutter 2.5.0. afclالقوائمamd64 amd64syscall ms reg swift. .afcأعيدamd64لـ COFF، إذاً وجود ملف Microsoft لم يتم اختياره من النموذج. afiأدرجت سبعة حجج لـeight_argsعلى لينكس، مرة أخرى دون rcx، و على Windows r8, rcx, rdxمع ثلاث فتحات، بدون r9وبدون فتحة في0x40. .afvلا يوجد ، أمر الإدراج هوafvlكاتر هو الجانب الجانبي على (ريسين)

angr 10.0.3 (BSD-2, run here). CFGFastيليها CompleteCallingConventions(recover_variables=True)المجموعاتfunction.calling_conventionإلىSimCCSystemVAMD64،SimCCMicrosoftAMD64أوSimCCAArch64، في شكل ثنائي، و function.prototypeلقد استعادت جميع الحجج الثمانيةeight_argsعلى كل الهدف الثلاثة، المؤشر الخفي منbig_retعلى x86-64 ك (BOT*, long long) -> BOT*، هياكل الإشارة المشتركة للنوافذby_valueكـ(BOT*, BOT*) -> BOT*، و النظام V المتغير sum_varargsكـ(long long, ...)فجواته مختلفة عن الرادار2mixedعاد كـ(long long, long long, double, float)في النظام V و AArch64، تسجل الجهات الصحيحة بالترتيب الخطأ، لأن قائمة الأعداد الكاملة يتم طباعتها قبل قائمة العائمة.big_retعاد كـ(long long) -> double، لذاx8لم يتم إلقاء نظرة على الإجتماع ويتم قراءة مخازن المتجهة نتيجة لذلك ، وsum_varargsعدت مع 16 ملامح، كل السجل حفظ المساحة.

Others.هوبر 6.6.0 هو إزالة التجميع والتفكيك التجاري ل macOS و Linux؛ لم يتم تشغيل أو توثيق معالجة الاتفاقيات الخاصة به لهذا الدروس.frame infoوregister readيظهر المجمع Explorer القوائم الثلاث جنبا إلى جنب من المصدر، وهو أسرع طريقة لتحديد قاعدة قبل البحث عنها في البايت.

ConceptGhidraIDABinary Ninjaradare2 / rizinangrthis lesson
The convention objectprototype in a .cspeccalling convention keyword in the function typeCallingConvention on a Platformafc name, cc-ARCH-BITS.sdbSimCC subclassexpected_locations(abi, name)
Default per target<default_proto> per cspeccompiler settingPlatform.default_calling_conventionafc=, anal.ccby formatdescribe_object()
Argument registers<pentry> list, <group> for positional@<reg> in __usercallint_arg_regs, float_arg_regs, arg_regs_share_indexcc.NAME.argNARG_REGS, FP_ARG_REGSINT_ARG_REGS, FLOAT_ARG_REGS
Shadow storelocalrange stack 8 to 39implicitstack_reserved_for_arg_regscc.ms.argn=stackSTACKARG_SP_DIFFSTACK_ARG_BASE[WIN64] = 40
Hidden result pointerhidden_return, storage="hiddenret"__return_ptr, __hiddenreturn type too large for int_return_regnot modelledBOT* first argumentHIDDEN_RETURN_REG
Callee-saved<unaffected>__spoils lists the oppositecallee_saved_regsprofileCALLEE_CLEANUP and archCALLEE_SAVED
Assigning one to a function"Call Convention ID" analyzer, "Establish Function's Prototype"user or type libraryheuristic detection with required_arg_regsafc, afva, aaftCallingConventionAnalysisread-before-write plus the rulebook

بناءها

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

bashcd phases/13-tools-and-protocols/38-calling-conventions-and-stack-frames
python3 code/main.py

إنتاج هو تقرير JSON واحد. لكل من السبعة الأشياء يطلق على النموذج، والآلة، والإب.إي.بي، ولكل من الوظائف الثانية عشرة يقدم البايتات البروجوجية، والسجلات المحفوظة مع تعويضات الدخول، وحجم الإطار، ومؤشر الإطار، ومؤشر الإطار، ومؤشر المعلمات، ومؤشرات الحجج المتعثرة، والسفائر، ومؤشر العودة أو المخفي، وعمق الدعوة، ومؤشرات الخروج ومخازن المندعين. تنتهي كل وظيفة بمراجعاتها: القاعدة والقيمة المتوقعة من التوقيع والقيمة الملاحظة من البايتات، وما إذا كانت توافق. و ينتهي التقرير بالتحققين المتقاطعين والآلة التي يتم التقاطها. في 84 تحليل وظيفي، تم إجراء 489 عملية فحص ويتفق جميع 489.

الشكل المتوقع:

json{
  "objects": {
    "convention-x86_64-windows-O2": {
      "format": "COFF", "machine": "AMD64", "abi": "Microsoft x64", "checks": "73/73 agree",
      "functions": {
        "keeps": {
          "prologue": ["56  pushq %rsi", "57  pushq %rdi", "53  pushq %rbx", "48 83 ec 20  subq $0x20, %rsp"],
          "frameBytes": 56,
          "savedRegisters": [{"register": "rsi", "entryOffset": -8}, {"register": "rdi", "entryOffset": -16}, {"register": "rbx", "entryOffset": -24}],
          "parameterRegisters": ["rcx"],
          "returnRegisters": ["rax"],
          "calls": [{"callee": "ext", "depth": 56}],
          "checks": [{"rule": "Microsoft x64: the caller must always allocate ...", "expected": "at least 32 bytes ...", "observed": [56], "agree": true}, "..."]
        }
      }
    }
  },
  "sehCrossCheck": ["..."],
  "ehFrameCrossCheck": {"...": "..."}
}

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

  1. describe_object()يقرأ رأس ELF أو COFF أو Mach-O والجدول الرمزي ويرد ABI وقائمة الوظائف.
  2. parse_listing()يفرقllvm-objdump -d -rيحتفظ الهدف من نقل كل مكالمة وقفز، ويخرج التعليقات مع علامة النص المطلوب: #لـ AT&T//و;لـ AArch64 ، حيث #يُدخل فوريًا.
  3. effect_x86()وeffect_arm()تحويل تعليمات واحدة إلى قراءة، قراءة العنوان، كتابة، تحميل، المحلات التجارية، و دلتا مؤشر كومة. آخر أوبراند AT&T هو الوجهة؛ أول أوبراند AArch64 هو الوجهة باستثناء المحلات التجارية، المقارنة، والفروع. leaيقرأ عنوان ولا يحمل أي شيءmov،cvtsi2sd،setcc، والعبارة الصفرةxor r, rهو كتابة فقط. مكالمة تكتب مجموعة متقلبة كاملة. متجر مقدم للتصفية يتحركspقبل وصوله و بعد تحميل المرجعي
  4. analyze_function()يمر الجسم مرة واحدة حتى الأولى retأو قفزة الذيل. يتتبع عمق مؤشر كومة أقل من قيمته الدخول، لذلك عمل ذاكرةdisp(%rsp)هو في المواجهة المدخول disp - depthوdisp(%rbp)هو فيframe_pointer + disp. يسجل سجلات فئة الحجج التي يتم قراءتها قبل كتابتها، ويحمل في أو فوق أول سجل حجة كومة تعويض من ABI، وتخزين سجلات الحجج في الإطار، والوصول أسفل مؤشر كومة الحالية، والعمق في كل مكالمة.
  5. _return_registers()يحتفظ سجل النتائج عندما يكون آخر وصول له قبل الخروج كتابة. قراءة كعمل بيانات تقتل المرشح. قراءة كقاعدة عناوين لا، وهو ما يحافظ raxحيّة فيbig_retتحت مايكروسوفت x64 ، حيث movq %rcx, %raxيتبعها المتاجر من خلال (%rax). . .
  6. expected_locations()يطبق ثلاثة كتب القواعد على توقيع C: القائمة System V مع فئات ثمانية بايت، وفرق Microsoft الموضعية مع إشارات إشارة، و AAPCS64 معدادات x8لنتائج تتجاوز 16 بايت.
  7. run_checks()يُقارن الاثنين ويضيف قواعد الإطار: يجب حفظ السجلات المكتوبة التي يتم حفظها من خلال الدعوات، (rsp + 8) % 16 == 0أوsp % 16 == 0في كل مكالمة، 32 بايت من الظل في كل مكالمة مايكروسوفت، لا توجد إمكانية الوصول تحت المؤشر المتعثر تحت مايكروسوفت و AAPCS64 و ما لا يزيد عن 128 بايت تحت النظام V، و إيبيلوغ الذي يعكس المبادئ الأولية مع مؤشر المتعثر مرة أخرى في قيمة دخولها.
  8. seh_cross_check()وeh_frame_cross_check()قراءة بيانات التوقف عن التحول من الأشياء التي بنيت دون -fno-asynchronous-unwind-tablesو قم بتقارنةها مع تحليل المبدء

هناك ثلاثة أوامر أخرىpython3 code/main.py analyze convention-x86_64-windows-O2 keepsيطبخ وظيفة واحدةpython3 code/main.py object FILEيطبخ قرار الرأسpython3 code/main.py sehيطبع الرمز المفكّرUNWIND_INFOمن كل وظيفة لديها واحدة.

استخدمها

استخدم المحلل بهذه الترتيب على جسم جديد قمت ببناءه

  1. أركضpython3 code/main.py object FILE.oواكتب ABI الذي يسميه. إذا كان الرأس و إقامة أمرك لا يوافقون، توقف؛ واحد منهم خاطئ.
  2. القبضllvm-objdump -d -r FILE.oقراءة البايتز البروجوج والسجلات المحفوظة قبل أي شيء آخر، ومقارنة حجم الإطار مع الضغطات وال sub. . .
  3. اقرأ سجلات المعلمات وتعديلات الكمبيوتر ضد توقيع المصدر الخاص بك. سجل لا يفسر توقيع هو مؤشر مخفي، علامة متغيرة، أو سجل خدش الذي أخطأ المحلل مع حججة. الحالة الأخيرة هي خطأ في جدول التأثيرات. إصلاحها مع قاعدة عامة لهذا التعليم.
  4. اقرأ التحققات التي تختلف، إذا كانت هناك، كل اسم القاعدة التي تستند إليها، لذا أول شيء يجب التحقق منه هو القاعدة، ثم البايت، ثم المحلل.
  5. عندما يكون لدى الكائن بيانات إزالة، قم بالتحقق المتقاطع. مشتقات متفقتان هي أقوى دليل هذا الدروس تنتج.
  6. عندما يتم تثبيت أداة أخرى، التقاط المخرج مع الأمر الدقيق ومقارنة. حيث توافق لديك ثلاثة مشتقات. حيث يختلف لديك سجل محدد وتعليم محدد للنظر في، وهذا هو العثور على الدروس 35.

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

المختبر (أ): تعليم واحد، ثلاثة تأثيرات

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

bashcd phases/13-tools-and-protocols/38-calling-conventions-and-stack-frames/code
python3 -q

أركض

pythonfrom main import *
effect(Instruction(0, "48 8d 04 0a", "leaq", "(%rdx,%rcx), %rax"), SYSV)
effect(Instruction(0, "f2 0f 2a d7", "cvtsi2sd", "%edi, %xmm2"), SYSV)
effect(Instruction(0, "a9bd7bfd", "stp", "x29, x30, [sp, #-0x30]!"), AAPCS64)

اكتب القراءات والعنوان القراءة والكتابة والثلتا المتوقع قبل كل مكالمة ثم تغيير[sp, #-0x30]!إلى[sp], #0x30معldpوراقب التحرّك من دلتاsp_deltaإلىpost_sp_delta. . .

المختبر ب: إطار الحفظات

pythoninfo, listing = load_fixture("convention-aarch64-linux-O2")
keeps = analyze_function("keeps", listing["keeps"], info.abi)
keeps.saved
keeps.frame_pointer
[c.to_dict() for c in frame_cells(keeps)]

مقارنة التخفيضات مع رمز اليد أعلاه ثم تحميلconvention-arm64-macos-O2و تشغيل نفس الخطوط الثلاثة، سجل ينتقل إلى -16 و أربعة سجلات تقع تحتها. ثم تحميلconvention-x86_64-linux-O2-fpو اقرأsavedلـkeeps: مؤشر الإطار هو مرة أخرى، وكذلك هو pushq %raxوالذي وظيفته الوحيدة هي أن تقوم(rsp + 8)مضاعف 16 عند المكالمة.

المختبر (ج): قراءة قبل الكتابة على مخلوط

pythoninfo, listing = load_fixture("convention-x86_64-linux-O2")
mixed = analyze_function("mixed", listing["mixed"], info.abi)
mixed.param_registers
mixed.return_registers
expected_locations(SYSV, "mixed")["parameters"]
expected_locations(WIN64, "mixed")["parameters"]

قائمة النظام V هيrdi, xmm0, rsi, xmm1و قائمة مايكروسوفت هيrcx, xmm1, r8, xmm3الآن قم بتحميل كائن ويندوز وتشغيل الخطوط الثلاثة الأولى مرة أخرى ثم افتح رادار2 التقاط للكائن لينكس وبحث[afv mixed]: ثلاثة مزدوجة. ابحث عن التعليمات التي تفسر الثالثة.

المختبر D: رأي الثاني من المُحَرِّر

pythonfor row in seh_cross_check():
    print(row["function"], row["sizeOfProlog"], row["unwindPushes"], row["unwindAllocBytes"], row["agree"])
for row in eh_frame_cross_check("convention-x86_64-linux-O2-eh"):
    print(row["function"], row["cfiSaved"], row["cfiMaxOffset"], row["deepestStack"], row["agree"])

إبحث عنpushq %raxمنsum_varargsفي جدول SEH ويشرح لماذا يكتب رمز التسريح كمخصص. ثم العثور على call8في.eh_frameو أوضحوا 32

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

أضف هدف رابع و كتاب قواعد رابع

المتطلبات:

  • قم بتجميعconvention.cمع-target x86_64-apple-macos -O2و تلتقط قائمةهاdescribe_object()لاقراءة ماخ-او cputype0x01000007 و خريطه إلى نظام V psABI، الذي تتبعها أبل على x86-64, مع _علامة المُسبق
  • تحقق من أن كل وظيفة تتفق مع التحققات النظام V. سجل الفرق الوحيد الذي تجده في المبادئ الأولية: داروين يحتفظ بمؤشر الإطار في كل مستوى من التحسينات.
  • إضافة-fstack-protector-strongبناء من كائن لينكس x86-64 . تمديد المسح البروج حتى تحميل القناري من %fs:0x28و المتاجر تحت السكان المحليين مسجلة كـcanaryالخلية، والمقارنة قبل retكالشيك الذي يحرس المقال
  • إضافة اختبار يفشل عندما يعتبر متجر القناري حجة سلبية
  • اكتب الإطارwith_canary-الرمز النمطي يدوياً قبل تشغيل المحلل، وابق الرسم بجوار الاختبار.

النجاح يعنيpython3 code/main.pyيبلغ الكائن الجديد مع كل مراجعة توافق، وخلايا الإطار من وظيفة المحمية تظهر القناري بين السجلات المحلية والمنقذ.

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

هذا الدروس يتضمنoutputs/skill-calling-conventions-and-stack-frames.mdاستخدمها لتحويل كائن قمت بإنشائه، وإدراجها، وتوقيعات C إلى مواقع المعلمات، وتخطيط الإطار، سجل العودة، ومراجعة كل استنتاج ضد القاعدة التي تستند إليها ومع بيانات التنسيق المتكامل.cvtsi2sdأوxor r, rالمواقع كما يقرأ، و ينتهي بالخلاف الأول.

تحقق من ذلك

إشغال التجربة والسلسلة التحديدية:

bashcd phases/13-tools-and-protocols/38-calling-conventions-and-stack-frames
python3 code/main.py
python3 -m unittest discover -s code/tests -v

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

  • الرؤوس ELF و COFF و Mach-O لسبعة كائنات اسم نظام V و Microsoft x64 و AAPCS64 و Apple arm64
  • كل جدول رمزية من الأشياء يرد نفس اثني عشر وظيفة، مع ماخ-او _المقبل والـltmp0اللوحة حل
  • المصفح الرائد يحافظ على قائمةextكهدف المكالمة ويحافظ على AArch64 على الفور مثل #-0x30غير متأثر
  • leaq (%rdx,%rcx), %raxيقرأ سجلين من السجلات ولا يحمل أي شيءxorl %eax, %eaxوcvtsi2sdهي كتابة فقط ، مؤشر مسبقstpتحركاتspقبل المتجر و بعد التسجيلldpبعد الحمل
  • keepsفي-O2هو55 41 56 53على النظام V مع إطار 24 بايت و لا مؤشر إطار، 56 57 53 48 83 ec 20على مايكروسوفت x64 مع إطار 56 بايت، و a9bd7bfdأول على AArch64 مع السجل في -48
  • إنّ إعداد Apple يضع السجل عند -16 فوق أربعة سجلات مدخنة
  • كل وظيفة لديها مؤشر الإطار في -O0على لينكس ولا يوجد-O2و-fno-omit-frame-pointerيعيدها مع دفع التوجه
  • الموقع-O0يستخدم ورقة 8 بايت من المنطقة الحمراء تحت النظام V، pushq %raxتحت مايكروسوفت x64، و sub sp, sp, #0x10بموجب AAPCS64-mno-red-zoneيزيل استخدام المنطقة الحمراء
  • كل قصة تعكس مقدمتها ومرجع الدليل في الموقع
  • eight_argsيقرأ ستة سجلات وفرق 8 و16 ، أربعة سجلات وفرق 40 إلى 64 ، أو x0إلىx7، على مستويات التحسين
  • mixedهوrdi, xmm0, rsi, xmm1في النظام V و rcx, xmm1, r8, xmm3تحت مايكروسوفت x64 ، مع xmm0نتيجة لذلك على كلتا
  • يمر الهيكل البيط 16 في سجلين تحت النظام V و AAPCS64 وبتحديد خلف مؤشر مخفي تحت Microsoft x64
  • إنّه يُرجع إلى الـ 32 بايتrdi،rcxأوx8
  • القول المتغير يقرأ%al, المنازلrdx, r8, r9في 16، 24، 32، ينقذ x1إلىx7وq0إلىq7أو يقرأ مؤشر مكالمة المتصل على Apple
  • يضع المتصلون السجلات المتوقعة، ويحفظون 7 و 8 عند 0 و 8 أو 5 إلى 8 عند 32 إلى 56، صفر %alللدعوة المتغيرة، وإرسال عنوان البوفر النتيجة في rdi،rcxأوx8
  • جميع 489 عملية التحقق توافق على قواعدهم
  • الستةUNWIND_INFOالإدخالات تتطابق مع البداية و لا يوجد أي أوراق
  • 24 FDE تتطابق مع تعويضات السجل المحفوظ وأعمق مؤشر كومة
  • الوسيلة تسجل رادار2 amd64وms، (ريزن)amd64على كائن COFF، المفقود rcx، الثلاثة مزدوجة، و النماذج الأولية Angr
  • البيانات الرقمية المضمنة في وحدة الموقع تساوي خروج المحلل

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

FailureWhat the weak tool reportsWhat the analysis must prove
COFF object read as System Vrdi and rsi as arguments that the function never readsThe header says 0x8664; the convention is Microsoft x64
Register read only inside a leaSeven arguments for an eight-argument functionBase and index registers are reads
cvtsi2sd destination counted as a readA third double argument in xmm2The first write to xmm2 is a write; mixed has two SSE arguments
Positional slots read as sequencesxmm0 named as the double argument on WindowsSlot 1 is XMM1, slot 3 is XMM3
push rbp taken as a frame pointerA frame pointer in an -O2 function that uses rbp as an accumulatorOnly mov %rsp, %rbp after the push creates one
Red zone measured from the entry stack pointer216 bytes "below the stack pointer"128 bytes below the current stack pointer after an 88-byte sub
Shadow store treated as localsStack arguments at 8 to 32Microsoft stack arguments start at 40
lea treated as a loadA stack argument at 0x60(%rsp) in a variadic calleelea computes overflow_arg_area; it loads nothing
Hidden pointer read as a normal argumentbig_ret(void *, long long)The pointer is stored through and copied to rax, rax, or stays in x8
Deepest CFA compared with the prologue frameA mismatch on a caller that pushes outgoing argumentsCompare with the deepest stack pointer the body reaches
Convention asserted from the ISAamd64 for a COFF objectThe format picks the rulebook, then the ISA picks the registers
Prototype trusted from one toolThree doubles, or sixteen variadic parametersThe source signature or a second derivation must agree

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

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

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

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.