Phase 13: Tools & Protocols

تماس با کنوانسیون ها و فریم های استیک: سیستم V، ویندوز 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و از رادار2.6.2.4 خواستند تا استدلال های eight_argsجوابش با هفت تا بود:rdi،rsi،rdx،r8،r9،rsp+0x8وrsp+0x10. منبع C هشت پارامتر داره . بايت ها می خوانند%rcxدقیقاً یک بار، درleaq (%rdx,%rcx), %rax، و بازیافت متغیر ابزار یک ثبت نام را که فقط در داخل یک آدرس ظاهر می شود، شمارش نمی کند.

سپس نسخه ویندوز از همان فایل را در رزین 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). بازوی AAPCS64 انتشار 2025Q4 (23 ژانویه 2026) بخش 6.1 تا 6.9. نوتاژ پلتفرم آرم 64 اپل این درس این قوانین را می خواند، آنها را به یک فایل C که به سه روش مرتب شده است، اعمال می کند و تحلیلگر را ایجاد می کند که یک لیست را به یک لیست چک شده از مکان های پارامتر، ثبت های ذخیره شده و فریم آفسیت ها تبدیل می کند.

یک سرنوشت کتاب قوانین را انتخاب می کند

convention.cدوتا وظیفۀ دارد:leaf_add،eight_args،mixed،by_value،big_ret،sum_varargs،keeps، و پنج نفر از تماس گیرندگانexternعملکردهای مشابهی.long long، چونlongاین برنامه 4 بایت در هدف MSVC و 8 بایت در بقیه است و یک ساختار است که تغییر اندازه تغییرات کنوانسیون است. اپل کلینگ 17.0.0 آن را هفت بار از این دستگاه مرتب:-target x86_64-unknown-linux-gnu،x86_64-pc-windows-msvcوaarch64-unknown-linux-gnuدر-O0و-O2وarm64-apple-macosدر-O2هیچ عنوان لینوکس و ویندوز نصب نشده است، بنابراین فایل آنچه را که نیاز دارد اعلام می کند و فقط شامل clang خود است 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: دو ردیف ثبت مستقل و یک منطقه قرمز

psABI 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)در-O227 بایت است:

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ساعت 8هhدر 16 سالگی

mixed(int i, double d, long long l, float f)دو لیست رو نشان ميده%ediو%rsi, اولین و دومین ثبت INTEGER.%xmm0و%xmm1، اولین و دومین ثبتات SSE.cvtsi2sd %edi, %xmm2و%xmm2یک کالا از خاکستری است که تابع قبل از خواندن آن می نویسد. یک تحلیلگر که به مقصد cvtsi2sdبه عنوان یک مطالعه یک استدلال سوم نقطه شناور اختراع می کند. رادار2 دقیقاً همین کار را کرد و گزارش دادmixedمثل(double arg1, double arg2, double arg3)درxmm0،xmm1،xmm2. .

by_value(struct pair p)یک ساختار 16 بایت به عنوان دو 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: "جای ۱۲۸ بایت فراتر از محل که توسط %rsp اشاره شده است، به عنوان محفوظ محسوب می شود و نباید توسط کنترل کننده های سیگنال یا قطع تغییر یابد".-O0،eight_args.pushq %rbp; movq %rsp, %rbpو بعد شش مغازه رو به-0x8(%rbp)از طریق-0x30(%rbp)بدون هیچsubqمغازه ها 48 بايت زیر شاخص ستک قرار دارن-O2ساختsum_varargs88 بایت را با 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: slot 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): ۴۰، ۴۸، ۵۶، ۶۴

طرف تماس دهنده حساب حساب را نشان می دهد.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، پس اونext32 بايت سايه خود را در زیر آدرس بازگشت پیدا می کند.

ساختارها قاعده ی خود را دنبال می کنند. "هر استدلال ای که در 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 نامناسب محسوب می شود: OS یا یک debugger ممکن است این حافظه را در طول یک جلسه debug کاربر یا یک دستیار قطع تغییر نامناسب تغییر دهد. "-O0 leaf_add8 بايت از مردم محلی رو ميخواد و باشون ميگيرهpushq %raxدر ورود وpopq %rcxقبل ازretq، دو تا دستورات یک بايت به جای یکsubqو یکaddqصفحه استفاده از استیک صفحه ای را تعریف می کند که می تواند این کار را انجام دهد: "یک تابع ورق یک است که نیازی به ورود به جدول عملکرد ندارد. نمی تواند تغییرات را در هر گونه ثبت نام غیر متغیر، از جمله RSP انجام دهد".

"برای عملکردهای وارارگ یا نمونه های اولیه، هر مقدار نقطه شناور باید در register عمومی مربوطه دوبرابر شود".sum_varargsدر-O2فروشگاه ها%rdx،%r8،%r9به0x18(%rsp)،0x20(%rsp)،0x28(%rsp)بعد از يکpushq %rax, که در حال تعویض ورود 16, 24, 32: خانه های دوم، سوم و چهارم register پارامترها است.va_list.leaq 0x18(%rsp), %rax، خونه ي%rdx، اولین بحث نامعلوم

AAPCS64 و آنچه اپل تغییر می کند

AAPCS64 6.8.2 یک لیست از قوانین را با دو شمارش کننده انجام می دهد. C.9: یک استدلال ادغام "به بیت های کمتر قابل توجه در x [NGRN]" و افزایش NGRN کپی می شود. C.1 برای استدلال های نقطه شناور با NSRN همین کار را انجام می دهد. C.12: ترکیبی از حداکثر 8 - NGRNدو کلمه "در registers عمومی استفاده متوالی کپی شده است". C.13 تنظیم می کند "NGRN به 8" هنگامی که یک استدلال به استیک می رود، بنابراین هیچ چیز به registers پس از آن باز نمی گردد. 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 اضافه می کند "هیچ الزامی برای calllee برای حفظ ارزش ذخیره شده در 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 در ورود به تابع فعلی باشد. " و "موقع ثبت فریم در یک فریم استیک مشخص نیست. " clang هر دو موقعیت را در این یک فایل نشان می دهد. keepsدر-O2در لینوکس رکورد را در پایین با stp x29, x30, [sp, #-0x30]!; mov x29, sp. همان عملکرد در -O0اون رو به سمت بالا ميذارهsub sp, sp, #0x20; stp x29, x30, [sp, #0x10]; add x29, sp, #0x10. .

یادداشت های arm64 اپل، ثبت و خط بندی را حفظ می کند و قاب، منطقه قرمز و تماس های مختلف را تغییر می دهد. "ریجستر اشاره کننده قاب (x29) همیشه باید به یک رکورد قاب معتبر مراجعه کند. برخی از عملکردها مانند عملکرد برگ یا تماس های دم ممکن است تصمیم بگیرند که واردات را در این لیست ایجاد نکنند".keepsپس انداز می کنهx22, x21, x20, x19اول و بالاترين رقم را مي گذارد:stp x29, x30, [sp, #0x20]; add x29, sp, #0x20. "پلتفرم ها از register x18 استفاده نکنند. " " منطقه قرمز ARM64 شامل 128 بايت درست زیر شاخص استاک است" و هنوز هم پخش می شودsub sp, sp, #0x10برای-O0ورق، بنابراین سازنده آن را به طور پیش فرض استفاده نمی کند. استدلال های Variadic "به تعداد مناسب از 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.41REX با 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، کد آپ83 /5با 8 بت فوری، ModRM ec.11 101 100.subq $0x20, %rspعمق 56

56 + آدرس برگشت 64 است، هموار شده 32 بايت فروشگاه سایه است کهextصفحه ایپلگ تنها اجازه می دهد "RSP، ثابت یا Lea RSP، ثابت [FPReg] را اضافه کنید، سپس یک سری از صفر یا بیشتر 8 بیت ثبت نام پاپ و بازگشت یا jmp" و بایت ها هستند.48 83 c4 20 5b 5f 5e c3. .

AArch64، 16 بايت در چهار کلمه، کوچک-endian:

  1. a9bd7bfd.stpبا پیش انڈیکس. بایت 31:30 10شماره 64 بت را انتخاب کنید، 2523 بت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]!: شاخص ستک 48 سقوط می کندx29به -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ساعت 8x21با 16 بايت از پر کردن با 24 بايتx20در 32 سالگیx19در 40. پایین ترین کلمه ی ثبت به ثبت قبلی اشاره دارد و کلمه ی بعدی LR را دارد، همانطور که 6.4.6 می طلبد. cmp w0, #0x1در میان ذخیره اول و دوم قرار دارد؛ برنامه نویس آن را به پیشگویی منتقل کرده و تحلیلگر یک مقایسه یا دستورالعمل ریاضی بین عملیات های دسته را تحمل می کند.

جمع کننده دو بار همان حقایق را نوشت

یک پیشگویی تجزیه یک مشتق است. سازنده یک دوم را برای unwinder منتشر می کند، و هر دو باید موافق باشند.

در ویندوز دومین مشتق این است.pdataو.xdata. ساختش رو-O2بدون هدف-fno-asynchronous-unwind-tablesوllvm-objdump -hنمایش ها.xdataبا متری 0x34 با متری.pdataاز 0x48 بایت. 0x48 برابر 72 است، ششRUNTIME_FUNCTIONنوشته های 12 بایت با 3 IMAGE_REL_AMD64_ADDR32NBهر يک از 6 نفر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، هیچ پرچم نیست. اندازه OfProlog 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، ثبت شماره 3rbx.02 70.rdi.01 60.rsi. کد ها به ترتیب اجرا برعکس ذخیره می شوند و به همان سه فشار و 32 بیت اختصاص داده می شوند که باایت ها هستند 56 57 53 48 83 ec 20.sum_varargsورود این است01 01 01 00 01 02 00 00: یک پیشگویی یک بایت با یک کدUWOP_ALLOC_SMALLاز 8 بايت. اين همونطوريه که اوني که ميخواد ببينهpushq %rax: یک تخصیص، چون%raxو هيچ چيز نجات نميده

در لینوکس، فرات دوم این است.eh_frame, که در psABI 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 ، یک join_dual_classقانون برای انواع تا 16 بایت، خروجی XMM0_Qa, XMM1_Qa, RAX, RDXوhidden_returnبرای بقیهx86-64-win.cspecاعلامیه__fastcallبا چهارتا<group>عناصر که همبستگی دارندXMM0_QaباRCX،XMM1_QaباRDX، و غیره، که قانون موقعیت است، یک ورودی دسته در تعویض 40convert_to_ptrبرای استروک های ۳، ۵، ۶ یا ۷ بایت با این نکته که "تنها استروک های اندازه ۸،۱۶،۳۲،۶۴ بیت را می توان برای ثبت بسته بندی کرد"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برای structs 17 byte یا بیشتر وkilledbycallاز جملهx8با نظر "رجستر محل نتایج غیر مستقیم، که در لیست پنتری منعکس نمی شود". مرحله نهایی تجزیه کننده "پروتایپ عملکرد ایجاد کنید" نامیده می شود؛ تحلیلگران "ID کنوانسیون تماس" و "ID پارامتر تجزیه کننده" هستند؛ گزینه برنامه "تقييم نمونه" مدل پیش فرض را انتخاب می کند.

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" از طریق decompiler یک __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).APlatform"معلومات مربوط به محیط اجرا دوگانه، به طور عمده کنوانسیون های تماس استفاده شده، سیستم عامل و معماری را شامل می شود" و لیست شامل 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، و دو پرچم که تفاوت ها را در این درس به طور مستقیم رمزگذاری می کنند:arg_regs_share_index"در صورت درست، استدلال Nth، نقطه Nth از لیست های ثبت عدد کامل و فلوت را بدون توجه به نوع آن مصرف می کند" وstack_reserved_for_arg_regs, " فضای سایه / خانه مورد استفاده در کنوانسیون تماس ویندوز 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برای AArch64afcگزارش کنوانسیون عملکرد فعلی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، بنابراین پروفایل مایکروسافت وجود دارد و از قالب انتخاب نشده است. afiهفت دلیل برایeight_argsدر لینوکس، دوباره بدونrcx، و در ویندوز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, ...). شکاف هاي آن با رادار2 متفاوت هستند:mixedبرگشتيم و(long long, long long, double, float)در سیستم V و AArch64، ثبت راست در ترتیب اشتباه، زیرا لیست اعداد کامل قبل از لیست شناور چاپ می شود.big_retبرگشتيم و(long long) -> double، پس اونx8کنوانسیون از دست داده شد و به همین دلیل فروشگاه های ویکتور خوانده شد و AArch64 sum_varargsبا 16 پارامتر برگشتم، کل منطقه ذخیره شده را در نظر گرفته شده.

Others.Hopper 6.6.0 یک جداکننده و جداکننده تجاری برای macOS و لینوکس است؛ مدیریت کنوانسیون آن برای این درس اجرا یا مستند نشده است. lldb 1703 و gdb نشان می دهد که فریم زنده با frame infoوregister read, که درسی 42 دید پویا از همان تعویض است. کمپایلر اکسپلورر سه لیست را کنار هم از منبع نشان می دهد، که سریع ترین راه برای تأیید یک قانون است قبل از اینکه به دنبال آن در بائته ها باشید.

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 است. برای هر یک از هفت شی نامگذاری شده است، فرمت، ماشین و ABI، و برای هر یک از دوازده تابع آن به بایت های پیشگام، ثبت ذخیره شده با تعویض ورود، اندازه فریم، نشان دهنده فریم، ثبت پارامتر، تعویضات استدلال سقف، ورودی، ثبت بازگشت یا نشان دهنده پنهان، عمق تماس و ثبت و ذخیره های خارج از تماس گیران داده شده است. هر تابع با چک های خود به پایان می رسد: قاعده، ارزش انتظار شده از امضا، ارزش مشاهده شده از بایت ها و اینکه آیا آنها موافق هستند. گزارش با دو چک عبور و ضبط ابزار به پایان می رسد. در ۸۴ تحلیل عملکرد، ۴۸۹ چک اجرا شده و ۴۸۹ موافق هستند.

شکل انتظار می رود:

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()در این حالت، این ورودی در حالت "مجموعه ای" قرار دارد.
  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در Microsoft x64، جایی که movq %rcx, %raxاز بعد از آن فروشگاه ها از طریق(%rax). .
  6. expected_locations()در این روش، سه کتاب قاعده را به یک امضا C اعمال می کند: دو لیست سیستم V با کلاس های هشت بایت، نقاط موقعیت مایکروسافت با structs by-reference و AAPCS64 counters با x8برای نتایج بالاتر از 16 بایت.
  7. run_checks()این دو را مقایسه می کند و قوانین چارچوب را اضافه می کند: ثبت نام های ذخیره شده توسط تماس باید ذخیره شوند.(rsp + 8) % 16 == 0یاsp % 16 == 0در هر تماس، 32 بایت سایه در هر تماس مایکروسافت، دسترسی زیر شاخص ستاک در Microsoft و 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 است.

آزمایشگاه تعاملی

لابراتوار A: یک دستورالعمل، سه اثر

ازcodeدایرکتوری، پیتون باز:

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. .

آزمایشگاه B: قاب نگهبان

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 در تماس

آزمایشگاه C: خواندن قبل از نوشتن در مخلوط

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 و توضیح دهید که چرا کد unwind آن را به عنوان یک تخصیص ثبت می کند.call8در.eh_frameميز رو رو بيان کنين

آزمایشگاه تمرین

يه هدف چهارم و يه قانون چهارم اضافه کن

الزامات:

  • جمع آوری کنید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، مایکروسافت x64, AAPCS64 و Apple arm64
  • جدول نماد هر شی، فهرست 12 تابع مشابه را با Mach-O_پیشگویی و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
  • ساخت اپل رکورد را در -16 بالاتر از چهار رکورد ذخیره شده قرار می دهد
  • هر تابع يه اشاره دار قاب داره-O0در لینوکس و هیچ کدام در -O2و-fno-omit-frame-pointerو با فشار تعادل آن را به عقب می آورد
  • .-O0برگ 8 بایت از منطقه قرمز تحت سیستم V استفاده می کندpushq %raxدر Microsoft 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در Microsoft x64 با xmm0در نتیجه هر دو
  • ساختار 16 بایت در دو ثبت در سیستم V و AAPCS64 و با توجه به یک اشاره پنهان در Microsoft x64 حرکت می کند
  • ساختار 32 بايت از طریق rdi،rcx، یاx8
  • وآره، اون کلي مختلف ميگه%al، خانه هاrdx, r8, r9در 16، 24، 32، نجات می دهد x1بهx7وq0بهq7، یا نشان دهنده ی دسته تماس گیرنده را در اپل می خواند
  • تماس گیرندگان به صورت انتظارات ثبت نام ها را تنظیم می کنند، 7 و 8 را به 0 و 8 یا 5 تا 8 را به 32 تا 56 ذخیره می کنند، صفر %alبرای تماس متغیر، و ارسال آدرس بفر نتیجه در rdi،rcx، یاx8
  • همه 489 چک با قوانینشون موافقند
  • ششUNWIND_INFOنوشته ها با شروع به کار مطابقت دارند و برگ ها هیچ کدام ندارند
  • 24 FDE با تعادل ذخیره شده از ثبت و عمیق ترین شاخص استاک مطابقت دارد
  • ابزار رادار2 رو ضبط ميکنهamd64وms، رزينamd64در مورد کاوف، گمشدهrcx، سه دوگانه و نمونه اولیه آنگر
  • داده های ارقام در ماژول سایت برابر با خروجی تحلیلگر است

روش های شکست تولید

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.