وقتی یک مدل زبانی درباره‌ی بایت‌های یک فایل اجرایی ادعایی می‌کند، آن ادعا را نباید پذیرفت. ابزار reverify دقیقا همین کار را می‌کند: مدل پیشنهاد می‌دهد و ابزار قطعی داوری می‌کند. در این اجرا، پیش‌فرض کتابیِ شروع تابع در x86-64 را روی نقطه‌ی شروع واقعی /usr/bin/ls در آدرس 0x6d30 آزمودیم و حکم REFUTED گرفت؛ پس از اصلاح ادعا با همان دستورهایی که ابزار گزارش کرد، حکم VERIFIED شد.

چرا ادعای مدل باید داوری شود، نه پذیرش

مدل زبانی در خواندن کد خوب است و در حدس‌زدن ساختار یک باینری ضعیف. پروژه‌ی reverify روی همین شکاف ساخته شده است: هر ادعا درباره‌ی فایل باید در برابر خودِ بایت‌ها بررسی شود، نه در برابر اعتماد ما به مدل.

ادعای مرجع در مخزن پروژه این است که روی ۷۱ فایل واقعی از پوشه‌ی System32 ویندوز، پاسخ کتابی مدل در ۶۹ مورد از ۷۱ مورد غلط بوده، یعنی ۹۷ درصد. مستند BENCHMARK.md توضیح می‌دهد دو فایل از همان ۷۱ فایل واقعا با push ; mov شروع می‌شوند و درست VERIFIED شدند، پس معیار دست‌کاری نشده است.

همان سند عدد دوم را می‌دهد: false VERIFIED برابر صفر است. کران بالای ۹۵ درصدی نرخ خطای پذیرشِ ادعای غلط روی آن ۷۱ فایل، ۵٫۱ درصد است. یعنی «صفر از ۷۱» اثباتِ بی‌خطایی نیست، فقط نشان می‌دهد خطا در این اندازه‌ی نمونه دیده نشده است.

چیزی که این پروژه را برای یک ایجنت جالب می‌کند، شماره‌ی ستاره‌ها نیست. در لحظه‌ی خواندن، مخزن روی گیت‌هاب ۱٬۲۵۲ ستاره و ۲۳۷ فورک دارد و روی PyPI هم فقط نسخه‌ی 0.10.0 منتشر شده است. ارزش آن در این است که حکمِ VERIFIED یا REFUTED همراه با شواهد بازمی‌گردد، نه یک پاسخ متنی.

نصب بدون هیچ وابستگی

مهم‌ترین ویژگی بسته این است که dependencies = [] دارد؛ یعنی بدون نصب هیچ چیز کار می‌کند. مستندات خود پروژه در pyproject.toml هسته را «pure-Python» معرفی می‌کند.

# کپی کردن مخزن؛ نیازی به نصب نیست
$ curl -sL https://codeload.github.com/2akouwu/reverify/tar.gz/refs/heads/main -o rv.tar.gz
$ tar xzf rv.tar.gz && cd reverify-main

# پیش از هر کاری ببینید کدام موتورها فعال‌اند
$ python3 reverify/cli.py backends
=== Reverify backends ===
disassembly      pure-python
emulation        pure-python
binary_parsing   pure-python
proof            none
semantic         pure-python
full fidelity:   False
upgrade:         pip install "reverify[full]"

خروجی بالا همان چیزی است که باید بخوانید. full fidelity: False یعنی هسته‌ی خالص پایتون فعال است و موتورهای اختیاری نصب نیستند. برای آزمونی که در ادامه می‌آید این کافی نیست، و دلیلش را در بخش محدودیت‌ها می‌بینید.

# فقط بسته‌ی capstone؛ چون داوری دستورها به دیساسمبلر نیاز دارد
$ pip install "reverify[capstone]"
# اگر pip را ندارید یا شبکه‌تان محدود است، چرخ Wheels را از PyPI بگیرید
# و در PYTHONPATH بگذارید؛ همان چیزی است که در این اجرا انجام شد
$ python3 -c "import capstone; print(capstone.__version__)"
5.0.7

چرخه‌ی واقعی: از REFUTED تا VERIFIED

حالا نقطه‌ی شروع واقعی فایل را می‌خوانیم. خروجی parse آدرس ورودی را می‌دهد و همان عدد را به ادعا می‌دهیم.

$ python3 reverify/cli.py parse /usr/bin/ls --json
{
  "format": "ELF",
  "arch": "x86_64",
  "bits": 64,
  "entrypoint": 27952,
  "backend": "pure-python"
}

# ۲۷۹۵۲ در مبنای شانزده برابر 0x6d30 است
# حالا پیش‌فرض کتابی مدل را کورکورانه روی همان آدرس ادعا می‌کنیم
$ python3 reverify/cli.py verify /usr/bin/ls --json --claim '{"kind":"instructions","offset":27952,"mnemonics":["push","mov"],"note":"textbook prologue"}'
--- rc: 2
  "refuted": 1,
  "verdict": "REFUTED",
  "detail": "mode=exact",
  "actual_mnemonics": ["endbr64","xor","mov","pop","mov","and","push","push"],
  "expected_mnemonics": ["push","mov"]

این همان چیزی است که ارزش این ابزار را نشان می‌دهد. مدل گفته بود push rbp ; mov rbp, rsp و ابزار با نمایش هر هشت دستور واقعی پاسخ داد: اول endbr64 است، بعد xor ebp, ebp. حکم REFUTED با شواهد آمد، نه یک جمله‌ی «به نظر نمی‌رسد درست باشد».

نکته‌ی مهم این است که کد خروجی rc: 2 است. یعنی می‌توانید همین حکم را مستقیم در خط لوله‌ی خود به‌عنوان شرط شکست بگذارید؛ ادعای ردشده یک خطای واقعی است، نه یک هشدار تزئینی.

ادعا را با همان دستورهایی که ابزار گزارش کرد دوباره می‌دهیم. این تنها بخشی است که از خود ابزار آمد، نه از مدل.

$ python3 reverify/cli.py verify /usr/bin/ls --json --claim '{"kind":"instructions","offset":27952,"mnemonics":["endbr64","xor","mov","pop","mov","and","push","push"]}'
--- rc: 0
  "verified": 1,
  "verdict": "VERIFIED",
  "grounded_ratio": 1.0,
  "information": 0.8,
  "trustworthy": true

برای همان آدرس حالا دو حکم متناقض داریم: اولی ردشده و دومی تاییدشده. تفاوت فقط در دستورهاست، نه در ابزار. همین ویژگی است که داوری را از حدس‌زدن جدا می‌کند.

کلید trustworthy: true را از grounded جدا کنید. حالت grounded: false در همان اجرا به این دلیل بود که آستانه‌ی پیش‌فرض min_information برابر ۱٫۰ است و وزن این ادعا ۰٫۸ شد. یعنی ادعا درست بود، اما به اندازه‌ی کافی چیزی نگفت که «مفید» باشد.

هر نتیجه یک رسید هم حمل می‌کند که قابل بازپخش است:

کلید رسیدمقدار در این اجرا
binary_sha2562726eb35…c4cd26cf
binary_size142312
reverify0.11.0
python3.14.7
engines.disassemblycapstone

هش را با sha256sum /usr/bin/ls چک کنید؛ در این اجرا دقیقا همان مقدار بود. یعنی حکمی که می‌خوانید به همین بایت‌ها گره خورده است، نه به یک فایل هم‌نام که فردا عوض می‌شود.

همان داوری، از راه MCP

این ابزار فقط خط فرمان نیست. سرور MCP خودش را هم می‌دهد و ۱۰ ابزار منتشر می‌کند، از جمله re_verify_claim و re_disasm. اینجا همان فراخوانی واقعی روی همان فایل است، از طریق پروتکل استانداردی که در مستندات چرخه‌ی عمر MCP تعریف شده است.

$ printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"demo","version":"0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
  '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"re_verify_claim","arguments":{"file_path":"/usr/bin/ls","claims":[{"kind":"instructions","offset":27952,"mnemonics":["push","mov"]}]}}}' \
  | python3 reverify/mcp_server.py
{"serverInfo": {"name": "reverify-mcp", "version": "0.11.0"}}
{"tools/list": 10 tools}
{"id":3, "refuted": 1, "verdict": "REFUTED"}

اگر آن را به فایل پیکربندی MCP خودتان اضافه کنید، ایجنت شما هر بار که درباره‌ی یک باینری ادعا کند می‌تواند اول داوری بخواهد. مشخصات ورودی دو نکته دارد که در آزمون اول من و در پیام خطای خود سرور دیده می‌شود: کلید file_path است نه path، و ادعاها آرایه‌ی claims هستند نه یک شیء claim تنها. با نام اشتباه، سرور خطای {"error": "'file_path'"} برمی‌گرداند.

چهار چیزی که این ابزار انجام نمی‌دهد

اول، بدون capstone حکم‌های دستوری داوری نمی‌شوند. در اجرای اولِ ما با هسته‌ی خالص پایتون، نتیجه به‌جای REFUTED یا VERIFIED برابر INCONCLUSIVE شد و خودِ ابزار نوشت که برای داوری این نوع ادعا capstone لازم است. این یک پیام خوب است: ابزار به‌جای حدس‌زدن، نمی‌دانستن را اعلام می‌کند.

دوم، ادعای شما درباره‌ی کد عادی هم می‌تواند همین مسیر را برود. پرچم equiv یک پیاده‌سازی مرجع و یک پیاده‌سازی نامزد را روی ورودی‌های مشترک اجرا می‌کند و اگر اختلاف داشته باشند، همان ورودی و هر دو خروجی را برمی‌گرداند.

سوم، دو نسخه از این ابزار را نباید یکی گرفت. آنچه روی PyPI منتشر شده 0.10.0 است، اما کدی که در اجرای ما اجرا شد 0.11.0 گزارش کرد. پس هر عددی که از نسخه‌ی نصب‌شده می‌خوانید را به همان فایل موجود وصل کنید.

چهارم، خودِ پروژه یک عدد را صریحا به‌عنوان کران اعلام کرده، نه یک دستاورد بی‌نقص. همان ۵٫۱ درصد کران بالای ۹۵ درصدی یادآوری است که «صفر خطا» روی ۷۱ فایل، اثبات نیست.

قاعده‌ی یک‌خطی

هر جا ایجنت شما درباره‌ی بایت‌ها، آفست‌ها یا رفتار یک فایل اجرایی ادعایی می‌کند، آن ادعا را اول به داور بفرستید و فقط حکم VERIFIED را گزارش کنید. برای همین قاعده، پیش از این نوشته درباره‌ی برگشت خالی ایجنت پس از فراخوانی ابزار نوشته بودیم که چرا حلقه باید صریح محدود شود؛ اینجا ابزار است که حلقه را می‌بندد، نه تنظیمات مدل.

اگر پروژه‌ای دارید که ادعاهایش را از خودِ ریپو می‌خوانید، چطور توجه کار می‌کند توضیح می‌دهد چرا عدد خام بدون داوری فقط یک عدد است. برای دیدن دو منبع اصلی این ابزار هم به صفحه‌ی PyPI و راهنمای رسمی نگاه کنید، نه هیچ خلاصه‌ی تجمیعی.

منابع

  1. مخزن 2akouwu/reverify — روش داوری، رسید و راهنمای نصب
  2. README پروژه — ادعای ۹۷ درصد و دوگانگی مقدار اطلاعات
  3. BENCHMARK.md — جدول نتایج ویندوز و کران ۹۵ درصدی
  4. EXAMPLE.md — یک اجرای گام‌به‌گام بدون کلید API
  5. pyproject.toml — نبود وابستگی و موتورهای اختیاری
  6. reverify روی PyPI — نسخه‌ی منتشرشده و وابستگی‌های extras
  7. آمار مخزن — ستاره، فورک و تاریخ آخرین تغییر
  8. چرخه‌ی عمر MCP — ترتیب initialize و tools/call روی stdio
  9. عکس نوشته: کارت گرافیک در کیس — Matheus Bertelli از Pexels