Phase 13: Tools & Protocols

Bằng chứng, Tin tưởng và Không biết trong Phân tích Binary

Một phát hiện về một chương trình được biên soạn là một bản ghi với một hash, một sự tin tưởng, một thẩm quyền, và một danh sách những gì nó không thể hiển thị.

Type: Build

Languages: Python, C

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

Time: ~105 minutes

Mục tiêu học tập

  • Xây dựng hồ sơ bằng chứng dựa trên mẫu của rea Evidencevới sự tin tưởng được quan sát, dẫn đến và suy luận.
  • Lập số các ID hash nội dung vẫn giống nhau khi tập tin di chuyển sang thư mục khác.
  • Viết những gì mỗi nhà cung cấp không thể cho thấy như giới hạn đi cùng với hồ sơ.
  • Từ chối tuyên bố kết quả cho đến khi một chạy của hàm được quan sát hỗ trợ nó.
  • Giữ các phần còn lại không rõ như các hồ sơ đã sửa đổi được kết nối bởi một chuỗi hash.
  • Nhà cung cấp bộ nhớ cache trả lời dưới một khóa chính xác và từ chối một bản phát lại lỗi thời.

Vấn đề

Anh hỏi một đại lý gì?gradetrong ledger-x86_64-O1.oTrình duyệt trả lời câu hỏi: Trình duyệt hỏi người đại lý biết như thế nào. Trình duyệt có một khối văn bản mà Ghidra in. Đối với con đường mặc định, văn bản đó đọcuVar1 = -(param_1 >> 0x1f) ^ (uint)((ulong)((long)param_1 * 0x66666667) >> 0x3f);Các byte ở điểm đó nóixor eax, eax- Tôi không biết.

Các biểu hiện và hướng dẫn đều tạo ra 0 cho mỗi đầu vào.NDSS BAR 2026Một nghiên cứu khác năm 2026 đã trồng văn bản bên trong các binary và phát hiện ra rằng các mô hình đề xuất hành động không an toàn được trồng trong 35 trong số 40 trường hợp (arXiv 2607.12507().

rea 6.5.0 cung cấp cho đại lý một từ vựng cho điều này.Evidenceghi lại với một confidencecủa observed- derived, hoặcinferred, một authority, và một danh sách limitations. Khả năng đóng gói nói với đại lý: "Mỗi kết luận phải phân biệt quan sát, suy luận và những điều không biết.

Có ba điều mà rea để lại cho bạn. Các ảnh chụp của nó lưu trữ kết quả truy vấn chính xác, không phải phân tích. Việc xác minh của nó vượt qua một yêu cầu khi một chiều kích so sánh không thay đổi, và bình luận của nó nói rằng một thông qua "không thiết lập sự tương đương thực hiện toàn cầu". sổ cái nghĩa vụ của nó chỉ lấy ứng cử viên từ JavaScript và biểu đồ được quản lý, vì vậy một hàm bản địa không bao giờ đạt được .verifiedqua nó.

Bài học này xây dựng phần thiếu sót trong Python đơn giản. Bạn viết một sổ cái lưu trữ mọi sự thật về thiết bị như một bản ghi với một nội dung hash. Bạn làm các dự đoán vềpercent_changevà gradeBạn nhập hai bản ghi thực tế và ảnh chụp nhanh chúng xuất phát từ, và sổ cái của bạn tính lại mọi bản ghi hash rea đã viết.

Ba từ cho sự tự tin, năm từ cho quyền lực

confidencelà một số với ba giá trị, không bao giờ là một số. authorityKhi một nhà sản xuất không nói gì, rea sử dụngshipped-artifactvới observed- Tôi không biết.

ValueMeaning on the fixtureRecords in this lesson
observedA fact read from bytes or from a runthe ELF reader's section and symbol reads, the two Ghidra records, 17 host runs
derivedA fact computed from observed recordsthe switch table model, the division model, every unknown mutation
inferredAn expectation that no observation states yet18 predictions
shipped-artifactThe file on disk was the sourceevery read of ledger-x86_64-O1.o
controlled-replayA run you controlled produced the factthe host runs of harness.c
analyst-inferenceYour own judgementpredictions and unknown mutations
historical-referenceAn older source tree or documentnone here
external-serviceA service outside the file and the hostnone here

Hai sự nhầm lẫn tốn nhiều thời gian nhất. Đầu tiên coi pseudocode là một quan sát về hành vi. Nó là một quan sát về những gì Ghidra in. thứ hai coi một danh sách trống như bằng chứng về sự vắng mặt. ghi chú thiết kế của rea là nghiêm ngặt: "Công tin không được biết, không phải sự vắng mặt. "code/main.pymã hóa cả hai quy tắc.

Lịch sử

Một bản ghi có chính xác mười sáu trường, và rea 6.5.0 từ chối bất kỳ trường nào khác. code/main.pygiữ tên giống như rea, vì vậy một hồ sơ từ cả hai bên xác nhận trên bên kia.relationship_coverage, cho thấy danh sách người gọi hoặc người gọi là bao nhiêu.complete- partial, hoặcunknown, hoặcnullkhi hoạt động báo cáo không có liên hệ gọi.

FieldWhat it holds
evidence_idev_ and 64 hex digits, a hash of the content
subjectname, digest.sha256, format, architecture, local_path, or null
providerid, name, version or null
analysis_profilethe provider's settings and their digest, or null, always present
predicate_typea tag, rea.analysis by default
operation, parametersthe tool and its input
raw_result, normalized_resultprovider output and the canonical result
confidence, authoritythe enums above
environmentid, platform, architecture, isolation, or null
limitationsplain sentences
relationship_coveragestatus complete, partial, or unknown with diagnostics, or null
locationsaddress, address-range, artifact-path, file-offset, file-offset-range
evidence_linksthe ev_ ids this record rests on

Đây là bản ghi thực sự mà Rea viết cho grade, cắt cho các lĩnh vực quan trọng ở đây.code/fixtures/rea-evidence-grade.json, 37.573 byte.

json{
  "evidence_id": "ev_67b6d3f992eaf49a2e16de084b6ebfdd9884e8c5c7f75e175b7bb20f4f748ce1",
  "subject": {
    "name": "ledger-x86_64-O1.o",
    "digest": { "sha256": "9a4a8082ba5e285a732552981a6935e0c5255725664f380e37c44ebfb04d803f" },
    "format": "elf",
    "architecture": "x86_64",
    "local_path": "/private/tmp/aiefs-re/phases/13-tools-and-protocols/35-evidence-confidence-and-unknowns/code/fixtures/ledger-x86_64-O1.o"
  },
  "provider": { "id": "ghidra", "name": "Ghidra", "version": "12.1.4" },
  "analysis_profile": {
    "provider": { "id": "ghidra", "name": "Ghidra", "version": "12.1.4" },
    "parameters": { "jump_table_evidence": "typed-case-default-blocks-v1", "import_mode": "ephemeral-source-immutable" },
    "digest": "9c7f6b24be69294e61da046e4583e3856cb9e40433b149c1bf8bb534d2fe03ef"
  },
  "operation": "analyze_function",
  "parameters": { "procedure": "grade" },
  "confidence": "observed",
  "authority": "shipped-artifact",
  "environment": null,
  "limitations": [
    "Default-space addresses use lowercase 0x-prefixed hexadecimal; other address spaces use <percent-encoded-space>:0x<hex>.",
    "Resolved reference metadata identifies computed, indirect, external, call, jump, and data edges; unresolved targetless flows remain unknown, and function classifications distinguish thunks and externals."
  ],
  "relationship_coverage": {
    "status": "complete",
    "diagnostics": [
      "Only resolved Ghidra call references are returned; unresolved computed or indirect calls remain unknown, while function classifications distinguish thunks and externals."
    ]
  },
  "locations": [],
  "evidence_links": []
}

Đúng là parametersđối tượng của hồ sơ có 25 khóa.limitationsdanh sách có mười câu. giữ chúng. Một hạn chế là một phần của nội dung, vì vậy bỏ một thay đổi ID, và sổ cái của bạn sau đó sẽ từ chối ghi lại.

Hãy chú ý những gì ghi chép không nói. environmentlà nullVì Ghidra đọc một tập tin và không tìm thấy gì.locationslà trống vì báo cáo hoạt động này địa chỉ bên trong normalized_result- relationship_coveragecó vị trí completeChẩn đoán của nó cho biết chỉ có tham chiếu cuộc gọi Ghidra được giải quyết được trả lại, và các cuộc gọi máy tính hoặc gián tiếp chưa giải quyết vẫn không được biết.

ID là một cái kết của sự hài lòng, và con đường không nằm trong nó

thực tính toán evidence_idnhư ev_cộng SHA-256 trên RFC 8785 JSON công giáo của một dự đoán của hồ sơ.digest- format, vàarchitecturevà giọt namevà local_pathNó rơi xuống.relationship_coveragekhi giá trị của nó là null, vì vậy một hồ sơ không có liên hệ gọi giữ lại danh tính giống như trước khi trường tồn tại.raw_resultvà mọi giới hạn, đều được phân tích.

RFC 8785 sắp xếp các phím đối tượng, loại bỏ không gian trắng, và sửa đổi các hình thức số và chuỗi. Đối với các hồ sơ có số là số nguyên, thư viện tiêu chuẩn của Python tạo ra các byte tương tự:

pythondef canonical_json(value):
    return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False, allow_nan=False)

code/main.pytừ chối floats trước khi nó hash, bởi vì RFC 8785 và Python in một số floats khác nhau. hai bản ghi rea và snapshot không giữ floats, do đó công thức tái tạo mỗi rea hash:

rea valueRecomputed by code/main.py
ev_67b6d3f992eaf49a… for gradeequal
ev_e88b10dc0c6400e5… for percent_changeequal
profile digest 9c7f6b24be69294e… over {provider, parameters}equal
query_26122aebe9d8abae… for the grade snapshot entryequal
query_0f95ef38038d3666… for the percent_change entryequal

Tại sao loại trừ đường đi? cùng quan sát của cùng một byte nhận được ID tương tự trên bất kỳ máy tính và trong bất kỳ thư mục.local_pathtrong danh sách trên có tên thư mục trên một Mac. ID không thay đổi khi bạn sao chép bộ nhớ này vào /home/you/re- rebind_subject_path()cho phép bạn hiển thị một bản ghi dưới một con đường mới.sha256- format, hoặcarchitecturekhác nhau. rea 6.5.0 làm tương tự với rebindEvidenceToTargetPathkhi nó tái phát một bản ghi hình ảnh chụp nhanh cho một mục tiêu ở một con đường mới.

validate_evidence()tính lại danh tính và từ chối sự không phù hợp với câu của Rea, "Cách chứng nhận ngữ nghĩa không phù hợp với hồ sơ của nó".analysis_profile.providerkhác với provider- Thử nghiệmtest_tampered_id_and_mismatched_profile_are_rejectedchỉnh sửa một dòng mã giả trong thực gradeghi lại và xem sổ cái từ chối nó.

Hãy tự quan sát vật thể

Trước bất kỳ nhà cung cấp nào, sổ cái đọc hồ sơ. observe_object()phân tích tiêu đề phần ELF64, .symtab- .strtab, và.rela.textvới struct.unpack_fromNó viết một .inspect_objectghi lại và một read_function_bytesghi trên mỗi biểu tượng hàm.observedvới thẩm quyền shipped-artifact, bởi vì nguồn gốc là tập tin trên đĩa.

RecordContentId
inspect_objectfive sections with offsets, sizes, and hashes, four functions, three relocationsev_645e0a145f28bd5c…
read_function_bytes percent_change16 bytes at .text+0x00ev_2572a7d254ad15cb…
read_function_bytes grade46 bytes at .text+0x10, SHA-256 ffcb75c2a7bb1104…ev_a467c2427bfc0c56…
read_function_bytes total31 bytes at .text+0x40ev_b1e845cea2543073…
read_function_bytes grade_label63 bytes at .text+0x60ev_c50041be26e6b7f4…

llvm-objdump -tđồng ý: grade0000000000000010với kích thước 2eBa vụ di chuyển vào năm.rela.textlà R_X86_64_PC32chống lại.rodatatrong các khoản bù đắp0x36- 0x84, và0x93, với các phụ lục0x10- 0x24, và-0x4Mỗi bản ghi đều có mộtfile-offset-rangevị trí và một hạn chế: "Bytes phần được đọc từ tệp trên đĩa. Người đọc không áp dụng chuyển đổi và không chạy mã".

Bài học 32 xây dựng người đọc này hoàn toàn. Đây là 60 dòng, bởi vì bài học này là về những gì bạn ghi lại về việc đọc.

Tìm ra bảng, và nói rằng bạn đã tìm ra nó

46 byte của gradechứa bốn mô hình mà bài học 33 giải mã:

BytesInstructionOffset in grade
48 69 c0 67 66 66 66imul rax, rax, 0x666666673
48 c1 f9 22sar rcx, 3413
83 c1 faadd ecx, -623
83 f9 04 77 0ccmp ecx, 4 then ja28

Một nhân bằng 0x66666667Sau đó là một thay đổi 34 là một phân chia được ký bởi 10.derive_grade_model()viết rằng thực tế như một giới hạn: "Đi phân 10 là một dẫn xuất từ nhân 0x66666667 và thay đổi 34.

  • add ecx, -6Đặt trường hợp đầu tiên lên 6.cmp ecx, 4với một cú nhảy không ký kết thừa nhận 5 trường hợp, 6 đến 10.
  • lea.text+0x33mang lại việc di chuyển với thêm 0x10. Một PC32 di chuyển đo từ cuối 4 byte di chuyển, do đó bảng bắt đầu từ .rodata+0x145 từ nhỏ nhặt đọc1, 2, 3, 4, 4- Đổi vào .ledger.ctrả lại 1 cho 60 đến 69, 2 cho thập niên 70, 3 cho thập niên 80, và 4 cho 90 đến 100.

Những ghi chép kết quảev_605106bff2d9998f…- Có confidence derived, và nó evidence_linksName the two observed records it rests on. Remove the bytes record from the ledger and the derived record has a hanging link.ev_a467c242…- Tôi không biết.

Bây giờ hãy so sánh với Ghidra.

cuint grade(int param_1)
{
  uint uVar1;
  uint uVar2;

  uVar2 = param_1 / 10 - 6;
  uVar1 = -(param_1 >> 0x1f) ^ (uint)((ulong)((long)param_1 * 0x66666667) >> 0x3f);
  if (uVar2 < 5) {
    uVar1 = *(uint *)(&DAT_001000b4 + (ulong)uVar2 * 4);
  }
  return uVar1;
}

Ghidra đã thực hiện việc di chuyển và đặt tên cho bảng DAT_001000b4, đó là .rodata+0x14sau khi nó được đặt .text0x100000Nó đã lấy lại sự chia bằng 10 và 5 trường hợp. Đối với giá trị mặc định nó in một biểu thức luôn là 0 và không bao giờ nói 0.native_value_flowđánh dấu các hoạt động đó is_dead: trueBản ghi chép là một quan sát trung thành của Ghidra. ý nghĩa bạn đọc từ nó được bắt nguồn, và giá trị bạn mong đợi từ một chạy được suy luận.

  • percent_changeHồ sơ cho thấy thất bại khác.undefined1 [16] percent_change(int param_1,int param_2,ulong param_3)Nguồn tin nóiint percent_change(int before, int after)- idivviết EDX:EAX, và đường đi không rời điEDXkhông bị chạm vào, vì vậy người giải trình suy luận về một phần trả lại 16 byte và một tham số thứ ba.native_api.return_type.confidencecho gradelà "low"- Chống lại chữ ký như là kết luận của nhà cung cấp, và ghi lại nó như vậy.

Những lời tiên đoán là những ghi chép được đưa ra

Một dự đoán là một tuyên bố về hành vi mà không có quan sát nào đã khẳng định. claim_suite()xây dựng mười tám trong số đó từ các mô hình bắt nguồn và từ nguồn. record_prediction()lưu trữ mỗi một đĩa với confidence inferredvà authority analyst-inference, liên kết với các hồ sơ mà nó dựa trên.

ClaimPredicted valueRests on
percent_change(12400, 15500)25, from 310000 / 12400division model ev_076a9167…
percent_change(0, 5)0, the zero guarddivision model
percent_change(100, 50)-50division model
percent_change(-7, 3)-142, because idiv truncates toward zerodivision model
grade(55)0, index -1 fails the unsigned comparetable model ev_605106bf…
grade(60), grade(69)1, 1table model
grade(70), grade(85)2, 3table model
grade(95), grade(100), grade(105)4, 4, 4table model
grade(110), grade(-5)0, 0table model
total(1, 2, 3), total()6, 0source record ev_2f1e6d25…
grade_label(85)"B"source record and table model
grade(score) for 90 to 1004 for all eleven inputstable model

predict()sử dụng ngữ nghĩa C, không phải ngữ nghĩa Python. c_div()truncates về phía không, và wrap32()Lập mỗi trung gian thành 32 bit. Python //vòng về phía âm vô hạn, vì vậy (3 - -7) * 100 // -7Chương trình C cho ra -142. Bài học 36 làm cho lưới này lớn hơn nhiều.

Mỗi dự đoán mở ra một phần còn lại của người chưa biết.observedbằng chứng với thẩm quyền controlled-replayvà đề nghị một con tàu thăm dò:execute_functionCâu hỏi cho yêu cầu cấp 1 đọc "Điều điểm ((95) == 4 giữ khi hàm được biên dịch chạy?"

Hãy kiểm tra chúng đối với một cuộc chạy

code/fixtures/harness.cbao gồm ledger.cvà in một kết quả cho mỗi lần gọi. observe_runs()biên soạn nó với đầu tiên của clang- cc, hoặcgcctrên đường đi của bạn và chạy mỗi đầu vào trong lưới một lần.

json{
  "operation": "execute_function",
  "parameters": { "function": "grade", "args": [95] },
  "normalized_result": { "result": 4, "stdout": "4\n", "exit_code": 0 },
  "confidence": "observed",
  "authority": "controlled-replay",
  "environment": { "id": "host-process", "platform": "darwin", "architecture": "arm64", "isolation": "process" },
  "limitations": [
    "The run executed a host build of ledger.c, not the x86-64 object. The claim about the object rests on the shared source and on the compiler.",
    "One run observes one input. It proves nothing about other inputs."
  ]
}

Chủ đề của một bản ghi chạy là bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhượng bộ nhịcourse-harnessvới dòng phiên bản của trình biên dịch, ở đây Apple clang version 17.0.0 (clang-1700.6.3.2)- evidence_linkstên ghi nguồn ev_2f1e6d251543d017…, bởi vì chạy và đối tượng chia sẻ ledger.cVà không có gì khác.

Đọc hạn chế đầu tiên hai lần. Đối tượng x86-64 không bao giờ chạy trên máy này. Điều chạy là một xây dựng thứ hai của cùng một nguồn cho kiến trúc khác. Đó vẫn là một quan sát, và nó là mạnh nhất có sẵn mà không có trình mô phỏng, vì vậy tuyên bố đi kèm với câu đó. Một báo cáo bỏ qua nó đã mất thông tin người đọc cần.

17 bộ chạy một lần đều phù hợp với dự đoán.code/fixtures/run-evidence.jsongiữ 17 hồ sơ đó và hồ sơ nguồn, xuất khẩu với --recordvào năm 2026-10-13. Khi không có trình biên dịch,build_ledger()Nhập khẩu gói đó thay vì chạy, và báo cáo nói như vậy trong nó runstrường.

Quy tắc khuyến mãi

Một yêu cầu chuyển từ suy luận đến hỗ trợ chỉ thông qua các lần chạy được quan sát. check_claim()tìm kiếmexecute_functionghi lại cùng một chức năng và lập luận, so sánh từng kết quả với dự đoán, và đếm các đầu vào được bao gồm:

StatusConditionrea's completion ledger
passevery input has an agreeing run and none disagreespass
failany run disagreesfail
unknownsome inputs have runs, others have noneunknown
unsupportedno input has a rununsupported

promote_claim()là hình thức nghiêm ngặt.ClaimErrorkhi bất kỳ ID nào là inferredhoặc derivedNó được tạo ra khi một id đặt tên cho một chuỗi của một hàm khác hoặc các lập luận khác. Nó được tạo ra khi danh sách trống, và khi các chuỗi bao gồm ít đầu vào hơn yêu cầu.grade(55), và cả hai đều không thể thúc đẩy nó.ev_7be90c0c…trong hình và xem khiếu nại rơi vào unsupportedTrong khi hai bản ghi về grade- Cứ ở lại.

Các yêu cầu phạm vi cho thấy trường hợp một phần. Chỉ hai trong số mười một đầu vào của nó, 95 và 100, xuất hiện trong lưới chạy. check_claim()trả lại unknownvới covered2 trong số 11, và promote_claim()từ chối với "2 trong 11 đầu vào đã quan sát chạy.

completion_ledger()gương của rea EvidenceCompletionLedger- Tên của nó làecl_cộng với hash của hồ sơ của nó, và completeđúng chỉ khipass=total. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .ecl_da64933ea13befed…với complete: false, vì một yêu cầu phạm vi.

Những thứ không biết là những bản ghi với chuỗi Hash

rea lưu trữ một số dư không rõ ràng như một hồ sơ nghiêm ngặt. code/main.pygiữ các trường và các biến động tương tự.

Đơn vị nhận dạng làunk_+ SHA-256 qua {domain, question, scope_digest}2 nhà phân tích hỏi cùng một câu hỏi về cùng một tệp nhận được cùng một ID.scope_digestlà SHA-256 của đối tượng.

Mỗi thay đổi là một bản sửa đổi mới.previous_revision_digest null. Mỗi lần sửa đổi sau đó tên gọi của revision_digestTrong số những người trước đó, và tiêu hóa bao gồm tất cả các cánh đồng ngoại trừ chính nó.verify_unknown_chain()kiểm tra rằng mỗi liên kết chỉ vào phiên bản sửa đổi trước đó. Nó kiểm tra rằng các bằng chứng đột biến của mỗi tên sửa đổi nằm trong sổ cái.

Mỗi đột biến tự nó là một hồ sơ bằng chứng, như thực sự làm với nhà cung cấp rea-unknown-registry- Chúng ta mang theo .confidence derived- authority analyst-inference"Một đột biến đăng ký ghi lại những gì nhà phân tích quyết định.

Đó là lý do tại sao 81 bản ghi của bản demo bao gồm 36 bản ghi đột biến bắt nguồn: 18 mở và 18 cập nhật.

Ba biến số được áp dụng cho mỗi sửa đổi:

  • Chỉ có một resolvedkhông biết mang theo một resolution, và chỉ có sửa đổi 1 không có tiền nhiệm.
  • A contradictedTên không rõ ít nhất một ID mâu thuẫn, và không có ID xuất hiện trong cả hai danh sách.
  • A verifiedgiải quyết tên ít nhất một ID bằng chứng với sự tin tưởng và thẩm quyền cần thiết.

Quy tắc thứ ba là nơi sổ cái thường từ chối. ghi chép lưu lượng công việc của rea nói "Chỉ có bằng chứng quan sát được xác nhận có thể xác minh một giải pháp". resolve_unknown()do đó bác bỏ mô hình bảng, bác bỏ một hồ sơ được quan sát với thẩm quyền shipped-artifact, và chấp nhận hồ sơ chạy ev_f4ffbe8f922ec7fe…. Việc sửa đổi được giải quyết cho grade(95)là sửa đổi 2, và nó previous_revision_digestlà ffca840b55a8a188…, bản ghi của sửa đổi 1.

update_unknown()- Đưa raexpected_revisionvà tăng lên revision-conflictKhi nó đã lỗi thời, như Rea update_unknownCông cụ có. phản ứng đúng là một ghi chú của rea: đọc lại sửa đổi hiện tại và quyết định lại.

Một người không biết vẫn mở sau khi trình diễn:unk_f2eb0d7f84c80a19…, "Công điểm ((score) == 4 cho mỗi điểm từ 90 đến 100 giữ khi hàm được biên soạn chạy?". Tình trạng của nó là investigating, các ID hỗ trợ của nó bao gồm hai chạy, và thăm dò của nó vẫn đặt tên cho chín đầu vào mà không có một chạy.

Một kho chứa câu trả lời không phải là một cơ sở dữ liệu phân tích

rea có ba thứ trông giống như một bộ nhớ cache.-readOnly -deleteProjectVà bị xóa ngay khi đóng.AnalysisSnapshotCachechứa lên đến 10.000 mục cho một danh tính nhị phân.target- binding- entries- workflow_entries, và một evidence_bundle- Tôi không biết.

Chìa khoá là query_+ SHA-256 qua {target, binding, operation, parameters}- targetlà {sha256, kind, format, architecture}, và một raw-binarymục tiêu cũng cóentry_point- bindinglà nhà cung cấp và toàn bộ hồ sơ phân tích, bao gồm cả tiêu hóa. Thay đổi bất kỳ thông số nào trong 25 hồ sơ, ví dụ jump_table_evidencetừ typed-case-default-blocks-v1đến một v2, và tiêu hóa thay đổi, vì vậy mỗi chìa khóa thay đổi.

code/fixtures/rea-snapshot.jsonlà tệp rea được viết trong hai lần chạy, 142.690 byte. rea đã viết nó với quyền chỉ có chủ sở hữu, và bản sao được giao là có thể đọc bởi mọi người. Nó có hai mục và một gói bằng chứng với hai hồ sơ tương tự. AnswerCache.import_snapshot()tính lại mỗi lần query_idvà từ chối tệp khi bất kỳ khác nhau. Nó từ chối một snapshot màtargethoặc bindingkhác với hoạt tính, với các từ của rea profile_mismatchNó từ chối một bức ảnh mà...format_versionKhông phải course-answer-cache-1- Tôi không biết.

Ba phép đo từ máy này.gradetruy vấn mất 8,6 giây, với một nhập khẩu Ghidra mới.percent_changetruy vấn đối với cùng một snapshot mất 8,5 giây, bởi vì một truy vấn khác là một cache bị bỏ lỡ.gradetruy vấn đã mất 2,1 s và trả lại bản ghi giống hệt với bản ghi giống hệt evidence_id. Phân tích trong bộ nhớ trong rea thêm giới hạn "Điều tải từ một ảnh chụp nhanh phân tích REA địa phương; cuộc gọi này không chạy lại nhà cung cấp. "lookup()thêm một câu giống nhau, để người đọc có thể phân biệt một replay từ một câu trả lời mới.

Một đột biến kết thúc bộ nhớ cache. Trong rea 6.5.0, một đổi tên hoặc bình luận xóa bộ nhớ cache snapshot trước khi rea gửi cuộc gọi đến nhà cung cấp. Một phản hồi thất bại không thể chứng minh rằng viết đã lăn lại, vì vậy một viết thất bại cũng ngừng phát lại. Một nhập siêu dữ liệu thay đổi cơ sở dữ liệu cũng làm tương tự.

Tại sao một đại lý cần điều này

Một đại lý điều khiển REA qua MCP sẽ xem toàn bộ hồ sơ của mỗi cuộc gọi và có thể trích dẫnevidence_idNghiên cứu từ năm 2026 cho thấy điều đó đi sai. Sự tin tưởng quá mức vào sản xuất công cụ là một trong bốn điểm yếu trong nghiên cứu NDSS BAR. Trong nghiên cứu văn bản trồng trọt, cho thấy nội dung nhị phân như dữ liệu một mình vẫn còn 15 đề xuất không an toàn trong 40, và kiểm tra nguồn gốc với ủy quyền công cụ đã loại bỏ chúng. Một nghiên cứu thứ ba đã xem một đại lý lái Ghidra thông qua MCP (arXiv 2606.06838Trong các binary có hàng trăm hàm, chỉ có 10 đến 15 phần trăm nhận được phân tích thực trước khi đại lý tạo ra các khối.

Các sổ cái trả lời mỗi câu hỏi này bằng một hồ sơ, và đại lý chỉ báo cáo những gì sổ cái chứa.unsupportedMột số lần chạy làunknownMột văn bản của nhà cung cấp làobservedCho đại lý hồ sơ kỹ năng trong.outputs/và làm cho sổ cái là nơi duy nhất nó viết kết luận. đó là dành cho Claude, Cursor, Codex, OpenClaw, Hermes, hoặc bất kỳ đại lý nào đọc SKILL.md.

Hãy xây dựng nó

Chạy trình diễn thư viện tiêu chuẩn:

bashcd phases/13-tools-and-protocols/35-evidence-confidence-and-unknowns
python3 code/main.py

Demos đọc đối tượng, nhập hai bản ghi rea, xác minh ảnh chụp nhanh rea và lấy hai mô hình. Sau đó nó ghi lại 18 dự đoán, mở 18 điều chưa biết, biên soạn và chạy vòng xoáy, kiểm tra mọi yêu cầu và giải quyết 17 điều chưa biết.

json{
  "records": 81,
  "by_confidence": { "observed": 25, "derived": 38, "inferred": 18 },
  "rea_snapshot": { "entries": 2, "replay_hit": true, "stale_profile_refused": true },
  "grade_table": [1, 2, 3, 4, 4],
  "runs": "live: Apple clang version 17.0.0 (clang-1700.6.3.2)",
  "claims": [ { "claim_id": "grade(95)", "status": "pass", "covered": "1/1" }, { "claim_id": "grade(90..100)", "status": "unknown", "covered": "2/11" } ],
  "completion_ledger_id": "ecl_da64933ea13befed9483f8b00447bb3f4ceb74324c01e2515eff03f3af3ca750",
  "complete": false,
  "unknowns": { "resolved": 17, "investigating": 1 }
}

Không có trình biên dịch C, runsđọc imported 17 recorded run records from run-evidence.jsonvà phần còn lại cũng như vậy.

Đọc code/main.pytheo thứ tự này:

  1. canonical_json()và compute_evidence_id()giữ công thức hash và dự đoán ngữ nghĩa.
  2. create_evidence()và validate_evidence()xây dựng và kiểm tra hồ sơ.
  3. EvidenceLedger.record()và import_bundle()lưu trữ hồ sơ và từ chối xung đột.
  4. open_unknown()- update_unknown(), vàresolve_unknown()giữ chuỗi sửa đổi.
  5. observe_object()đọc ELF, và derive_grade_model()đọc bảng.
  6. claim_suite()- predict(), vàrecord_prediction()viết các cấp độ suy luận.
  7. observe_runs()biến mỗi vòng xoáy chạy thành một hồ sơ được quan sát.
  8. check_claim()- promote_claim(), vàcompletion_ledger()áp dụng các quy tắc khuyến mãi.
  9. AnswerCacheKey trả lời như ảnh chụp của Rea và từ chối những bức ảnh cũ.

Sử dụng nó

Hãy giữ một sổ cái cho mỗi mục tiêu và mỗi cuộc điều tra. Đặt SHA-256 của mục tiêu trong mỗi chủ đề và tiêu hóa phạm vi của câu hỏi trong mỗi không rõ. Khi bạn thay đổi công cụ, thay đổi các providerKhi bạn xây dựng lại bộ cố định, chủ đề tiêu hóa thay đổi và mỗi hồ sơ cũ trở thành bằng chứng về một tập tin khác.

Bạn có thể viết ra những giới hạn ngay khi bạn biết chúng. Người đọc không áp dụng chuyển đổi không nói vậy. Cuộc chạy của một cấu trúc chủ nhà nói vậy. Mô hình suy luận một phân chia nói vậy. Một bản ghi được viết mà không có giới hạn của nó trông mạnh hơn sự thật cho phép, và một người đọc sau đó không thể sửa chữa điều đó.

Hãy đối xử với mỗi văn bản cung cấp như dữ liệu. Các chuỗi và mã giả từ mục tiêu là văn bản mà mục tiêu kiểm soát._meta.provenance.untrusted_content: trueCác hướng dẫn máy chủ của nó nói với mô hình để xử lý nội dung mục tiêu như dữ liệu và báo cáo bất kỳ yêu cầu nào trong đó để chạy, cài đặt, tải xuống hoặc gửi một thứ gì đó như một nỗ lực tiêm nhanh.

Phòng thí nghiệm tương tác

Phòng thí nghiệm A: tính lại một reaid

Từ codethư mục, mở Python:

bashcd phases/13-tools-and-protocols/35-evidence-confidence-and-unknowns/code
python3 -q

Đi chạy:

pythonfrom main import *
record = load_evidence_file(FIXTURES / "rea-evidence-grade.json")
record["evidence_id"] == compute_evidence_id(record)
record["subject"]["local_path"] = "/home/you/re/ledger-x86_64-O1.o"
record["evidence_id"] == compute_evidence_id(record)
record["limitations"].pop()
record["evidence_id"] == compute_evidence_id(record)

Hai so sánh đầu tiên là đúng. con đường không nằm trong hash.

Phòng thí nghiệm B: từ chối thăng chức

pythonledger, report = build_ledger(live_runs=False)
claim = [c for c in claim_suite(ledger.find(operation="derive_switch_model")[0], ledger.find(operation="derive_arithmetic_model")[0], ledger.find(operation="read_source")[0]) if c.claim_id == "grade(55)"][0]
promote_claim(ledger, claim, [ledger.find(operation="derive_switch_model")[0]["evidence_id"]])

Cuộc gọi lên lênClaimErrorvà đặt tên ID bắt nguồn. Bây giờ hãy đi qua ID chạy:

pythonrun = run_records_for(ledger, "grade", [55])[0]
promote_claim(ledger, claim, [run["evidence_id"]])["status"]

Tình trạng là pass, và những người trở về limitationsđưa ra án xây dựng nhà.

Phòng thí nghiệm C: từ chối một bức ảnh nhanh bị lỗi thời

pythonimport json
snapshot = json.loads(REA_SNAPSHOT_PATH.read_text())
target, binding = rea_snapshot_binding(snapshot)
AnswerCache(target, binding).import_snapshot(snapshot)
stale = dict(binding["analysis_profile"]["parameters"], jump_table_evidence="typed-case-default-blocks-v2")
AnswerCache(target, {"provider": binding["provider"], "analysis_profile": make_profile(binding["provider"], stale)}).import_snapshot(snapshot)

Lần đầu tiên xuất nhập khẩu 2. lần thứ hai tăng CacheErrorvới profile_mismatchMột chuỗi phiên bản thay đổi, và toàn bộ ảnh chụp được từ chối.

Phòng thí nghiệm D: phá vỡ chuỗi

pythonunknown_id = [u for u, r in ledger.unknowns.items() if r[-1]["status"] == "investigating"][0]
ledger.verify_unknown_chain(unknown_id)
ledger.unknowns[unknown_id][0]["severity"] = "critical"
ledger.verify_unknown_chain(unknown_id)

Lần gọi đầu tiên trả lại 2 lần gọi thứ hai.EvidenceIntegrityError, bởi vì sửa đổi 1 không còn phù hợp với bản tiêu hóa của riêng nó và sửa đổi 2 điểm ở một bản tiêu hóa không còn tồn tại nữa.

Phòng thí nghiệm thực hành

Đóng không rõ mở và thêm một nhà cung cấp thứ hai.

Yêu cầu:

  • Tăng run_grid()Vì vậy, các mục nhập thiếu sót của phạm vi yêu cầu chạy, sau đó xác nhận các chuyển động không rõ đến resolvedtrong phiên sửa đổi 3.
  • Thêm llvm-objdump -dnhư một nhà cung cấp thứ hai với riêng mình providerđối tượng và ghi lại danh sách của nógradenhư observed- Tôi không biết.
  • Hãy viết một derivedghi lại hai danh sách, của Ghidra và của llvm-objdump, giải mã cùng 14 hướng dẫn, và liên kết cả hai.
  • Mở một cái tên không rõgrade_label(105)với độ nghiêm trọng high, vì chỉ số bảng 4 đọc labels[4], và giải quyết nó bằng cách chạy.
  • Xuất khẩu sổ cái với export_bundle(), nhập vào một sổ cái mới, và chứng minh mọi chuỗi vẫn xác minh.

Thành công là một báo cáo trong đó mỗi câu trích dẫn một ID từ gói và một unknownyêu cầu đã biến mất.

Bài học: Cây tạo vật

Bài học này sẽ mang lại kết quả outputs/skill-evidence-ledger.mdNó cho biết cho một đại lý làm thế nào để viết mỗi phát hiện như một hồ sơ với sự tin tưởng, thẩm quyền, giới hạn, và liên kết. Nó cho đại lý biết làm thế nào để giữ những điều không rõ như sửa đổi, và khi một yêu cầu làpass- fail- unknown, hoặcunsupported- Tôi không biết.

Hãy kiểm tra

Chạy demo và bộ xác định:

bashcd phases/13-tools-and-protocols/35-evidence-confidence-and-unknowns
python3 code/main.py
python3 -m unittest discover -s code/tests -v

28 thử nghiệm chứng minh:

  • cả hai rea evidence_idgiá trị, hồ sơ tiêu hóa, và cả hai snapshot query_idgiá trị tính lại từ nội dung
  • một con đường thay đổi giữ ID và một giới hạn thay đổi nó
  • Một hồ sơ bị vi phạm, một nhà cung cấp hồ sơ không phù hợp, một float và một giá trị enum không rõ được từ chối
  • một hồ sơ sao chép trả lại duplicate, một kỷ lục mâu thuẫn tăng, và một gói nhập khẩu là nguyên tử
  • Các nhập khẩu hàng loạt được ghi nhận với 18 hồ sơ và không có liên kết treo
  • một người không biết mở tại sửa đổi 1, từ chối một lỗi expected_revision, và giải quyết chỉ với quan sátcontrolled-replaybằng chứng
  • một sửa đổi đã được chỉnh sửa phá vỡ chuỗi
  • khuyến mãi từ chối kết luận, dẫn xuất, trống, và không liên quan bằng chứng, và đi qua với một chạy đồng ý
  • bảo hiểm một phần là unknownvà một cuộc chạy đua không đồng ý là fail
  • bộ nhớ cache nhấn vào khóa chính xác và bỏ lỡ các tham số khác
  • bộ nhớ cache từ chối một phiên bản hồ sơ bị đập, một mục tiêu sai, một phiên bản định dạng sai, và một phím bị vi phạm
  • người đọc ELF đồng ý với llvm-objdumpvề các sự thay đổi, kích thước, byte, và di chuyển, và bảng đọc 1, 2, 3, 4, 4
  • Các dự đoán sử dụng phân chia C, và các chạy ghi lại phù hợp với tất cả 17 yêu cầu nhập đơn
  • Với một trình biên dịch hiện diện, các chạy trực tiếp cũng đồng ý

Các chế độ sản xuất thất bại

FailureWhat the weak report saysWhat the ledger requires
Pseudocode read as behaviour"grade returns 0 for failing scores"an execute_function record for that input, or unsupported
Decompiler signature trusted"percent_change returns 16 bytes"the signature marked as the provider's inference with its low confidence
Empty list read as absence"the function has no callers"an unknown status, or a coverage field when the tool provides one
Path hashed into the id"the record changed" after a copythe semantic projection without name and local_path
Limitation dropped from a copya record that looks stronger than the sourceid mismatch and rejection on import
Partial grid rounded up"all scores from 90 pass"unknown with covered 2 of 11
Host run presented as the object's run"the x86-64 object returned 25"the host-build limitation carried on the claim
Unknown closed by a sentence"resolved, see above"a verified resolution with observed ids of the required authority
Stale revision overwrittentwo analysts' edits colliderevision-conflict and a reread
Old snapshot replayed after a releaseanswers from a changed contractprofile_mismatch on import
Cache kept after a renamea replay that hides a metadata writeinvalidation before dispatch and a failed export

Quy tắc hoạt động

Hãy ghi lại những gì bạn đọc, những gì bạn tính toán và những gì bạn mong đợi như ba loại ghi lại với ba từ.

Đọc thêm

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.