Phase 13: Tools & Protocols

بازسازی و ثابت کردن مساوی: آزمایش های تفاوت، مقایسه بایت ها و حلقه شواهد

گذراندن آزمون ها توافق در آزمون ها را ثابت می کند، بنابراین برابری به یک شبکه نیاز دارد که به هر لبه و بایت ها برسد که بعد از نقاب انتقال مطابقت داشته باشد.

Type: Build

Languages: Python, C

Prerequisites: Phase 13 · 34 (lifting to pseudocode), Phase 13 · 35 (evidence, confidence, and unknowns)

Time: ~110 minutes

اهداف یادگیری

  • از فهرست دستورالعمل ها یک بازسازی بنویسید و پرونده شواهد را که از آن آمده نام ببرید.
  • یک شبکه ورودی را با یک کلاس در هر خطر بسازید: حفاظت صفر، مقادیر منفی، تقسیم کوتاه کردن، 32 بیت بیش از حد و یک تله تقسیم.
  • اصل و بازسازی رو در یک برنامه اجرا کن و هر سلول رو بشمول یک تله رو ضبط کن
  • بازسازی را با پرچم های اصلی دوباره جمع آوری کنید و بایت های تابع را پس از پنهان کردن زمینه های نقل مکان مقایسه کنید.
  • ثابت ها را که نقطه ی انتقال به آن ها را می خوانید و مقایسه کنید، بنابراین یک حرف واقعی اشتباه نمی تواند عبور کند.
  • سرور MCP rea رو از یک مشتری استودیوی کوچک هدایت کن و هر مرحله رو با هویت شواهد ثبت کن
  • یک پرونده اثبات شکست خورده که هویتش یک هاشه بر روی ادعاها و لینک های شواهد است.

مشکل

تو از ريا از پرونده وظيفه هايpercent_changeدر قسمت ماledger-x86_64-O1.oگيدرا 12.1.4 کد پديده رو برگرداند و مامور اين سي را از اون نوشت:

cint percent_change(int before, int after) {
    if (before == 0) return 0;
    return (int)(((long)after - before) * 100 / before);
}

چهار تست عبور کرد:(100, 150)50 ميده(200, 100)-50 میره(0, 5)0 می دهد(50, 100)اين 100 تا ميده، و مامور هم دوباره ساخته شدهgradeچهار تاif،در گزارش نوشته شده که "مطمئن شده"

این گزارش هیچ کدام از این سوال ها را جواب نمی دهد:

  • وقتی اصل برگرده چه اتفاقی می افتد؟(after - before) * 100در 32 بیت نمیشه؟
  • اصلش چه مقدار به خاطر نمره 110 باز می گردد؟
  • آیا بازسازی به همان 16 بایت با اصل کامپایل می شود؟
  • وقتی دو تابع جمع آوری شده باایت های مشابه داشته باشند، آیا جابجایی آنها به ثابت های مشابه اشاره دارد؟
  • از چه مدرکي اين بازسازی اومده و مامور اين فهرست رو يا کد مخففي رو خوند؟
  • ثابت چه حالتی در میزبان بدون کامپایلر C دارد؟

هر هدف در اين درس برنامه اي است که ما نوشتيم و مرتب کرديم.

آنچه شواهد می گویند

. حلقات مامور داخلcode/main.pyشش بار به ريال 6.5.0 از طریق استديو تماس گرفتمcode/fixtures/runs/agent-run.jsonسرور جواب دادinitializeبا نسخه پروتکل2025-11-25سه تماس به ثبت شواهد برگشت:

StepToolTimeEvidence id
2analyze_function percent_change6.31 sev_e88b10dc0c6400e51bb6f7fdc3eaea8d2c97cc02463f0db3e6afeefc273197cd
3analyze_function grade0.02 sev_67b6d3f992eaf49a2e16de084b6ebfdd9884e8c5c7f75e175b7bb20f4f748ce1
4read_bytes 0x1000b4, 200.00 sev_c26146cfedf4c1ee146d8ff00cfa9a5d3f5335bdd9c97ccf4e1af5f6ea3ed6bc

اولین تماس برای واردات و تجزیه و تحلیل خودکار گیدرا پرداخت شد.confidence: "observed"،authority: "shipped-artifact", و SHA-256 از این شی ,9a4a8082ba5e285a732552981a6935e0c5255725664f380e37c44ebfb04d803f. گيدرا اين كسي را كه ميتونه جايگزين شود بار ميده.textدر0x100000، پسpercent_changeدر0x100000وgradeدر0x100010. .

رمز مخففي برايpercent_changeاينجوريlongاز:

cundefined1  [16] percent_change(int param_1,int param_2,ulong param_3)
{
  long lVar1;
  undefined1 auVar3 [16];
  if (param_1 != 0) {
    lVar1 = (long)((param_2 - param_1) * 100);
    auVar3._0_8_ = lVar1 / (long)param_1 & 0xffffffff;
    auVar3._8_8_ = lVar1 % (long)param_1 & 0xffffffff;
    return auVar3;
  }
  ...
}

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .cltdوidivlهر دوتا رو بنویسیedxوeaxو یک مقدار بازگشت 16 بیت با تقسیم 64 بیت مدل کرد. لیست در همان رکورد چیزی ساده تر می گوید:

0x100000: TEST EDI, EDI
0x100002: JZ 0x0010000d
0x100004: SUB ESI, EDI
0x100006: IMUL EAX, ESI, 0x64
0x100009: CDQ
0x10000a: IDIV EDI
0x10000c: RET
0x10000d: XOR EAX, EAX
0x10000f: RET

هر عمليات 32 بت عرض دارهIMUL EAX, ESI, 0x64در 32 بیت ضرب می شود و نصف پایین را نگه می دارد.CDQ-مدد علامتeaxبهedxوIDIV EDIاین دو تا را با یک تقسیم کننده 32 بت تقسیم می کند.100 * (after - before) / beforeدرint. .

.gradeسئو کود اسم جدول را می دهد*(uint *)(&DAT_001000b4 + (ulong)uVar2 * 4)، و یک عبارت پیش فرض غیر قابل خواندن ساخته شده از 0x66666667. فهرست نشان ميده که قسمت 10 به عنوانIMUL RAX, RAX, 0x66666667،SAR RCX, 0x22،SHR RAX, 0x3f،ADD ECX, EAXپسADD ECX, -0x6،CMP ECX, 0x4وJAده ها نفر رو از 6 تا 10 نگه دار.XOR EAX, EAXقبل از مقایسه، پیش فرض 0 است.LEA RCX, [0x1000b4]وMOV EAX, dword ptr [RCX + RAX*0x4]جدول پنج تایپ 4 بایت را بخوانید.

مرحله 4 اين 20 بايت رو بخوان:01000000 02000000 03000000 04000000 04000000. ميز اينه1, 2, 3, 4, 4برای ده ها، شش، هفت، هشت، نه، ده، این استswitchدرledger.c، باcase 10وcase 94- تقسیم ارزش

هر دو مدرک در صفحات شواهد ریا از لیست و از read_bytesاولين رمز پشو کود DX-Ball بودFUN_00406400(void)بدون ورودی ستک، و نمای دستورالعمل آن را اصلاح کرد. ابتدا لیست را بخوانید. نام ثبت را ذکر کنید، سپس C را بنویسید.

نامزدها را بنویسید

پوشهcode/fixtures/candidates/چهار تا از این دو متنی به همان کد مرتب شده است. چهار تا از این متنی که یک آزمون دست نوشته می کند قابل قبول و اشتباه است.

FileSourceWhat it does
percent_change_mul_first.c100 * (after - before) / beforethe listing in C
percent_change_split.c(after * 100 - before * 100) / beforedifferent text, same bytes after clang folds it
percent_change_wide.c(int)(((long)after - before) * 100 / before)the pseudocode's long, divides before it wraps
percent_change_div_first.c(after - before) / before * 100divides first, so rounding differs
grade_switch.cswitch (score / 10) with the five casesthe original source
grade_table.cunsigned slot = score / 10 - 6; slot < 5 ? points[slot] : 0the listing in C
grade_thresholds.cif (score >= 90) return 4; ...no upper bound on the top band
grade_case10_wrong.ccase 10: return 3;one table entry wrong

هر فایل با دستور نصب جمع آوری می شودclang -target x86_64-unknown-linux-gnu -O1 -fno-asynchronous-unwind-tables -c. اجسام جمع آوری شده در کنار منابع انجام می شوند بنابراین تست ها بدون clang روی میزبان اجرا می شوند.

پا اول: اجرا و مقایسه

تعریف مک کیمن در سال 1998 از آزمایش های متمایز به "دو یا چند سیستم قابل مقایسه" نیاز دارد که "مشهد آزمایش تولید شده مکانیک" را تغذیه کند و نتیجه، آسیب یا تصادف را به عنوان نامزد خطا در نظر می گیرد. او بخش سخت را نامید: "زشت ترین مشکل در آزمایش ارزیابی نتیجه آزمایش است". ما نیازی نداریم که پاسخ درست را بدانیم. ما به اصل و بازسازی نیاز داریم تا هیچ جا در شبکه ای که به هر خطر برسد اختلاف نکند.

طراحی شبکه

input_grid()درcode/main.py92 سلول را می سازد.percent_changeهر جفت از ده تا طول مي کشيدbeforeارزش ها و هفتafterارزش ها:

before: 0, 1, -1, 3, -3, 7, 100, -100, 2147483647, -2147483648
after:  0, 5, -5, 105, 536870911, 2147483647, -2147483648

برایgrade22 تا نمره داره: هر دو طرف هر لبه باند، منفی، 0، 110 و دوintمحدودیت هاclassify()برچسب هر سلول. جریان بیش از حد دارای 32 سلول، منفی 17، مرز 14، ساده 12 و حفاظت صفر است.

هر کلاس به يه دليل وجود داره سلول هاي نگهبان صفرTEST EDI, EDIشاخه. سلول های منفی بررسی بخش تراکم: C و idivبه سمت صفر گرد، پس-9 / 100 و -10 / 10سلول های گردی بررسی می کنند که ضرب قبل از تقسیم اتفاق می افتد، بنابراین(105 - 100) * 100 / 1005 و نه 0 است.(after - before) * 100بیش از 32 بیت. یک سلول گیربنده باعث می شود محصول بسته شده برابر باشدINT_MINباbeforeبرابر با -1.

یانگ، چن، ایده و ریجر Csmith را برای تولید برنامه هایی که بدون رفتار نامعین وجود دارد ساخته اند. اختلاف نظر در مورد رفتار نامعین شور و هرگز گزارش خطا است. overflow امضا شده در C نامعین است. Oracle ما یک شی جمع آوری شده با یک رفتار ثابت است، بنابراین سلول های overflow در محدوده هستند. درس این است که بدانید کدام سلول ها بر روی استاندارد و کدام بر روی بایت های جمع آوری شده می باشند.

راننده و تله

code/driver.cیک سلول در هر خط از stdin را می خواند و ورودی ها، نتیجه اصلی و نتیجه بازسازی را چاپ می کند. build_harness()کاندید را با -Dpercent_change=cand_percent_change -Dgrade=cand_gradeدر یک میزبان لینوکس x86-64، اصلی خود شی نصب است. در هر میزبان دیگر آن استledger.cبه صورت بومی جمع آوری شده و گزارش ها ثبت شده استoriginal_kind: fixture-source. .

راننده يه دستگاه نصب مي کنهSIGFPEباsigsetjmpوsiglongjmp. برایbefore = -1وafter = 536870911، تفاوت 536870912 و محصول 32 بت به -2147483648 بسته می شود.idivبا این تقسیم و تقسیم کننده -1، استثناء خطا تقسیم را افزایش می دهد. این مقدار در 32 بیت (Intel SDM جلد 2، IDIV) قرار نمی گیرد. عامل آن را به مقدار ثبت می کند trap. .

در آرک 64sdivو به نظر می رسد که این کار به اندازه کافی قابل انجام است تا به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی به اندازه کافی است.

نتایج

prove_behaviour(PLAUSIBLE)ساخت و سازlongاون ده مورد ساده از دست رفته، شبکه در 28 سلول شکست خورده

FunctionInputsClassOriginalRebuild
percent_change3, 2147483647overflow-133-1431655899
percent_change100, 2147483647overflow-1012147483547
percent_change2147483647, 5overflow0-99
grade110beyond the switch04
grade2147483647beyond the switch04

همه 26percent_changeشکست ها سلول های پرتاب هستند|before| > 1. برایbeforeبرابر با 1 یا -1، مقدار 64 بیت به مقدار بسته شده باز می گردد، بنابراین این سلول ها به طور تصادفی با هم موافق هستند.gradeشکست می خورد چون سوئیچ اصلی هیچ دلیل برای ده ها تا 11 و بالاتر ندارد و110 / 1011 است

prove_behaviour(EQUAL)ساخت و ساز می کنهpercent_change_mul_first.cوgrade_switch.cهمه 92 سلول موافقندpercent_change_div_first.cدو مورد از چهار مورد ساده، که تنها موردی است که یک آزمون دست نوشته پیدا می کند، شکست می خورد.

oracle_disagreements()يه چيز ديگه رو چک ميکنهpercent_change_model()وgrade_model()مدل های پایتون این لیست هستند، با wrap32()برای ضرب 32 بت و idiv32()برای قانون معماری. گزارش مدل را با اصلی مشاهده شده در هر سلول مقایسه می کند. صفر اختلافات به این معنی است که مدل و دوگانه در هر سلول موافق هستند. مدل شواهد حاصل شده و اجرا شواهد مشاهده شده است. گزارش آنها را در زمینه های جداگانه نگه می دارد.

پا دوم: جمع آوری و مقایسه

رفتار در یک شبکه یک پا است. پا دوم می پرسد که آیا بازسازی، که با همان کامپایلر و پرچم ها مرتب شده است، باایت های مشابهی تولید می کند. پروژه DX-Ball گزارش "63 باایت مطابقت" برای دستیار خود را. پروژه TH04 گزارش یک مطابقت 2.139 باایت. هر یک از آنها از کامپایلر دوره خود استفاده کرد. rea خود نمی تواند این کار را انجام دهد.compare_functionsمتن ارائه دهنده خطوط و محدودیت "اجمع متن ارائه دهنده غیر شفاف است؛ نرمال سازی نقل مکان در دسترس نیست".

شی را بخونید

ElfObjectدرcode/main.pyیک ELF64 را می خواند که با struct.unpack_from. اون جادويي رو چک ميکنه ، کلاس 64 بت ، داده هاي کوچولوe_machine۶۲، وe_typeبعد از اون به عنوانات بخش ها، جدول رشته ها،.symtab، و هر.relaبخش. در دستگاهpercent_changeشروع می شه.textتعویض 0 با اندازه 16 و gradeدر0x10با اندازه 46totalشروع می شه0x40با اندازه 31 و grade_labelدر0x60با اندازه 63

16 بايت از percent_change.85 ff 74 09 29 fe 6b c6 64 99 f7 ff c3 31 c0 c3. وظيفه هيچ جايگزيني ندارهgradeیک: تعویض0x26داخل تابع، نوعR_X86_64_PC32، نماد.rodata، اضافه کردن0x10. متعلق به 7 بايتleaqدر تعویض0x23، که چهار بايت آخرش میدان جابجا شدن است

ماسک، پس از آن، ضبط ها را مقایسه کنید

در یک شی RELA، اضافه در پرونده نقل مکان زندگی می کند و چهار بایت میدان صفر هستند.grade_switch.oیک بایت ساده مقایسه می گذرد در حالی که دو نقل مکان نام مکان های مختلف را می دهد. mask_relocations()به هر حال میدان را در هر دو طرف صفر می کند، بنابراین همان روش برای اشیاء REL و Mach-O، جایی که میدان شامل اضافه می شود، صدق می کند.

پسprove_bytes()مقایسه پرونده های نقل مکان با بخش های تعویض، نوع و هدف..rodata+0x10و نامزد میگه.rodata-0x4. اضافه متفاوت است چون موضوع کاندید هیچlabels.relجدول در مقابل میز سوئیچ آن. یک اضافه متفاوت یک تعویض متفاوت است، نه یک تابع متفاوت.

ثابت ها را بخوانید نقاط نقل مکان در

برای یک فیلدی مربوط به PC که دستورالعمل خود را به پایان می رساند، CPU آدرس دستورالعمل بعدی را اضافه می کند، بنابراین هدف رمز افزون اضافه 4 است. در اصل که .rodata+0x14، و در کاندیدایش هم هست.rodata+0x0.read_table()پنج تا 4 بايت وارد شده است1, 2, 3, 4, 4. .

شماره پنج از لیست آمده:CMP ECX, 0x4باJAشاخص های 0 تا 4 را پذیرفته است و[RCX + RAX*0x4]4 بايت در هر شاخص ميخوادCLAIMSدرcode/main.pyاین شکل را برای gradeو ثبت صفر نقل مکان برای percent_change. .

این مرحله به دلیل یک خطای مستند شده توسط پروژه TH08 وجود دارد. مقایسه قدیمی آن "در زمینه نقل مکان دستورالعمل، آدرس هدف را تکرار کرد، سپس باایت های دستورالعمل را بدون بررسی داده های لغوی شناور در آن آدرس مقایسه کرد. منبع 0.0بنابراین ممکن است به نظر برسد که دقیقاً در مقابل هدف قرار داده شده است128.0." این اصلاح 1548 مرجع متغیر را بررسی کرده و 12 مرجع دیگر را اصلاح کرده است. grade_case10_wrong.cاین نسخه ما از این خطا است. 46 بایت کد آن برابر با اصلی است، رکورد نقل مکان آن دارای شکل مشابه است، و جدول آن است1, 2, 3, 4, 3فقط چک ثابت شکست میده

نتایج

CandidateSizeMasked bytesRelocation recordsTableStatus
percent_change_mul_first16 vs 16equalnonenonepass
percent_change_split16 vs 16equalnonenonepass
percent_change_wide16 vs 26size differsnonenonefail
percent_change_div_first16 vs 18size differsnonenonefail
grade_switch46 vs 46equalsame shape1,2,3,4,4 bothpass
grade_table46 vs 46equalsame shape1,2,3,4,4 bothpass
grade_thresholds46 vs 39size differs1 vs 0nonefail
grade_case10_wrong46 vs 46equalsame shape1,2,3,4,4 vs 1,2,3,4,3fail

دو نتیجه ارزش نگاه دوم رو دارهpercent_change_split.cمتن منبع مختلف و بائتهای یکسان دارد، زیرا Clang به عنوان نامحدود و پوشیده شده، عبور را تحت پوشش قرار می دهد after * 100 - before * 100به يک چندانgrade_table.cهمچنین باایت با بیت مطابقت دارد، بنابراین کامپایلر از یک شاخص آرایه و از یک جدول به همان جدول رسید.switchیک بایت مطابقت ثابت می کند که این کامپایلر با این پرچم ها، کد مشابهی را از کاندید تولید کرده است. این ثابت نمی کند که کاندید متن منبع اصلی است.

اندازه یک تشخیص است نه یک پذیرش. صفحات شواهد rea یک کاندیدای 1,825 بایت با طول مناسب و 467 بایت متفاوت را ثبت می کند.wideبازسازي 26 بايت است چونmovslq،imulq،cqtoوidivqاین لیست قبل از هر کامپایل، عرض آن را به ما می گفت.

مامور "لوپ" از روي "رویا"

۶۵ ابزار MCP rea هیچ فرمان CLI ندارند وverify_reconstructionیکی از اونا هستMcpStdioClientدرcode/main.pyکوچکترین مشتری که به آنها می رسد.npx -y rea-agents@6.5.0 mcp، یک درخواست JSON-RPC را در هر خط به stdin می نویسد و یک شی JSON را در هر خط از stdout در یک موضوع می خواند.initializeبا نسخه پروتکل2025-11-25، پسnotifications/initialized، پسtools/call.مدت پیش فرض هر تماس 330 ثانیه است، همان شماره rea اجازه می دهد تا Ghidra سرد شروع شود.

agent_loop()اون شش تماس رو ميکنه و هر يک رو ضبط ميکنه:

json{
  "step": 2,
  "tool": "analyze_function",
  "arguments": {"procedure": "percent_change"},
  "seconds": 6.31,
  "is_error": false,
  "evidence_id": "ev_e88b10dc0c6400e51bb6f7fdc3eaea8d2c97cc02463f0db3e6afeefc273197cd",
  "confidence": "observed",
  "authority": "shipped-artifact",
  "limitations": ["Resolved reference metadata identifies computed, indirect, external, call, jump, and data edges; unresolved targetless flows remain unknown, and function classifications distinguish thunks and externals.", "..."],
  "result_sha256": "..."
}

پرونده های کامل شواهد زیر شناسه های آنها در همان فایل ذخیره می شوند. کد نامزدی و لیست بازسازی از آن آمده بخشی از دستگاه هستند.table_address()پیدا می کنهLEAو درgradeفهرستش رو ميذاره و بهشون ميدهread_bytes.open_binary،get_evidence_bundleوclose_binaryهیچ ثبت شواهد را بازنمی گرداند و با یک شناسه بی فایده ثبت می شود.

run_agent(live=True)راننده های واقعیnpxدر راه است وGHIDRA_INSTALL_DIRنام یک دایرکتوری را می دهد. در غیر این صورت این دستگاه را دوباره می کند و می گوید که در stderr. تست ها یک قدم بیشتر می روند.code/tests/fake_rea_server.pyیک سرور جایگزین است که به هر یک پاسخ می دهدtools/callکلائنت و حلقه در هر آزمایش با هیچ rea، Ghidra یا Java نصب نشده با آن مواجه می شوند.

چه چیزی می تواند و نمی تواند تایید کننده rea بگوید

واقعاًverify_reconstructionدر این گزارش، در مورد یک عملکرد، یک ادعا در مورد یک عملکرد، متن ارائه دهنده را از ۰.۱۰۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱۰.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.۱.compare_functionsیک ادعای رفتاری دو ثبت شده فرآیند ضبط را با compare_process_capturesوقتی یک سوابق منبع پوشش تماس های نامکمل را دارد، ادعای مربوط به تماس ها استunknownهیچ چیز در داخل rea یک تابع بازسازی شده را مرتب نمی کند یا آن را بر روی شبکه ورودی شما اجرا نمی کند. دو پا در این درس بخشی هستند که rea به شما می گذارد.

دفتر حساب تعهدات rea انتظار دارد که یک سوابق اثبات شده با predicate_type: "rea.reconstruction-proof"،operation: "verify_reconstruction_obligations"،confidence: "observed"وnormalized_result.passed === true. هیچ ابزار واقعی عمومی چیزی را نمی دهدbuild_proof()درcode/main.pyاین را می کند:

json{
  "predicate_type": "rea.reconstruction-proof",
  "operation": "verify_reconstruction_obligations",
  "confidence": "observed",
  "authority": "controlled-replay",
  "normalized_result": {
    "passed": true,
    "status": "pass",
    "claims": [
      {"claim_id": "percent_change.behaviour", "kind": "behavioral", "status": "pass", "evidence_ids": ["ev_e88b10dc..."]},
      {"claim_id": "grade.behaviour", "kind": "behavioral", "status": "pass", "evidence_ids": ["ev_67b6d3f9..."]},
      {"claim_id": "percent_change.bytes", "kind": "structural-function", "status": "pass", "evidence_ids": ["ev_e88b10dc..."]},
      {"claim_id": "grade.bytes", "kind": "structural-function", "status": "pass", "evidence_ids": ["ev_67b6d3f9..."]},
      {"claim_id": "grade.referenced-constants", "kind": "structural-function", "status": "pass", "evidence_ids": ["ev_67b6d3f9..."]}
    ]
  },
  "evidence_links": ["ev_e88b10dc...", "ev_67b6d3f9..."],
  "evidence_id": "ev_..."
}

اسمش اینهev_به علاوه SHA-256 از ضبط بدون شناسه، از طریق طبقه بندی کلید کامپکت JSON. aggregate()بسته شده است: failپس برنده میشهunknown، و لیست خالی درخواست هاunknownدر یک میزبان بدون یک C کمپایلر دو ادعای رفتارunknown، پس پرونده ميگهunknownحتی وقتی هر دو ادعای بایت از دست میرسد.authority.controlled-replay، چون مدرک از دست دستمزد ما مياد نه تنها از پرونده اشياء

آنچه تحقیقات می گوید

لیو، راف و میسینسکی هشت سیستم تجزیه را در نه پیکربندی در سال 2026 اندازه گیری کردند. کاندیداهای که هر آزمون را که معیار معیار شامل آن است، به پایان رسانده اند، هنوز هم در مورد ورودی های گیج شده متفاوت هستند. این نرخ ۴.۹ درصد در کل و تا ۱۳ درصد برای یک سیستم بود. در 300 عملکرد کتابخانه گیت هاب و 287 عملکرد مبتنی بر CVE، قوی ترین مدل اصلاح، میزان ساخت گیدرا را از 75 درصد به 90 درصد افزایش داد. در طول عملکردهای مشابه، میزان مطابقت رفتاری از ۷۴ درصد به ۶۲ درصد کاهش یافت. آنها علت آن را به زمینه های اختراع شده، انواع، کالای ها و نگهبانان که جایگزین ناشناخته های قابل مشاهده شده یک decompiler سنتی را پس می گذارد، ردیابی کردند.

ماpercent_change_wide.cاین نوع اختراع شده یکی از این نوع ها است.longدر این مورد، در سال ۲۰۱۴، در یک آزمایش جدید، به عنوان یک آزمایش جدید، یک آزمایش جدید انجام شد که در آن به طور کامل به عنوان یک آزمایش جدید انجام شد. در سال ۲۰۱۴، این آزمایش دوباره انجام شد و نتیجه آن مرتب شد، ده آزمایش را به پایان رساند و ۲۶ سلول تخلیه شکست خورد. بازسازی حد درجه یک محافظ اختراع شده است. هر دو به عنوان قابل اجرا مجدد تحت متریک LLM4Decompile حساب می شوند، که تولید را دوباره جمع آوری می کند و ادعاهای معیار را اجرا می کند. خود جیدرا در 20.12 درصد از این ادعاها در HumanEval-Decompile عبور کرد.

DecompileBench 23400 عملکرد را از 130 برنامه واقعی اندازه گیری کرد. روش های LLM را 52.2 درصد کمتر از قابلیت های کاربردی از تجزیه کننده های صنعتی با نمره های درک بالاتر یافت.

سه مدرک که میدان استفاده می کند سه پا هستند که می توانید بسازید. فینکس و درام پیدایش رو دوباره جمع آوری کرده و تست های برنامه اصلی رو اجرا می کنن مک کیمن و سمیت ورودی های تولید شده را در مقابل اصلی با ورودی های نگهداری شده در درون رفتار تعریف شده اجرا می کنند. راموس و انگلر دو تابع C را با اجرای رمزنگاری محدود بررسی می کنند که برابری را در تمام مسیرهای مورد بررسی تا اندازه ورودی ثابت می کند. این درس دو تا اول را می سازد. سومين، آزمایشگاهي در درس 35 است که در دفتر شواهد وجود دارد، وقتی که شبکه ای برای اعتماد خیلی کوچک است.

آن را بسازید

. با استفاده از بند استاندارد کتابخانه:

bashcd phases/13-tools-and-protocols/36-rebuild-and-prove-equal
python3 code/main.py

با clang در مسیر، دمو هر دو جفت کاندید را جمع آوری می کند و برای هر کدام 92 سلول را اجرا می کند. آن هشت کاندید را دوباره جمع آوری می کند، اجرا کننده را دوباره اجرا می کند و رکورد اثبات را می کند. بدون clang آن را می خواند اجزای انجام شده و گزارش ادعاهای رفتار به عنوانunknown. .

شکل انتظار شده در یک arm64 Mac:

json{
  "host": "aarch64 Darwin",
  "originalKind": "fixture-source",
  "gridCells": 92,
  "plausible": {"naivePassed": true, "gridMismatches": 28, "oracleDisagreements": 0},
  "equal": {"naivePassed": true, "gridMismatches": 0, "oracleDisagreements": 0},
  "legTwo": {
    "percent_change_mul_first": {"status": "pass", "reasons": []},
    "percent_change_wide": {"status": "fail", "reasons": ["size 16 vs 26 bytes"]},
    "grade_case10_wrong": {"status": "fail", "reasons": ["referenced constants differ: [1, 2, 3, 4, 4] vs [1, 2, 3, 4, 3]"]}
  },
  "agentRun": {"mode": "replayed fixture", "server": {"name": "rea", "version": "6.5.0", "protocolVersion": "2025-11-25"}},
  "proof": {"status": "pass", "evidence_id": "ev_..."}
}

بخونcode/main.pyدر این ترتیب:

  1. wrap32()،c_div()،idiv32()و دوتا*_model()تابع ها دارای معنای عددی کامل لیست هستند.
  2. input_grid()وclassify()و سلول های 92 را بسازید و برچسب بزنید.
  3. build_harness()وexecute()یک برنامه را از اصلی، نام های جدید نامزد ها جمع آوری کنید وdriver.c، بعد از اين سلول ها رو اجرا کن
  4. prove_behaviour()گزارش مرحله اول را با عدم مطابقت و اختلافات مدل باز می گرداند.
  5. ElfObjectسرشت ها، نمادها و.relaسوابقmask_relocations()وread_table()مقایسه رو آماده کن
  6. prove_bytes()گزارش دو پا را با اندازه ها، محدوده های پوشیده، شکل نقل مکان و جدولها باز می گرداند.
  7. McpStdioClientوagent_loop()هر قدم رو ضبط کن
  8. build_proof()وaggregate()ثبت پرونده ی بسته شده

ازش استفاده کن

برای اثبات یک تابع جدید برابر، این مراحل را تکرار کنید:

  1. بیاanalyze_functionبرای عملکرد و ثبت هویت شواهد. لیست قبل از کد مخفف را بخوانید.
  2. نامزدی را از عرض عملیات لیست بنویسید. نام عملکرد اصلی را نگه دارید.
  3. هر ضرب، اضافه، حذف و تقسیم را در لیست لیست کنید. ورودی های شبکه را اضافه کنید که هر یک را در عرض خود بسته می کند.
  4. هر دو طرف هر ثابت مقایسه را در لیست اضافه کنید. برای gradeاین ها بعد از معاینه 6 و 4 بودند.
  5. هر قسمتگر رو که ميتونه در هدف گیر کنه اضافه کن و ثبت کن که ساختار رو اجرا کرد
  6. هر دو پا رو بزن و قبل از وضعيت دليل رو بخوني
  7. پرونده اثبات رو کنار نامزد نگه دارevidence_linksبه خواننده بگو که ثبت ادعای بر چه چیزی است.

پس از هر بروزرسانی کامپایلر هر دو پا را تکرار کنید. یک بایت مطابقت یک بیانیه در مورد یک کامپایلر با یک مجموعه پرچم است.

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

آزمایشگاه A: مدل و اجرا

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

bashcd phases/13-tools-and-protocols/36-rebuild-and-prove-equal/code
python3 -q

راه رفتن:

pythonfrom main import *
percent_change_model(3, INT_MAX)
percent_change_model(-1, 536870911, "x86_64")
percent_change_model(-1, 536870911, "aarch64")
report = prove_behaviour(PLAUSIBLE)
report.naive_passed, len(report.mismatches), report.mismatches[0]

اولین تماس -133، محصول بسته به 3 تقسیم می شود. دومین تماس -133 می دهد.'trap'و سومين شماره -2147483648 است. گزارش نشان ميده 10 مورد ساده گذريده و 28 سلول شبکه شکست خورده است.report.oracle_disagreementsبا یه لیست خالی

لابراتوار ب: اشیا را بخونید

pythonobj = ElfObject(ORIGINAL_OBJECT)
grade = obj.function("grade")
grade.size, grade.data[0x26:0x2a].hex(), grade.relocations
read_table(obj, grade.relocations[0], 5, 4)

بائتهاي فيلد ها 00000000. نامي که به جاي ديگري منتقل شده.rodataبا اضافه کردن0x10، و ميز ميگه[1, 2, 3, 4, 4]. .

لابراتوار C: یک ثابت را شکستن

pythonreport = prove_bytes("grade", CANDIDATES / "grade_case10_wrong.o")
report.masked_equal, report.relocations_match, report.tables_equal, report.reasons()

بايت ها همديگه، سوابق همديگه و جدول ها همديگه نيست. حالا ویرایش کنیدgrade_case10_wrong.cپسcase 10دوباره 4 را باز می گرداند، با دستور تنظیم مجدد آن را جمع آوری می کند و وضعیت را به تغییر می دهدpass. .

آزمایشگاه D: درایو ریا

با نصب REA 6.5.0 و Ghidra 12.1.4:

bashGHIDRA_INSTALL_DIR=/opt/homebrew/Cellar/ghidra/12.1.4/libexec \
JAVA_HOME=/opt/homebrew/opt/openjdk@21 \
python3 code/main.py --live

اولينanalyze_functionچند ثانیه طول می کشد تا Ghidra اشیاء را وارد کند. ID های جدید شواهد را با اجرا انجام شده مقایسه کنید. همان بائتهای تحت همان پروفایل تجزیه و تحلیل همان ID ها را می دهند، زیرا ID یک هاش محتوا است که مسیر فایل را خارج می کند.

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

هر دو پا رو به totalوgrade_labelاز همان جسم

الزامات:

  • برایtotalسلول هایی را با تعداد 0، تعداد منفی، یک عنصر و مجموعی که در 32 بیت بسته می شوند بسازید.
  • برایgrade_label، تابع صدا می کندgradeخط و متنlabels.rel, جدول پنج تعویض رشته ای نسبی با نقل مکان های خود در .rela.rodata. .
  • اضافه کنیدCLAIMSثبت نام برای grade_labelبا دو نقل مکان و یک جدول از پنج واردات 4 بایت، و مقایسه رشته های واردات اشاره به.
  • ثبت کنید که کدام سلول ها مدل و اجرا در مورد آنها اختلاف دارند و هر کدام را از لیست توضیح دهید.
  • یک ادعا را در هر پای در هر عملکرد به ثبت اثبات اضافه کنید و کل را بسته نگه دارید.

موفقیت به این معنی است که ثبت اثبات چهار تابع را فهرست می کند، هر ادعای دارای یک هویت شواهد است وgrade_labelوقتی یک رشته برچسب متفاوت باشد شکست می خورد.

مهارت های تولید

این درس به ما کمک می کندoutputs/skill-rebuild-and-prove-equal.md. از آن برای تبدیل شواهد عملکرد و بازسازی یک کاندید به یک اثبات دو پای و یک ثبت اثبات استفاده کنید. مهارت نیاز به فهرست قبل از کد مخفف، یک شبکه با هر کلاس خطر، ماسک انتقال و یک چک ثابت و یک مجموعه شکست بسته است.

بررسی کنید

نمایش و آزمايش را اجرا کنيد:

bashcd phases/13-tools-and-protocols/36-rebuild-and-prove-equal
python3 code/main.py
python3 -m unittest discover -s code/tests -v

35 تست ثابت ميکنه:

  • c_div()به سمت صفر و wrap32()بعد از دو نفر
  • مدل -133 برای (3, INT_MAX)،trapبرای سلول های گیرنده در x86-64 و -2147483648 در AArch64
  • شبکه 92 سلول و هر کلاس خطر داره و پرونده های ساده ای از هر کلاس سخت اجتناب می کنن
  • خواننده ELF چهار تابع را در اندازه و تعویض ثبت شده پیدا می کند
  • percent_change16 بايت بدون نقل مکان وgradeيه نفر دارهR_X86_64_PC32در0x26
  • بائتهای میدان نقل مکان صفر هستند و پوشاندن هیچ تغییری در این شی RELA ندارد
  • تمام هشت نامزد متعهد به وضعیت انتظار می رود، با دلایل ثبت شده
  • grade_case10_wrongباایتهای پوشیده را رد می کند و تنها چک ثابت را شکست می دهد
  • رنز های ثبت شده از پا اول نشان می دهد ده پاس ساده، 28 عدم مطابقت و اختلافات صفر مدل
  • با یک کمپایلر، هر دو جفت دوباره ساخته و دوباره اجرا می شود با همان نتیجه
  • هدف انجام شده توسط عامل توسط SHA-256 در ترتیبev_شناسه ها در هر مرحله اثبات
  • .read_bytesثبت برابر با جدول که خواننده ELF پیدا می کند
  • مشتری سرور جعلی را اجرا می کند و هویت های شواهد را با اجرا واقعی ثبت می کند
  • یک نتیجه خطا از سرور وارد رکورد اجرا می شود
  • aggregate()بسته شده و سند اثبات از محتوای آن محاسبه می شود

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

FailureWhat the weak report saysWhat the harness must prove
Rebuild keeps the decompiler's long"ten tests pass"26 overflow cells differ from the original
Thresholds replace a switch"every grade band passes"110 and larger return 0 in the original
Divide before multiply"formula is algebraically equal"rounding cells differ, naive cases fail
Trap cell skipped"no crashes"x86-64 raises #DE, AArch64 returns INT_MIN, the report names the host
Byte compare without masking"bytes equal"relocation records name different offsets
Masking without reading constants"bytes equal after masking"1,2,3,4,3 differs from 1,2,3,4,4
Size taken as acceptance"same length"differing bytes inside the same length
Different compiler or flags"bytes differ, rebuild wrong"the same source gives different bytes, so the compare is void
Model treated as observation"model agrees"the run is observed, the model is derived, disagreements are listed
Claim without evidence id"verified"every claim links an ev_ record of the function it covers
No compiler on the CI host"passed"behaviour claims are unknown and the aggregate is unknown
Pseudocode read as source"decompiler says long"the listing shows IMUL EAX, CDQ, IDIV EDI

قاعده عملیاتی

بازسازی را از لیست بنویسید و نام رکورد را که از آن آمده است نام دهید. آن را با اصلی بر روی یک شبکه اجرا کنید که هر میانگین را بسته و هر ثابت مقایسه را عبور می کند. آن را با پرچم های اصلی جمع آوری کنید، زمینه های نقل مکان را پنهان کنید، رکورد ها را مقایسه کنید و ثابت هایی را که به آن اشاره می کنند بخوانید. هر ادعای را با هویت شواهد خود ثبت کنید و اجازه دهید ادعای غیر تأیید شده نامعلوم بماند.

خواندن بیشتر

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.