mirror of
https://github.com/morluto/rea.git
synced 2026-11-07 13:56:47 -10:00
Compare commits
219
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96606f5114 | ||
|
|
ebfef27b46 | ||
|
|
0ffed7a48c | ||
|
|
675d4076de | ||
|
+1 |
1ddee1089b | ||
|
|
250dc81cd6 | ||
|
|
54756ff24e | ||
|
|
19ab239278 | ||
|
|
1926fc2dac | ||
|
|
b33f4a5a1b | ||
|
|
cd878ad57d | ||
|
|
8f920bb65b | ||
|
|
77b09314ff | ||
|
|
b1ff7cdacc | ||
|
|
767f6afc18 | ||
|
|
6bb831df60 | ||
|
|
37342ecde0 | ||
|
|
a47dcca010 | ||
|
|
6b68fb642a | ||
|
|
81378efb71 | ||
|
|
72039ecca9 | ||
|
|
d77104daab | ||
|
|
cce33142ed | ||
|
|
c5f50e80d8 | ||
|
|
9d68aac76d | ||
|
|
24398a89e4 | ||
|
|
0ce76e70f4 | ||
|
|
6d19649c0b | ||
|
|
bfa082f777 | ||
|
|
317bf3fe23 | ||
|
|
3b647132c6 | ||
|
|
249b90c5e3 | ||
|
|
940d71a45a | ||
|
|
4a8d8f72b3 | ||
|
|
395b598383 | ||
|
|
b663c79552 | ||
|
|
a4c183b750 | ||
|
|
fa1aa64ce4 | ||
|
|
b894be6361 | ||
|
|
5f9187cd27 | ||
|
|
1c14f66356 | ||
|
|
1da304b282 | ||
|
|
da5ec6b62c | ||
|
|
c0c3902207 | ||
|
|
845080aef6 | ||
|
|
bf115be2cd | ||
|
|
539a494d25 | ||
|
|
ec4a0a01c4 | ||
|
|
8188497f13 | ||
|
|
cac6e0613e | ||
|
|
a108a1b817 | ||
|
|
b3d31ed106 | ||
|
|
34577eb1cc | ||
|
|
e124bdfc54 | ||
|
|
22cab8215a | ||
|
|
5c05eb88e5 | ||
|
|
6fa48f201f | ||
|
|
1ef5918179 | ||
|
|
51ad84516e | ||
|
|
01e00dae72 | ||
|
|
860fdd8fbe | ||
|
|
d3ecf68000 | ||
|
|
c88e1b0b43 | ||
|
|
131fbe0754 | ||
|
|
3503578f91 | ||
|
|
bd3792566d | ||
|
|
f7cd4e5256 | ||
|
|
2b85a4a2ba | ||
|
|
e3d8d20236 | ||
|
|
17ceb77ca5 | ||
|
|
f25d1e3e9f | ||
|
|
124e97eac5 | ||
|
|
95637a3d70 | ||
|
|
ca666ec130 | ||
|
|
45cc935964 | ||
|
|
d82ba11ce2 | ||
|
|
c9bf6a9df7 | ||
|
|
afc18131f4 | ||
|
|
54f5cf7e14 | ||
|
|
f60e42a9ae | ||
|
|
ddefba83ef | ||
|
|
b966ebeb22 | ||
|
|
fca331804a | ||
|
|
4fbce5c122 | ||
|
|
35ea02d27e | ||
|
|
2bfd84b2c8 | ||
|
|
d39b3000ec | ||
|
|
d157560d40 | ||
|
|
429355ca4d | ||
|
|
50b2ab137f | ||
|
|
cf9f010dcd | ||
|
|
c19f13ca03 | ||
|
|
62ce357f16 | ||
|
|
953a7689df | ||
|
|
3dcb40dc26 | ||
|
|
7b9bcf724f | ||
|
|
7ca216a266 | ||
|
|
419a211304 | ||
|
|
63f05d1cad | ||
|
|
95f0625781 | ||
|
|
611c30cb20 | ||
|
|
78a1e1956e | ||
|
|
59a895a193 | ||
|
|
3536ea2f49 | ||
|
|
70a8325c38 | ||
|
|
9e1a1e700a | ||
|
|
33d6975749 | ||
|
|
0386efd1e1 | ||
|
|
c92322b473 | ||
|
|
0448f318e6 | ||
|
|
640e19d79d | ||
|
|
6db024dc96 | ||
|
|
4671947c97 | ||
|
|
b7442c1958 | ||
|
|
a965cbab06 | ||
|
|
64d282b0a6 | ||
|
|
30936d7596 | ||
|
|
3a46047aa7 | ||
|
|
7c5700542e | ||
|
|
ef9ab91e42 | ||
|
|
5147b6e306 | ||
|
|
c7722c8eeb | ||
|
|
b0b25ad93e | ||
|
|
3a512303d9 | ||
|
|
794907fa3d | ||
|
|
2129c17925 | ||
|
|
0179d94420 | ||
|
|
bbd4989654 | ||
|
|
32b3722d2f | ||
|
|
844bb46351 | ||
|
|
086abf3996 | ||
|
|
9b4546276c | ||
|
|
f256492ff3 | ||
|
|
63491645fd | ||
|
|
a4bd924772 | ||
|
|
66f5b650d9 | ||
|
|
1631dcb09a | ||
|
|
42d5425417 | ||
|
|
07dfd12613 | ||
|
|
f1da7f7670 | ||
|
|
3142f7b0dd | ||
|
|
fc24b08851 | ||
|
|
edc908af58 | ||
|
|
b4923f85c5 | ||
|
|
9ac9f91ab5 | ||
|
|
c2cc7e6eb0 | ||
|
|
a001231256 | ||
|
|
8c83886891 | ||
|
|
fd297b1b17 | ||
|
|
16cfe30dab | ||
|
|
473cfa36b8 | ||
|
|
5082b50f07 | ||
|
|
31c028f496 | ||
|
|
e0719cffa4 | ||
|
|
21b192706d | ||
|
|
286629b570 | ||
|
|
50d731d456 | ||
|
|
f9acfdcf49 | ||
|
|
9b880e0e3e | ||
|
|
76c7698ac9 | ||
|
|
83cd1e04c9 | ||
|
|
29945d435d | ||
|
|
6c205d8a79 | ||
|
|
4e663beeb8 | ||
|
|
1e088c19ad | ||
|
|
cc5a4062ff | ||
|
|
6c76a7ffb0 | ||
|
|
114731eb1e | ||
|
|
583a316e11 | ||
|
|
f6380282fb | ||
|
|
2aa0d45e13 | ||
|
|
5f146b3b19 | ||
|
|
553f19590f | ||
|
|
e03ff93913 | ||
|
|
78a350e0b6 | ||
|
|
52617bd50e | ||
|
|
675c73fb4d | ||
|
|
bd687bbc40 | ||
|
|
b0880d660f | ||
|
|
2dd9a3092e | ||
|
|
5c60720ad7 | ||
|
|
9b7c2bb1ac | ||
|
|
0759fb9ad5 | ||
|
|
46c457f74c | ||
|
|
1b636c890f | ||
|
|
fe52ea12c3 | ||
|
|
00bd92c56e | ||
|
|
37827af591 | ||
|
|
2f3c71f39e | ||
|
|
b75419b61e | ||
|
|
8f9af920ef | ||
|
|
e23cb3b240 | ||
|
|
4b0ff68e2e | ||
|
|
19032204aa | ||
|
|
f19436c156 | ||
|
|
44331d04d2 | ||
|
|
0a272d5cf5 | ||
|
|
0747e46401 | ||
|
|
183e2e2d1e | ||
|
|
5119d08daf | ||
|
|
1e421242b9 | ||
|
|
5bef2b48b6 | ||
|
|
e79ad6ca8e | ||
|
|
128c2cf632 | ||
|
|
aaf4d21068 | ||
|
|
aba158506b | ||
|
|
477f63ae21 | ||
|
|
60ab4da329 | ||
|
|
f9e7571a3d | ||
|
|
685f6db960 | ||
|
|
b21a975faf | ||
|
|
d49a1504ca | ||
|
|
4109271bcb | ||
|
|
a6295e433b | ||
|
|
af1ccb6506 | ||
|
|
7dbebb4e7d | ||
|
|
dfa0689890 | ||
|
|
251e27ef3b | ||
|
|
64196b08ca |
No files matched your search
@@ -2,7 +2,7 @@
|
||||
name: reverse-engineer-anything
|
||||
description: Reverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets with REA, and build agent environments (AgentEnv bundles) of web applications from a live instance or a capture. Use shipped-artifact or requested runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis.
|
||||
metadata:
|
||||
version: "53"
|
||||
version: "55"
|
||||
---
|
||||
|
||||
# REA
|
||||
@@ -94,6 +94,9 @@ explicit path or endpoint and do not need it.
|
||||
than extra calls and schemas. Runtime options are metadata, not files.
|
||||
Compact delivery still inventories and hashes members. See the
|
||||
[Python packaged applications guide](https://github.com/morluto/rea/blob/main/docs/python-packaged-applications.md).
|
||||
- Bun `--compile` executable: `open_binary`, then `inspect_artifact`; the Bun
|
||||
module graph is the application layer. Extract stored modules and analyze the
|
||||
JavaScript. See [Bun standalone executables](https://github.com/morluto/rea/blob/main/docs/bun-standalone.md).
|
||||
- Apple app plist, Interface Builder, asset catalog, or keyed archive resources:
|
||||
`open_bundle_resources`, then the selected resource tool. This does not
|
||||
require `CFBundleExecutable` or a deep provider. Resource sessions have no
|
||||
@@ -106,6 +109,8 @@ explicit path or endpoint and do not need it.
|
||||
`extract_firmware` when extraction is requested, with a caller-selected new
|
||||
absolute output directory. These tools use caller-supplied Binwalk/Unblob on
|
||||
Linux; see the [firmware guide](https://github.com/morluto/rea/blob/main/docs/firmware-analysis.md).
|
||||
- ESP32-family app or bootloader image (`0xE9` magic): `inspect_artifact`
|
||||
without a provider; see the ESP section of `references/native-and-artifacts.md`.
|
||||
- .NET NativeAOT PE/ELF: native Ghidra analysis. Native code can yield pseudocode;
|
||||
consult the NativeAOT workflow in `references/native-and-artifacts.md` for
|
||||
optional metadata recovery and its supported host/layout boundary.
|
||||
@@ -145,7 +150,9 @@ explicit path or endpoint and do not need it.
|
||||
and field names/types before choosing fields for `inspect_packet_capture`.
|
||||
Query/page the relevant records; registrations do not establish observed traffic.
|
||||
- Recorded packet captures: `inspect_packet_capture` with selected TShark fields,
|
||||
display filters and decode-as rules. Requires Linux, util-linux prlimit and `REA_TSHARK_COMMAND`; see
|
||||
display filters and decode-as rules. Requires Linux, util-linux prlimit and
|
||||
TShark 4.x on an absolute `PATH` entry or via the optional absolute
|
||||
`REA_TSHARK_COMMAND` override; see
|
||||
[capture guide](https://github.com/morluto/rea/blob/main/docs/packet-captures.md).
|
||||
Packet limits count input packets before filtering. Output defaults to 50 matching
|
||||
frames; use `match_offset` / `match_limit` for later pages, or explicit null
|
||||
|
||||
@@ -124,9 +124,11 @@ shape, with the application's own locators, paths and headers:
|
||||
}
|
||||
```
|
||||
|
||||
Give every step a `timeout_ms`. A step without one waits until the scenario
|
||||
is cancelled, so a locator that never matches hangs the capture, and the
|
||||
client with it. Match `wait_for` locators to exactly one element.
|
||||
Give each step that accepts `timeout_ms` a deadline. Without one, a step waits
|
||||
until it completes or the scenario is cancelled, so a locator that never
|
||||
matches hangs the capture and the client with it. The `wait_for_timeout` pause
|
||||
instead uses `duration_ms` and does not accept `timeout_ms`. Match `wait_for`
|
||||
locators to exactly one element.
|
||||
|
||||
1. Sign in through the UI: `fill` the user and password fields (the password
|
||||
as a secret reference), submit, then `wait_for` an element only a signed-in
|
||||
@@ -153,13 +155,17 @@ client with it. Match `wait_for` locators to exactly one element.
|
||||
with varied free text. After each write, and before the next one, read the
|
||||
object back by id and then its list: create 1, read 1, list, create 2,
|
||||
read 2, list; never several writes before their reads.
|
||||
4. Leave more than a second between a create and its first edit
|
||||
(`wait_for_timeout` with `duration_ms: 1100`).
|
||||
4. Leave more than a second between two creates and between a create and its
|
||||
first edit (`wait_for_timeout` with `duration_ms: 1100`), so lists sorted
|
||||
by creation time show them in order.
|
||||
5. Update both objects and read each back, changing the fields a person
|
||||
would change (a name, an email address, a status, a due date) rather than
|
||||
only a description: a served update accepts only the members a recorded
|
||||
update stored. Delete both and read each back (expect 404, or the object
|
||||
marked deleted) and the list.
|
||||
update stored. Run an action that turns something on or off (star,
|
||||
bookmark, archive) twice in a row on one object, reading it back after
|
||||
each: the second call shows whether it sets or flips the field, and the
|
||||
environment serves the action only once a call has shown it. Delete both
|
||||
and read each back (expect 404, or the object marked deleted) and the list.
|
||||
6. Vary what the two creates send, however you write them: the first every
|
||||
field the application takes, the second only what a person must give (its
|
||||
title or name), with the other fields left out or empty. A served create
|
||||
@@ -235,17 +241,17 @@ Re-record a withheld write at most twice, and only for a recording gap. Stop at
|
||||
once when the reason is application behaviour, and report the write as
|
||||
withheld with its hint:
|
||||
|
||||
| Reason | What to do |
|
||||
| --------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| `no-state-target` | Re-record: read the collection or item the write changes. |
|
||||
| `no-observation` | Re-record: read the entity back by id after the write; read it first for an update or delete. |
|
||||
| `unconfirmed` | Re-record: read the entity and its list after the write. |
|
||||
| `incomplete-entities` | Re-record: read the entity through every view that lists it. |
|
||||
| `unexplained-change` | Re-record once with a second, different call of the same write. |
|
||||
| `no-call` | Re-record once with a write that succeeds. |
|
||||
| `side-effect` | Stop: the application changes other entities. |
|
||||
| `contradicted` | Stop: a later read disagrees with the modelled effect. |
|
||||
| `body-unusable` | Re-record a UI write once with `request` steps (its body was not exposed); else stop. |
|
||||
| Reason | What to do |
|
||||
| --------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `no-state-target` | Check the path template and recorded views; record missing reads. The route form may not be supported as a mutation target. |
|
||||
| `no-observation` | Re-record: read the entity back by id after the write; read it first for an update or delete. |
|
||||
| `unconfirmed` | Re-record: read the entity and its list after the write. |
|
||||
| `incomplete-entities` | Re-record: read the entity through every view that lists it. |
|
||||
| `unexplained-change` | Re-record once with a second, different call of the same write. |
|
||||
| `no-call` | Re-record once with a write that succeeds. |
|
||||
| `side-effect` | Stop: the application changes other entities. |
|
||||
| `contradicted` | Stop: a later read disagrees with the modelled effect. |
|
||||
| `body-unusable` | Re-record a UI write once with `request` steps (its body was not exposed); else stop. |
|
||||
|
||||
Use new scratch names on each attempt, and delete what an earlier attempt
|
||||
created before recording again (through the UI, or a `request` step with the
|
||||
|
||||
@@ -46,7 +46,10 @@ Use comparisons with complete, compatible page sets when claiming equivalence
|
||||
or absence:
|
||||
|
||||
- `compare_artifacts` compares inventory pages by occurrence path, content,
|
||||
metadata, and graph relations.
|
||||
metadata, and graph relations. Name each side as
|
||||
`{kind: "retained-evidence", evidence_id}` (an `inspect_artifact` result,
|
||||
its nested inventory or its summary) or
|
||||
`{kind: "evidence-file", path, evidence_id?}` instead of resending Evidence.
|
||||
- `compare_functions` compares explicit function Evidence, not fuzzy
|
||||
whole-binary matches. It rejects an `analyze_function` summary reply; pass
|
||||
the summary's `parent_evidence_id` as a `retained-evidence` reference or
|
||||
|
||||
@@ -516,6 +516,11 @@ names), coverage and per-collection counts. Page rows with
|
||||
`view: {kind: "managed-members", collection: "call_edges", offset: 0, limit: 64}`
|
||||
over `types`, `exported_types`, `fields`, `methods`, `member_refs`, `call_edges`,
|
||||
`field_accesses` or `user_strings`.
|
||||
Use exact `names` and `declaring_types` filters before paging supported
|
||||
collections. For a compact method lookup, request `fields: ["name",
|
||||
"declaring_type", "signature"]`; omit `body` to avoid anchors. Identity tokens,
|
||||
original `source_index`, module/MVID and source coverage remain. Check
|
||||
`unresolved_filter_rows` before interpreting an empty match as absence.
|
||||
|
||||
### .NET NativeAOT
|
||||
|
||||
@@ -669,3 +674,41 @@ IDs. Header addresses/CPU/OS are declarations; payloads remain as stored.
|
||||
Multi-file components retain their aligned physical ranges; the full payload
|
||||
is also materialized. Unknown name text retains its original 32 bytes. See
|
||||
[U-Boot uImage](https://github.com/morluto/rea/blob/main/docs/uimage.md).
|
||||
|
||||
## ESP images
|
||||
|
||||
For an ESP32-family app or bootloader image, `open_binary` then
|
||||
`inspect_artifact` with `detail: "summary"`. `root_format_metadata` holds the
|
||||
observed `header` and `descriptor` (its `kind` is the app or bootloader role)
|
||||
and the derived `chip`, `checksum`, `appended_sha256` and
|
||||
`undescribed_trailing` ranges. Segment rows (`segment-NN.bin`) carry
|
||||
`load_addr`, `classification` (`mapped`, `loaded`, `not-loaded` or `unknown`,
|
||||
per ESP-IDF `should_map`/`should_load`; RAM ranges are not checked) and
|
||||
`source_location`; select them with `inspect_analysis_view` and
|
||||
`logical_paths`. Signature blocks are `unverified`; `public_key_sha256`
|
||||
matches eFuse key digests.
|
||||
|
||||
Unknown `source_coverage` means truncation or undescribed trailing bytes, such
|
||||
as the flash segments of a `--ram-only-header` image; do not infer absence
|
||||
from it. Erased flash is described. Integrity mismatches are facts, not
|
||||
refusals. ESP8266 images are refused, and flash-encrypted images are not
|
||||
recognized. Segments are not disassembled, and RISC-V or Xtensa segments
|
||||
cannot be opened as raw-binary. See
|
||||
[ESP images](https://github.com/morluto/rea/blob/main/docs/esp-image.md).
|
||||
|
||||
## Bun standalone executables
|
||||
|
||||
A `bun build --compile` executable stores its module graph in Mach-O
|
||||
`__BUN,__bun`, a PE or ELF `.bun` section, or an appended trailer.
|
||||
`open_binary` then `inspect_artifact` reports root format `bun-standalone` with
|
||||
the carrier, structural layout, module count, entry point, raw flags and
|
||||
compile exec-argv; each module keeps its `/$bunfs/...` source name, loader,
|
||||
encoding, sizes and SHA-256, with sourcemap, bytecode and module-info regions as
|
||||
separate children. Use summary root metadata `entry_point_logical_path` as the
|
||||
exact inventory `logical_paths` selector, then read the selected content node by
|
||||
its artifact ID; the reader owns virtual-name normalization and indexed fallback. `extract-artifact` writes stored contents through the safe
|
||||
output tree; route extracted JavaScript to `analyze_javascript_application`.
|
||||
Layout labels describe record shapes, not a detected compiler version; unknown
|
||||
or ambiguous layouts are unsupported. Bytecode is retained, not decoded, and the
|
||||
executable is never run. See
|
||||
[Bun standalone executables](https://github.com/morluto/rea/blob/main/docs/bun-standalone.md).
|
||||
@@ -0,0 +1,12 @@
|
||||
# Review changes to security-sensitive automation and dependency inputs.
|
||||
/.github/CODEOWNERS @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/.github/dependabot.yml @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/.github/workflows/ @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/.github/actions/ @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/package.json @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/package-lock.json @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/scripts/verify-tools/skills/package.json @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/scripts/verify-tools/skills/package-lock.json @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/scripts/fixtures/http3-lab-requirements.txt @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/website/requirements.txt @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
/third_party/ @morluto @kaoru0822-kitauji @N0zoM1z0 @gensokyo-dev
|
||||
@@ -0,0 +1,33 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directories:
|
||||
- /
|
||||
- /scripts/verify-tools/skills
|
||||
schedule:
|
||||
interval: weekly
|
||||
cooldown:
|
||||
default-days: 7
|
||||
open-pull-requests-limit: 5
|
||||
groups:
|
||||
npm-minor-and-patch:
|
||||
update-types:
|
||||
- minor
|
||||
- patch
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /website
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 5
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 5
|
||||
groups:
|
||||
actions-minor-and-patch:
|
||||
update-types:
|
||||
- minor
|
||||
- patch
|
||||
@@ -61,6 +61,9 @@ jobs:
|
||||
qualification_run_id: ${{ steps.qualification.outputs.run_id }}
|
||||
code: ${{ steps.plan.outputs.code }}
|
||||
reverse_tools: ${{ steps.plan.outputs.reverse_tools }}
|
||||
python: ${{ steps.plan.outputs.python }}
|
||||
packet_capture: ${{ steps.plan.outputs.packet_capture }}
|
||||
signal_recording: ${{ steps.plan.outputs.signal_recording }}
|
||||
sqlite: ${{ steps.plan.outputs.sqlite }}
|
||||
runtime: ${{ steps.plan.outputs.runtime }}
|
||||
package: ${{ steps.plan.outputs.package }}
|
||||
@@ -144,6 +147,9 @@ jobs:
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
- name: Validate source architecture before dependency installation
|
||||
if: needs.changes.outputs.code == 'true'
|
||||
run: node scripts/verify/architecture-guards.mjs
|
||||
- name: Cache npm package downloads
|
||||
id: npm-cache
|
||||
uses: ./.github/actions/npm-cache
|
||||
@@ -264,6 +270,27 @@ jobs:
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
|
||||
python:
|
||||
name: Python producer tests
|
||||
needs: changes
|
||||
if: needs.changes.outputs.python == 'true' && needs.changes.outputs.tier == 'fast'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
- name: Cache npm package downloads
|
||||
id: npm-cache
|
||||
uses: ./.github/actions/npm-cache
|
||||
- run: npm ci
|
||||
# Analysis-efficiency checks import compiled process modules.
|
||||
- name: Reuse portable build outputs across runs
|
||||
uses: ./.github/actions/portable-build-cache
|
||||
- run: npm run test:prepare
|
||||
- run: npm run test:python
|
||||
|
||||
test-source:
|
||||
name: Source tests
|
||||
needs: changes
|
||||
@@ -391,7 +418,9 @@ jobs:
|
||||
needs.changes.outputs.web_network == 'true' ||
|
||||
needs.changes.outputs.web_runtime == 'true' ||
|
||||
needs.changes.outputs.web_source_map == 'true' ||
|
||||
needs.changes.outputs.agentenv == 'true'
|
||||
needs.changes.outputs.agentenv == 'true' ||
|
||||
needs.changes.outputs.packet_capture == 'true' ||
|
||||
needs.changes.outputs.signal_recording == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
@@ -773,6 +802,7 @@ jobs:
|
||||
tests/boundary/providers/native/nativeSignatureTargetBinding.test.ts
|
||||
tests/boundary/cli/nativeSignatureCli.test.ts
|
||||
tests/boundary/cli/nativeMachoArm64_32Cli.test.ts
|
||||
tests/boundary/cli/nativeMachoEncryptionCli.test.ts
|
||||
tests/boundary/mcp/nativeSignatureTargetBindingMcp.test.ts
|
||||
src/process/capture/FilesystemSnapshot.test.ts
|
||||
tests/process-global/filesystemSnapshotFallbackCancellation.test.ts
|
||||
@@ -1091,6 +1121,26 @@ jobs:
|
||||
build_cache_artifact: rea-build-cache
|
||||
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
|
||||
|
||||
packet_capture:
|
||||
needs: [changes, static, build]
|
||||
if: needs.changes.outputs.packet_capture == 'true'
|
||||
secrets:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
uses: ./.github/workflows/real-packet-capture.yml
|
||||
with:
|
||||
build_cache_artifact: rea-build-cache
|
||||
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
|
||||
|
||||
signal_recording:
|
||||
needs: [changes, static, build]
|
||||
if: needs.changes.outputs.signal_recording == 'true'
|
||||
secrets:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
uses: ./.github/workflows/real-signal-recording.yml
|
||||
with:
|
||||
build_cache_artifact: rea-build-cache
|
||||
remote_cache_write: ${{ inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) }}
|
||||
|
||||
nativeaot:
|
||||
needs: [changes, static]
|
||||
if: needs.changes.outputs.nativeaot == 'true'
|
||||
@@ -1117,6 +1167,9 @@ jobs:
|
||||
static-deep,
|
||||
build,
|
||||
reverse-tools-quality,
|
||||
python,
|
||||
packet_capture,
|
||||
signal_recording,
|
||||
test-shard,
|
||||
test-source,
|
||||
sqlite-runtime,
|
||||
|
||||
@@ -62,3 +62,36 @@ jobs:
|
||||
> "${probe_root}/output.log" 2>&1 || { cat "${probe_root}/output.log"; exit 1; }
|
||||
cat "${probe_root}/output.log"
|
||||
grep -F 'REA_ARM_CONTEXT_OK arm=0 thumb=1 unavailable=null (injected provider value)' "${probe_root}/output.log"
|
||||
# Each probe imports source-owned bytes at 0x1000, away from the Cortex-M
|
||||
# vector symbols that ARMCortex.pspec defines at 0, and decodes them from
|
||||
# the language's default context, so M-profile Thumb state must hold at
|
||||
# the first byte. The bytes are never executed.
|
||||
- name: Decode M-profile ARM and Xtensa bytes in their default context
|
||||
shell: bash
|
||||
run: |
|
||||
java_home_variable="JAVA_HOME_${GHIDRA_JAVA_MAJOR}_X64"
|
||||
export JAVA_HOME="${!java_home_variable}"
|
||||
probe_root="${RUNNER_TEMP}/rea-decode"
|
||||
mkdir -p "${probe_root}"
|
||||
# mrs r0, msp; bx lr
|
||||
printf '\357\363\010\200\160\107' > "${probe_root}/cortex.bin"
|
||||
# mrs r0, msplim (ARMv8-M only); bx lr
|
||||
printf '\357\363\012\200\160\107' > "${probe_root}/v8m.bin"
|
||||
# entry a1, 32; retw.n
|
||||
printf '\066\101\000\035\360' > "${probe_root}/xtensa.bin"
|
||||
decode() {
|
||||
local name="$1" language="$2"
|
||||
shift 2
|
||||
mkdir -p "${probe_root}/${name}-project"
|
||||
timeout 180s "${GHIDRA_INSTALL_DIR}/support/analyzeHeadless" "${probe_root}/${name}-project" Decode \
|
||||
-import "${probe_root}/${name}.bin" -loader BinaryLoader -loader-baseAddr 0x1000 \
|
||||
-processor "${language}" -noanalysis -readOnly -deleteProject \
|
||||
-scriptPath "${GITHUB_WORKSPACE}/tests/conformance/ghidra" \
|
||||
-postScript ReaDecodeProbe.java "${language}" "$@" \
|
||||
> "${probe_root}/${name}.log" 2>&1 || { cat "${probe_root}/${name}.log"; exit 1; }
|
||||
cat "${probe_root}/${name}.log"
|
||||
grep -F "REA_DECODE_OK ${language} $*" "${probe_root}/${name}.log"
|
||||
}
|
||||
decode cortex ARM:LE:32:Cortex mrs/4/msp bx/2/lr
|
||||
decode v8m ARM:LE:32:v8-m mrs/4/msplim bx/2/lr
|
||||
decode xtensa Xtensa:LE:32:default entry/3/a1 retw.n/2
|
||||
@@ -11,6 +11,7 @@ on:
|
||||
- tests/conformance/android/**
|
||||
- tests/fixtures/android/static-initializers/**
|
||||
- tests/fixtures/android/direct-invokes/**
|
||||
- tests/fixtures/android/external-invokes/**
|
||||
- .nvmrc
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
@@ -44,7 +45,8 @@ jobs:
|
||||
"$JAVA_HOME/bin/javac" -J-Xmx512m -J-XX:ActiveProcessorCount=2 \
|
||||
-classpath "$jar" -d "$classes" \
|
||||
bridge/android/ReaJadxBridge.java \
|
||||
tests/conformance/android/ReaJadxMetadataRegression.java
|
||||
tests/conformance/android/ReaJadxMetadataRegression.java \
|
||||
tests/conformance/android/ReaJadxExternalReferencesRegression.java
|
||||
"$JAVA_HOME/bin/java" -Xmx512m -XX:ActiveProcessorCount=2 \
|
||||
-classpath "$classes:$jar" ReaJadxMetadataRegression \
|
||||
"$android_root/ApiDemos-debug.apk" \
|
||||
@@ -53,3 +55,9 @@ jobs:
|
||||
| tee "$android_root/metadata.log"
|
||||
grep -F 'RAW_CLASS_SELECTOR_REGRESSION_PASS nested=true metadata=true references=true' \
|
||||
"$android_root/metadata.log"
|
||||
"$JAVA_HOME/bin/java" -Xmx512m -XX:ActiveProcessorCount=2 \
|
||||
-classpath "$classes:$jar" ReaJadxExternalReferencesRegression \
|
||||
"$GITHUB_WORKSPACE/tests/fixtures/android/external-invokes" "$classes" \
|
||||
| tee "$android_root/external-references.log"
|
||||
grep -F 'EXTERNAL_REFERENCE_REGRESSION_PASS prototypes=2 using_nodes=3 sites=4' \
|
||||
"$android_root/external-references.log"
|
||||
@@ -1,39 +1,35 @@
|
||||
name: Real packet capture
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
build_cache_artifact:
|
||||
description: Portable build cache artifact from the calling CI run.
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
remote_cache_write:
|
||||
description: Trusted release qualification may publish the remote cache.
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
secrets:
|
||||
TURBO_TOKEN:
|
||||
description: Remote cache token. Only trusted callers pass it.
|
||||
required: false
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- "tests/boundary/captures/**"
|
||||
- "tests/boundary/cli/captureCleanup.test.ts"
|
||||
- "tests/boundary/mcp/packetCaptureMcp.test.ts"
|
||||
- "src/captures/**"
|
||||
- "src/pcap/**"
|
||||
- "src/domain/pcap/**"
|
||||
- "src/domain/analysisView/pcapCaptureView.ts"
|
||||
- "src/application/pcap/**"
|
||||
- "src/contracts/pcap/**"
|
||||
- "src/server/registerPcapTools.ts"
|
||||
- "tests/boundary/pcap/**"
|
||||
- "src/domain/captures/**"
|
||||
- "src/application/captures/**"
|
||||
- "src/contracts/captures/**"
|
||||
- "src/composition/captures.ts"
|
||||
- "src/cli/captureCommands.ts"
|
||||
- "src/server/registerCaptureTools.ts"
|
||||
- "scripts/verify-packet-capture.mjs"
|
||||
- ".github/workflows/real-packet-capture.yml"
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
HUSKY: "0"
|
||||
# Writes only on the default branch for push, schedule, manual dispatch,
|
||||
# and workflow_call. Pull requests get an empty token and remote read-only mode.
|
||||
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
|
||||
# A called workflow sees the caller event, so workflow_call is not an event
|
||||
# name here. Writes when remote_cache_write is set, or on the default branch
|
||||
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
|
||||
# and use the local cache only.
|
||||
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
|
||||
concurrency:
|
||||
group: real-packet-capture-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
tshark:
|
||||
runs-on: ubuntu-24.04
|
||||
@@ -48,8 +44,18 @@ jobs:
|
||||
uses: ./.github/actions/npm-cache
|
||||
- run: sudo apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y tshark util-linux python3
|
||||
- run: npm ci
|
||||
- uses: ./.github/actions/portable-build-cache
|
||||
with:
|
||||
build_cache_artifact: ${{ inputs.build_cache_artifact }}
|
||||
- run: npm run build:cached
|
||||
- run: npm run test:focused -- tests/boundary/captures/fieldDiscovery.test.ts src/process/LinuxResourceLimits.test.ts tests/boundary/captures/captureProvider.test.ts tests/boundary/captures/captureDescriptorCleanup.test.ts tests/boundary/pcap/pcapProvider.test.ts tests/boundary/pcap/pcapProviderCrossPlatform.test.ts tests/boundary/captures/resourceLimits.test.ts tests/boundary/captures/packetOutput.test.ts tests/boundary/mcp/packetCaptureMcp.test.ts tests/boundary/cli/captureCleanup.test.ts
|
||||
- name: Run focused tests and require Linux resource and cleanup cases
|
||||
run: |
|
||||
report=".cache/rea-packet-required-tests.json"
|
||||
mkdir -p .cache
|
||||
rm -f "$report"
|
||||
node scripts/run-exact-tests.mjs run --reporter=default --reporter=json --outputFile.json="$report" \
|
||||
tests/boundary/captures/fieldDiscovery.test.ts src/process/LinuxResourceLimits.test.ts tests/boundary/captures/captureProvider.test.ts tests/boundary/captures/captureDescriptorCleanup.test.ts tests/boundary/pcap/pcapProvider.test.ts tests/boundary/pcap/pcapProviderCrossPlatform.test.ts tests/boundary/captures/resourceLimits.test.ts tests/boundary/captures/packetOutput.test.ts tests/boundary/mcp/packetCaptureMcp.test.ts tests/boundary/cli/captureCleanup.test.ts
|
||||
node scripts/ci/require-provider-tests.mjs packet "$report"
|
||||
- run: node scripts/verify-packet-capture.mjs
|
||||
env:
|
||||
REA_TSHARK_COMMAND: /usr/bin/tshark
|
||||
|
||||
@@ -1,32 +1,35 @@
|
||||
name: Real signal recording
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
build_cache_artifact:
|
||||
description: Portable build cache artifact from the calling CI run.
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
remote_cache_write:
|
||||
description: Trusted release qualification may publish the remote cache.
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
secrets:
|
||||
TURBO_TOKEN:
|
||||
description: Remote cache token. Only trusted callers pass it.
|
||||
required: false
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- "tests/boundary/signals/**"
|
||||
- "tests/boundary/cli/signalCleanup.test.ts"
|
||||
- "tests/boundary/mcp/signalRecordingMcp.test.ts"
|
||||
- "src/signals/**"
|
||||
- "src/domain/signals/**"
|
||||
- "src/application/signals/**"
|
||||
- "src/contracts/signals/**"
|
||||
- "src/composition/signals.ts"
|
||||
- "src/cli/signalCommands.ts"
|
||||
- "src/server/registerSignalTools.ts"
|
||||
- "scripts/verify-signal-recording.mjs"
|
||||
- ".github/workflows/real-signal-recording.yml"
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
HUSKY: "0"
|
||||
# Writes only on the default branch for push, schedule, manual dispatch,
|
||||
# and workflow_call. Pull requests get an empty token and remote read-only mode.
|
||||
TURBO_TOKEN: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && secrets.TURBO_TOKEN || '' }}"
|
||||
# A called workflow sees the caller event, so workflow_call is not an event
|
||||
# name here. Writes when remote_cache_write is set, or on the default branch
|
||||
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
|
||||
# and use the local cache only.
|
||||
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
TURBO_CACHE: "${{ (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')) && 'local:rw,remote:rw' || 'local:rw,remote:r' }}"
|
||||
concurrency:
|
||||
group: real-signal-recording-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
sigrok:
|
||||
runs-on: ubuntu-24.04
|
||||
@@ -41,8 +44,18 @@ jobs:
|
||||
uses: ./.github/actions/npm-cache
|
||||
- run: sudo apt-get update && sudo apt-get install -y sigrok-cli util-linux python3
|
||||
- run: npm ci
|
||||
- uses: ./.github/actions/portable-build-cache
|
||||
with:
|
||||
build_cache_artifact: ${{ inputs.build_cache_artifact }}
|
||||
- run: npm run build:cached
|
||||
- run: npm run test:focused -- tests/boundary/signals/decoderDiscovery.test.ts src/process/LinuxResourceLimits.test.ts src/domain/signals/annotationTextWindow.test.ts tests/boundary/signals/recordingProvider.test.ts tests/boundary/signals/recordingDescriptorCleanup.test.ts tests/boundary/signals/resourceLimits.test.ts tests/boundary/mcp/signalRecordingMcp.test.ts tests/boundary/cli/signalCleanup.test.ts
|
||||
- name: Run focused tests and require Linux resource and cleanup cases
|
||||
run: |
|
||||
report=".cache/rea-signal-required-tests.json"
|
||||
mkdir -p .cache
|
||||
rm -f "$report"
|
||||
node scripts/run-exact-tests.mjs run --reporter=default --reporter=json --outputFile.json="$report" \
|
||||
tests/boundary/signals/decoderDiscovery.test.ts src/process/LinuxResourceLimits.test.ts src/domain/signals/annotationTextWindow.test.ts tests/boundary/signals/recordingProvider.test.ts tests/boundary/signals/recordingDescriptorCleanup.test.ts tests/boundary/signals/resourceLimits.test.ts tests/boundary/mcp/signalRecordingMcp.test.ts tests/boundary/cli/signalCleanup.test.ts
|
||||
node scripts/ci/require-provider-tests.mjs signal "$report"
|
||||
- run: node scripts/verify-signal-recording.mjs
|
||||
env:
|
||||
REA_SIGROK_COMMAND: /usr/bin/sigrok-cli
|
||||
+15
-1
@@ -232,6 +232,8 @@ Use the development toolchain pinned in `.nvmrc` and
|
||||
`package.json#packageManager`. Run `nvm use` before installing dependencies;
|
||||
installed-package runtime support is documented in
|
||||
[installation](docs/installation.md#start-setup).
|
||||
Use Node.js and npm for source builds and verifier scripts; the installed
|
||||
package's Bun runtime support does not extend to those development scripts.
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
@@ -246,6 +248,15 @@ catalogs, documentation projections, or managed verification evidence. Turbo
|
||||
caches deterministic builds and static checks across Git worktrees. After a package, lockfile, or managed-skill version change, run
|
||||
`npm run metadata:generate` before building.
|
||||
|
||||
Dependabot proposes updates for the npm lockfiles, website Python requirements,
|
||||
and GitHub Actions. Review dependency changes and run the checks relevant to
|
||||
their consumers. For dependencies maintained outside Dependabot, including
|
||||
`third_party/` and the HTTP/3 lab's pinned requirements, the maintainer should
|
||||
review upstream security advisories when updating or using them. Preserve source
|
||||
and version provenance, update license notices when needed, and report which
|
||||
verification was actually repeated. The lab requirements describe a recorded
|
||||
environment; a dependency update does not verify the revised environment.
|
||||
|
||||
Repository invariants live in [AGENTS.md](AGENTS.md). Keep provider-specific
|
||||
protocols in adapters and shared CLI/MCP workflows in the application layer.
|
||||
|
||||
@@ -272,7 +283,10 @@ The general source suite (`npm run test:fast`, `npm run test:changed`, and
|
||||
On a Windows checkout, some source tests fail because fixtures use POSIX paths,
|
||||
`#!/bin/sh` tool stubs, or POSIX rename semantics. Compare failures against the
|
||||
base revision, or run the suite on Linux or WSL, before attributing them to a
|
||||
change. See [testing](docs/testing.md#developer-commands) for command scopes
|
||||
change. The embedded-artifact parent-swap tests exercise the selected-path
|
||||
replacement when the rename succeeds; if Windows refuses it while the admitted
|
||||
file is open, they instead verify the refusal and cleanup. See
|
||||
[testing](docs/testing.md#developer-commands) for command scopes
|
||||
and lane selection.
|
||||
|
||||
`git submodule update --init --recursive` fails at the pinned Unblob submodule
|
||||
|
||||
@@ -62,7 +62,7 @@ See a feature in an app that you want in your own product? Ask your agent to inv
|
||||
|
||||
REA connects your agent to tools for inspecting native binaries, JavaScript and Electron apps, .NET assemblies, and websites. You can also use the same tools from your terminal. Analysis runs locally, and results include the evidence and limitations behind each conclusion.
|
||||
|
||||
Setup registers REA with your agent and installs matching workflow instructions. Native analysis can use an existing Hopper, Ghidra, or IDA installation; setup can optionally install Hopper with approval. Static JavaScript analysis needs no native analysis engine.
|
||||
Setup registers REA with your agent and installs matching workflow instructions. Native analysis can use an existing Hopper, Ghidra, IDA or Kuna installation; setup can optionally install Hopper with approval. Static JavaScript analysis needs no native analysis engine.
|
||||
|
||||
> **[Visit the REA website](https://rea.tools/)** for setup instructions, illustrated guides, and real case studies.
|
||||
|
||||
@@ -192,7 +192,7 @@ Additional tools and host support depend on the target:
|
||||
| Target | What REA returns | Requirements and guide |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Desktop installations | Runtime candidates, supporting files, component markers and next probes | Built-in bounded directory/header inspection; [desktop applications](docs/desktop-applications.md) |
|
||||
| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](docs/native-investigation.md) |
|
||||
| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra, IDA or Kuna; [native analysis](docs/native-investigation.md) |
|
||||
| Offline ELF layout | Sections, segments, original symbols/relocations and static mitigation candidates | Caller-supplied pwntools on Linux x64; [binary diagnostics](docs/binary-diagnostics.md) |
|
||||
| Go binaries | Embedded compiler version, modules, replacements and build settings | Built-in static ELF/PE/thin Mach-O inspection; no Go installation required |
|
||||
| GPU code objects | CUDA/HIP targets, selected kernel parameters and resources, retained PTX text | Built-in static ELF/PE/fatbin/CUBIN/PTX inspection; [GPU code objects](docs/gpu-code-objects.md) |
|
||||
@@ -344,11 +344,13 @@ Any agent that supports local MCP servers. Setup configures the
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Do I need Hopper, Ghidra or IDA?</strong></summary>
|
||||
<summary><strong>Do I need a native analysis engine?</strong></summary>
|
||||
|
||||
Deep native analysis uses one of them. Static JavaScript and .NET inspection
|
||||
work without a native analysis engine. Setup can install Hopper after approval;
|
||||
Ghidra and IDA use your existing installations. See [provider setup](docs/installation.md#hopper).
|
||||
Deep native analysis uses Hopper, Ghidra, IDA or Kuna, depending on the target
|
||||
and operation. Static JavaScript and .NET inspection work without a native
|
||||
analysis engine. Setup can install Hopper after approval; Ghidra, IDA and Kuna
|
||||
use your existing installations. See [provider setup](docs/installation.md#hopper)
|
||||
for the options and their supported targets.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ import jadx.api.plugins.input.insns.InsnIndexType;
|
||||
import jadx.api.plugins.input.insns.Opcode;
|
||||
import jadx.core.codegen.TypeGen;
|
||||
import jadx.core.dex.info.MethodInfo;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.nodes.*;
|
||||
import jadx.core.xmlgen.BinaryXMLParser;
|
||||
import java.io.PrintStream;
|
||||
import java.io.StringReader;
|
||||
import java.io.InputStream;
|
||||
@@ -50,17 +52,25 @@ class ReaJadxBridge {
|
||||
private Map<String, List<ClassSnapshot>> classes = Map.of();
|
||||
private JadxSession manifestSession;
|
||||
private ManifestSnapshot manifestSnapshot;
|
||||
private ExternalInventory externalInventory;
|
||||
|
||||
private record MethodSnapshot(String name, String rawName, String shortId, List<String> bodyAbsenceMarkers,
|
||||
Map<String, Object> summary) {}
|
||||
private record ClassSnapshot(JavaClass node, List<MethodSnapshot> methods, Map<String, Object> summary,
|
||||
Map<String, Object> summaryWithValues) {}
|
||||
private record ManifestSnapshot(String text, Map<String, Object> summary) {}
|
||||
private record ExternalMethod(MethodInfo info, Map<String, Object> summary) {}
|
||||
private record ExternalInventory(JadxSession session, String className, String methodName,
|
||||
List<ExternalMethod> methods) {}
|
||||
|
||||
private static final class InputFailure extends IllegalArgumentException {
|
||||
final String field;
|
||||
InputFailure(String field, String message) { super(message); this.field = field; }
|
||||
}
|
||||
private static final class ReferenceLimit extends IllegalArgumentException {
|
||||
final String stage;
|
||||
ReferenceLimit(String stage) { super("External reference representation limit"); this.stage = stage; }
|
||||
}
|
||||
|
||||
private ReaJadxBridge(SessionHolder holder) { this.holder = holder; }
|
||||
|
||||
@@ -187,6 +197,7 @@ class ReaJadxBridge {
|
||||
private void clearManifest() {
|
||||
manifestSession = null;
|
||||
manifestSnapshot = null;
|
||||
externalInventory = null;
|
||||
}
|
||||
|
||||
// One bounded DEX at a time, beside the already admitted analysis JVM. The
|
||||
@@ -400,10 +411,7 @@ class ReaJadxBridge {
|
||||
selected = resource;
|
||||
}
|
||||
if (selected == null) throw new IllegalArgumentException("Root AndroidManifest.xml not found");
|
||||
var content = selected.loadContent();
|
||||
if (content == null || content.getDataType() != jadx.core.xmlgen.ResContainer.DataType.TEXT)
|
||||
throw new IllegalArgumentException("Root AndroidManifest.xml did not decode as text");
|
||||
String xml = content.getText().getCodeStr();
|
||||
String xml = manifestText(selected);
|
||||
ManifestSnapshot snapshot = new ManifestSnapshot(xml, manifestSummary(xml));
|
||||
manifestSnapshot = snapshot;
|
||||
manifestSession = current;
|
||||
@@ -411,6 +419,23 @@ class ReaJadxBridge {
|
||||
return manifestSnapshot;
|
||||
}
|
||||
|
||||
/** Decode with resource names but without JADX's class alias substitution. */
|
||||
static String manifestText(ResourceFile resource) {
|
||||
var decompiler = resource.getDecompiler();
|
||||
// BinaryXMLParser resolves android:name against its root's class identities
|
||||
// and replaces raw '$' and relative names with Java-style aliases. A fresh
|
||||
// root owns no classes, while its resource-name table preserves reference
|
||||
// rendering from the loaded target.
|
||||
RootNode root = new RootNode(decompiler.getArgs());
|
||||
root.getConstValues().setResourcesNames(decompiler.getRoot().getConstValues().getResourcesNames());
|
||||
try {
|
||||
return ResourcesLoader.decodeStream(resource,
|
||||
(size, input) -> new BinaryXMLParser(root).parse(input).getCodeStr());
|
||||
} catch (jadx.core.utils.exceptions.JadxException failure) {
|
||||
throw new IllegalArgumentException("Root AndroidManifest.xml did not decode as text", failure);
|
||||
}
|
||||
}
|
||||
|
||||
/** One parsed XML owner supplies namespace-aware values alongside the exact decoded text. */
|
||||
static Map<String, Object> manifestSummary(String xml) {
|
||||
Element root;
|
||||
@@ -454,7 +479,7 @@ class ReaJadxBridge {
|
||||
return Collections.unmodifiableMap(summary);
|
||||
}
|
||||
|
||||
private ClassSnapshot selected(JsonObject args) {
|
||||
private void indexClasses() {
|
||||
JadxSession current = session();
|
||||
if (indexedSession != current) {
|
||||
Map<String, List<ClassSnapshot>> index = new LinkedHashMap<>();
|
||||
@@ -530,6 +555,10 @@ class ReaJadxBridge {
|
||||
classes = Collections.unmodifiableMap(index);
|
||||
indexedSession = current;
|
||||
}
|
||||
}
|
||||
|
||||
private ClassSnapshot selected(JsonObject args) {
|
||||
indexClasses();
|
||||
String name = string(args, "class_name");
|
||||
List<ClassSnapshot> candidates = classes.get(name);
|
||||
if (candidates == null) throw new InputFailure("class_name", "Exact class not found: " + name
|
||||
@@ -629,12 +658,18 @@ class ReaJadxBridge {
|
||||
// JSON-RPC/CallToolResult envelope and generated numeric request id, and
|
||||
// account for JSON text being escaped again inside TextContent.
|
||||
private static final int MAX_XREF_TEXT_BYTES = 8 * 1024 * 1024 - 1024;
|
||||
// Leave room for the prototype reply, reference reply, retained raw calls,
|
||||
// normalized Evidence and their text/structured MCP copies, not just one frame.
|
||||
private static final int MAX_EXTERNAL_XREF_BYTES = MAX_XREF_TEXT_BYTES / 8;
|
||||
private static int escapedJsonBytes(Object value) {
|
||||
return JSON.toJson(JSON.toJson(value)).getBytes(StandardCharsets.UTF_8).length;
|
||||
}
|
||||
private static final class InvokeBudget {
|
||||
long remaining;
|
||||
InvokeBudget(long remaining) { this.remaining = Math.max(0, remaining); }
|
||||
boolean fitsText(long characters) {
|
||||
return remaining >= 256 && characters <= (remaining - 256) / 12;
|
||||
}
|
||||
boolean admit(Map<String, Object> site) {
|
||||
// Check a conservative two-layer escape bound before serialization.
|
||||
long bound = 256;
|
||||
@@ -649,26 +684,55 @@ class ReaJadxBridge {
|
||||
}
|
||||
private record DirectInvokes(List<Map<String, Object>> sites, boolean exhaustive) {}
|
||||
|
||||
/** Raw DEX invokes within one JADX using method; offsets are code units from its code start. */
|
||||
private static DirectInvokes directInvokes(JavaMethod source, MethodInfo target, InvokeBudget budget) {
|
||||
MethodNode node = source.getMethodNode();
|
||||
@FunctionalInterface private interface InvokeVisitor {
|
||||
void accept(MethodInfo target, int offset, int index, Opcode opcode);
|
||||
}
|
||||
|
||||
/** Decode raw invoke identity once at the shared bridge boundary, without generating source. */
|
||||
private static void visitInvokes(MethodNode node, InvokeVisitor visitor) {
|
||||
checkNativeInterrupted();
|
||||
ICodeReader code = node.getCodeReader();
|
||||
if (code == null) return null;
|
||||
List<Map<String, Object>> sites = new ArrayList<>();
|
||||
boolean[] exhaustive = {true};
|
||||
if (code == null) return;
|
||||
code.visitInstructions(insn -> {
|
||||
checkNativeInterrupted();
|
||||
insn.decode();
|
||||
if (insn.getIndexType() != InsnIndexType.METHOD_REF) return;
|
||||
Opcode opcode = insn.getOpcode();
|
||||
if (!opcode.name().startsWith("INVOKE_")) return;
|
||||
IMethodRef ref = insn.getIndexAsMethod();
|
||||
ref.load();
|
||||
if (!MethodInfo.fromRef(node.root(), ref).getRawFullId().equals(target.getRawFullId())) return;
|
||||
visitor.accept(MethodInfo.fromRef(node.root(), ref), insn.getOffset(), insn.getIndex(), opcode);
|
||||
});
|
||||
}
|
||||
|
||||
/** Raw DEX invokes within one JADX using method; offsets are code units from its code start. */
|
||||
private static DirectInvokes directInvokes(JavaMethod source, MethodInfo target, InvokeBudget budget) {
|
||||
return directInvokes(source.getMethodNode(), target, budget);
|
||||
}
|
||||
|
||||
private static void visitDirectInvokes(MethodNode node, MethodInfo target, InvokeVisitor visitor) {
|
||||
visitInvokes(node, (referenced, offset, index, opcode) -> {
|
||||
if (referenced.getRawFullId().equals(target.getRawFullId()))
|
||||
visitor.accept(referenced, offset, index, opcode);
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean referencesMethod(MethodNode node, MethodInfo target) {
|
||||
boolean[] found = {false};
|
||||
visitDirectInvokes(node, target, (referenced, offset, index, opcode) -> found[0] = true);
|
||||
return found[0];
|
||||
}
|
||||
|
||||
private static DirectInvokes directInvokes(MethodNode node, MethodInfo target, InvokeBudget budget) {
|
||||
if (node.getCodeReader() == null) return null;
|
||||
List<Map<String, Object>> sites = new ArrayList<>();
|
||||
boolean[] exhaustive = {true};
|
||||
visitDirectInvokes(node, target, (referenced, offset, index, opcode) -> {
|
||||
Map<String, Object> site = Map.of(
|
||||
"dex_entry", node.getInputFileName(),
|
||||
"source_raw_method_id", node.getMethodInfo().getRawFullId(),
|
||||
"dex_code_unit_offset", insn.getOffset(),
|
||||
"dex_method_index", insn.getIndex(),
|
||||
"dex_code_unit_offset", offset,
|
||||
"dex_method_index", index,
|
||||
"opcode", opcode.name());
|
||||
if (budget.admit(site)) sites.add(site);
|
||||
else exhaustive[0] = false;
|
||||
@@ -676,6 +740,143 @@ class ReaJadxBridge {
|
||||
return new DirectInvokes(sites, exhaustive[0]);
|
||||
}
|
||||
|
||||
private List<ClassSnapshot> sourceClasses() {
|
||||
indexClasses();
|
||||
Set<ClassSnapshot> seen = Collections.newSetFromMap(new IdentityHashMap<>());
|
||||
List<ClassSnapshot> result = new ArrayList<>();
|
||||
for (List<ClassSnapshot> group : classes.values())
|
||||
for (ClassSnapshot source : group) if (seen.add(source)) result.add(source);
|
||||
result.sort(Comparator.comparing(source -> source.node().getRawName()));
|
||||
return result;
|
||||
}
|
||||
|
||||
private static long displayTypeCharacters(ArgType type) {
|
||||
if (type.isArray())
|
||||
return 2L * type.getArrayDimension() + displayTypeCharacters(type.getArrayRootElement());
|
||||
if (type.isPrimitive()) return type.getPrimitiveType().getLongName().length();
|
||||
if (type.isObject() && !type.isGeneric() && !type.isGenericType()) return type.getObject().length();
|
||||
throw new IllegalArgumentException("External prototype contains a non-DEX type");
|
||||
}
|
||||
|
||||
private static Map<String, Object> externalMethodSummary(MethodInfo info, InvokeBudget budget) {
|
||||
String name = info.getName();
|
||||
long signatureCharacters = name.length() + 4L + displayTypeCharacters(info.getReturnType())
|
||||
+ 2L * Math.max(0, info.getArgsCount() - 1);
|
||||
for (ArgType type : info.getArgumentsTypes()) signatureCharacters += displayTypeCharacters(type);
|
||||
long descriptorCharacters = info.getShortId().length() - (long) name.length();
|
||||
// Use parsed type facts and the existing short-id length before copying/joining strings.
|
||||
if (!budget.fitsText(2L * name.length() + descriptorCharacters + signatureCharacters))
|
||||
throw new ReferenceLimit("method_inventory");
|
||||
String descriptor = info.getShortId().substring(name.length());
|
||||
String signature = name + "(" + info.getArgumentsTypes().stream()
|
||||
.map(Object::toString).collect(Collectors.joining(", "))
|
||||
+ "): " + info.getReturnType();
|
||||
Map<String, Object> summary = Map.of("name", name, "raw_name", name, "signature", signature,
|
||||
"dex_descriptor", descriptor, "is_constructor", info.isConstructor(), "def_pos", 0);
|
||||
if (!budget.admit(summary)) throw new ReferenceLimit("method_inventory");
|
||||
return summary;
|
||||
}
|
||||
|
||||
/** Only directly referenced prototypes, not invented definitions or an external classpath. */
|
||||
private List<ExternalMethod> externalMethods(JsonObject args) {
|
||||
String className = string(args, "class_name");
|
||||
String methodName = string(args, "method_name");
|
||||
JadxSession current = session();
|
||||
if (externalInventory != null && externalInventory.session() == current
|
||||
&& externalInventory.className().equals(className) && externalInventory.methodName().equals(methodName))
|
||||
return externalInventory.methods();
|
||||
// Retain only the latest bounded selection, never results from a replaced APK/session.
|
||||
externalInventory = null;
|
||||
SortedMap<String, ExternalMethod> methods = new TreeMap<>();
|
||||
boolean[] observedClass = {false};
|
||||
InvokeBudget budget = new InvokeBudget(MAX_EXTERNAL_XREF_BYTES
|
||||
- 4096L - 12L * (className.length() + (long) methodName.length()));
|
||||
for (ClassSnapshot source : sourceClasses()) {
|
||||
for (MethodSnapshot selected : source.methods()) {
|
||||
visitInvokes(method(source, selected).getMethodNode(), (info, offset, index, opcode) -> {
|
||||
if (!info.getDeclClass().getRawName().equals(className)) return;
|
||||
observedClass[0] = true;
|
||||
if (!info.getName().equals(methodName) || methods.containsKey(info.getShortId())) return;
|
||||
methods.put(info.getShortId(), new ExternalMethod(info, externalMethodSummary(info, budget)));
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!observedClass[0]) throw new InputFailure("class_name",
|
||||
"No APK definition or direct DEX invoke references the exact class: " + className);
|
||||
if (methods.isEmpty()) throw new InputFailure("method_name",
|
||||
"No direct DEX invoke references " + className + "." + methodName);
|
||||
List<ExternalMethod> result = List.copyOf(methods.values());
|
||||
externalInventory = new ExternalInventory(current, className, methodName, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, Object> externalSummary(JsonObject args) {
|
||||
List<ExternalMethod> methods = externalMethods(args);
|
||||
return Map.of("class_name", string(args, "class_name"), "reference_target", "external",
|
||||
"observed_method_count", methods.size(),
|
||||
"prototypes", methods.stream().map(ExternalMethod::summary).toList());
|
||||
}
|
||||
|
||||
private record ExternalCaller(MethodNode node, Map<String, Object> row) {}
|
||||
|
||||
/** Reserve the complete using-node inventory before optional instruction positions. */
|
||||
private List<ExternalCaller> externalCallers(MethodInfo target, InvokeBudget budget) {
|
||||
List<ExternalCaller> callers = new ArrayList<>();
|
||||
for (ClassSnapshot source : sourceClasses()) {
|
||||
String className = String.valueOf(source.summary().get("full_name"));
|
||||
Map<String, Integer> overloads = new HashMap<>();
|
||||
for (MethodSnapshot candidate : source.methods()) {
|
||||
int overload = overloads.merge(candidate.name(), 1, Integer::sum) - 1;
|
||||
MethodNode node = method(source, candidate).getMethodNode();
|
||||
if (!referencesMethod(node, target)) continue;
|
||||
if (classes.get(className).size() != 1)
|
||||
throw new IllegalArgumentException("External caller has an ambiguous APK class identity: " + className);
|
||||
Map<String, Object> row = new LinkedHashMap<>(Map.of(
|
||||
"kind", "method", "name", candidate.name(), "full_name", className + "." + candidate.name(),
|
||||
"containing_class", className, "top_class", source.node().getTopParentClass().getFullName(),
|
||||
"def_pos", 0, "source_selector", Map.of("class_name", className,
|
||||
"method_name", candidate.name(), "overload_index", overload),
|
||||
"direct_invokes", List.of(), "direct_invokes_exhaustive", false));
|
||||
if (!budget.admit(row)) throw new ReferenceLimit("caller_inventory");
|
||||
callers.add(new ExternalCaller(node, row));
|
||||
}
|
||||
}
|
||||
return List.copyOf(callers);
|
||||
}
|
||||
|
||||
private Map<String, Object> externalReferences(JsonObject args) {
|
||||
List<ExternalMethod> methods = externalMethods(args);
|
||||
if (methods.size() != 1 && !args.has("overload_index"))
|
||||
throw new InputFailure("overload_index", "Select one of " + methods.size() + " observed external prototypes");
|
||||
int index = integer(args, "overload_index", 0);
|
||||
if (index >= methods.size()) throw new InputFailure("overload_index", "External prototype index out of range: " + index);
|
||||
ExternalMethod method = methods.get(index);
|
||||
MethodInfo target = method.info();
|
||||
Map<String, Object> selected = method.summary();
|
||||
InvokeBudget budget = new InvokeBudget(MAX_EXTERNAL_XREF_BYTES
|
||||
- 4096L - escapedJsonBytes(selected));
|
||||
List<ExternalCaller> callers = externalCallers(target, budget);
|
||||
List<Map<String, Object>> items = new ArrayList<>();
|
||||
for (ExternalCaller caller : callers) {
|
||||
DirectInvokes invokes = directInvokes(caller.node(), target, budget);
|
||||
caller.row().put("direct_invokes", invokes.sites());
|
||||
caller.row().put("direct_invokes_exhaustive", invokes.exhaustive());
|
||||
items.add(caller.row());
|
||||
}
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
result.put("target", string(args, "class_name") + "." + target.getName());
|
||||
result.put("reference_target", "external");
|
||||
result.put("reference_scope", "direct_dex_invokes");
|
||||
result.put("dex_descriptor", selected.get("dex_descriptor"));
|
||||
result.put("reported_signature", selected.get("signature"));
|
||||
result.put("overload_index", index);
|
||||
result.put("total", items.size());
|
||||
result.put("count", items.size());
|
||||
result.put("resolve_line", false);
|
||||
result.put("items", items);
|
||||
return result;
|
||||
}
|
||||
|
||||
private CallToolResult handle(String name, kotlinx.serialization.json.JsonObject input) {
|
||||
JsonObject args = JsonParser.parseString(input.toString()).getAsJsonObject();
|
||||
if (name.equals("rea_jvm_status")) return json(Map.of(
|
||||
@@ -712,6 +913,12 @@ class ReaJadxBridge {
|
||||
"scope", "top_level", "offset", offset, "limit", limit,
|
||||
"items", items));
|
||||
}
|
||||
indexClasses();
|
||||
if (flag(args, "reference_target") && !classes.containsKey(string(args, "class_name"))) {
|
||||
if (name.equals("get_class_summary")) return json(externalSummary(args));
|
||||
if (name.equals("get_xrefs_to_method")) return json(externalReferences(args));
|
||||
throw new InputFailure("class_name", "External prototypes are only available to method reference queries");
|
||||
}
|
||||
ClassSnapshot cls = selected(args);
|
||||
if (name.equals("get_class_summary"))
|
||||
return json(flag(args, "dex_static_values") ? cls.summaryWithValues() : cls.summary());
|
||||
@@ -785,6 +992,9 @@ class ReaJadxBridge {
|
||||
try { return bridge.handle(name, request.getArguments()); }
|
||||
catch (InputFailure error) { return text(JSON.toJson(Map.of(
|
||||
"kind", "invalid-input", "field", error.field, "message", error.getMessage())), true); }
|
||||
catch (ReferenceLimit error) { return text(JSON.toJson(Map.of(
|
||||
"kind", "reference-output-limit", "stage", error.stage,
|
||||
"limit_bytes", MAX_EXTERNAL_XREF_BYTES)), true); }
|
||||
catch (IllegalArgumentException error) { return text(error.getMessage(), true); }
|
||||
});
|
||||
}
|
||||
@@ -797,7 +1007,7 @@ class ReaJadxBridge {
|
||||
SessionHolder holder = new SessionHolder(defaults);
|
||||
ServerCapabilities capabilities = new ServerCapabilities(
|
||||
new ServerCapabilities.Tools(null), null, null, null, null, null, null, Map.of());
|
||||
Server server = new Server(new Implementation("rea-jadx-bridge", "9", null, null, null),
|
||||
Server server = new Server(new Implementation("rea-jadx-bridge", "10", null, null, null),
|
||||
new ServerOptions(capabilities), "", ignored -> Unit.INSTANCE);
|
||||
SessionToolsKt.registerSessionTools(server, holder);
|
||||
ClassToolsKt.registerClassTools(server, holder);
|
||||
@@ -847,6 +1057,12 @@ class ReaJadxBridge {
|
||||
if (name.equals("get_class_summary")) properties.put("dex_static_values",
|
||||
new kotlinx.serialization.json.JsonObject(Map.of(
|
||||
"type", kotlinx.serialization.json.JsonElementKt.JsonPrimitive("boolean"))));
|
||||
if (name.equals("get_class_summary") || name.equals("get_xrefs_to_method"))
|
||||
properties.put("reference_target", new kotlinx.serialization.json.JsonObject(Map.of(
|
||||
"type", kotlinx.serialization.json.JsonElementKt.JsonPrimitive("boolean"))));
|
||||
if (name.equals("get_class_summary")) properties.put("method_name",
|
||||
new kotlinx.serialization.json.JsonObject(Map.of(
|
||||
"type", kotlinx.serialization.json.JsonElementKt.JsonPrimitive("string"))));
|
||||
String description = switch (name) {
|
||||
case "list_classes" -> "Pages of case-sensitive matching top-level class names; offset and next_offset are inventory positions, limit bounds matching rows. Omitted or empty query inventories all names.";
|
||||
case "get_class_summary" -> "Parsed member metadata for one exact class name; no source generation. Set dex_static_values to include encoded static final field values.";
|
||||
|
||||
@@ -1313,7 +1313,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
||||
flow.addProperty("computed", false);
|
||||
if (instruction == null) {
|
||||
result.addProperty("status", !currentProgram.getMemory().contains(address) ? "outside-memory" : currentProgram.getListing().getInstructionContaining(address) != null
|
||||
? "not-instruction-boundary" : currentProgram.getListing().getDefinedDataContaining(address) != null ? "data" : "undecodable");
|
||||
? "not-instruction-boundary" : currentProgram.getListing().getDefinedDataContaining(address) != null ? "data" : "not-in-listing");
|
||||
for (String key : List.of("bytes", "length", "mnemonic", "raw_disassembly")) result.add(key, JsonNull.INSTANCE);
|
||||
} else {
|
||||
result.addProperty("status", "decoded");
|
||||
@@ -1385,6 +1385,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
||||
result.add("incoming_references", incomingReferences);
|
||||
}
|
||||
List<String> limitations = new ArrayList<>(List.of("Operand components are Ghidra Listing decoder tokens; effective memory base/index/displacement roles and per-instruction context mode are unavailable. The mode field is the program language variant."));
|
||||
if (result.get("status").getAsString().equals("not-in-listing")) limitations.add("No listed instruction or defined data covers this in-memory address. REA did not attempt a decode; the memory may be uninitialized or contain valid instructions.");
|
||||
if (flow.get("kind").getAsString().equals("terminal")) limitations.add("No RETURN operation was observed in the provider's instruction p-code; terminal classification remains generic.");
|
||||
result.add("limitations", GSON.toJsonTree(limitations));
|
||||
return result;
|
||||
|
||||
+161
-5
@@ -22,6 +22,9 @@ HOPPER_SYMBOL_NAME_UTF16_UNITS = 1024
|
||||
# that does not fit is null, not an older descriptor path.
|
||||
# 536870887 is Node's 536870888-character string ceiling minus the framing LF.
|
||||
# The ceiling is the encoded payload; JSON expansion is measured before it.
|
||||
# Encoded JSON allowance, in bytes, shared by one instruction list, one
|
||||
# native-caller list, and one caller-scan page. This release has no runtime override.
|
||||
CALLER_SCAN_ALLOWANCE_BYTES = 512 * 1024
|
||||
_BRIDGE_MAX_REQUEST_BYTES_SETTING = "REA_BRIDGE_MAX_REQUEST_BYTES"
|
||||
DEFAULT_BRIDGE_MAX_REQUEST_BYTES = 16 * 1024 * 1024
|
||||
MINIMUM_BRIDGE_MAX_REQUEST_BYTES = 7464
|
||||
@@ -232,6 +235,9 @@ EXHAUSTIVE_ANALYSIS_METHODS = frozenset(
|
||||
"procedure_assembly",
|
||||
"procedure_callees",
|
||||
"procedure_callers",
|
||||
"rea_caller_scan_page",
|
||||
"rea_caller_scan_target",
|
||||
"rea_caller_base",
|
||||
"procedure_info",
|
||||
"procedure_pseudo_code",
|
||||
"procedure_references",
|
||||
@@ -485,19 +491,30 @@ def _instruction_addresses(procedure):
|
||||
return result
|
||||
|
||||
|
||||
def _native_calls(procedure, direction):
|
||||
def _iter_native_calls(procedure, direction):
|
||||
references = procedure.getAllCallees() if direction == "outgoing" else procedure.getAllCallers()
|
||||
kinds = {0: "none", 1: "unknown", 2: "direct", 3: "objective_c"}
|
||||
calls = {}
|
||||
unresolved = []
|
||||
for reference in references:
|
||||
source, target, kind = reference.fromAddress(), reference.toAddress(), reference.type()
|
||||
if source in BAD_ADDRESSES:
|
||||
yield None, None, None
|
||||
continue
|
||||
if target in BAD_ADDRESSES:
|
||||
unresolved.append({"address": _hex(source), "reason": "Native CallReference has no resolved target (type %s)" % kind})
|
||||
yield source, None, {"address": _hex(source), "reason": "Native CallReference has no resolved target (type %s)" % kind}
|
||||
continue
|
||||
calls[(source, target)] = {"classification": kinds.get(kind, "unknown"), "provider_type": kind, "provenance": "hopper-public-python-api:CallReference"}
|
||||
yield source, target, {"classification": kinds.get(kind, "unknown"), "provider_type": kind, "provenance": "hopper-public-python-api:CallReference"}
|
||||
|
||||
|
||||
def _native_calls(procedure, direction):
|
||||
calls = {}
|
||||
unresolved = []
|
||||
for source, target, detail in _iter_native_calls(procedure, direction):
|
||||
if detail is None:
|
||||
continue
|
||||
if target is None:
|
||||
unresolved.append(detail)
|
||||
else:
|
||||
calls[(source, target)] = detail
|
||||
return calls, sorted(unresolved, key=lambda item: int(item["address"], 16))
|
||||
|
||||
|
||||
@@ -547,6 +564,136 @@ def _procedure_map(document):
|
||||
return result
|
||||
|
||||
|
||||
def _caller_target_data(procedure):
|
||||
addresses = []
|
||||
seen = set()
|
||||
size = 0
|
||||
for block in procedure.basicBlockIterator():
|
||||
for address in _block_instruction_addresses(procedure, block):
|
||||
if address in seen:
|
||||
continue
|
||||
encoded = _hex(address)
|
||||
size += len(encoded) + 4
|
||||
if size > CALLER_SCAN_ALLOWANCE_BYTES:
|
||||
return {"target": _procedure_identity(procedure), "instructions": addresses, "instructions_complete": False}
|
||||
addresses.append(encoded)
|
||||
seen.add(address)
|
||||
return {"target": _procedure_identity(procedure), "instructions": addresses, "instructions_complete": True}
|
||||
|
||||
|
||||
def _caller_scan_target(document, params):
|
||||
return _caller_target_data(_procedure(document, params.get("procedure")))
|
||||
|
||||
|
||||
def _caller_base(document, params):
|
||||
procedure = _procedure(document, params.get("procedure"))
|
||||
callers = []
|
||||
size = 0
|
||||
complete = True
|
||||
for item in procedure.getAllCallerProcedures():
|
||||
address = _hex(item.getEntryPoint())
|
||||
size += len(address) + 4
|
||||
if size > CALLER_SCAN_ALLOWANCE_BYTES:
|
||||
complete = False
|
||||
break
|
||||
callers.append(address)
|
||||
return {
|
||||
**_caller_target_data(procedure),
|
||||
"callers": sorted(callers, key=lambda value: int(value, 16)),
|
||||
"callers_complete": complete,
|
||||
}
|
||||
|
||||
|
||||
def _caller_scan_page(document, params):
|
||||
"""Observe forward relationships in one bounded, stateless bridge request."""
|
||||
start = params.get("start")
|
||||
if isinstance(start, bool) or not isinstance(start, int) or start < 0:
|
||||
raise InvalidRequestError("Caller scan start must be a non-negative integer")
|
||||
segments = document.getSegmentsList()
|
||||
counts = [segment.getProcedureCount() for segment in segments]
|
||||
total = sum(counts)
|
||||
end = min(start + 64, total)
|
||||
if start > total:
|
||||
raise InvalidRequestError("Caller scan start exceeds the procedure inventory")
|
||||
items = []
|
||||
item_bytes = 0
|
||||
page_limit = CALLER_SCAN_ALLOWANCE_BYTES
|
||||
oversized = False
|
||||
identities = {}
|
||||
containing = {}
|
||||
|
||||
def identity(procedure):
|
||||
entry = procedure.getEntryPoint()
|
||||
if entry not in identities:
|
||||
identities[entry] = _procedure_identity(procedure)
|
||||
return identities[entry]
|
||||
|
||||
def owner(address):
|
||||
if address not in containing:
|
||||
procedure, _ = _containing_procedure(document, address)
|
||||
containing[address] = identity(procedure) if procedure is not None else None
|
||||
return containing[address]
|
||||
|
||||
segment_start = 0
|
||||
for segment, count in zip(segments, counts):
|
||||
begin, stop = max(start - segment_start, 0), min(end - segment_start, count)
|
||||
segment_start += count
|
||||
for index in range(begin, max(begin, stop)):
|
||||
candidate = segment.getProcedureAtIndex(index)
|
||||
item = {"caller": identity(candidate), "callees": [], "references": []}
|
||||
size = len(json.dumps(item, ensure_ascii=True).encode("utf-8")) + 1
|
||||
remaining = page_limit - item_bytes
|
||||
too_large = size > remaining
|
||||
if not too_large:
|
||||
for callee in candidate.getAllCalleeProcedures():
|
||||
address = _hex(callee.getEntryPoint())
|
||||
size += len(address) + 4
|
||||
if size > remaining:
|
||||
too_large = True
|
||||
break
|
||||
item["callees"].append(address)
|
||||
if not too_large:
|
||||
callee_entries = set(item["callees"])
|
||||
for source, destination, call in _iter_native_calls(candidate, "outgoing"):
|
||||
# Account for every native record, even when its target cannot
|
||||
# be associated with an observed procedure.
|
||||
size += 32
|
||||
if size > remaining:
|
||||
too_large = True
|
||||
break
|
||||
if destination is None:
|
||||
continue
|
||||
source_procedure = item["caller"] if _hex(source) == item["caller"]["address"] else owner(source)
|
||||
target_address = _hex(destination)
|
||||
if target_address in callee_entries:
|
||||
target_entry = target_address
|
||||
else:
|
||||
target_procedure = owner(destination)
|
||||
if target_procedure is None:
|
||||
continue
|
||||
target_entry = target_procedure["address"]
|
||||
edge = {
|
||||
"source_address": _hex(source), "target_address": _hex(destination),
|
||||
"source_procedure": "caller" if source_procedure is not None and source_procedure["address"] == item["caller"]["address"] else source_procedure,
|
||||
"target_procedure": target_entry,
|
||||
"call": call,
|
||||
}
|
||||
size += len(json.dumps(edge, ensure_ascii=True).encode("utf-8")) + 1
|
||||
if size > remaining:
|
||||
too_large = True
|
||||
break
|
||||
item["references"].append(edge)
|
||||
if too_large:
|
||||
oversized = not items
|
||||
break
|
||||
items.append(item)
|
||||
item_bytes += size
|
||||
else:
|
||||
continue
|
||||
break
|
||||
return {"start": start, "next": start + len(items), "total": total, "items": items, "oversized": oversized}
|
||||
|
||||
|
||||
def _string_record(segment, address, display):
|
||||
"""Read one native typed object, retaining its shortened display separately."""
|
||||
length = segment.getObjectLength(address)
|
||||
@@ -887,6 +1034,15 @@ def _dispatch(method, params):
|
||||
if method in EXHAUSTIVE_ANALYSIS_METHODS:
|
||||
_api().require_analysis_complete(document, method)
|
||||
|
||||
if method == "rea_caller_scan_target":
|
||||
return _caller_scan_target(document, params)
|
||||
|
||||
if method == "rea_caller_base":
|
||||
return _caller_base(document, params)
|
||||
|
||||
if method == "rea_caller_scan_page":
|
||||
return _caller_scan_page(document, params)
|
||||
|
||||
if method == "analyze_function":
|
||||
return _analyze_function(document, params)
|
||||
if method == "read_function_instructions":
|
||||
|
||||
@@ -103,6 +103,10 @@ existing analysis families directly, for example
|
||||
| `start_adb_activity` | **mutates device** | Starts an intent (`am start -a` with optional URI, component, and up to 16 typed extras); preserves the activity manager's verdict |
|
||||
| `stop_adb_app` | **mutates device** | Force-stops every process of a package, ending a dynamic-analysis run |
|
||||
|
||||
Screen capture validates the PNG signature, IHDR framing, dimensions, and IHDR
|
||||
checksum before publishing. It does not validate encoding fields or decode and
|
||||
validate image contents; that limitation is retained in Evidence.
|
||||
|
||||
When `push_adb_file` receives an existing directory, adb places the local file
|
||||
inside it under the local basename; Evidence reports that effective file path
|
||||
while retaining the caller's directory path in the input parameters. The
|
||||
|
||||
@@ -158,12 +158,12 @@ assigned by the app.
|
||||
|
||||
Use the report's hints to decide what to record next:
|
||||
|
||||
| Reason | Next step |
|
||||
| ------------------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| `unconfirmed` | Read the item and its list after the change. |
|
||||
| `no-state-target` | Record reads of the collection or item the operation changes. |
|
||||
| `no-observation` | Read back a created item. For an edit or delete, also read it before changing it. |
|
||||
| `contradicted` or `side-effect` | Inspect the reported disagreement. The operation may need behavior REA cannot model yet. |
|
||||
| Reason | Next step |
|
||||
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `unconfirmed` | Read the item and its list after the change. |
|
||||
| `no-state-target` | Check the path template and recorded views; record missing reads. The route form may not be supported as a mutation target. |
|
||||
| `no-observation` | Read back a created item. For an edit or delete, also read it before changing it. |
|
||||
| `contradicted` or `side-effect` | Inspect the reported disagreement. The operation may need behavior REA cannot model yet. |
|
||||
|
||||
See the [full reason table](agent-environments.md#build-a-bundle-in-one-step)
|
||||
for the other cases. Rebuild from the new recording and check the report
|
||||
|
||||
+14
-10
@@ -174,7 +174,7 @@ what to record next; hints never change what is served:
|
||||
|
||||
| Reason | Hint |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `no-state-target` | The write's path names no collection or item the capture reads. Read the collection or item it changes. |
|
||||
| `no-state-target` | The write could not be linked to a modelled target. Check the path template and recorded views; record missing reads. Some route forms may not be supported. |
|
||||
| `no-call` | No recorded call of this tool was modelled, for example because every call failed. Record a successful call. |
|
||||
| `body-unusable` | The retained request or response cannot be modelled. Record a successful call with a complete supported request and reproducible response. |
|
||||
| `no-observation` | Nothing showed the entity or document this write changed. Read a created entity back by id right after the write; for an update or delete the state must already hold the entity, so read it before the write or record the create that made it. |
|
||||
@@ -723,6 +723,8 @@ and `POST` tools the capture shows only reading (a lookup answering as a `GET`
|
||||
did, an RPC tunnel naming read operations, a session renewal), stay served and
|
||||
answer from their recordings with the reason `query-body`; they are not write
|
||||
tools.
|
||||
`HEAD`, `OPTIONS` and `TRACE` tools also replay their captured responses; their
|
||||
state views report `method-replay` and coverage counts them as recorded reads.
|
||||
|
||||
A line establishes whole-collection membership only from the beginning:
|
||||
`offset`, `start`, `_start` and `page` must be zero when present. Positive or
|
||||
@@ -737,14 +739,14 @@ tools are not served, so no call claims a change it does not make; each one's
|
||||
plan states why in its `reason`. A served write changes the live state, which
|
||||
every MCP session and `data/get` then see:
|
||||
|
||||
| Effect | Call |
|
||||
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `create` | Adds an entity to the collection the path names, built from the observed entity with each ruled field taken from the call or generated, at the plan's `insert` position. A plan tied to its exemplar's collection writes only there. |
|
||||
| `update` | Sets the sent members on the entity the path names, constants for members accepted only with their recorded value, and the clock, nested clock, increment, slug, stamp, derived, composed, reference, unique and renewed changes the plan models. |
|
||||
| `update` (action) | A `POST`, `PUT` or `PATCH` to an item path plus an action segment (`/{type}/{id}/archive`) sets, on the entity before the segment, each scalar the recorded calls showed the action set (`set`), with any sent members; it is served only when a recorded call found those fields already set, so a toggle never is. |
|
||||
| `delete` | Removes the entity the path names. |
|
||||
| bulk `update` or `delete` | A `DELETE`, `PUT` or `PATCH` at a collection, or a `POST` to it plus `delete`, `remove` or `destroy`, applies its effect to every entity the body names, as recorded: an array of ids or of objects carrying the id field, at the root or as the body's one array member (`{"IDs": […], "Read": true}`). |
|
||||
| `document` | Merges the body into the plan's document object, or replaces it for `PUT`. |
|
||||
| Effect | Call |
|
||||
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `create` | Adds an entity to the collection the path names, built from the observed entity with each ruled field taken from the call or generated, at the plan's `insert` position. A plan tied to its exemplar's collection writes only there. |
|
||||
| `update` | Sets the sent members on the entity the path names, constants for members accepted only with their recorded value, and the clock, nested clock, increment, slug, stamp, derived, composed, reference, unique and renewed changes the plan models. |
|
||||
| `update` (action) | A `POST`, `PUT` or `PATCH` to an item path plus an action segment (`/{type}/{id}/archive`) sets, on the entity before the segment, each scalar the recorded calls showed the action set (`set`), or flips each boolean they showed it flipping both ways (`toggle`), with any sent members; it is served only when a recorded call found what it sets already set, or flipped back what it toggles. |
|
||||
| `delete` | Removes the entity the path names. |
|
||||
| bulk `update` or `delete` | A `DELETE`, `PUT` or `PATCH` at a collection, or a `POST` to it plus `delete`, `remove` or `destroy`, applies its effect to every entity the body names, as recorded: an array of ids or of objects carrying the id field, at the root or as the body's one array member (`{"IDs": […], "Read": true}`). |
|
||||
| `document` | Merges the body into the plan's document object, or replaces it for `PUT`. |
|
||||
|
||||
An update's unsent changes follow the plan's rules. A `held-clock` is a clock
|
||||
the client sends back as it read it and the application stamps anew (Ghost's
|
||||
@@ -755,7 +757,9 @@ the entity already names under its `created…by` counterpart into a
|
||||
`modified…by` or `updated…by` field. A `derived` field takes a value showing
|
||||
the one sent member's text that the entity stores nowhere (a field Ghost
|
||||
derives from `html`), only with that member's recorded value. An action's
|
||||
`set` rule sets a scalar to the value the recorded calls left it at.
|
||||
`set` rule sets a scalar to the value the recorded calls left it at, and its
|
||||
`toggle` rule flips a boolean, refusing a call on an entity that holds none
|
||||
there (Miniflux's `PUT /v1/entries/{id}/bookmark` stars and unstars).
|
||||
|
||||
Its answer has the status and content type of the plan's recorded response,
|
||||
with the written entity or its identity rendered in, no body, or the recorded
|
||||
|
||||
@@ -39,7 +39,9 @@ unverified.
|
||||
|
||||
`inspect_android_package` also returns a static inventory of declared
|
||||
activities, aliases, services, receivers and providers from the decoded
|
||||
manifest. `declared_name` preserves the source attribute; `name` resolves a
|
||||
manifest. The binary XML decoder preserves component class spelling, including
|
||||
`$` in nested classes, without applying JADX class aliases. `declared_name`
|
||||
preserves the decoded source attribute; `name` resolves a
|
||||
relative name only when the manifest package is known and the resolved copy
|
||||
fits the UTF-8 byte budget. An unresolved package or exhausted name budget
|
||||
retains the declared name and marks the inventory partial. Empty component
|
||||
@@ -250,6 +252,35 @@ queries accept the same `overload_index`; the bridge resolves the selected
|
||||
method node and the result reports its index and displayed signature. These
|
||||
indices are tied to the current artifact and engine, not stable across builds.
|
||||
|
||||
Method reference queries also accept an external class, such as
|
||||
`android.app.NotificationManager --method-name notify`, when the APK directly
|
||||
invokes that exact DEX class and method name. If multiple prototypes are observed,
|
||||
the input error lists their exact DEX descriptors and local overload indices;
|
||||
repeat with an explicit `--overload-index`. These are the prototypes observed in
|
||||
the APK, not the complete method inventory of an Android framework or library.
|
||||
|
||||
Such results report `target_definition: "external"` and
|
||||
`reference_scope: "direct_dex_invokes"`. Each using method has `source_selector`
|
||||
with `class_name`, `method_name` and `overload_index`; pass those fields with the
|
||||
same APK path to `inspect_android_method` to inspect the caller. Repeated direct
|
||||
invokes in one method remain one using node with multiple instruction offsets.
|
||||
This scans raw invoke instructions in JADX's admitted APK methods without
|
||||
generating their source. It does not resolve reflection, JNI, method handles,
|
||||
inherited method lookup or possible runtime dispatch. Class-only queries and
|
||||
class/method inspection still require an APK definition; an external target has
|
||||
no invented body. Unknown class/method names remain input errors.
|
||||
|
||||
External prototype and caller metadata use a bridge-frame-derived representation
|
||||
allowance that reserves space for retained raw calls and CLI/MCP copies. Exhausting
|
||||
it returns a typed `resource_constraint`, rather than a truncated caller list
|
||||
reported as complete. Direct instruction offsets have their separate explicit
|
||||
`direct_invokes_exhaustive` coverage. Older retained Evidence may omit the new
|
||||
definition, scope and caller-selector fields; omission does not establish them.
|
||||
The bridge checks prototype expansion before copying descriptors or joining
|
||||
displayed signatures. It reuses one bounded prototype inventory for the exact
|
||||
class/method selection in the current APK session; replacing the session or
|
||||
selection invalidates that retained result.
|
||||
|
||||
`inspect_android_class` also reports `dex_static_value` for each `static final`
|
||||
field whose class definition encodes a value in its DEX static values, so
|
||||
compile-time constants are readable even when the class has no `<clinit>`.
|
||||
@@ -734,3 +765,7 @@ containing node's unknown `dex_offset`. `direct_invokes_exhaustive: false`
|
||||
means instruction rows were bounded by the local bridge frame budget; `null`
|
||||
means the producer did not establish instruction coverage. Using-node totals
|
||||
and coverage do not imply complete instruction evidence.
|
||||
`direct_invokes_coverage` reports counts of using nodes with complete, partial,
|
||||
or unknown positions, plus the number of retained instruction sites. This
|
||||
aggregate makes position truncation visible without scanning every caller;
|
||||
older retained Evidence may omit it, which means the aggregate was unexamined.
|
||||
+17
-12
@@ -179,26 +179,31 @@ share the application workflow, projection, retention and publication owners.
|
||||
- `schemes_agree_on_signer` (observed): every present block scheme presents
|
||||
the same _set_ of signer certificates. An extra signer in one scheme is
|
||||
disagreement; a signer without a certificate makes it `null` (unknown).
|
||||
Build-tools 33+ rotate through v3.1 by default, so a rotated app usually
|
||||
reads `false` here and `true` below.
|
||||
A single present block scheme with known signers agrees with itself;
|
||||
v1 is compared separately below.
|
||||
- `signer_change_declared_by_rotation` (declared): the signers differ, but
|
||||
each appears in a lineage the APK declares. Read the two together: a
|
||||
rotated APK shows `false` / `true`; signers that differ with no declared
|
||||
lineage containing them show `false` / `false`. It is `null` when a
|
||||
signer's identity is unknown, or when the signers differ and a declared
|
||||
lineage could not be decoded.
|
||||
each appears in a lineage the APK declares. Read the two together: block
|
||||
schemes with different signers covered by a declared lineage show `false`
|
||||
/ `true`; differing signers without such a lineage show `false` / `false`.
|
||||
A lineage alone does not establish a change between block schemes. It is
|
||||
`null` when a signer's identity is unknown, or when the signers differ and
|
||||
a declared lineage could not be decoded.
|
||||
- `v1_signers_match_block_signers` (observed): the v1 signer certificates
|
||||
equal what the lowest block scheme that has signers (v2, else v3, else
|
||||
v3.1) expects v1 to carry. That is its signer set, except that a v3/v3.1
|
||||
signer declaring a rotation lineage expects the lineage's first
|
||||
(original) certificate, as apksig requires. `false` is notable: the JAR
|
||||
signature names a different key than the block signature. A key rotation
|
||||
keeps v1 (and v2) on the original key, so it reads `true` while
|
||||
`schemes_agree_on_signer` reads `false`, with or without v2. `null` when
|
||||
v1 or a block scheme is absent, any signer's identity is unknown (a
|
||||
signature names a different key than the block signature. When v1 uses
|
||||
the lineage's original key and v3 its newer key, this comparison reads
|
||||
`true`. If v3 is the only present block scheme, agreement is `true` and
|
||||
declared inter-block signer change is `false` even though rotation is
|
||||
present. If v2 also uses the original key, agreement is `false` and the
|
||||
declared inter-block change is `true`. `null` when
|
||||
v1 or a populated block scheme is absent, any signer's identity is unknown (a
|
||||
`decode_error`, a `null` certificate or a `subjectKeyIdentifier`
|
||||
`SignerInfo`), or the lineage's original certificate cannot be
|
||||
identified; a limitation then says why.
|
||||
identified. When identities or a lineage origin are unknown, limitations
|
||||
explain why; absence is shown in the scheme records.
|
||||
- `strongest_scheme`, `rotation_present`, `source_stamp_present`,
|
||||
`self_consistent`.
|
||||
|
||||
|
||||
@@ -101,8 +101,8 @@ limitation reports how many inventoried entries were left out. IPA projection
|
||||
still lists every archive component, including `SwiftSupport/`.
|
||||
|
||||
`platforms` lists `macos` for application roots with `Contents/`. It lists `ios`
|
||||
for shallow application roots that have an `Info.plist`. An application root
|
||||
with neither, such as an empty inventory, has no platform.
|
||||
for shallow application roots that have an `Info.plist` at their root. An
|
||||
application root with neither, such as an empty inventory, has no platform.
|
||||
|
||||
## macOS bundle anatomy
|
||||
|
||||
@@ -149,6 +149,11 @@ directories rather than `Versions/Current`. A framework's `info_plist_path` is
|
||||
because `Versions/Current` decides which one applies) or when its single
|
||||
version directory has no `Resources/Info.plist`.
|
||||
|
||||
A `shallow` bundle's `info_plist_path` is its root `Info.plist`. Without one,
|
||||
it is `Resources/Info.plist`: a flattened macOS framework keeps its binary,
|
||||
`_CodeSignature/`, and `Resources/` directly in the `.framework`, like a single
|
||||
`Versions/<version>/` directory without the `Versions/` wrapper.
|
||||
|
||||
AppleDouble sidecar files (`._*` and `__MACOSX/`) are inventory facts, but they
|
||||
describe neighbouring files. They are excluded from roots, bundle roles, and the
|
||||
anatomy components.
|
||||
|
||||
@@ -52,7 +52,11 @@ observations may omit the coverage field; treat omission as `unknown` rather
|
||||
than inferring completeness from the array.
|
||||
|
||||
Passive DOM comparison checks complete node inventories and complete frame
|
||||
parent/child structure independently. Frame IDs and sibling enumeration order
|
||||
parent/child structure independently. Node value lengths are comparable only
|
||||
when both nonempty snapshots declare the same `node_value_length_unit`.
|
||||
Missing or different units leave length comparison unknown; independent node
|
||||
or frame structural differences can still prove change. Empty inventories have
|
||||
no value lengths to compare. Frame IDs and sibling enumeration order
|
||||
are capture-local and do not establish a change; duplicate IDs, missing parents,
|
||||
and cyclic ancestry remain unknown. A complete frame difference can still prove
|
||||
change when DOM nodes are incomplete, and vice versa. Partial DOM or metadata
|
||||
@@ -400,7 +404,19 @@ contextual evidence with `timestamp: null`, accompanied by a limitation stating
|
||||
that it does not establish activity in the selected window. Main-frame scope
|
||||
enforcement still applies to contextual navigation events. Network redirect
|
||||
events retain their paired prior-hop response context when the timestamped
|
||||
next-request event falls inside the window. The pre-arm timeline buffer is bounded
|
||||
next-request event falls inside the window. A redirect row's optional
|
||||
`redirect_response` contains the prior response `url`, CDP-reported `status`,
|
||||
and `scope`. The URL has transport credentials removed; URL and status are
|
||||
withheld unless its origin is approved. Missing or malformed response URLs have
|
||||
null scope and add `invalid_protocol_value` timeline coverage; a valid URL with an
|
||||
unsupported protocol has `unsupported` scope. Outside-policy and unsupported
|
||||
responses mark the timeline as policy-filtered with `disallowed_origin` or
|
||||
`unsupported_url`. Missing status remains null rather than zero. A supplied
|
||||
non-numeric status is also null and records `invalid_protocol_value` coverage;
|
||||
the other valid response facts remain available. Historical rows may omit this
|
||||
field; omission does not establish that no prior response existed. Response
|
||||
headers and bodies are discarded. The row timestamp belongs to the next request,
|
||||
not an exact prior response time. The pre-arm timeline buffer is bounded
|
||||
by original CDP message bytes. If clock sampling completes after that budget is
|
||||
exhausted, the operation returns `payload_limit` instead of a partial window.
|
||||
Cancellation and clock-request failures retain their own outcomes. Session
|
||||
@@ -449,7 +465,7 @@ not bound the whole process heap.
|
||||
REA retains local observation data and removes only URL userinfo credentials, explicitly declared scenario secrets, and values from structured credential/storage fields:
|
||||
|
||||
- URL observations preserve the complete local URL, including query values, fragments, duplicate parameters, and their order. Only username/password userinfo is removed; malformed original URL strings remain available with `origin: null`.
|
||||
- DOM snapshots retain node types, node names, value lengths, and attribute names, but not text or attribute values.
|
||||
- DOM snapshots retain node types, node names, value lengths, and attribute names, but not text or attribute values. `dom.node_value_length_unit` is `utf16-code-units` for web observations and applies to every node's `node_value_length`; it counts JavaScript string code units, not Unicode code points or UTF-8 bytes. Electron observations declare `utf8-bytes` instead. Historical captures without the unit leave it unknown; reading them does not infer a unit or convert their stored lengths.
|
||||
- Supported DOM URL attributes are projected separately as resolved destinations. Empty `action` on HTML or XHTML forms and empty `formaction` on HTML or XHTML submit controls resolve to the document URL; other relative URL attributes resolve against the captured document base.
|
||||
- Accessibility structure and reported roles are retained by default, while names and descriptions require `include_accessibility_text: true`. The browser protocol may omit an individual role; that role remains unknown for comparison. Other observed accessibility differences can still establish a change.
|
||||
- Network observations retain method, status, MIME type, size, type, initiator stack location, and complete URLs with userinfo credentials removed. Redirects reported by CDP are attached as ordered `redirects` on the one request ID, with the prior request URL, CDP response URL, method/type, response status/MIME/encoded length, request timestamp, and the next `requestWillBeSent` event timestamp. CDP delivers `redirectResponse` with that next request event, so the latter is an event boundary rather than an exact response timestamp. Redirect response headers and bodies are discarded; hops outside the selected origins are discarded with the request chain. Headers are discarded after an allowlisted projection of length/encoding, structured CSP/Link/policy fields, and untrusted agent hints. Cookies and authorization headers are never retained.
|
||||
|
||||
@@ -411,8 +411,10 @@ data you may change. This scenario creates one item:
|
||||
- Request steps follow no redirects: a redirect answer fails the step, and
|
||||
nothing is sent to the location it names, though a write the redirect
|
||||
answered may already have been applied. `expected_status` cannot name a 3xx
|
||||
status. Give the path the redirect names; with header values selected, the
|
||||
capture records its `Location`.
|
||||
status. Manual redirects can be opaque to the page and may not produce a
|
||||
response event; their status and `Location` can therefore be unavailable even
|
||||
when network events and header values were selected. Such captures report
|
||||
incomplete event coverage.
|
||||
- Header values are literals, declared secrets, a cookie the browser holds for
|
||||
the request URL (`{"source": "cookie", "name"}`, HttpOnly cookies included,
|
||||
whose value the page's scripts can then see while the request runs), or a
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Bun standalone executables
|
||||
|
||||
`inspect-artifact` inventories embedded Bun module graphs in Mach-O `__BUN,__bun`,
|
||||
PE `.bun`, ELF `.bun`, and appended trailers. `extract-artifact` writes their stored
|
||||
module contents through the existing safe output tree. Neither operation executes
|
||||
the executable or decompiles bytecode.
|
||||
|
||||
```sh
|
||||
rea inspect-artifact ./hello --json
|
||||
rea extract-artifact ./hello --json
|
||||
```
|
||||
|
||||
In MCP, open the executable with `open_binary`, then call `inspect_artifact`.
|
||||
Use `detail: "summary"` for large graphs and `inspect_analysis_view` to page retained
|
||||
Evidence. The root metadata's `entry_point_logical_path` is the reader-owned
|
||||
location of its entry module. Use it as an inventory `logical_paths` filter,
|
||||
then read selected node fields with the returned content identity. This also
|
||||
works for names mapped to indexed extraction paths. The complete Evidence stays
|
||||
retained; no source-name normalization is needed in the caller.
|
||||
|
||||
The root reports the carrier, layout, module count, entry point, raw flags and
|
||||
compile exec-argv. Each module retains its source name, loader and encoding values,
|
||||
entry-point status, sizes and SHA-256. Sourcemaps, bytecode and module-info regions
|
||||
are separate children. Source names such as `/$bunfs/root/main.js` remain in
|
||||
metadata; extraction uses a relative path. Unsafe or non-UTF-8 names receive an
|
||||
indexed path and retain their source spelling or bytes. Virtual names deeper
|
||||
than 256 logical path parts also use an indexed path with an explicit limitation,
|
||||
preventing unbounded path-tree work while retaining the source fact. Duplicate names remain
|
||||
separate occurrences; ordinary extraction collision rules apply.
|
||||
|
||||
The recognized record shapes are the 36-byte Bun 1.3.3 layout and the 52-byte
|
||||
Bun 1.3.9 layout. These labels identify structural layouts, not a detected compiler
|
||||
version. Bun does not store an explicit revision identifier: unknown table sizes
|
||||
and ambiguous known layouts are unsupported. A future layout that is byte-for-byte
|
||||
compatible cannot be distinguished. Invalid pointers and truncated claimed sections
|
||||
are malformed. An absent trailer without a named section does not establish a Bun
|
||||
graph. Unknown enum values remain raw, with a null name.
|
||||
|
||||
Sourcemaps are stored Bun regions, not necessarily standalone JSON source maps.
|
||||
Extracted contents retain their original encoding. Use JavaScript analysis only on
|
||||
compatible source files; bytecode is retained as evidence, not decoded.
|
||||
|
||||
Module parsing reads exact metadata ranges rather than loading stored asset
|
||||
bodies or whole pages around small pointers. A cache retains at most 256 KiB
|
||||
and 1,024 ranges for one reader preparation. Cumulative uncached metadata reads
|
||||
are limited to 256 MiB, checked before allocation or I/O. The module table,
|
||||
decoded strings and combined logical path tree have separate admission checks;
|
||||
at most 250,000 distinct path prefixes are admitted before inventory construction.
|
||||
Stored bodies are range-streamed for hashing and extraction. Header/suffix observations are reused
|
||||
only for the same admitted file state, with selected-path checks before publication.
|
||||
|
||||
See [limits and recovery](design/limits-and-recovery.md) for admission ceilings.
|
||||
Synthetic tests cover the carriers and malformed declarations. Run
|
||||
`node scripts/verify-bun-standalone.mjs` after `npm run build:cached` for local Bun
|
||||
verification, and add `--docker` to compile a Linux fixture with `oven/bun:1.4.0`.
|
||||
Bun and Docker are fixture producers only and are not installed by REA.
|
||||
|
||||
Layout references: [Bun 1.3.3 serializer](https://github.com/oven-sh/bun/blob/bun-v1.3.3/src/StandaloneModuleGraph.zig)
|
||||
and [Bun 1.3.9 serializer](https://github.com/oven-sh/bun/blob/bun-v1.3.9/src/StandaloneModuleGraph.zig).
|
||||
|
||||
The current 52-byte record order can also be checked in the
|
||||
[Bun 1.4.4 Rust serializer](https://github.com/oven-sh/bun/blob/bun-v1.4.4/src/standalone_graph/StandaloneModuleGraph.rs).
|
||||
+74
-3
@@ -165,6 +165,15 @@ into the current shell:
|
||||
eval "$(rea completions bash)"
|
||||
```
|
||||
|
||||
For zsh, initialize completion before loading the hook. If your shell already
|
||||
runs `compinit`, place the hook after that existing initialization:
|
||||
|
||||
```zsh
|
||||
autoload -Uz compinit
|
||||
compinit
|
||||
eval "$(rea completions zsh)"
|
||||
```
|
||||
|
||||
The Bash hook supports macOS system Bash 3.2. It uses optional completion
|
||||
features when the shell provides them and falls back to portable registration.
|
||||
Completion includes standard global options and the active command's options;
|
||||
@@ -261,6 +270,17 @@ Format versions 6 through 8 retain header, block and directory facts with
|
||||
none/LZ4/LZ4HC block decompression. See [UnityFS](unityfs.md) for encryption
|
||||
and LZMA coverage boundaries.
|
||||
|
||||
Inspect an ESP32-family app or bootloader image without esptool:
|
||||
|
||||
```sh
|
||||
rea inspect-artifact firmware.bin --json
|
||||
rea extract-artifact firmware.bin --json
|
||||
```
|
||||
|
||||
The inventory lists each segment with its ESP-IDF load classification, the
|
||||
checksum and SHA-256 results, the descriptor and any Secure Boot v2 signature
|
||||
blocks. See [ESP images](esp-image.md) for recognition, coverage and refusals.
|
||||
|
||||
Inspect a Node.js SEA carrier without running it:
|
||||
|
||||
```sh
|
||||
@@ -291,6 +311,22 @@ rea extract-artifact ./firmware.bin --json
|
||||
See [U-Boot uImage](uimage.md) for verified CRCs, physical component ranges,
|
||||
unknown names, resource limits and retained views. Compressed bytes stay stored.
|
||||
|
||||
`inspect-artifact` and `extract-artifact` also read ZIP members compressed with
|
||||
Zstandard (standard method 93). They retain the shared ZIP CRC, declared-size,
|
||||
overlap and archive expansion checks. The native streaming decoder keeps the
|
||||
existing 128 MiB Zstandard window cap; frames requiring a larger window are
|
||||
refused. Deprecated method 20 and other unregistered ZIP codecs remain unsupported.
|
||||
|
||||
Inventory and extract U-Boot FIT images:
|
||||
|
||||
```sh
|
||||
rea inspect-artifact ./boot.itb --json
|
||||
rea extract-artifact ./boot.itb --json
|
||||
```
|
||||
|
||||
See [U-Boot FIT images](fit-images.md) for recognition, data sources, hashes
|
||||
and limits.
|
||||
|
||||
Inspect local model declarations without loading weights:
|
||||
|
||||
```bash
|
||||
@@ -594,6 +630,11 @@ rea compare left.json right.json --record_pairs '[{"left_evidence_id":"ev_<left-
|
||||
Migration: replace `rea compare-bundles` with `rea compare`; the former command
|
||||
has been removed. The MCP tool remains `compare_bundles`.
|
||||
|
||||
`rea compare` compares records by Evidence identity and explicit pairs. It does
|
||||
not read artifact contents: the inventories of two builds are unresolved
|
||||
records, or one opaque change when you pair them. Use `compare-artifacts`,
|
||||
described at the end of this section, to compare their contents.
|
||||
|
||||
`--record_pairs` supplies an explicit JSON array of observation pairs, matching
|
||||
MCP `compare_bundles.record_pairs`. Pair IDs must exist on their named sides and
|
||||
be one-to-one. Without pairs, one-sided membership remains unknown; REA does
|
||||
@@ -617,6 +658,24 @@ including bundles exported from an MCP session. The same view JSON works for
|
||||
every supported parent kind; no target is reopened and no record is selected
|
||||
by file order. Omit `--evidence-bundle` when the request supplies inline Evidence.
|
||||
|
||||
Compare two artifact inventories with `compare-artifacts`. It takes the same
|
||||
`left` and `right` input as MCP `compare_artifacts`: complete Evidence, or an
|
||||
`evidence-file` source with an optional `evidence_id` that selects one record
|
||||
from a bundle. Relative paths resolve from the working directory:
|
||||
|
||||
```bash
|
||||
rea inspect-artifact old.zip --json > old.json
|
||||
rea inspect-artifact new.zip --json > new.json
|
||||
rea compare-artifacts '{"left":{"kind":"evidence-file","path":"old.json"},"right":{"kind":"evidence-file","path":"new.json"}}' --json
|
||||
```
|
||||
|
||||
A one-shot command keeps no session Evidence, so it refuses a
|
||||
`retained-evidence` source with `details.reason: "missing"`. Select the record
|
||||
from a saved bundle instead.
|
||||
For an artifact summary selected from a bundle, include its complete parent
|
||||
inventory in the same bundle. The command resolves that parent from the
|
||||
authenticated file records; a summary-only file cannot supply missing facts.
|
||||
|
||||
## Import historical source
|
||||
|
||||
Historical source inventories preserve exact filenames, including literal backslashes
|
||||
@@ -999,8 +1058,8 @@ Malformed format values and token windows fail with `INVALID_OUTPUT_VALUE` in th
|
||||
selected structured format. Token limits and offsets must be nonnegative safe
|
||||
integers; zero selects an empty window. These checks run before command execution. `--json` is indented on a terminal and compact when piped or
|
||||
redirected, which keeps large results smaller for agents and scripts; pipe
|
||||
through `jq .` for indented files. Output selection and formatting do not change
|
||||
operation status.
|
||||
through `jq .` for indented files. A formatting refusal exits nonzero even when
|
||||
the underlying operation succeeded.
|
||||
|
||||
`--format md` escapes backslashes, pipes, and inline Markdown syntax in table
|
||||
headers and cells so source text is displayed literally, and renders cell line
|
||||
@@ -1012,6 +1071,12 @@ values instead of replacing them with an object label. Table widths are measured
|
||||
iteratively, so an admitted row page is not limited by the JavaScript function
|
||||
argument count.
|
||||
|
||||
Markdown refuses selected NUL characters and unpaired UTF-16 surrogates because
|
||||
renderers or UTF-8 output would substitute them. TOON refuses selected unpaired
|
||||
surrogates for the same UTF-8 reason. Use JSON or YAML to retain those values.
|
||||
An authored replacement character and valid supplementary characters are not
|
||||
treated as malformed.
|
||||
|
||||
`--format csv` and `--format tsv` export one selected row collection. Select an
|
||||
exact array path with `--filter-output` and provide comma-separated direct
|
||||
scalar columns with `--columns`; column order is the output column order:
|
||||
@@ -1031,7 +1096,8 @@ delimiter, quotes, or line breaks are quoted and embedded quotes are doubled.
|
||||
Values are emitted as UTF-8 without Unicode normalization. Missing and `null`
|
||||
cells are empty; booleans and finite numbers use their ordinary text forms.
|
||||
String cells and headers that begin with spreadsheet formula syntax are refused
|
||||
with a structured error; JSON retains those values unchanged.
|
||||
with a structured error; unpaired surrogates in selected cells or headers are
|
||||
also refused. JSON retains those values unchanged.
|
||||
|
||||
Delimited output does not flatten nested Evidence or nested field values.
|
||||
It returns a structured error and a nonzero status if the filter does not
|
||||
@@ -1190,3 +1256,8 @@ rea inspect-pe-load-config /absolute/path/to/application.exe --json
|
||||
Reports TLS callbacks and size-covered load-config fields without execution.
|
||||
Use `--max-callbacks` and `--max-file-bytes` to set read budgets. See
|
||||
[PE TLS and load configuration](pe-load-config.md).
|
||||
|
||||
Bun standalone executables use the existing `inspect-artifact` and
|
||||
`extract-artifact` commands to inventory and materialize embedded source,
|
||||
sourcemaps and bytecode without running the executable. See
|
||||
[Bun standalone executables](bun-standalone.md) for layout coverage and limits.
|
||||
@@ -273,7 +273,7 @@ This headroom is a practical default, not a guarantee for every analysis
|
||||
duration. Setup preserves positive timeout values already in the `rea` entry.
|
||||
|
||||
Setup also forwards explicitly selected input/output schema profiles,
|
||||
`REA_MCP_MAX_RESPONSE_BYTES`, provider paths and supported Ghidra, JADX and Kuna
|
||||
`REA_MCP_MAX_RESPONSE_BYTES`, `REA_MCP_MAX_INPUT_ELEMENTS`, provider paths and supported Ghidra, JADX and Kuna
|
||||
settings. It also forwards explicit executable and resource selections for ADB,
|
||||
apktool, packet capture, GDB/Rizin/objdump, Cutter, WABT, Wakaru, firmware and
|
||||
signal tools, browser inspection, and pwntools/pwndbg. This includes their
|
||||
@@ -283,8 +283,9 @@ patterns. A provider being unavailable does not discard its selected paths;
|
||||
doctor reports its readiness separately. Explicit selections override discovered
|
||||
defaults, including when setup runs again with a changed selection. Unrelated
|
||||
environment variables, process ownership tokens and one-shot target paths are not
|
||||
copied. Existing client environment overrides remain intact unless setup supplies
|
||||
the same key.
|
||||
copied. For an explicitly configured startup target, see the
|
||||
[initial-target settings](mcp-contracts.md#initial-target-at-startup). Existing
|
||||
client environment overrides remain intact unless setup supplies the same key.
|
||||
You can edit `startupTimeoutMs` and `toolTimeoutMs` there; doctor keeps positive
|
||||
caller-selected values aligned and reports a non-blocking advisory when a tool
|
||||
timeout is shorter than the known provider allowance.
|
||||
@@ -616,9 +617,10 @@ the fallback file untouched. Existing REA environment overrides are preserved
|
||||
when refreshing its command. A malformed or unreadable fallback file fails setup instead of
|
||||
being silently suppressed; repair or remove it and rerun. Uninstall removes an
|
||||
REA-owned `rea` entry from both the native table and the fallback, backing up
|
||||
each changed file, so an emptied native table cannot load a leftover fallback
|
||||
registration; other fallback servers, settings and a foreign `rea` entry are
|
||||
kept. ZCode disables a
|
||||
each changed file. If removing the last native server would activate a retained
|
||||
fallback server, uninstall refuses before changing either file; review the
|
||||
fallback configuration before retrying. Other fallback servers, settings and a
|
||||
foreign `rea` entry are kept. ZCode disables a
|
||||
server with `enable: false` on its entry; doctor reports such a registration
|
||||
as stale, and rerunning setup removes the flag to repair it. Native configuration
|
||||
uses strict JSON; setup refuses comments, trailing commas and a BOM rather than
|
||||
|
||||
@@ -378,3 +378,17 @@ The [verification report](../verification/runtime-analysis-settings.md) separate
|
||||
public MCP checks, simulated provider coverage, real Ghidra execution, and
|
||||
measured task costs. It does not establish real-provider behavior for every
|
||||
editable setting or active worker telemetry.
|
||||
|
||||
## Bun standalone module graphs
|
||||
|
||||
`MAX_BUN_MODULE_COUNT` admits at most 100,000 module records.
|
||||
`MAX_BUN_RETAINED_BYTES` admits at most 256 MiB of serialized graph payload and
|
||||
separately bounds retained entry metadata. Physical metadata read work is also
|
||||
limited to 256 MiB per preparation, including repeated uncached ranges. A
|
||||
256 KiB / 1,024-entry exact-range cache avoids full-page amplification. The
|
||||
combined logical path tree admits at most 250,000 distinct prefixes; this is
|
||||
checked before adding nodes, with shared prefixes counted once. The shared
|
||||
artifact expansion budget also bounds the sum of referenced member lengths. Refusals name the boundary.
|
||||
There is no runtime override; additional host memory or `NODE_OPTIONS` does not
|
||||
raise these ceilings. Use a smaller producer fixture or a separately reviewed
|
||||
reader for larger graphs. No partial extraction is claimed on admission failure.
|
||||
@@ -135,11 +135,13 @@ observations, not an atomic directory snapshot. Unread bytes remain unknown.
|
||||
## Resource bounds and reuse
|
||||
|
||||
Defaults are 20,000 examined entries and 8 MiB of total probe reads. Callers may
|
||||
select up to 100,000 entries and 64 MiB. A separate 32 MiB conservative
|
||||
representation budget bounds retained paths and facts before growth. Limits
|
||||
and failed probes produce partial coverage. Traversal and reads are serial.
|
||||
Each reader admits one inspection at a time; overlapping requests receive a
|
||||
retryable capacity refusal without cancelling the admitted caller.
|
||||
select up to 100,000 entries and 64 MiB. A separate 32 MiB representation
|
||||
budget bounds retained rows, paths and facts before growth. Each retained path
|
||||
is charged at the larger of its UTF-16 heap size and its escaped JSON size, so
|
||||
typical macOS bundle paths fit about 20,000 rows, and control-character paths
|
||||
fewer. Limits and failed probes produce partial coverage. Traversal and reads
|
||||
are serial. Each reader admits one inspection at a time; overlapping requests
|
||||
receive a retryable capacity refusal without cancelling the admitted caller.
|
||||
|
||||
Unity reference decoding stops after a witness in each `Data/Managed` directory;
|
||||
other assemblies' references remain unexamined, while their headers are still
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
# .NET single-file bundles
|
||||
|
||||
Use `rea inspect-artifact /absolute/path/host --json` to inventory an ordinary
|
||||
.NET single-file host and `rea extract-artifact /absolute/path/host --json` to
|
||||
materialize its members into a fresh, REA-owned output directory. With a host
|
||||
selected through `open_binary`, the corresponding MCP tools are
|
||||
`inspect_artifact` and `extract_artifact`. No .NET installation is needed for
|
||||
inspection or extraction.
|
||||
|
||||
For a compact inventory, call `inspect_artifact` with `detail: "summary"`,
|
||||
then use `inspect_analysis_view` with the returned `parent_evidence_id`.
|
||||
Inventory occurrence pages accept `logical_paths`, `occurrence_ids`, selected
|
||||
`fields`, `offset`, and `limit`; node pages accept batches of `artifact_ids`
|
||||
to retrieve expanded-byte digests. Include `format_metadata` and
|
||||
`source_location` when member declarations and stored extents matter. Identity
|
||||
fields survive projection, and the complete inspection Evidence stays retained.
|
||||
|
||||
REA detects the apphost marker and its preceding header offset from PE, ELF,
|
||||
and thin Mach-O bytes, regardless of filename. An unbundled apphost's zero
|
||||
offset remains an ordinary native artifact. Universal Mach-O slice inventory
|
||||
keeps its existing behavior; bundled contents inside slices are not expanded.
|
||||
When a native file has a recognized PyInstaller CArchive, apphost-marker
|
||||
scanning stops before its payload. A .NET helper stored inside that archive
|
||||
does not replace the outer container's format; an outer .NET host can still
|
||||
contain a PyInstaller helper as a member.
|
||||
|
||||
## Supported layout
|
||||
|
||||
| Header | Producer generation | Member encoding |
|
||||
| ------ | ---------------------------------- | --------------------------- |
|
||||
| 1.0 | .NET Core 3.x | Uncompressed |
|
||||
| 2.0 | .NET 5 | Uncompressed |
|
||||
| 6.0 | .NET 6 and later using this layout | Uncompressed or raw DEFLATE |
|
||||
|
||||
Versions, minor versions, and flags outside this set are refused explicitly;
|
||||
they do not silently become an ordinary PE or a successful empty inventory.
|
||||
Flags 0 and the v2+ compatibility flag 1 are admitted. Unknown file-type bytes
|
||||
are retained with a limitation, rather than treated as executable authority.
|
||||
Encrypted/protected wrappers and recovering their payloads are outside this
|
||||
reader's scope.
|
||||
|
||||
The host keeps its whole-file SHA-256. Each embedded file gets its expanded-byte
|
||||
SHA-256, path, declared size, compressed size, and `format_metadata` declaration
|
||||
(`major_version`, `minor_version`, `file_type`). Its `source_location` describes
|
||||
the stored host extent, including the compressed length when applicable.
|
||||
The root manifest's `root_format` is `dotnet-bundle`; the root content node
|
||||
still records its native PE/ELF/Mach-O format. A file-type declaration or `.dll`
|
||||
suffix does not establish a valid assembly. Inspect an extracted component
|
||||
explicitly with the managed tools to establish PE/CLI facts.
|
||||
|
||||
## Admission and containment
|
||||
|
||||
Metadata is range-read with a 64 KiB cache. Policy budgets are 16 MiB of
|
||||
manifest metadata, 100,000 files, 64 KiB per UTF-8 string, 512 MiB of stored or
|
||||
expanded bytes per file, 256 path parts per member, 250,000 distinct in-memory
|
||||
path-tree nodes, and 2 GiB of aggregate expanded bytes. The node budget counts
|
||||
shared directory prefixes only once. These are REA
|
||||
resource policies, not limits imposed by Microsoft's format. Marker scanning
|
||||
streams 64 KiB chunks and reuses completed probe facts during extraction;
|
||||
ordinary native files without a marker incur one extra
|
||||
read pass before host hashing.
|
||||
|
||||
Extraction hashes the whole host again through the same descriptor used to read
|
||||
members and compares it with the inventory's root digest before creating an
|
||||
output directory. This adds a full-host read pass to extraction, including when
|
||||
the embedded members themselves are small.
|
||||
|
||||
Malformed/truncated headers, unsafe or conflicting paths, overlapping member
|
||||
ranges, members crossing the manifest, contradictory configuration extents,
|
||||
invalid UTF-8, corrupt/trailing compressed data, and incorrect expanded sizes
|
||||
fail before output publication. Source descriptor/path identity is checked
|
||||
during reading; extraction verifies the host digest and member bytes against
|
||||
the inventory. Existing output roots are never overwritten. Cancellation and
|
||||
failures release owned streams/descriptors through the shared extraction
|
||||
rollback scope.
|
||||
|
||||
## Reproduce producer fixtures
|
||||
|
||||
The source-owned generator uses the installed .NET 8 SDK's **Microsoft
|
||||
HostModel** producer to emit x64 v1, v2, plain v6, and compressed v6 bundles
|
||||
for Windows, Linux, or macOS. It does not run generated hosts or download runtime packs. Supply an
|
||||
SDK apphost template from
|
||||
`packs/Microsoft.NETCore.App.Host.<rid>/<version>/runtimes/<rid>/native/apphost`
|
||||
(`apphost.exe` on Windows). Pass `windows` (the default), `linux`, or `osx`
|
||||
as the optional third generator argument to match that template.
|
||||
|
||||
```bash
|
||||
dotnet build scripts/fixtures/dotnet-bundle/BundleFixture.csproj -c Release --configfile scripts/fixtures/dotnet-bundle/NuGet.Config -o /absolute/path/producer -p:BaseIntermediateOutputPath=/absolute/path/producer-obj/
|
||||
dotnet /absolute/path/producer/BundleFixture.dll /absolute/path/apphost.exe /absolute/path/absent-bundles-directory
|
||||
rea inspect-artifact /absolute/path/absent-bundles-directory/net8-compressed/Probe.exe --json
|
||||
rea extract-artifact /absolute/path/absent-bundles-directory/net8-compressed/Probe.exe --json
|
||||
```
|
||||
|
||||
The generator writes `oracle.json` beside each host. An independent C#
|
||||
`BinaryReader`/`DeflateStream` pass records version, member types and stored
|
||||
extents, then compares every expanded member digest with its source file.
|
||||
Compare those records with inspection Evidence and the extracted bytes.
|
||||
This verifies Microsoft's compression writer separately from synthetic parser
|
||||
fixtures; it is not evidence that the bundled host executes on a target runtime.
|
||||
|
||||
Deterministic boundary and public-entrypoint coverage:
|
||||
|
||||
```bash
|
||||
npm run test:focused -- tests/boundary/filesystem/dotnetBundleArtifacts.test.ts tests/acceptance/dotnetBundleJourney.test.ts
|
||||
```
|
||||
|
||||
Layout references: Microsoft's [manifest writer](https://github.com/dotnet/runtime/blob/v8.0.22/src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs),
|
||||
[file entry writer](https://github.com/dotnet/runtime/blob/v8.0.22/src/installer/managed/Microsoft.NET.HostModel/Bundle/FileEntry.cs),
|
||||
[apphost marker handling](https://github.com/dotnet/runtime/blob/v8.0.22/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs),
|
||||
and [compression producer](https://github.com/dotnet/runtime/blob/v8.0.22/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs).
|
||||
@@ -75,6 +75,13 @@ DOM node indices retain their snapshot positions. Invalid rows are omitted with
|
||||
completeness diagnostics, so `total_nodes` can exceed the retained node count
|
||||
and a parent index can refer to an omitted source node.
|
||||
|
||||
`dom.node_value_length_unit` is `utf8-bytes`: each node's `node_value_length`
|
||||
counts the bytes needed to encode its value as UTF-8, not characters. Web
|
||||
observations instead declare `utf16-code-units`. These existing measurements
|
||||
are preserved; the unit is reported once for the whole DOM, without retaining
|
||||
text values. Historical captures without the unit leave it unknown; reading
|
||||
them does not infer a unit or convert their stored lengths.
|
||||
|
||||
Script metadata retains its execution-context frame ID when CDP supplies one and
|
||||
records admission separately in `frame_scope`. An `authorized` scope refers to
|
||||
the observed document generation; `unknown` retains the known frame ID without
|
||||
|
||||
@@ -701,7 +701,7 @@
|
||||
"calculated_sha256",
|
||||
"unpacked"
|
||||
],
|
||||
"additionalProperties": false
|
||||
"additionalProperties": {}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
@@ -727,7 +727,7 @@
|
||||
"calculated_md5",
|
||||
"unpacked"
|
||||
],
|
||||
"additionalProperties": false
|
||||
"additionalProperties": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
# ESP images
|
||||
|
||||
REA reads ESP32-family firmware images through `inspect-artifact` /
|
||||
`inspect_artifact` and `extract-artifact` / `extract_artifact`. OTA downloads,
|
||||
app partitions and second-stage bootloaders are all ESP images. Reading is
|
||||
static: no esptool, device or flash access is needed, and no code is run or
|
||||
disassembled.
|
||||
|
||||
```sh
|
||||
rea inspect-artifact ./firmware.bin --json
|
||||
rea inspect-artifact ./ota.bin --detail summary --evidence_output evidence.json --json
|
||||
rea extract-artifact ./firmware.bin --json
|
||||
```
|
||||
|
||||
For MCP, open the file with `open_binary`, then call `inspect_artifact`. The
|
||||
summary's `root_format_metadata` holds the image facts. Use its
|
||||
`parent_evidence_id` with `inspect_analysis_view` to select segment rows.
|
||||
`extract_artifact` writes one file per segment and per signature block.
|
||||
|
||||
For agent sessions, advertise the `session,artifact,application` tool families
|
||||
and consider setting both `REA_MCP_INPUT_SCHEMA_PROFILE` and
|
||||
`REA_MCP_OUTPUT_SCHEMA_PROFILE` to `compact`. The output profile bounds each
|
||||
advertised output schema to 4,096 bytes by relaxing nested client validation;
|
||||
REA still validates complete results against the canonical contracts. Pair
|
||||
this with retained summaries and selected inventory views to limit the context
|
||||
needed for one question. See [MCP contracts](mcp-contracts.md) for the profiles
|
||||
and their client compatibility tradeoffs.
|
||||
|
||||
The layout facts follow ESP-IDF v6.1 (`esp_app_format.h`, `esp_app_desc.h`,
|
||||
`esp_bootloader_desc.h`, `esp_image_format.c`, the ROM `secure_boot.h`
|
||||
headers and `docs/en/security/secure-boot-v2.rst`) and esptool v5.6.0
|
||||
(`bin_image.py`, `cmds.py`, `loader.py`, espsecure).
|
||||
|
||||
## Recognition
|
||||
|
||||
The container format is `esp-image`. A file is an ESP image when its bytes
|
||||
show all of these; the file name does not matter:
|
||||
|
||||
- magic `0xE9` at offset 0 and 1 to 16 segments. A count of 0 is valid but
|
||||
loads nothing, and accepting it would admit x86 programs that begin
|
||||
`E9 00`;
|
||||
- a flash mode and flash speed code that ESP-IDF's enums define;
|
||||
- a `hash_appended` byte of 0 or 1, as esptool requires;
|
||||
- when the file holds the first segment header, a segment length that is a
|
||||
multiple of 4.
|
||||
|
||||
Later segments, the checksum and the digest are integrity facts. A truncated
|
||||
download is still an ESP image, with its integrity reported as unavailable.
|
||||
|
||||
| Input | Outcome |
|
||||
| --------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| ESP8266 image (v1 or v3): same magic, 8-byte header | Refused: "ESP8266 firmware images are not supported…" |
|
||||
| Flash-encrypted image (ciphertext) | Not recognized: the bytes carry no magic. Unknown, not malformed |
|
||||
| ESP8266 v2 image (magic `0xEA`) | Not recognized |
|
||||
|
||||
An ESP8266 image has its first segment header at offset 8, and that segment
|
||||
loads into ESP8266 DRAM, IRAM (Arduino's eboot links at `0x4010F000`) or the
|
||||
IROM flash window, where v3 and Arduino app images begin. In an ESP32-family
|
||||
header the same bytes hold `wp_pin` and the drive settings, which esptool and
|
||||
ESP-IDF write as `0xEE` and zeros. Inside another container, an ESP8266 image
|
||||
is classified as a plain file.
|
||||
|
||||
Recognition cannot exclude every file that starts with an x86 near jump
|
||||
(`0xE9`), such as a DOS `.com` program. An explicit `--target-format dos-com`
|
||||
or `raw-binary` selection skips ESP recognition.
|
||||
|
||||
## Image facts
|
||||
|
||||
Root `format_metadata` has `kind: "esp-image"`:
|
||||
|
||||
| Field | Label | Meaning |
|
||||
| ------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| `header` | observed | Every `esp_image_header_t` field, with ESP-IDF's names, for example `entry_addr`, `chip_id`, `min_chip_rev_full` |
|
||||
| `chip` | derived | `target`, `isa` and the table's `source` (`ESP-IDF v6.1`) from `chip_id`; `null` for an ID the table lacks |
|
||||
| `checksum` | derived | `offset`, `stored`, `computed` and `status`: `valid`, `invalid` or `unavailable` |
|
||||
| `appended_sha256` | derived | The digest `hash_appended` adds: `offset`, `stored`, `computed` and `status`, including `not-appended` |
|
||||
| `image_end` | derived | End of the checksum block and any appended digest; `null` when the file ends before it |
|
||||
| `signature_sector_offset` | derived | The Secure Boot v2 signature sector, when it holds at least one valid block |
|
||||
| `undescribed_trailing` | derived | Byte ranges after the image that nothing describes; empty when every byte is described |
|
||||
| `descriptor` | observed | `esp_app_desc_t` or `esp_bootloader_desc_t` fields, with ESP-IDF's names, and the descriptor's file `offset` |
|
||||
|
||||
The descriptor's `kind`, derived from its magic, classifies the image as an
|
||||
`app` or a `bootloader`. Without a descriptor the role is unknown.
|
||||
|
||||
The ISA comes from `chip_id`, never from the series letter: ESP32-S31 is
|
||||
RISC-V. The chip table covers every `esp_chip_id_t` in ESP-IDF v6.1:
|
||||
|
||||
| `chip_id` | Target | ISA | `chip_id` | Target | ISA |
|
||||
| --------- | --------- | ------ | --------- | ---------- | ----- |
|
||||
| `0x0000` | `esp32` | xtensa | `0x0012` | `esp32p4` | riscv |
|
||||
| `0x0002` | `esp32s2` | xtensa | `0x0014` | `esp32c61` | riscv |
|
||||
| `0x0005` | `esp32c3` | riscv | `0x0017` | `esp32c5` | riscv |
|
||||
| `0x0009` | `esp32s3` | xtensa | `0x0019` | `esp32h21` | riscv |
|
||||
| `0x000C` | `esp32c2` | riscv | `0x001C` | `esp32h4` | riscv |
|
||||
| `0x000D` | `esp32c6` | riscv | `0x0020` | `esp32s31` | riscv |
|
||||
| `0x0010` | `esp32h2` | riscv | | | |
|
||||
|
||||
Other IDs, for example esptool v5.6.0's ESP32-E22 (`0x1F`), have `chip: null`
|
||||
and unclassified segments.
|
||||
|
||||
**Integrity.** The checksum is the XOR of every segment data byte, seeded with
|
||||
`0xEF`, in the last byte of the next 16-byte block. The appended SHA-256 covers
|
||||
every byte through the checksum. Both are facts, not admission rules: a
|
||||
mismatch is reported with a limitation and the segments stay readable.
|
||||
|
||||
**Descriptors.** Both descriptors begin segment 0: ESP-IDF's bootloader reads
|
||||
the app descriptor there, and esptool places the bootloader descriptor there.
|
||||
Strings stop at the first NUL and are omitted, with a limitation, when they
|
||||
are not valid UTF-8. The bootloader descriptor's magic is a single byte
|
||||
(`0x50`), so its reserved bytes, which ESP-IDF zero-fills, must also be zero.
|
||||
A `--ram-only-header` image puts RAM segments first, so its app descriptor is
|
||||
not in segment 0 and its role is unknown. `mmu_page_size` keeps ESP-IDF's
|
||||
name and value: the MMU page size as a base-2 logarithm, as
|
||||
`esp_app_desc_t` declares it, so `16` means 64 KiB. It is `0` in images built
|
||||
before ESP-IDF v5.4. `spi_flash_mode` is the next byte, which ESP-IDF v6.1
|
||||
names, kept as stored and not interpreted; releases that reserve it leave it
|
||||
`0`. A file can end inside the app descriptor: every field it holds in full
|
||||
is kept, a field it cuts off is `null`, and `observed_length` gives the
|
||||
descriptor bytes the file holds. The segment's truncation is reported as usual.
|
||||
|
||||
## Segments
|
||||
|
||||
Each header-declared segment is one entry named `segment-<index>.bin`, for
|
||||
example `segment-00.bin`, so two builds pair segments by position. Its
|
||||
`source_location` is the segment data in the image file. `format_metadata`
|
||||
(`esp-image-segment`) records `index`, `load_addr`, `data_len`,
|
||||
`header_offset` and `classification`.
|
||||
|
||||
`classification` follows ESP-IDF's bootloader (`should_map` and
|
||||
`should_load` in `esp_image_format.c`) on a cold boot:
|
||||
|
||||
| Value | Meaning |
|
||||
| ------------ | ------------------------------------------------------------------------------------------------- |
|
||||
| `mapped` | Inside the chip's IROM, DROM or, where the MMU is per memory type, PSRAM range (`soc.h`) |
|
||||
| `loaded` | `should_load` selects it: not mapped, at or above `0x10000000`. RAM ranges are not checked |
|
||||
| `not-loaded` | Below `0x10000000`: the padding segments esptool writes at address 0, including `--secure-pad-v2` |
|
||||
| `unknown` | The chip is unknown, or the mapping depends on the bootloader's MMU page size |
|
||||
|
||||
`loaded` does not mean the bootloader accepts the segment. Before loading,
|
||||
ESP-IDF's `verify_load_addresses` rejects the image when a loaded segment is
|
||||
not entirely in the chip's DRAM, IRAM, RTC memory or SPM, or overlaps the
|
||||
bootloader's own stack, data or loader code. For example, an ESP32-C6
|
||||
segment at `0x43000000` is `loaded` here and rejected there. REA models no
|
||||
RAM ranges.
|
||||
|
||||
Padding segments are inventoried and extractable, but are never load regions.
|
||||
When waking from deep sleep, ESP-IDF also skips RTC-memory segments; that
|
||||
runtime case is not modelled. ESP32-C6 and ESP32-H2 map flash from
|
||||
`0x42000000` through 256 pages of the bootloader's configured MMU page size,
|
||||
which no image records. The app descriptor's page size describes the app's
|
||||
build, not the bootloader's. With page sizes from 8 KiB (which the hardware
|
||||
supports and esptool builds for) to 64 KiB, segments from `0x42200000` to
|
||||
`0x43000000` are `unknown`. Ranges follow ESP-IDF's `should_map`, not esptool's
|
||||
wider placement ranges.
|
||||
|
||||
A segment cut short by the end of the file is the bytes the file holds, with
|
||||
an entry limitation that gives the declared length.
|
||||
|
||||
Artifact comparison uses each segment's `load_addr` and `data_len` as its
|
||||
declaration, so a segment that moves with unchanged bytes is `changed` in
|
||||
`metadata`. Segments pair by index: inserting or removing one shifts the
|
||||
paths of the segments after it. Header offsets and `classification` are not
|
||||
compared; the image's own change covers the header and chip. The image's and
|
||||
the signature blocks' `format_metadata` carry no declaration: their fields
|
||||
come from their own bytes, which content comparison covers, and a block's
|
||||
`image_digest_matches` follows the image's content.
|
||||
|
||||
## Secure Boot v2 signatures
|
||||
|
||||
A signature sector starts at the next 4 KiB boundary after the image and
|
||||
holds up to three 1216-byte slots. A slot holds a block when it has the `0xE7`
|
||||
magic and a matching CRC32 at offset 1196, the rule ESP-IDF and espsecure
|
||||
apply. Each slot is examined independently, so an erased or damaged slot does
|
||||
not hide a later block. Each block is an entry, `signature-block-<slot>.bin`,
|
||||
with `esp-image-signature-block` metadata:
|
||||
|
||||
| Field | Meaning |
|
||||
| ---------------------------------- | ------------------------------------------------------------------------- |
|
||||
| `index`, `version`, `scheme` | Slot 0 to 2, version byte, and `rsa` (`0x02`) or `ecdsa` (`0x03`) |
|
||||
| `sha_version`, `curve_id` | For ECDSA, the third byte (0 is SHA-256, 1 SHA-384) and the curve ID byte |
|
||||
| `digest_algorithm`, `image_digest` | The digest the block records |
|
||||
| `image_digest_matches` | Whether it equals the digest of every byte before the sector |
|
||||
| `public_key_sha256` | SHA-256 of the block's public key, the value eFuse key digests hold |
|
||||
| `signature_status` | Always `unverified` |
|
||||
|
||||
Signatures are observed, not verified: REA checks no public key, signature or
|
||||
eFuse. `public_key_sha256` is the digest espsecure `signature-info-v2`
|
||||
prints, so it can be compared with `espefuse summary`. An unknown version or
|
||||
`sha_version` leaves the layout-dependent fields `null`. A slot with the magic
|
||||
but no matching CRC32 is not a block: it is reported in a limitation, whether
|
||||
or not another slot holds a block, and its bytes are undescribed. Secure Boot
|
||||
v1 signatures are not decoded.
|
||||
|
||||
## Coverage and limitations
|
||||
|
||||
Bytes after the image are described when they are erased flash (`0xFF`) or a
|
||||
signature sector's blocks; erased slots and slack in that sector count as
|
||||
erased flash. Every other byte is in `undescribed_trailing`.
|
||||
|
||||
| Situation | Outcome |
|
||||
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| Segment data or a segment header beyond the end of the file | Truncation limitation; checksum and SHA-256 `unavailable`; coverage `unknown` |
|
||||
| File ends before the checksum or the appended digest | That status is `unavailable`, with a limitation; coverage `unknown`, since a signature sector could follow |
|
||||
| Checksum or SHA-256 mismatch | `invalid`, with a limitation; coverage is unchanged |
|
||||
| Erased flash after the image that runs past the three slots | Described; no limitation |
|
||||
| Erased flash that ends before the three slots are complete | Limitation; coverage `unknown`, since a signed image cut there would have lost its sector |
|
||||
| A signature sector the file cuts short | Limitation; coverage `unknown` |
|
||||
| Any other bytes after the image | Ranges in `undescribed_trailing`, a limitation, and coverage `unknown` |
|
||||
| Segment length that is not a multiple of 4 | Limitation: ESP-IDF rejects such an image |
|
||||
| Segment of 16 MiB or more, except on chips with 32-bit cache addresses | Limitation: ESP-IDF rejects such an image |
|
||||
|
||||
ESP32-S3, ESP32-P4, ESP32-C5, ESP32-C61, ESP32-H4 and ESP32-S31 map flash
|
||||
through 32-bit cache addresses (`SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP`), so
|
||||
ESP-IDF sets no 16 MiB segment limit for them. For an unknown chip the limit
|
||||
is not applied.
|
||||
|
||||
Undescribed bytes include other flash contents such as an app partition's
|
||||
stale data, a Secure Boot v1 signature, and the flash segments that esptool
|
||||
`--ram-only-header` writes after the checksum without counting them. REA
|
||||
reports their ranges and does not guess their structure. In the padding, in a
|
||||
sector without a valid block, in the sector's slack and after the sector, the
|
||||
first byte that is not erased starts a range to the end of that region. A
|
||||
slot that is neither a block nor erased is reported whole. Adjacent ranges
|
||||
are merged.
|
||||
|
||||
A whole-flash dump of a chip whose bootloader is at offset 0, such as
|
||||
ESP32-C3 or ESP32-S3, is recognized as that bootloader image; the partition
|
||||
table, apps and data follow as undescribed bytes.
|
||||
|
||||
## Limits
|
||||
|
||||
An image has at most 16 segments and 3 signature blocks. Decoding reads each
|
||||
byte once and retains only fixed-size fields. It reads through erased flash to
|
||||
find the first byte that is not erased, and stops there. There is no
|
||||
file-size limit.
|
||||
|
||||
## Analyzing a segment
|
||||
|
||||
Inventory does not disassemble code or build a memory map. `open_binary`
|
||||
admits neither RISC-V nor Xtensa as a raw-binary architecture, so a segment
|
||||
cannot yet be opened as a raw image. Each segment's `source_location` and
|
||||
`load_addr` give the file offset and address to map it at by hand, for
|
||||
example with the Rizin tool's `om` command.
|
||||
|
||||
## Verification
|
||||
|
||||
Synthetic fixtures with computed checksums, digests and CRCs cover
|
||||
recognition, ESP8266 layouts, the ESP32, ESP32-C3, ESP32-C6 and ESP32-P4
|
||||
memory maps, truncation at each structure, integrity mismatches, erased and
|
||||
undescribed trailing bytes, signature slots including damaged and unknown
|
||||
layouts, and the refusals. CLI and stdio MCP tests exercise the same artifact
|
||||
provider and advertised schemas.
|
||||
|
||||
The optional real lane builds ELF files from source, converts them with
|
||||
esptool and compares REA's facts with `esptool image-info`:
|
||||
|
||||
```sh
|
||||
REA_RISCV_CLANG=/path/to/clang REA_RISCV_LLD=/path/to/ld.lld \
|
||||
REA_ESPTOOL_PYTHON=/path/to/python-with-esptool \
|
||||
npm run verify:esp-images
|
||||
```
|
||||
|
||||
It needs a Clang with the RISC-V target, `ld.lld` and a Python that can run
|
||||
`esptool` and `espsecure`. It checks each tool before building anything and
|
||||
names the variable to set when one is missing, and it warns when esptool is
|
||||
not v5.6.0, the version whose sources the layout facts cite. It builds an
|
||||
ESP32-C3 app, the same app with `--dont-append-digest`, `--secure-pad-v2`,
|
||||
`--ram-only-header` and `--pad-to-size`, a bootloader, and ESP8266 v1 and v3
|
||||
images. It then checks:
|
||||
|
||||
- entry point, chip ID, each segment's length, address and header offset,
|
||||
checksum, digest and descriptor fields against `image-info`;
|
||||
- each segment's classification in the app, its variants and the
|
||||
bootloader, whose linker scripts fix every section's region, including the
|
||||
`not-loaded` padding that `--secure-pad-v2` adds;
|
||||
- after signing with RSA-3072 and appending ECDSA P-256 and P-384 blocks,
|
||||
each block's `public_key_sha256` against espsecure `signature-info-v2`,
|
||||
and that its recorded digest matches;
|
||||
- extraction of the app and the signed image: each segment file equals the
|
||||
bytes after esptool's segment header offset, each signature block equals
|
||||
its slot in the sector espsecure appended, and the source's SHA-256 is
|
||||
unchanged and equals the reported `root_sha256`;
|
||||
- the `--pad-to-size` erased tail is described; the `--ram-only-header`
|
||||
flash segments are undescribed;
|
||||
- a flipped checksum, a flipped digest byte, a truncated segment (where
|
||||
`image-info` stops with "End of file reading segment"), and both ESP8266
|
||||
refusals.
|
||||
|
||||
`REA_XTENSA_ESP32_GCC` adds an ESP32 (Xtensa) app built with Espressif's
|
||||
`xtensa-esp32-elf-gcc`. Without it the report marks that image as skipped.
|
||||
|
||||
Each command runs as a process tree owned by the shared verifier command
|
||||
owner, so a timeout also stops the linker or assembler a compiler driver
|
||||
starts. The lane removes its workspace only after every tree has stopped and
|
||||
keeps it when that cleanup cannot be confirmed.
|
||||
|
||||
The lane ran on macOS arm64 with Node 24.22.1, Homebrew Clang and LLD 21.1.8,
|
||||
and `xtensa-esp32-elf-gcc` 14.2.0 (crosstool-NG esp-14.2.0_20251107), once
|
||||
with esptool and espsecure v5.6.0 and once with 4.12.0. All checks passed for
|
||||
all 13 images in both runs. With v5.6.0 the complete run, including the builds
|
||||
and every esptool call, took 21.7 s elapsed, 16.9 s user CPU and 6.1 s system
|
||||
CPU under `/usr/bin/time -l` with warm caches. The largest single process
|
||||
peaked at a 253 MiB resident set; the combined peak of all processes was not
|
||||
measured.
|
||||
|
||||
The lane does not establish:
|
||||
|
||||
- the other chips: only ESP32-C3 (RISC-V) and ESP32 (Xtensa) images come
|
||||
from a real producer; the other rows of the chip table are checked against
|
||||
the ESP-IDF v6.1 headers by reading them;
|
||||
- images from a real ESP-IDF project build, an OTA download or a device's
|
||||
flash, none of which it inspects;
|
||||
- that a signature is valid: it compares digests, and nothing verifies a
|
||||
signature.
|
||||
|
||||
It does not run in CI.
|
||||
@@ -80,8 +80,10 @@ without bytecode text or duplicated raw stdout:
|
||||
}
|
||||
```
|
||||
|
||||
The result is distinct derived Evidence linked to its complete parent. Its
|
||||
`normalized_result.summary` preserves every producer-returned selector, decoded
|
||||
The result is distinct view Evidence linked to its complete parent. Like the
|
||||
parent, it has `confidence: inferred`; projection never strengthens inferred
|
||||
candidates. Its `normalized_result.summary` preserves every producer-returned
|
||||
selector, decoded
|
||||
byte offset, dispatch, argument/mutability string including null, carrier/decoded
|
||||
identities, original limitations and explicit unknowns. Payload `evidence_kind`
|
||||
remains `inferred`. It preserves stderr/truncation and records stdout text length.
|
||||
|
||||
@@ -82,6 +82,11 @@ Published file `relative_path` preserves producer spelling for lineage; `path`
|
||||
uses the writer's actual normalized filename. An extracted filename that cannot
|
||||
be represented losslessly as UTF-8 fails publication explicitly with its raw
|
||||
name bytes in hexadecimal instead of silently omitting the entry.
|
||||
Unpublished symlinks retain the extracted tree's target bytes in lowercase
|
||||
`link_target_hex`; `link_target` is null when those bytes are not valid UTF-8.
|
||||
Older retained Evidence may omit the hexadecimal field. Unblob may have rewritten
|
||||
the target before REA observed it, so these bytes are not necessarily those stored
|
||||
in the firmware image.
|
||||
|
||||
## CLI and MCP
|
||||
|
||||
@@ -286,6 +291,15 @@ REA_FIRMWARE_VERIFY_GHIDRA=1 npm run verify:firmware
|
||||
generated gzip/USTAR/ext4 with a Linux x64 ELF child; SquashFS, UBIFS, proprietary
|
||||
firmware, other hosts and architectures remain unverified.
|
||||
|
||||
## Inspect ESP images
|
||||
|
||||
Use `inspect-artifact` / `inspect_artifact` on an ESP32-family app or
|
||||
bootloader image, such as an OTA download or app partition, for its chip,
|
||||
classified segments, checksum and SHA-256 results, descriptor and Secure Boot
|
||||
v2 signature blocks. `extract-artifact` / `extract_artifact` writes one file
|
||||
per segment and signature block. Reading is portable and needs no external
|
||||
tool. See [ESP images](esp-image.md).
|
||||
|
||||
## Inspect extracted devicetrees
|
||||
|
||||
Use [`inspect_devicetree`](devicetree.md) / `rea inspect-devicetree` on an
|
||||
@@ -308,9 +322,17 @@ portable and requires no external tool. See
|
||||
The root facts record the 64-byte header (architecture, OS, type, and
|
||||
compression as raw values and names, load and entry addresses, image name,
|
||||
and timestamp) with the header and data CRC32 verified; the stored payload
|
||||
is extractable as `payload.bin`, and multi-file images additionally expose
|
||||
each sub-image as `image-<n>.bin` from the stored size table. Declared
|
||||
is extractable as `payload.bin`, and multi-file and script images additionally
|
||||
expose each sub-image as `image-<n>.bin` from the stored size table. Declared
|
||||
addresses are facts from the header, not proven entry points, and compressed
|
||||
payloads stay as stored. Intel HEX/S-record and FIT images are separate
|
||||
readers and are not covered here. See [U-Boot legacy uImage](uimage.md) for
|
||||
component padding, preserved names, resource policies and verification scope.
|
||||
|
||||
## Inspect U-Boot FIT images
|
||||
|
||||
Use `inspect-artifact` / `inspect_artifact` on a U-Boot FIT (`.itb`) for its
|
||||
images, declared load and entry addresses, configurations and verified hashes,
|
||||
then `extract-artifact` / `extract_artifact` for one raw file per image.
|
||||
Decoding is portable and requires no external tool. See
|
||||
[U-Boot FIT images](fit-images.md).
|
||||
@@ -0,0 +1,172 @@
|
||||
# U-Boot FIT images
|
||||
|
||||
REA inventories U-Boot Flattened Image Tree (FIT, `.itb`) files through
|
||||
`inspect-artifact` / `inspect_artifact`, and materializes the stored bytes of
|
||||
each image through `extract-artifact` / `extract_artifact`. Decoding is static
|
||||
and needs no external tool.
|
||||
|
||||
```sh
|
||||
rea inspect-artifact ./boot.itb --json
|
||||
rea inspect-artifact ./boot.itb --detail summary --evidence_output evidence.json --json
|
||||
rea extract-artifact ./boot.itb --json
|
||||
```
|
||||
|
||||
For MCP, open the file with `open_binary`, then call `inspect_artifact`. Summary
|
||||
delivery retains the complete Evidence; use `parent_evidence_id` with
|
||||
`inspect_analysis_view` to read selected images and fields. `extract_artifact`
|
||||
returns a fresh `output_root` containing one raw file per image. FIT summaries
|
||||
use the current projection identity; there is no pre-coverage FIT summary variant.
|
||||
|
||||
## Recognition
|
||||
|
||||
A FIT is a flattened devicetree (FDT v16 or v17) with a top-level `/images`
|
||||
node. Recognition walks the structure block within the first 4 KiB of the file
|
||||
only; the file name does not matter. A devicetree whose `/images` node begins
|
||||
after 4 KiB, a devicetree without `/images`, and any other FDT version stay on
|
||||
the plain devicetree route: `open_binary` refuses them and
|
||||
[`inspect_devicetree`](devicetree.md) still parses them. A U-Boot control DTB
|
||||
that contains `/images` is treated as a FIT. The container format is `fit`.
|
||||
|
||||
Recognition is a probe. The complete devicetree parse decides, so a file whose
|
||||
prefix declares `/images` but whose structure is malformed fails as a
|
||||
malformed FIT rather than falling back to plain classification.
|
||||
|
||||
## Images and metadata
|
||||
|
||||
Each child of `/images` is one inventory entry named `images/<unit-name>.bin`,
|
||||
listed in devicetree order. Its bytes come from exactly one data source:
|
||||
|
||||
| Source | Stored bytes |
|
||||
| --------------- | --------------------------------------------------------------------------------------- |
|
||||
| `data` | The embedded property value |
|
||||
| `data-offset` | `data-size` bytes at `data-offset` past the devicetree end, aligned to 4 (`mkimage -E`) |
|
||||
| `data-position` | `data-size` bytes at `data-position` from the start of the file (`mkimage -p`) |
|
||||
|
||||
`data-position` is read as U-Boot reads it: an offset from the start of the
|
||||
FIT, not a machine address.
|
||||
|
||||
Image `format_metadata` (`fit-image`) records `index`, `name`, `description`,
|
||||
`type`, `arch`, `os`, `compression`, `load` and `entry`, the `data_source`,
|
||||
the raw `declared_offset` for external data, `image_data` (the shared-data
|
||||
link), `cipher_present`, `cipher_algo`, `hash_algorithms`, `hashes_verified`,
|
||||
`hashes_unverified`, `signature_count`, `signatures_unreadable` and
|
||||
`signature_algorithms`. Algorithm lists are arrays. Nullable declaration fields
|
||||
are absent unless named in `unreadable_fields`, which records parsing failures
|
||||
per field. Hash or signature warnings do not make unrelated declarations unknown.
|
||||
`load` and `entry` fold one or two 32-bit cells into a lowercase
|
||||
`0x…` value, as U-Boot does, independent of `#address-cells`.
|
||||
|
||||
Root `format_metadata` (`fit`) records `fdt_version`, `fdt_totalsize`,
|
||||
`external_data_base` (the aligned devicetree end), the root `description`,
|
||||
`timestamp` (seconds since 1970) and `address_cells`, plus
|
||||
`default_configuration` and `configurations`. A missing description or
|
||||
timestamp is `null`.
|
||||
|
||||
Image bytes are reported as stored. Compressed images are not decompressed and
|
||||
ciphered images are not decrypted: entries report `encrypted: false` and the
|
||||
cipher declaration in `cipher_present` and algorithm in `cipher_algo`. A missing
|
||||
or malformed algorithm stays `null`; it does not establish unciphered bytes.
|
||||
Embedded `image-data` links require byte-identical stored properties; external
|
||||
links require matching physical ranges.
|
||||
|
||||
The extracted file holds the stored bytes. Direct-analysis suggestions require
|
||||
`compression: "none"` and `cipher_present: false`.
|
||||
|
||||
## Hashes and signatures
|
||||
|
||||
Hash subnodes are children whose name starts with `hash`. Inventory verifies
|
||||
`crc32` (4 bytes, big-endian), `md5`, `sha1`, `sha256`, `sha384` and `sha512`
|
||||
over the stored bytes, the same bytes mkimage hashed after any ciphering. All
|
||||
hashes of an image are computed in one streamed pass while the inventory is
|
||||
prepared, so a mismatch fails the whole inventory, naming the image, hash
|
||||
node, algorithm, and the declared and computed values. A supported algorithm
|
||||
whose value has the wrong length also fails.
|
||||
|
||||
Other algorithms such as `crc16-ccitt`, `crc8` or `sm3_256`, a hash without a
|
||||
readable `algo`, and a hash without a `value` are not verified; each is
|
||||
counted in `hashes_unverified` and reported as an image limitation.
|
||||
|
||||
Signature subnodes (names starting with `signature`) on images and
|
||||
configurations retain the total declaration count, readable algorithms and
|
||||
`signatures_unreadable`. Missing or malformed algorithms carry source limitations
|
||||
so unknown declarations remain distinguishable from absence. Signatures are never
|
||||
verified.
|
||||
|
||||
## Configurations
|
||||
|
||||
`/configurations` is optional. Each child records its `name`, `description`,
|
||||
and the image references `kernel`, `firmware`, `fdt` (base plus overlays),
|
||||
`ramdisk` and `loadables`, always as lists, plus its signature algorithms.
|
||||
`compatible`, `fpga`, `script`, `cmdline` and `load-only` are not reported. A
|
||||
reference to a name that is not an `/images` child, and a `default` that names
|
||||
no configuration, are reported as limitations and kept as declared. Each
|
||||
configuration carries `unresolved_reference_count`; dangling references share one
|
||||
configuration-level diagnostic while every original reference remains available.
|
||||
|
||||
## Facts, limitations and failures
|
||||
|
||||
| Situation | Outcome |
|
||||
| ---------------------------------------------------------------------------------------------- | ------------------------------------ |
|
||||
| Malformed devicetree, truncated header, `totalsize` past the end of the file | Fails as malformed |
|
||||
| No data source, more than one data source, external data without `data-size` | Fails as malformed |
|
||||
| `data-offset`, `data-position` or `data-size` not one 32-bit cell, `image-data` not one string | Fails as malformed |
|
||||
| External data outside the file, overlapping the devicetree or another image | Fails as malformed |
|
||||
| Two images with an identical external range linked by `image-data` | Accepted as shared data |
|
||||
| A dangling, chained or mismatched `image-data` link | Fails as malformed |
|
||||
| Hash mismatch, or a supported hash value with the wrong length | Fails integrity |
|
||||
| Unsupported, algorithm-less or value-less hashes | Unverified, reported as a limitation |
|
||||
| Malformed `description`, `type`, `arch`, `os`, `compression`, `load`, `entry` or `timestamp` | `null`, reported as a limitation |
|
||||
| Dangling configuration reference, missing default configuration | Reported as a limitation |
|
||||
|
||||
Failures apply to the whole file and return no partial inventory.
|
||||
|
||||
## Limits
|
||||
|
||||
The devicetree, including any embedded image data, must be at most 16 MiB; a
|
||||
larger `totalsize` fails as a memory limit. Store large images externally
|
||||
(`mkimage -E`): external data of any size is streamed from the file and never
|
||||
loaded into memory. A FIT may declare at most 1,024 images and 1,024
|
||||
configurations, and an image at most 8 hash nodes; the devicetree parser's
|
||||
node, property and depth bounds also apply. The sum of declared image sizes
|
||||
is bounded by the shared archive expansion budget. These are fixed resource
|
||||
bounds with no runtime override. Configurable ceilings are tracked in
|
||||
[#6176](https://github.com/morluto/rea/issues/6176).
|
||||
|
||||
## Analyzing an image
|
||||
|
||||
Inventory does not execute anything, and `load` and `entry` are declarations.
|
||||
After extraction:
|
||||
|
||||
- inspect `flat_dt` images with [`inspect_devicetree`](devicetree.md);
|
||||
- open an uncompressed image with `open_binary` using format `raw-binary`, an
|
||||
architecture matching its declared `arch`, and `entry_point` set to its
|
||||
declared `load` address; raw-binary maps file offset 0 and seeds analysis at
|
||||
`entry_point`. Automatic suggestions require nonempty bytes, an admitted
|
||||
architecture/address/extent, and a declared entry that is absent or equal to
|
||||
load. Distinct or unreadable entry declarations remain in Evidence without
|
||||
a raw-loader suggestion, since this loader cannot represent separate mapping
|
||||
and analysis entry addresses.
|
||||
|
||||
## Comparison
|
||||
|
||||
Artifact comparison reports changes to an image's payload interpretation,
|
||||
including load and entry declarations. Equivalent external offset forms and
|
||||
inventory positions leave those declarations unchanged. Unavailable
|
||||
interpretations remain unknown, while independently known changes survive.
|
||||
|
||||
## Verification
|
||||
|
||||
Synthetic fixtures with computed hashes cover embedded, `data-offset` and
|
||||
`data-position` layouts, shared data, overlap and bounds failures, every
|
||||
verified hash algorithm, configurations, resource limits, inventory,
|
||||
extraction and reader lifecycle. CLI and stdio MCP tests exercise the same
|
||||
artifact provider and advertised schemas. Real U-Boot `mkimage` 2023.01 output
|
||||
has also been verified for embedded, `-E -B 0x200`, and
|
||||
`-E -p 0x2000 -B 0x200` layouts, with byte-exact extraction checked against
|
||||
`dumpimage`. The OpenWrt 24.10.3 ABT ASR3000 recovery FIT was checked against
|
||||
`mkimage`, `fdtget` and `dumpimage`, including its kernel, initrd and devicetree.
|
||||
No image was executed.
|
||||
|
||||
For small containers, complete delivery avoids an additional view request.
|
||||
Choose summary and selected views when the omitted facts justify that extra
|
||||
request; summary delivery does not reduce the underlying inventory work.
|
||||
+1
-1
@@ -119,7 +119,7 @@ installation's language catalog, the same catalog REA uses to admit
|
||||
and still succeeds on the stock checks.
|
||||
|
||||
The ELF lane (`npm run verify:ghidra:ppc`) is separate. See
|
||||
[PowerPC ELF analysis through Ghidra](/ghidra-ppc).
|
||||
[PowerPC ELF analysis through Ghidra](ghidra-ppc.md).
|
||||
|
||||
## Not supported yet
|
||||
|
||||
|
||||
@@ -299,7 +299,7 @@ host/provider acceptance run with only the host compiler.
|
||||
`--dll`. These static fixtures contain source-owned encoded instructions; they
|
||||
are not compiler-produced programs. See the [Windows verification scope](windows-ghidra-p0.md#native-authority-and-target-identity)
|
||||
for real-provider coverage and exclusions.
|
||||
These lanes check all 26 read-only operations, target/snapshot/import SHA-256 linkage,
|
||||
These lanes check all 27 read-only operations, target/snapshot/import SHA-256 linkage,
|
||||
and project, endpoint, process, and runtime cleanup. The independent native
|
||||
lane checks DACLs, handle admission, cancellation, and Job Object lifecycle.
|
||||
`npm run verify:ghidra:windows:package` packs and installs REA into an isolated
|
||||
|
||||
@@ -220,6 +220,12 @@ For guided registration, set `REA_IDA_MCP_CONFIG` before `rea setup --client <cl
|
||||
|
||||
## Coverage and evidence
|
||||
|
||||
REA admits x86, x86_64, arm and arm64 executables through IDA. Every other CPU
|
||||
family, including families that REA recognizes later, is refused until REA
|
||||
admits it explicitly. Raw-binary and GameCube DOL targets are refused; open
|
||||
them with Ghidra. Admission is not verification: the real workflows under
|
||||
[Verification](#verification) cover x86_64 and arm64 only.
|
||||
|
||||
All profiles support procedure/string inventory and literal or regex search, procedure resolution, pseudocode, assembly, raw function instructions, resolved callees, incoming address references, and a function dossier. Inventories and modern pseudocode/assembly follow upstream pagination. Upstream limits on modern xrefs and callees are retained as explicit truncation limitations. In the modern headless profile, targets that are not proven x86-only use processor-neutral `callgraph` edges instead of the x86 instruction checks in upstream `callees` (mrexodia/ida-pro-mcp#549). REA requests depth zero: the pinned upstream emits the root's outgoing edges without scanning child functions, then REA batches function-name lookup for those addresses. The graph covers recognized function destinations only; imports and other non-function targets remain unknown. A server without `callgraph` returns an empty relationship list with an explicit coverage limitation. Graph and path workflows retain those limitations alongside observed edges. A failed or inconsistent graph reply remains an error. A transport-level truncated preview is rejected rather than reported as complete evidence; the error preserves upstream retrieval guidance.
|
||||
|
||||
All profiles expose `list_documents` as the single target admitted for the session. Attached mode verifies its digest against IDA metadata before returning it; headless mode binds the digest-checked private input. `inspect_address_context`, `trace_feature`, and `binary_overview` can therefore resolve that identity without upstream document-listing tools. Segment enumeration is optional: when the selected profile cannot provide it, `binary_overview` still returns document and procedure/string counts and omits `segments` and `segment_count`; omission means unobserved, not empty. The modern headless profile also supports `resolve_containing_procedure`. An address resolves through upstream `lookup_funcs` to the canonical entry of the function that contains it; the body stays unavailable like other IDA identities. When no function contains it, REA reads the database-scoped minimal `survey_binary` and reports `not_in_procedure` for an address inside one of its segments (ends are exclusive) and `outside_segments` otherwise. A missing, truncated or inconsistent survey fails the read instead of guessing a reason. `trace_feature` marks a trace truncated, with a residual unknown for that address, when upstream caps the references it returned. Attached profiles do not declare address containment resolution.
|
||||
|
||||
@@ -528,6 +528,12 @@ message names one reason:
|
||||
| `image-range-overlap` | Two images claim the same type definitions. |
|
||||
| `invalid-string` | A name index is outside the strings section, its string is unterminated, or it is not valid UTF-8. |
|
||||
|
||||
Record extents are checked for the decoded images, types, methods, fields,
|
||||
properties, events, parameters, string literals, nested types, generic
|
||||
containers, generic parameters and interface offsets. Other header sections
|
||||
are checked for file bounds and overlap; their internal record layouts are not
|
||||
decoded or validated by this inventory.
|
||||
|
||||
A version field that disagrees with the file's layout, for example a version
|
||||
39 file relabeled as 29, usually surfaces as `unexpected-header-size` or
|
||||
`record-size-mismatch`.
|
||||
|
||||
+14
-14
@@ -47,20 +47,20 @@ For runtime instrumentation, see the [Frida guide](./frida-instrumentation.md).
|
||||
|
||||
## Choose a guide
|
||||
|
||||
| Task | Guides |
|
||||
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Identify a desktop installation | [Runtime candidates, evidence and follow-up files](desktop-applications.md) |
|
||||
| Inspect native functions, references, or types | [Native binaries](native-investigation.md), [Go metadata](go-binaries.md), [Rust dependencies](rust-binaries.md), [CPython pyc files](python-pyc.md), [PE certificates](pe-certificates.md), [PE imports](pe-imports.md), [PE TLS/load config](pe-load-config.md), [ELF notes](elf-notes.md), [Linux kernel modules](kernel-modules.md), [Apple IPS](apple-ips.md), [Erlang BEAM](erlang-beam.md), [offline ELF layout](binary-diagnostics.md), [recorded crashes](recorded-crashes.md) |
|
||||
| Inspect native functions, references, or types | [Native binaries](native-investigation.md), [Go metadata](go-binaries.md), [Rust dependencies](rust-binaries.md), [CPython pyc files](python-pyc.md), [PE certificates](pe-certificates.md), [PE imports](pe-imports.md), [PE TLS/load config](pe-load-config.md), [ELF notes](elf-notes.md), [Apple IPS](apple-ips.md), [Erlang BEAM](erlang-beam.md), [offline ELF layout](binary-diagnostics.md), [recorded crashes](recorded-crashes.md) |
|
||||
| Select a native provider or import format | [Ghidra semantics](ghidra-provider.md), [Windows](windows-ghidra-p0.md), [DOS](ghidra-dos.md), [raw bytes](raw-binary.md), [GameCube DOL](ghidra-dol.md), [MIPS](ghidra-mips.md), [PSP](ghidra-psp.md), [NativeAOT](ghidra-nativeaot.md), [IDA](ida-provider.md), [Kuna](kuna-provider.md), [JEB](jeb-analysis.md) |
|
||||
| Analyze JavaScript or Electron artifacts | [Static analysis](javascript-artifact-reconstruction.md), [tracing and comparisons](javascript-application-workflows.md), [application graph](javascript-application-graph.md), [source recovery](javascript-recovery.md) |
|
||||
| Compare static JavaScript with runtime observations | [Runtime attribution](javascript-runtime-observation.md), [reconciliation](javascript-runtime-reconciliation.md), [Electron observation](electron-observation.md), [Electron fuses](electron-fuses.md) |
|
||||
| Inspect assemblies, packages, or firmware | [Godot PCK](godot-pck.md), [UnityFS](unityfs.md), [U-Boot uImage](uimage.md), [.NET](managed-code-analysis.md), [Python packages](python-packaged-applications.md), [Android](android-analysis.md), [APK signatures](apk-signature.md), [Apktool resources](apktool-resource-analysis.md), [ADB acquisition](adb-device-analysis.md), [Apple](apple-application-analysis.md), [Harmony](harmony-analysis.md), [firmware](firmware-analysis.md), [WASM](wasm-artifacts.md), [EVM](evm-bytecode.md) |
|
||||
| Observe or compare a browser scenario | [CDP observation](browser-observation.md), [scenarios](browser-scenario-contract.md), [runtime evidence](web-runtime.md), [historical captures](web-network-captures.md) |
|
||||
| Serve recorded behavior as an agent environment | [Agent environments](agent-environments.md) |
|
||||
| Trace captured website source | [Source locations](web-source-location.md), [module traces](website-module-trace.md), [script export](website-script-export.md) |
|
||||
| Capture and compare a command | [Process capture](process-capture.md) |
|
||||
| Use CLI/MCP and retain evidence | [CLI](cli.md), [MCP contracts](mcp-contracts.md), [agent prompts](mcp-prompts.md), [obligation ledgers](reconstruction-obligation-ledgers.md) |
|
||||
| Task | Guides |
|
||||
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Identify a desktop installation | [Runtime candidates, evidence and follow-up files](desktop-applications.md) |
|
||||
| Inspect native functions, references, or types | [Native binaries](native-investigation.md), [Go metadata](go-binaries.md), [Rust dependencies](rust-binaries.md), [CPython pyc files](python-pyc.md), [PE certificates](pe-certificates.md), [PE imports](pe-imports.md), [PE TLS/load config](pe-load-config.md), [ELF notes](elf-notes.md), [Linux kernel modules](kernel-modules.md), [Apple IPS](apple-ips.md), [Erlang BEAM](erlang-beam.md), [offline ELF layout](binary-diagnostics.md), [recorded crashes](recorded-crashes.md) |
|
||||
| Inspect native functions, references, or types | [Native binaries](native-investigation.md), [Go metadata](go-binaries.md), [Rust dependencies](rust-binaries.md), [CPython pyc files](python-pyc.md), [PE certificates](pe-certificates.md), [PE imports](pe-imports.md), [PE TLS/load config](pe-load-config.md), [ELF notes](elf-notes.md), [Apple IPS](apple-ips.md), [Erlang BEAM](erlang-beam.md), [offline ELF layout](binary-diagnostics.md), [recorded crashes](recorded-crashes.md) |
|
||||
| Select a native provider or import format | [Ghidra semantics](ghidra-provider.md), [Windows](windows-ghidra-p0.md), [DOS](ghidra-dos.md), [raw bytes](raw-binary.md), [GameCube DOL](ghidra-dol.md), [MIPS](ghidra-mips.md), [PSP](ghidra-psp.md), [NativeAOT](ghidra-nativeaot.md), [IDA](ida-provider.md), [Kuna](kuna-provider.md), [JEB](jeb-analysis.md) |
|
||||
| Analyze JavaScript or Electron artifacts | [Static analysis](javascript-artifact-reconstruction.md), [tracing and comparisons](javascript-application-workflows.md), [application graph](javascript-application-graph.md), [source recovery](javascript-recovery.md) |
|
||||
| Compare static JavaScript with runtime observations | [Runtime attribution](javascript-runtime-observation.md), [reconciliation](javascript-runtime-reconciliation.md), [Electron observation](electron-observation.md), [Electron fuses](electron-fuses.md) |
|
||||
| Inspect assemblies, packages, or firmware | [Godot PCK](godot-pck.md), [UnityFS](unityfs.md), [U-Boot uImage](uimage.md), [.NET](managed-code-analysis.md), [Python packages](python-packaged-applications.md), [Android](android-analysis.md), [APK signatures](apk-signature.md), [Apktool resources](apktool-resource-analysis.md), [ADB acquisition](adb-device-analysis.md), [Apple](apple-application-analysis.md), [Harmony](harmony-analysis.md), [firmware](firmware-analysis.md), [ESP images](esp-image.md), [WASM](wasm-artifacts.md), [EVM](evm-bytecode.md) |
|
||||
| Observe or compare a browser scenario | [CDP observation](browser-observation.md), [scenarios](browser-scenario-contract.md), [runtime evidence](web-runtime.md), [historical captures](web-network-captures.md) |
|
||||
| Serve recorded behavior as an agent environment | [Agent environments](agent-environments.md) |
|
||||
| Trace captured website source | [Source locations](web-source-location.md), [module traces](website-module-trace.md), [script export](website-script-export.md) |
|
||||
| Capture and compare a command | [Process capture](process-capture.md) |
|
||||
| Use CLI/MCP and retain evidence | [CLI](cli.md), [MCP contracts](mcp-contracts.md), [agent prompts](mcp-prompts.md), [obligation ledgers](reconstruction-obligation-ledgers.md) |
|
||||
|
||||
For development, use [testing](testing.md), [client verification](client-verification.md),
|
||||
[tool design](tool-design.md), [admission limits and recovery](design/limits-and-recovery.md),
|
||||
|
||||
+44
-4
@@ -381,7 +381,7 @@ Select the part you want to check:
|
||||
| Task | Readiness check |
|
||||
| ----------------------------------- | ------------------------------------------------------------------------ |
|
||||
| Static JavaScript/Electron analysis | Run `rea analyze-javascript-application PATH --json` directly. |
|
||||
| One analysis engine | `rea doctor --provider ghidra --json` (or `hopper`, `ida`) |
|
||||
| One analysis engine | `rea doctor --provider ghidra --json` (or `hopper`, `ida`, `kuna`) |
|
||||
| One agent registration | `rea doctor --client codex --json` (see [client IDs](#supported-agents)) |
|
||||
| Installed workflow instructions | `rea doctor --skill --json` |
|
||||
|
||||
@@ -928,7 +928,12 @@ selected only when it is the arm64 family's only candidate. REA checks the
|
||||
entire source's SHA-256 while copying the slice; source identity and reported
|
||||
offsets still refer to the original container. Any other ambiguous architecture
|
||||
subtype requires an explicitly extracted thin image; REA does not guess.
|
||||
Configured loader arguments remain explicit overrides.
|
||||
Set `HOPPER_LOADER_ARGS_JSON` in REA's launch environment to a JSON array of
|
||||
strings to override the derived Hopper loader arguments, for example
|
||||
`["-l","Mach-O"]`. Empty string elements are preserved; NUL bytes are not
|
||||
accepted. An omitted setting or empty array uses the derived arguments. `rea
|
||||
setup` forwards an explicitly selected setting to supported registrations;
|
||||
restart the MCP server to apply a change. These arguments are Hopper-specific.
|
||||
FAT64 is distinct from the CPU architecture: FAT32 containers can contain 64-bit
|
||||
executable images. This preparation avoids the Raw Binary loader dialog observed
|
||||
with native FAT64 loading on Hopper 6.1.0-demo.
|
||||
@@ -988,6 +993,14 @@ When Hopper cannot start in CI, run
|
||||
`rea doctor --provider hopper --json` in the failing runner.
|
||||
Structured failures distinguish private-display dependencies, an unsupported
|
||||
demo dialog or build, process-ownership conflicts, and an early lifecycle exit.
|
||||
Once launcher authentication succeeds, an absent first-run dialog is reported as
|
||||
`demo_dialog_absent` rather than a build or publisher rejection. The watcher
|
||||
waits 10 seconds by default. Set `REA_HOPPER_DEMO_DIALOG_TIMEOUT_MS` in the
|
||||
environment that starts REA to a positive decimal integer of milliseconds from
|
||||
1 to 2147483647 when a slower host needs a longer window. An invalid value is
|
||||
`invalid_dialog_timeout`: the error names that setting, shows the rejected
|
||||
value and its source, lists the allowed range, and asks you to correct the
|
||||
setting and restart REA.
|
||||
If a private-display probe times out or is cancelled and its process cleanup
|
||||
fails, REA retains that exact probe owner and reports `cleanup_incomplete`.
|
||||
Session close retries the probe before releasing its cleanup marker; doctor
|
||||
@@ -1020,7 +1033,7 @@ reported as incompatible instead of being admitted from its directory name, and
|
||||
a header that cannot be read or recognized is reported as unknown. REA does not
|
||||
build or install native tools, or change Gatekeeper quarantine settings.
|
||||
|
||||
The adapter exposes 26 read-only operations: fourteen inventory/name/search
|
||||
The adapter exposes 27 read-only operations: fifteen inventory/name/search
|
||||
operations and twelve function-analysis operations. These cover metadata,
|
||||
decompilation, assembly, resolved calls, typed references, xrefs, function
|
||||
dossiers, instructions, recovered data types, measured load mappings, loaded
|
||||
@@ -1404,6 +1417,33 @@ REA passes `-processor`/`-cspec`, checks both against the installation's `.ldefs
|
||||
|
||||
Language definitions must be well-formed XML encoded as UTF-8 or BOM-marked UTF-16, with any encoding declaration matching the bytes. Literal Unicode replacement characters (U+FFFD) are accepted; malformed source bytes are rejected.
|
||||
|
||||
Ghidra imports little-endian ARM ELF files, including Cortex-M
|
||||
(`arm-none-eabi`) firmware, as `ARM:LE:32:v8`. That language defaults to ARM
|
||||
state, and its ELF loader marks code as Thumb only where `$t` mapping symbols
|
||||
or odd function-symbol addresses say so. Cortex-M cores run only Thumb code, so
|
||||
the gap matters mainly for code without those markers, such as stripped images
|
||||
and handlers reached only through the vector table. REA has no M-profile ARM
|
||||
lane. As an unverified interim, select an M-profile language, which decodes in
|
||||
Thumb state by default. For ARMv6-M, ARMv7-M and ARMv7E-M cores:
|
||||
|
||||
```bash
|
||||
export REA_GHIDRA_LANGUAGE_ID="ARM:LE:32:Cortex"
|
||||
```
|
||||
|
||||
For ARMv8-M cores, use `ARM:LE:32:v8-m` instead. REA has not verified either
|
||||
language for Cortex-M analysis. While the variable is set, it applies to every
|
||||
Ghidra import in the REA server:
|
||||
|
||||
- raw-binary, DOS, GameCube DOL and PSP opens are refused, as are opens in
|
||||
lanes that reject a different language, such as RISC-V;
|
||||
- REA asks Ghidra to import everything else in the selected ARM language,
|
||||
including x86, x86-64, arm64, PowerPC and Hexagon ELF files and PE and
|
||||
Mach-O files, because it does not check that the override's processor
|
||||
matches the target.
|
||||
|
||||
Restart REA without the variable before you analyze other targets. A future
|
||||
M-profile lane may refuse it; remove the setting then.
|
||||
|
||||
To seed code that auto-analysis cannot reach (computed jumps, pointers in data):
|
||||
|
||||
```bash
|
||||
@@ -1555,7 +1595,7 @@ On a controlled Windows x64 runner, use
|
||||
`npm run verify:ghidra:windows`. The verifier generates a deterministic native
|
||||
PE fixture from source bytes and requires the Windows native authority before
|
||||
opening the provider. The controls are implemented on main; see the
|
||||
[release boundary](#released-package-and-main). The lane verifies all 26 admitted
|
||||
[release boundary](#released-package-and-main). The lane verifies all 27 admitted
|
||||
read-only operations, digest identity, and runtime cleanup. The separate
|
||||
`verify:ghidra:windows:package` lane checks the packed CLI/MCP boundary with an
|
||||
ordinary user. It requires the built Windows native bundle and an existing
|
||||
|
||||
@@ -161,6 +161,17 @@ reached through `contains` from one of its children only leads further up its
|
||||
containment chain, so a shared asset or artifact root does not pull in its
|
||||
other children.
|
||||
|
||||
When a string seed has no application match and the supplied Evidence has a
|
||||
semantic graph, `semantic_discovery` lists matching retained semantic node
|
||||
labels and direct string call arguments using the same matching mode and case
|
||||
rules. These are candidate starting
|
||||
points, not application trace matches. Its graph coverage and total describe the
|
||||
retained graph; missing or partial source coverage cannot establish absence.
|
||||
Results follow retained node order and default to offset 0 and limit 64. Supply
|
||||
`semantic_page` and follow `next_offset` for further matches. Use a returned
|
||||
`trace_seed` with the same application Evidence and `trace_javascript_semantics`
|
||||
to examine relationships from that node. Other typed seeds do not search labels.
|
||||
|
||||
The result contains the matching basis, complete reachable subgraph, terminal
|
||||
paths, authority summaries, and native handoffs. A handoff binds
|
||||
the exact native artifact digest and requested exports from the application
|
||||
@@ -187,6 +198,10 @@ rereading mutable files. A seed may identify a semantic or application node,
|
||||
literal, function fingerprint, property, endpoint, event, or boundary field.
|
||||
For a recovered parse, coercion, or validation boundary, its field value is the
|
||||
static operation's method name (for example, `Number`).
|
||||
When a recovered boundary call directly supplies a scalar binding, the graph
|
||||
connects the boundary to that binding; unresolved boundary calls remain
|
||||
candidates. A boundary nested inside another expression or compound assignment
|
||||
does not establish a direct result binding.
|
||||
The query declares backward provenance, forward influence, callers, or
|
||||
ownership and can restrict admitted relation kinds. REA returns every matching
|
||||
seed and the complete reachable subgraph; callers do not choose node, relation,
|
||||
@@ -209,6 +224,25 @@ resulting value. Deferred callback bodies do not become inputs to the enclosing
|
||||
assignment. Computed method keys belong to the enclosing callable; parameter
|
||||
defaults and method bodies belong to the method. Uncertain later property reads
|
||||
remain opt-in through `include_ambiguous_dynamic_edges`.
|
||||
|
||||
Binary, logical, unary, template, conditional, and sequence expressions retain
|
||||
`influences` edges from supported immediate inputs to the result, then to a
|
||||
direct declaration, assignment, call argument, or return. These are static
|
||||
dependencies, not aliases or proof that the expression executed; conditional
|
||||
operands and logical-assignment writes carry `conditional: true`. Unsupported
|
||||
operand dependencies, unmodeled receiving containers, dynamic call results,
|
||||
and sequence side effects remain unknown. An applicable
|
||||
unknown makes the trace status `partial` even when a seed was found. Literal
|
||||
operator operands, direct call arguments and directly returned scalar literals
|
||||
can also be seeds. Older graphs that only recorded a call-site literal remain
|
||||
searchable. The offered per-file node capacity also bounds the producer's
|
||||
expression and operand collections before graph projection.
|
||||
Expression nodes and unknowns share the existing per-file graph admission
|
||||
budgets; omitted facts make graph coverage truncated and the trace partial.
|
||||
Consumers that previously treated `found` as compatible with a relevant
|
||||
unknown should handle `partial` and inspect the returned unknowns. Retained
|
||||
graphs without `influences` edges remain readable but do not gain edges until
|
||||
the application is analyzed again.
|
||||
Global timer, `fetch`, `WebSocket`, `JSON.parse`, and coercion calls receive
|
||||
these built-in effects only when the file has no visible possible write to that
|
||||
global, including a computed write through a global object. The check does not
|
||||
@@ -273,7 +307,14 @@ mapped candidate, but structural reachability, semantic influence, runtime
|
||||
observation, and causal proof remain separate claims.
|
||||
|
||||
Semantic literal nodes keep their complete value in `properties.value`; literal
|
||||
queries match that field. String labels use `string literal` when that is
|
||||
queries match that field. Call-site nodes also retain direct scalar arguments in
|
||||
`properties.arguments`, with source argument indexes; literal queries can start
|
||||
at those call sites. These are syntactic facts, not runtime values, and an index
|
||||
after a spread is not necessarily the runtime argument position. Nonliteral
|
||||
arguments and values not representable in JSON are omitted. The primitive byte
|
||||
bound and the worker transfer record ceiling can also omit direct values; the
|
||||
call-site unknown reports the applicable limit. String labels use
|
||||
`string literal` when that is
|
||||
shorter than the complete JSON value. A literal's `identity.role_key` commits
|
||||
its canonical JSON value as `value-sha256:<digest>` when the digest key is
|
||||
shorter; smaller values keep their existing JSON key. This keeps large values
|
||||
|
||||
@@ -560,6 +560,8 @@ alternative object. A traced invocation whose key, API object or world stays
|
||||
unresolved or guarded keeps the call's own unresolved observation.
|
||||
Unknown spreads, reassigned bindings, accessors,
|
||||
dynamic channels and unsupported syntax do not become exact implementations.
|
||||
Literal switch cases retain their selection conditions. Possible fallthrough
|
||||
remains partial; dynamic case expressions remain unknown.
|
||||
This pass neither executes the bundle nor proves that runtime guards pass.
|
||||
An ambiguous or unresolved handler retains its channel registration but does
|
||||
not acquire a path to one arbitrarily selected callback. Unknown factory
|
||||
@@ -642,7 +644,13 @@ identity. This static check does
|
||||
not evaluate arbitrary call side effects or runtime registration. Missing findings
|
||||
do not establish that an application has no Electron boundary usage.
|
||||
|
||||
IPC pairing is an inference, not an observation. A renderer `invoke` pairs only
|
||||
IPC pairing is an inference, not an observation. A main handler registered on an
|
||||
unresolved channel may receive any literal channel, so a compatible renderer send
|
||||
or `invoke` beside it is ambiguous, not unpaired. A wrapper's registration is
|
||||
exempt only when every invocation is a traced direct call supplying a literal
|
||||
channel, each recorded as its own finding. A guarded invocation keeps its
|
||||
predicate on a call path instead, so its channel still competes without pairing.
|
||||
A renderer `invoke` pairs only
|
||||
with one unique `ipcMain.handle`/`handleOnce` candidate on the same exact literal
|
||||
channel; a renderer send pairs only with one unique `ipcMain.on`/`once`/`addListener`
|
||||
candidate. Dynamic channels are never paired, and multiple compatible handlers
|
||||
|
||||
@@ -99,7 +99,9 @@ nodes. REA evaluates compatible static candidates conservatively:
|
||||
content digest can match. Whole-asset digests and reconstructed module-factory source
|
||||
digests remain distinguishable in the reported basis.
|
||||
3. Without captured bytes, one unique mapped artifact path can produce a
|
||||
medium-confidence location match.
|
||||
medium-confidence location match. A proven factory module contained within
|
||||
the located asset is not a competing whole-file location; separate assets
|
||||
and independently plausible modules remain candidates.
|
||||
4. Multiple candidates remain `ambiguous`; no `observed_as` edge is emitted.
|
||||
With captured source and mapped candidates, only mapped content matches
|
||||
qualify; unrelated content matches elsewhere are excluded.
|
||||
|
||||
@@ -40,6 +40,38 @@ inspection is needed; see [selected member inspection](#selected-member-inspecti
|
||||
Compare separate builds with [member comparison](#member-comparison), preserving
|
||||
their paths, digests, and selection scope.
|
||||
|
||||
### Field constant defaults
|
||||
|
||||
`inspect_managed_members` reads field-owned values from the ECMA-335 `Constant`
|
||||
table without loading the assembly. Each selected field's `constant` contains
|
||||
the declaration's row offset, element-type code, blob index and exact `raw_hex`,
|
||||
plus its decoded `element_type` and `value`. For example, an `i4` declaration
|
||||
with bytes `865d0000` returns `23942`.
|
||||
|
||||
Boolean, character, signed/unsigned integers, floating-point, UTF-16 strings
|
||||
and class-null declarations are supported. `i8` and `u8` values are decimal
|
||||
strings to avoid JSON integer precision loss. Floating-point negative zero,
|
||||
NaN and infinities are the strings `-0`, `NaN`, `Infinity` or `-Infinity`;
|
||||
`raw_hex` preserves their original bits. UTF-16 code units, including embedded
|
||||
NULs and unpaired surrogates, are preserved.
|
||||
|
||||
`constant: null` means neither a Constant declaration nor `HasDefault` was
|
||||
observed. Historical Evidence can omit the field entirely; omission does not
|
||||
prove that the artifact has no default. Missing or duplicate declarations,
|
||||
inconsistent flags, malformed values and unsupported element types return
|
||||
`state: "unavailable"`, a limitation and partial coverage while retaining other
|
||||
member facts. This decoding shares the existing metadata representation budget
|
||||
and only decodes blobs for the selected fields.
|
||||
|
||||
Retained `managed-members` field pages can select `fields: ["constant"]` while
|
||||
keeping original field identity and source offsets. These values are metadata
|
||||
declarations, including enum members' encoded underlying constants, not observed
|
||||
runtime state or inferred enum-name mappings. Parameter/property defaults are
|
||||
not exposed by this field-focused reader. Member comparison still covers field
|
||||
names, flags and signatures; it does not compare constant defaults.
|
||||
|
||||
The encoding follows [ECMA-335, Partition II, sections 22.9 and 23.1.16](https://ecma-international.org/publications-and-standards/standards/ecma-335/).
|
||||
|
||||
### Metadata overview and retained rows
|
||||
|
||||
The existing CLI and omitted/complete MCP detail return complete metadata
|
||||
@@ -120,6 +152,50 @@ literal pool's own coverage. Older Evidence that never examined exported types
|
||||
or user strings reports a null count and refuses those pages rather than
|
||||
returning an empty one.
|
||||
|
||||
To find specific retained members without returning their IL anchors, select
|
||||
exact names and defining types, then project columns:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"kind": "retained-evidence",
|
||||
"evidence_id": "<parent_evidence_id>"
|
||||
},
|
||||
"view": {
|
||||
"kind": "managed-members",
|
||||
"collection": "methods",
|
||||
"names": ["ParseNumber", "ParseReadNumber"],
|
||||
"declaring_types": ["Newtonsoft.Json.JsonTextReader"],
|
||||
"fields": ["name", "declaring_type", "signature"],
|
||||
"offset": 0,
|
||||
"limit": 64
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Filters are exact and case-sensitive; lists are alternatives and filters
|
||||
intersect. An empty list matches nothing. Names select `name` in types,
|
||||
exported types, fields, methods and member references; in call edges they select
|
||||
`target_name`, and in field accesses `field_name`. Declaring-type filters select
|
||||
`declaring_type` in fields/methods, `parent_name` in member references,
|
||||
`target_declaring_type` in call edges and `field_declaring_type` in field accesses.
|
||||
Types, exported types and user strings do not accept a declaring-type filter;
|
||||
user strings do not accept a name filter. No display strings are reparsed.
|
||||
|
||||
`fields` accepts only columns of that collection. Omitting it preserves full
|
||||
rows, including method bodies. Selecting `body` explicitly returns the full
|
||||
recorded body and anchors; selecting no columns (`[]`) returns identity fields.
|
||||
Projected or filtered rows add their original `source_index`; tokens and source
|
||||
byte offsets remain, with defining/parent tokens or IL-site endpoints where
|
||||
applicable. The page retains module/MVID, artifact digest, parent Evidence,
|
||||
producer selection and source coverage. Full facts remain in the parent.
|
||||
|
||||
Paging offsets and totals count known matches in original order. `source_count`
|
||||
counts the producer-returned collection; `unresolved_filter_rows` counts rows
|
||||
that could match but lack a requested name/type. Those candidates remain unknown
|
||||
and are excluded from the matched total. Exhausting the known matches does not
|
||||
prove absence among unresolved or unexamined source rows.
|
||||
|
||||
#### CLI summary and saved member rows
|
||||
|
||||
The CLI accepts the same `complete` and `summary` detail choices. Omitted or
|
||||
@@ -167,13 +243,17 @@ authenticates the saved bundle; the full source is retained on disk.
|
||||
|
||||
The canonical parser admits PE/CLI bytes and their metadata/CIL without loading
|
||||
an assembly. It reports observed implementation markers and unavailable facts;
|
||||
it does not unpack .NET single-file hosts or infer a NativeAOT identity from an
|
||||
ordinary native PE. It does not decode IL2CPP; use
|
||||
it does not itself unpack .NET single-file hosts or infer a NativeAOT identity
|
||||
from an ordinary native PE. It does not decode IL2CPP; use
|
||||
[IL2CPP metadata](il2cpp-metadata.md) for the image, type and method names in a
|
||||
Unity `global-metadata.dat`. Inputs without admitted CLI metadata do not
|
||||
become managed assemblies through naming or routing guesses.
|
||||
Inspect separately obtained components explicitly and preserve their identities.
|
||||
|
||||
For ordinary .NET single-file hosts, use the existing artifact tools to
|
||||
[inventory and extract bundle members](dotnet-bundles.md), then inspect the
|
||||
extracted assembly explicitly with the managed tools.
|
||||
|
||||
A valid implementation marker establishes a candidate native boundary, not
|
||||
recovered native semantics or runtime behavior.
|
||||
|
||||
@@ -432,8 +512,18 @@ raw digest stands in. Missing or unreadable TypeDef and TypeRef operands are
|
||||
reported as coverage issues. Invalid NestedClass rows retain their failure
|
||||
reasons and withhold TypeDef signature identities; type names and nesting are
|
||||
parsed once by their shared owner. Each current inspection records
|
||||
`signature_resolution: "type-names-v1"`, even when none of its operands can be
|
||||
resolved. Historical Evidence defaults this attestation to `null`. When either
|
||||
`signature_resolution: "type-names-v2"`, even when none of its operands can be
|
||||
resolved. Version 2 also appends readable names to signature operands, for
|
||||
example `class:7772 (AnalysisJob)`. Coded indexes remain build-local references;
|
||||
names are display text and do not change raw or resolved signature digests.
|
||||
Nested names use `Outer/Inner`. Generic instantiations keep their decoded
|
||||
arguments, for example ``class:9 (System.Collections.Generic.List`1)<string>``;
|
||||
custom modifiers are named too. Valid but unresolved TypeSpecs, invalid scopes,
|
||||
unreadable type names, cycles and nesting beyond the cap keep their raw operand
|
||||
spelling. Invalid or missing metadata coordinates retain the existing malformed
|
||||
signature result and source issue; rendering does not bypass validation.
|
||||
Version 1 Evidence remains readable and compares using the same digest policy.
|
||||
Historical Evidence defaults this attestation to `null`. When either
|
||||
observation predates resolution, both sides compare raw digests, which pair only where type rows agree,
|
||||
and the comparison reports that limitation. The signature is exact whether or
|
||||
not REA decoded it, so undecoded signatures pair by that tuple too, but they
|
||||
|
||||
+128
-20
@@ -26,8 +26,21 @@ can be passed directly to `compare_functions`, and `inspect_artifact` Evidence
|
||||
to `compare_artifacts`. Use `get_evidence_bundle` when the task needs broader
|
||||
retained session history or an explicit bundle for transfer.
|
||||
|
||||
`compare_artifacts` does not need that Evidence sent back. Name each side once
|
||||
with a source that `inspect_analysis_view` also accepts:
|
||||
`{"kind": "retained-evidence", "evidence_id": "<id>"}` for a record retained in
|
||||
this session, or `{"kind": "evidence-file", "path": "/absolute/evidence.json"}`
|
||||
for a saved record or bundle. Add `evidence_id` to select one record from a
|
||||
bundle that holds more than one. Complete inline Evidence is still accepted as
|
||||
the third form. The comparison cites the records that the sources resolve to,
|
||||
so all three forms give the same comparison Evidence. A retained reference that
|
||||
the session cannot resolve is refused with `evidence_integrity_mismatch` and
|
||||
`details.reason: "missing"`.
|
||||
|
||||
`compare_artifacts` can also resolve an artifact summary to its exact retained
|
||||
parent in the session. Supported historical summaries keep their original
|
||||
parent in the session, or from the authenticated bundle containing a file-selected
|
||||
summary. File-local records take precedence over the session lookup. Unrelated
|
||||
records are not retained by the file resolver. Supported historical summaries keep their original
|
||||
Evidence identity and omissions; a missing or mismatched parent is rejected.
|
||||
|
||||
`analyze_function` does not deliver its complete record by default. Without
|
||||
@@ -56,13 +69,14 @@ the same Evidence authentication failures: an admitted source that fails
|
||||
authentication is `evidence_integrity_mismatch`, while an authenticated source with an unsupported
|
||||
workflow role or invalid selector is `invalid_request`.
|
||||
|
||||
Ghidra inventories and function replies use `raw_result: null` when their facts
|
||||
are already preserved in `normalized_result`, limitations, locations and
|
||||
relationship coverage. Distinct overview details, measured load-image
|
||||
observations, file-offset selection roles and database types supplemented with
|
||||
derived metadata keep their upstream representation. Read function results from
|
||||
`normalized_result`; older retained Evidence keeps its original representation
|
||||
and identity.
|
||||
Ghidra inventories, measured load-image observations and function replies use
|
||||
`raw_result: null` when their useful facts are already preserved in
|
||||
`normalized_result`, limitations, locations and relationship coverage. Distinct
|
||||
overview details, file-offset selection roles and database types supplemented
|
||||
with derived metadata keep their upstream representation. Native load-image
|
||||
attestation continues to use the bridge reply locally before Evidence
|
||||
projection. Read function results from `normalized_result`; older retained
|
||||
Evidence keeps its original representation and identity.
|
||||
|
||||
Artifact source-map filename relationships require a unique, identified regular
|
||||
file at the sibling path. A known directory cannot be the mapped file; the map
|
||||
@@ -163,8 +177,13 @@ if retention is unavailable or fails, the diagnostic reports that reason.
|
||||
SDK-generated input validation failures are normalized into the same canonical
|
||||
`invalid_request` text when the bounded diagnostic fits the response budget.
|
||||
The complete field/type diagnostic is preserved when normalization fits the
|
||||
response budget, including request-specific rejected fields and reasons. Oversized
|
||||
SDK diagnostics keep the existing retained-Evidence recovery path. An unknown
|
||||
response budget, including request-specific rejected fields and reasons. Zod
|
||||
input issues retain their field paths and available type and range constraints.
|
||||
SDK diagnostic parts may be distributed between field issues and the main
|
||||
message so each retained explanation appears once.
|
||||
If their conservative projection allowance is exhausted, the response states
|
||||
that field-level detail was omitted and retains the original SDK diagnostic.
|
||||
Oversized SDK diagnostics keep the existing retained-Evidence recovery path. An unknown
|
||||
tool remains an MCP JSON-RPC `-32602` error, but its message directs the caller
|
||||
to `tools/list` and an advertised operation instead of repeating the unknown
|
||||
name.
|
||||
@@ -329,8 +348,11 @@ When `record_unknown` or `update_unknown` commits but its complete reply exceeds
|
||||
the response budget, `details.reported_limits.committed_unknown` identifies the
|
||||
exact unknown ID, committed revision and mutation Evidence IDs. Its retained
|
||||
Evidence reference remains available on the same connection. Export the bundle
|
||||
or page `list_unknowns` to recover the result; do not repeat the committed
|
||||
mutation. A delivery failure does not undo that revision.
|
||||
to recover the result; do not repeat the committed mutation. A single unknown
|
||||
may be too large for a `list_unknowns` page. A delivery failure does not undo
|
||||
that revision. If a list response overflows, retry on the same connection with
|
||||
the same filters and offset and a smaller limit; export if one head still cannot
|
||||
fit.
|
||||
|
||||
For a portable exported bundle, the CLI shares this projection:
|
||||
`rea inspect-evidence-bundle '{"path":"/tmp/evidence.json","detail":"summary","filters":{"operation":"analyze_function"}}' --format json`.
|
||||
@@ -351,6 +373,38 @@ that buffer. It does not raise REA's reserved single-string limit, which is
|
||||
raise that Node ceiling. It does not change analysis coverage or retained
|
||||
content. Ordinary responses keep their existing complete result contract.
|
||||
|
||||
### Input validation resource allowance
|
||||
|
||||
Both HTTP and stdio admit at most 1,024 combined array elements and object
|
||||
members in one tool's arguments by default. The pinned SDK counts them before
|
||||
canonical schema validation or lazy runtime materialization. Oversized calls
|
||||
return a bounded, nonretryable `resource_constraint` with resource `transport`
|
||||
and `reported_limits.max_input_elements`; the full element count is not claimed.
|
||||
No provider or tool handler starts for a refused call. Subsequent calls remain
|
||||
usable.
|
||||
|
||||
Set `REA_MCP_MAX_INPUT_ELEMENTS` to a positive decimal safe integer and restart
|
||||
REA to select another allowance for a larger complete observation or batch.
|
||||
Where a tool supports retained-Evidence or Evidence-file selectors, prefer
|
||||
those selectors to resending large inline records. Admission never truncates
|
||||
the caller's selected input or removes retained Evidence.
|
||||
This is a configurable transport admission policy, not a per-array `maxItems`
|
||||
contract or an exact heap guarantee. Missing required fields can amplify one
|
||||
input element into many issues: on the pinned Evidence array schema,
|
||||
1,024 empty objects produced 16,384 issues and about 26 MiB heapUsed delta
|
||||
before SDK formatting. The default therefore admits at most 1,023 such objects
|
||||
plus the root member, rather than extrapolating the scalar case to larger batches;
|
||||
actual memory also depends on schema branches, runtime state and concurrent
|
||||
work. HTTP's separate request-byte limit and the client's receive limit still
|
||||
apply.
|
||||
|
||||
Canonical schemas and CLI/application analysis semantics remain shared and
|
||||
unchanged. Admitted arguments retain the same values and ordinary validation
|
||||
diagnostics. SDK embedders can select `maxToolInputElements` in the server
|
||||
options; the common REA MCP server supplies the finite default to eager and
|
||||
deferred registrations alike. This does not impose the separate semantic
|
||||
batch-workload limit tracked in issue #5930.
|
||||
|
||||
### Error recovery and deadline ownership
|
||||
|
||||
Initialization instructions and the static JavaScript tool description teach
|
||||
@@ -386,10 +440,12 @@ result's `_meta`, whether the call succeeded or failed:
|
||||
```
|
||||
|
||||
The marker is declared once per tool contract (`returnsTargetContent`) and is
|
||||
on by default: only `export_evidence_bundle` and `record_unknown`, whose
|
||||
results and errors contain only REA session state or caller-supplied values,
|
||||
omit it. Tools whose results or errors can include provider, launcher, or
|
||||
device output stay marked, including `binary_session` (provider failure
|
||||
on by default: `export_evidence_bundle`, `record_unknown`, `search_guidance`,
|
||||
and `read_guidance_section` omit it. The first two contain only REA session
|
||||
state or caller-supplied values; the guidance tools return REA's own installed
|
||||
documentation, not text from an analysis target. Tools whose results or errors
|
||||
can include provider, launcher, or device output stay marked, including
|
||||
`binary_session` (provider failure
|
||||
reasons and availability diagnostics), `close_binary` (provider cleanup
|
||||
diagnostics with captured launcher output), `inspect_adb_client` and
|
||||
`inspect_apktool_client` (version output and stderr excerpts), and
|
||||
@@ -426,6 +482,9 @@ session retention refuses summary detail with `capability_unavailable`;
|
||||
For `inspect_artifact`, omission also keeps the original request parameters and
|
||||
complete output shape. Delivery selection never reaches the inventory engine;
|
||||
the complete inspection and its atomic inventory Evidence remain retained.
|
||||
A view is never more certain than its parent: a summary or other view of
|
||||
`inferred` Evidence is `inferred`. Other views are `derived`, unless the
|
||||
view kind itself infers, as described below.
|
||||
|
||||
`inspect_analysis_view` also accepts `api-surface` for retained HAR capture Evidence,
|
||||
grouping request lines by method, origin and format-rule path template. Templated
|
||||
@@ -541,10 +600,12 @@ reach WABT or change the original source Evidence ID.
|
||||
Completed `inspect_macho` Evidence supports a summary and
|
||||
`view: {kind: "macho", facet: "exports", offset: 0, limit: 64}`. Facets are
|
||||
`entrypoints`, `architectures`, `build_metadata`, `load_commands`,
|
||||
`dependencies`, `imports`, `exports`, `segments`, and `provenance`; pages return
|
||||
the original rows. The summary keeps the selected slice, header fields and UUID,
|
||||
and replaces each collection with its returned count, reported total and
|
||||
`exhaustive` flag. Each page repeats the paged collection's `source_total` and
|
||||
`dependencies`, `imports`, `exports`, `segments`, `encryption`, and
|
||||
`provenance`; pages return the original rows. Evidence retained before
|
||||
`encryption` was reported pages no encryption rows and reports that collection
|
||||
as non-exhaustive with an unknown status. The summary keeps the selected
|
||||
slice, header fields and UUID, and replaces each collection with its returned
|
||||
count, reported total and `exhaustive` flag. Each page repeats the paged collection's `source_total` and
|
||||
`source_exhaustive`; exhausting a non-exhaustive collection does not establish
|
||||
that unreturned symbols are absent. Large frameworks return megabytes of
|
||||
symbols (Electron Framework: 2.5 MB of imports and exports, 3.3 KB as a
|
||||
@@ -700,6 +761,37 @@ concrete version, selection source, and complete analysis profile through
|
||||
choices return typed selection details. A selected provider is never replaced
|
||||
automatically after a runtime failure.
|
||||
|
||||
`open_binary` resolves an Apple bundle directory (`.app`, `.appex`,
|
||||
`.framework`, `.xpc`, `.systemextension`, `.bundle` or `.plugin`, compared
|
||||
case-insensitively) to the program file its `Info.plist` names in
|
||||
`CFBundleExecutable`; the Evidence subject is that program file. It reads the
|
||||
macOS `Contents/` layout or the flat root layout. A framework with `Versions/`
|
||||
may instead keep `Info.plist` in `Versions/Current/Resources/` with its program
|
||||
file in `Versions/Current/`; a flattened framework without `Versions/`, as
|
||||
Electron and Gecko apps ship it, keeps `Resources/Info.plist` beside its
|
||||
program file. An app keeps its iOS-on-Mac `Wrapper` resolution. For the
|
||||
other types, exactly one layout may declare the bundle, and its `Info.plist`,
|
||||
program directory and program file must stay inside the bundle. Resolution
|
||||
never guesses a program file. Each refusal reports one `details.constraint`:
|
||||
|
||||
- `bundle_info_plist_missing`, with `probed_paths` listing every layout's
|
||||
`Info.plist`.
|
||||
- `bundle_layout_ambiguous`, with `probed_paths` listing the `Info.plist`
|
||||
files found.
|
||||
- `bundle_current_version_missing`, with `probed_paths` naming
|
||||
`Versions/Current`.
|
||||
- `bundle_path_escapes`, with `probed_paths` naming the path that resolved
|
||||
outside the bundle.
|
||||
- `bundle_executable_undeclared`, with `info_plist`.
|
||||
- `bundle_program_missing`, with `info_plist` and `probed_paths` naming the
|
||||
declared program file.
|
||||
|
||||
An unreadable or malformed `Info.plist` keeps its reason without a bundle
|
||||
constraint, and `details.path` names that file. A `.dext`, `.kext`,
|
||||
`.qlgenerator` or `.mdimporter` directory reports `bundle_type_unsupported`. A
|
||||
resource root reports its `layout` as `contents`, `root`,
|
||||
`versioned-framework` or `flattened-framework`.
|
||||
|
||||
`open_bundle_resources` selects a separate read-only app resource session
|
||||
without resolving `CFBundleExecutable`, including when it is absent or
|
||||
unresolvable. `binary_session` reports `session_kind: "bundle_resources"` and the
|
||||
@@ -742,6 +834,22 @@ inspection fails or is cancelled before a provider client exists. If no client
|
||||
remains, no provider run or health observation is available; follow the cleanup
|
||||
error's reported resources.
|
||||
|
||||
## Initial target at startup
|
||||
|
||||
MCP normally starts without a target; use `open_binary` to select one during the
|
||||
session. To open a target before serving MCP, set `HOPPER_TARGET_PATH` to the
|
||||
selected path in REA's launch environment. `HOPPER_TARGET_KIND` accepts
|
||||
`executable` (the default) or `database`. Despite the names, these are initial
|
||||
session settings; the configured provider still determines how the target is
|
||||
opened. If the initial open fails, REA reports the failure and exits with code 1
|
||||
without serving MCP. Shutdown during startup cancels and cleans up the open as
|
||||
described below.
|
||||
|
||||
The source-checkout helper `node scripts/print-mcp-config.mjs /path/to/target`
|
||||
prints a registration containing these settings; `--kind database` selects the
|
||||
database kind. The helper is not part of the installed npm package. `rea setup`
|
||||
does not copy these one-shot target settings into generated registrations.
|
||||
|
||||
## Transports
|
||||
|
||||
The eager stdio runtime owns SIGINT, SIGTERM and stdin EOF before opening an
|
||||
|
||||
+25
-3
@@ -18,6 +18,26 @@ non-string values are rejected with field paths. `action: "list"` accepts no
|
||||
workflow identifier or arguments. The MCP adapter respects the same
|
||||
`REA_MCP_TOOL_FAMILIES` scope as native prompts, including render requests.
|
||||
|
||||
To find a section in the installed guidance bundle by analyst question, use
|
||||
`search_guidance` and pass a returned locator to `read_guidance_section`. The
|
||||
CLI equivalent is `rea guidance --query "exact JavaScript module"`, followed
|
||||
by `rea guidance --action read --locator LOCATOR`. Search is limited to the
|
||||
packaged managed skill files, works without providers or a target, and returns
|
||||
deterministically paged matches. Every non-generic query word must occur in the
|
||||
section; generic-only queries return no matches. Results are documentation; locators
|
||||
are bound to the installed bundle and report stale or unavailable guidance without
|
||||
returning cached section content. A no-match result says nothing about analysis
|
||||
capability availability.
|
||||
|
||||
Search returns at most 20 matches per page with 500-code-unit context excerpts.
|
||||
Read retrieves the complete selected section. Admission permits 1 MiB per file,
|
||||
4 MiB per bundle, 4,096 sections, and 25,165,824 expanded UTF-16 code units before
|
||||
section text is materialized. Unreadable or oversized bundles return
|
||||
`bundle_unavailable`, with no partial index or inferred absence. Cleanup failures
|
||||
remain errors with their retained retry owner. The bundle and complete section
|
||||
are bound by fixed-size hashes in locators, so a long heading does not make its own
|
||||
locator unreadable.
|
||||
|
||||
## Prompt inventory
|
||||
|
||||
| Prompt | Purpose |
|
||||
@@ -51,9 +71,11 @@ directly to `analyze_javascript_application` with `input_path`; it does not
|
||||
require `open_binary`. When that Evidence, or `inspect_binary_layout` Evidence,
|
||||
is already retained, it suggests `inspect_analysis_view` before tracing a
|
||||
feature seed. The CLI equivalent is `rea analyze <directory>`.
|
||||
`open_binary` and the doctor target check admit files and macOS app bundles.
|
||||
A directory outside that opening route is reported with an available analysis
|
||||
action; this does not establish support for every directory format.
|
||||
`open_binary` and the doctor target check admit files and Apple bundle
|
||||
directories (`.app`, `.appex`, `.framework`, `.xpc`, `.systemextension`,
|
||||
`.bundle` and `.plugin`). Another Apple bundle type is refused as unsupported,
|
||||
and another directory is reported with an available analysis action; this does
|
||||
not establish support for every directory format.
|
||||
|
||||
For target paths in `compare_application_versions`, the prompt suggests
|
||||
opening each target before calling `inspect_artifact`; inspection operates on
|
||||
|
||||
@@ -127,7 +127,11 @@ rea inspect-native-data-type <binary> --address <typed-data-address> --provider
|
||||
|
||||
Instruction facts include bytes, length, decoder text, ordered register/scalar/
|
||||
address tokens, typed references and flow destinations. Mid-instruction, data,
|
||||
outside-memory and undecodable addresses have separate outcomes. Effective
|
||||
outside-memory and unlisted addresses have separate outcomes. For Ghidra,
|
||||
`not-in-listing` means the address is in memory without a listed instruction or
|
||||
defined data. REA does not attempt a decode there: the memory may be uninitialized
|
||||
or contain valid instructions. Older Evidence may report `undecodable` for this
|
||||
same ambiguous case; it does not establish that a decode failed. Effective
|
||||
memory base/index/displacement roles remain unavailable. Ghidra reports its program
|
||||
language variant in `mode`; other providers retain their own mode label. Ghidra
|
||||
MIPS results additionally expose `decoder_context`
|
||||
@@ -138,7 +142,7 @@ that do not expose this facet. The context is an analysis observation, not proof
|
||||
of a runtime processor state.
|
||||
|
||||
`inspect_native_instruction` also returns `incoming_references` to the exact
|
||||
queried address, including data, interior-instruction and undecodable addresses.
|
||||
queried address, including data, interior-instruction and unlisted addresses.
|
||||
Ghidra enumerates its ReferenceManager, excludes synthetic entry-point
|
||||
references, and returns deterministic source-address ordering while retaining
|
||||
distinct operand references from the same source. `[]` means that enumeration
|
||||
@@ -339,6 +343,27 @@ Hopper regex mode.
|
||||
|
||||
## Bounded static traces
|
||||
|
||||
Hopper caller queries, incoming procedure references and function dossiers
|
||||
reconcile reported reverse relationships with forward call observations. Each
|
||||
standalone query or composed workflow scans the current document in pages of at
|
||||
most 64 procedures and retains at most 4 MiB of encoded scan results. A composed
|
||||
workflow reuses its own index and clears it when the workflow finishes. The
|
||||
default cooperative scan budget is
|
||||
2,000 ms; set `REA_HOPPER_CALLER_SCAN_BUDGET_MS` to a positive integer number of
|
||||
milliseconds before starting REA to change it. The default limits additional
|
||||
work on the serial Hopper bridge; larger documents may need a higher setting.
|
||||
Results report the examined procedure count and any budget interruption.
|
||||
An individual page, native caller list, and target instruction list each have
|
||||
a 512 KiB encoded allowance. Hitting one reports the incomplete observation.
|
||||
Cancellation is checked between pages, but cannot interrupt a Hopper API call
|
||||
already executing; Hopper's native API itself materializes its reference arrays
|
||||
before REA can bound their copies. Hopper exposes no document revision token, so scans are not
|
||||
reused across workflows and coverage and consistency during a live scan remain
|
||||
unknown even when every procedure was examined.
|
||||
Hopper observations are re-observed rather than replayed from snapshots because
|
||||
the provider has no document revision token. Safe observations may still be
|
||||
retained as Evidence.
|
||||
|
||||
`trace_native_ui_action` / `rea trace-native-ui-action <target> <seed>` accepts
|
||||
one authored selector/object ID, native symbol or exact function address. It
|
||||
joins UI wiring to uniquely matched class/selector implementations and follows
|
||||
@@ -487,8 +512,10 @@ output-budget omissions remain omissions.
|
||||
|
||||
Source input is limited to 64 MiB. Binary and direct XML decoding reserve an
|
||||
estimated 64 MiB decode budget before parsing; this is not a hard process-memory
|
||||
bound. JSON decode memory has not been measured and has no equivalent decode
|
||||
estimate. A refused input reports non-retryable `resource_constraint` with
|
||||
bound. The XML estimate charges every element and every text, comment or CDATA
|
||||
node of the decoder's DOM at a measured upper bound, so a plist made of many
|
||||
small elements reaches it at a few MiB of source. JSON decode memory has not
|
||||
been measured and has no equivalent decode estimate. A refused input reports non-retryable `resource_constraint` with
|
||||
`reported_limits.maximum_input_bytes` or `maximum_decoded_bytes` as applicable.
|
||||
Ordinary direct-source decoding has a ceiling of 998 source nesting levels,
|
||||
derived from the existing 1000-level JSON result capacity by reserving one level
|
||||
@@ -533,7 +560,21 @@ support for core-dump analysis, historical FVMLIB layouts, or unobserved native
|
||||
diagnostic spellings. Unknown or contradictory header values and signalled
|
||||
commands remain failures.
|
||||
|
||||
`inspect_macho.selected_architecture` identifies the exact selected lipo slice
|
||||
`inspect_macho` reads load-command framing and fields from the selected Mach-O
|
||||
bytes. It does not use line-delimited tool output to decide where a command,
|
||||
section, or embedded string begins. Names whose bytes are not valid UTF-8 have
|
||||
a null text value and retain their original bytes as lowercase hexadecimal in
|
||||
`name_bytes_hex`, `segment_bytes_hex`, or `path_bytes_hex`; fixed-width names
|
||||
stop at the first NUL, and command paths exclude their NUL terminator. Older
|
||||
retained Evidence may omit the byte fields. Large binary sizes and offsets that
|
||||
cannot be represented as safe JSON integers retain an exact hexadecimal field;
|
||||
the corresponding numeric field is null. A section alignment too large to
|
||||
represent in bytes retains `alignment_exponent` instead.
|
||||
|
||||
Unknown or partially decoded commands retain their selected-slice-relative
|
||||
offset and size. Their unexamined fields are described in load-command coverage
|
||||
limitations; an exhaustive command inventory does not by itself establish that
|
||||
every payload field was decoded. `inspect_macho.selected_architecture` identifies the exact selected lipo slice
|
||||
and its `container_file_offset` in the input file. A thin Mach-O has a known
|
||||
offset of zero; an unknown universal-slice offset stays null. The Evidence
|
||||
subject format describes the input container: `mach-o-universal` for FAT files,
|
||||
@@ -541,15 +582,49 @@ including those with one slice. The normalized result also reports the container
|
||||
in `format`; `selected_architecture` identifies the selected Mach-O image.
|
||||
Architecture `file_offset` values are container-relative. Entrypoint, segment
|
||||
and section `file_offset` values retain their source meaning and are relative
|
||||
to the selected Mach-O slice. Raw load-command fields retain their original values.
|
||||
A field otool prints more than once, such as each `LC_BUILD_VERSION` tool, is
|
||||
keyed `name #n` in print order. Each `LC_LINKER_OPTION` string is keyed
|
||||
`string #n` and checked against the declared `count`. Evidence locations map the LC_MAIN entrypoint and nonempty file-backed segment
|
||||
to the selected Mach-O slice. Decoded load-command fields retain their original
|
||||
values. Repeated fields, such as each `LC_BUILD_VERSION` tool, are keyed
|
||||
`name #n` in order. Each decoded `LC_LINKER_OPTION` string is keyed `string #n`
|
||||
and checked against the declared `count`. Evidence locations map the LC_MAIN entrypoint and nonempty file-backed segment
|
||||
ranges to container offsets by adding the observed slice offset. Zero-fill
|
||||
segments do not produce file ranges. When the selected slice's container offset
|
||||
is unknown, those mapped locations are omitted with an explicit limitation;
|
||||
architecture inventory locations remain available.
|
||||
|
||||
`inspect_macho.encryption` reports the `LC_ENCRYPTION_INFO(_64)` state of every
|
||||
slice, not only the selected one. It decodes only the FAT table, slice headers
|
||||
and load commands. Like every Mach-O container read, a `0xcafebabe` input of at
|
||||
most 16 MiB is first read whole to rule out a JVM class file, so that read
|
||||
includes code bytes; larger inputs and thin images read only the structures
|
||||
above. A slice is `encrypted` when its single encryption command has a nonzero
|
||||
`cryptid`, `not-encrypted` when `cryptid` is zero, and `absent` only when every
|
||||
load command was read and none was an encryption command. A command whose width
|
||||
or `cmdsize` contradicts the image, more than one such command, or a range past
|
||||
the slice is `malformed`; a slice whose commands could not be fully read is
|
||||
`malformed` or `unknown` with a reason, keeping any commands seen before the
|
||||
failure. A slice with more than two encryption commands keeps the first two
|
||||
and states the count in its reason. Range mapping in all slices shares one
|
||||
budget of segment and section records (16,384, a sixteenth of the native
|
||||
output budget); a slice past it keeps its status and reports its mapping as
|
||||
`unknown` with that reason. Framing caps retained segment commands before decoding.
|
||||
Only a successful mapping consumes the shared allowance; failed mappings leave
|
||||
it available to later slices. Each slice's `range` is end-exclusive in slice and input-file
|
||||
coordinates and maps to file-backed segment fragments, VM addresses and the
|
||||
overlapping nonempty sections; bytes outside every segment remain unmapped
|
||||
fragments. A segment with no VM size keeps its file bytes as fragments with
|
||||
null VM addresses, and a segment whose file size exceeds its VM size or whose
|
||||
VM range leaves the address space makes the mapping `unknown` with a reason
|
||||
while the slice keeps its encryption status. `architecture` is the lipo name of the record at the same offset,
|
||||
size and CPU identity, and is null when no single record matches. A ciphertext
|
||||
range adds a limitation naming its input-file bytes, because disassembly,
|
||||
decompilation, strings and references derived from them do not describe
|
||||
program code. Encryption is read through the same regular-file descriptor
|
||||
that `inspect_macho` binds for its load-command reads, whose SHA-256 must match
|
||||
the session target before and after the native tools run, or the call reports
|
||||
`artifact_changed`. A target that cannot be opened, or a symlinked, non-regular
|
||||
or changing target, fails the call instead of reporting tool facts without an
|
||||
encryption status.
|
||||
|
||||
Hopper's `address_to_file_offset` combines the native image-relative mapping with
|
||||
original-file coordinates only after checking the source against the session's
|
||||
SHA-256. FAT tables and embedded Mach-O headers come from that same hashing pass.
|
||||
@@ -586,6 +661,9 @@ complete observation.
|
||||
undecodable filenames and skipped symlinks, as partial coverage. Known
|
||||
executable roots remain available; unexamined names and symlink targets
|
||||
cannot establish an empty root set or the absence of other roots.
|
||||
A dependency symlink whose target is not valid UTF-8 is undetermined, with
|
||||
its stored target bytes in the limitation and partial coverage; a selected
|
||||
root crossing such a symlink is refused with the same bytes in its diagnostic.
|
||||
- `inspect_asset_catalog` / `rea inspect-asset-catalog <app>` reads compiled
|
||||
`Assets.car` metadata through macOS `assetutil --info`. Catalog digests, raw
|
||||
rendition fields, pagination and exact UI resource-name matches are returned.
|
||||
@@ -739,6 +817,11 @@ complete observation.
|
||||
files and universal slices before metadata decoding. CPU subtypes and
|
||||
capability bits remain source facts; an `arm64` request may select an
|
||||
`arm64e` image under the existing slice preference policy.
|
||||
Objective-C class, protocol and category lists require eight-byte entries;
|
||||
Swift type and conformance sections require four-byte entries. Misaligned
|
||||
section lengths and unsupported non-PowerPC big-endian CPU declarations return
|
||||
`unsupported_target` with the selected path and precise reason. Recovery
|
||||
selects a well-formed or supported artifact and reopens that target.
|
||||
The byte reader holds the whole selected file in memory, so it admits files up
|
||||
to 64 MiB / 67108864 bytes by default. Select a larger budget with
|
||||
`max_input_bytes` (CLI `--max-input-bytes`), at most 1 GiB / 1073741824
|
||||
@@ -833,7 +916,11 @@ complete observation.
|
||||
and `__objc_catlist` categories are also decoded. Categories record the
|
||||
extended class, local or external, plus
|
||||
their methods, protocols and properties; category methods appear as
|
||||
implementations with a `category`. Swift field-offset globals that are only
|
||||
implementations with a `category`. A category whose class reference is null,
|
||||
or is bound to a symbol other than `_OBJC_CLASS_$_`, such as the `_$s…CN`
|
||||
metadata symbol of another module's Swift class, keeps a null class, and
|
||||
`objc_properties_categories` coverage names that reference. Swift
|
||||
field-offset globals that are only
|
||||
initialized at runtime stay unresolved. Generic, resilient, async and
|
||||
coroutine tables, and inherited overrides, have explicit unsupported or
|
||||
partial coverage. Other providers retain the
|
||||
|
||||
@@ -106,6 +106,17 @@ URI leaves coverage partial. The HTTP URI profile covers HTTP/1 and HTTP/2;
|
||||
HTTP/3 URI semantics are unexamined. All admitted URI fields share the same
|
||||
credential exclusion and source-value retention rules.
|
||||
Counts preserve distinct observed source URIs before omission or coalescing.
|
||||
|
||||
Failed capture-summary TShark commands apply the same HTTP URI policy to
|
||||
retained JSON diagnostics, including cancellation, output-limit and cleanup
|
||||
failures. JSON spelling outside the excluded credential spans is preserved.
|
||||
An unfinished or malformed JSON token and its following suffix are withheld,
|
||||
with `captured_output.truncated: true`; complete preceding fields remain
|
||||
available. Diagnostic byte counts and output allowances describe original
|
||||
producer input, before credential exclusion. Caller-selected packet-field tools
|
||||
continue to return their selected recorded values.
|
||||
Origin-form request targets and HTTP/2 `:path` values retain path semantics,
|
||||
including leading double slashes and userinfo-like text within the path.
|
||||
`coverage: "partial"` records unresolved DNS attribution or URI item loss;
|
||||
component credential exclusion is also counted explicitly. Diagnostics retain
|
||||
both tool stderr streams. Recorded fields do not establish decrypted payloads,
|
||||
|
||||
+11
-1
@@ -40,6 +40,12 @@ signer identifier facts. A signer identified by subject key identifier reports
|
||||
that value as `subject_key_identifier_hex`. Other certificate types keep
|
||||
`pkcs7` null.
|
||||
|
||||
Each signer reports `unsigned_attribute_oids`: null means the field was absent,
|
||||
and an array lists the types when present. Older retained Evidence may omit the
|
||||
field. Unsigned attribute contents, including nested signatures and timestamp
|
||||
tokens, are not decoded; their presence makes coverage partial and adds a
|
||||
limitation. Certificate and signer counts refer to the outer SignedData.
|
||||
|
||||
A missing table is observed absence of that directory. It is not proof the
|
||||
image is unsigned in every catalog or overlay sense.
|
||||
|
||||
@@ -54,7 +60,11 @@ fails the same way. SignedData must contain at least one `SignerInfo`, and
|
||||
each `SignerInfo` must carry a non-empty signature value. Each embedded X.509
|
||||
certificate must include `subjectPublicKeyInfo` and `signatureValue`. Decoded
|
||||
certificate name text, serials, validity spellings, and subject key identifiers
|
||||
share a 64 KiB budget per PKCS#7 payload. Unsupported certificate name
|
||||
share a 64 KiB budget per PKCS#7 payload, and each payload decodes at most
|
||||
16,384 ASN.1 values. Exhausting either fixed allowance returns a nonretryable
|
||||
`resource_constraint` error naming it, not an invalid-input error; this release
|
||||
has no runtime override, and `max_file_bytes` and `max_entries` do not raise
|
||||
it. Unsupported certificate name
|
||||
encodings, including GeneralString, fail explicitly. TeletexString (T.61)
|
||||
values are rendered with the ISO-8859-1 compatibility mapping used by OpenSSL;
|
||||
this is not a full T.61 decoder, so the result includes a limitation whenever
|
||||
|
||||
@@ -257,7 +257,9 @@ A bare executable name uses the scenario's `PATH` override, then the inherited
|
||||
An explicitly empty `PATH` searches only the working directory. Executable,
|
||||
working-directory, and observation paths preserve native `symlink/..` traversal.
|
||||
|
||||
Terminal dimensions must satisfy `columns × (rows + scrollback) ≤ 1,000,000`.
|
||||
Terminal width must be at least two columns: the pinned xterm renderer cannot
|
||||
represent a one-column screen. This applies to the initial size and every resize.
|
||||
Terminal dimensions must also satisfy `columns × (rows + scrollback) ≤ 1,000,000`.
|
||||
Every scheduled resize uses the same selected scrollback and must fit this
|
||||
working-buffer budget. REA rejects oversized scenarios before launching the
|
||||
command; it never clamps the requested dimensions. This limit is independent
|
||||
@@ -353,9 +355,12 @@ recapture both sides with the same observation version before comparison.
|
||||
When path normalization is enabled, aliases apply to selected path identities
|
||||
at clear text delimiters. A selected executable path does not alias a longer
|
||||
sibling filename such as `tool-helper`; selected parent directories still
|
||||
normalize within descendant paths. The comparison contract records these rules as
|
||||
`path-component-boundaries-v2`, so captures made with the earlier prefix rules
|
||||
cannot be compared as if the text had the same meaning.
|
||||
normalize within descendant paths, including when the working directory or an
|
||||
observation path is spelled with a trailing `/` or `/.`. A selected filesystem
|
||||
root `/` also aliases descendant paths, without rewriting URL separators or
|
||||
HTML closing tags. The comparison contract
|
||||
records these rules as `path-component-boundaries-v3`, so captures made with the
|
||||
earlier rules cannot be compared as if the text had the same meaning.
|
||||
|
||||
Rendered frame `lines` hold the visible rows after normalization, with trailing
|
||||
U+0020 spaces removed. Blank rows and internal spaces remain. `columns` records
|
||||
|
||||
+9
-5
@@ -10,24 +10,28 @@ inferred from a `.bin` suffix or from unrecognized bytes.
|
||||
## Open and inspect
|
||||
|
||||
```bash
|
||||
rea inspect /absolute/path/to/ecu.bin --target-format raw-binary --architecture arm --entry-point 0x8000000 --provider ghidra --json
|
||||
rea function /absolute/path/to/ecu.bin 0x8000000 --target-format raw-binary --architecture arm --entry-point 0x8000000 --provider ghidra --json
|
||||
rea inspect-native-load-image /absolute/path/to/ecu.bin --target-format raw-binary --architecture arm --entry-point 0x8000000 --provider ghidra --json
|
||||
rea inspect /absolute/path/to/kernel.img --target-format raw-binary --architecture arm --entry-point 0x8000 --provider ghidra --json
|
||||
rea function /absolute/path/to/kernel.img 0x8000 --target-format raw-binary --architecture arm --entry-point 0x8000 --provider ghidra --json
|
||||
rea inspect-native-load-image /absolute/path/to/kernel.img --target-format raw-binary --architecture arm --entry-point 0x8000 --provider ghidra --json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "open_binary",
|
||||
"arguments": {
|
||||
"path": "/absolute/path/to/ecu.bin",
|
||||
"path": "/absolute/path/to/kernel.img",
|
||||
"format": "raw-binary",
|
||||
"architecture": "arm",
|
||||
"entry_point": "0x8000000",
|
||||
"entry_point": "0x8000",
|
||||
"provider_id": "ghidra"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The example maps a 32-bit ARM-state image at `0x8000`. For `arm`, decoding
|
||||
starts at the entry in ARM (A32) state, so Thumb-only images, including Cortex-M
|
||||
firmware, are not supported. See [Limitations](#limitations).
|
||||
|
||||
`architecture` is one of `x86`, `x86_64`, `arm`, `arm64`, `6502`, or `m68k`. `entry_point` is a
|
||||
hexadecimal address of the form `0x…`. The complete file is mapped starting at
|
||||
that address, and Ghidra seeds an `entry` function there before auto-analysis.
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
يربط REA وكيلك بأدوات لفحص الملفات الثنائية للشيفرة الأصلية، وتطبيقات JavaScript وElectron، وتجميعات .NET، والمواقع. يمكنك أيضًا استخدام الأدوات نفسها من الطرفية. يجري التحليل محليًا، وتتضمن النتائج الأدلة والقيود التي تستند إليها كل خلاصة.
|
||||
|
||||
يسجّل الإعداد REA لدى وكيلك ويثبّت تعليمات العمل المطابقة. يمكن للتحليل الأصلي استخدام Hopper أو Ghidra أو IDA المثبّت مسبقًا؛ ويمكن تثبيت Hopper بعد موافقتك. لا يحتاج التحليل الثابت لـ JavaScript إلى محرك تحليل أصلي.
|
||||
يسجّل الإعداد REA لدى وكيلك ويثبّت تعليمات العمل المطابقة. يمكن للتحليل الأصلي استخدام Hopper أو Ghidra أو IDA أو Kuna المثبّت مسبقًا؛ ويمكن تثبيت Hopper بعد موافقتك. لا يحتاج التحليل الثابت لـ JavaScript إلى محرك تحليل أصلي.
|
||||
|
||||
> **[زر موقع REA](https://rea.tools/ar/)** للاطلاع على تعليمات الإعداد والأدلة المصوّرة ودراسات الحالة الفعلية.
|
||||
|
||||
@@ -151,7 +151,7 @@ npx rea-agents@latest setup
|
||||
|
||||
| الهدف | ما يعيده REA | المتطلبات والدليل |
|
||||
| ------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| الملفات الثنائية للشيفرة الأصلية | شيفرة شبه برمجية، وتعليمات تجميع، وسلاسل نصية، ورموز، واستدعاءات، ومراجع | Hopper أو Ghidra أو IDA؛ [تحليل الشيفرة الأصلية](../native-investigation.md) |
|
||||
| الملفات الثنائية للشيفرة الأصلية | شيفرة شبه برمجية، وتعليمات تجميع، وسلاسل نصية، ورموز، واستدعاءات، ومراجع | Hopper أو Ghidra أو IDA أو Kuna؛ [تحليل الشيفرة الأصلية](../native-investigation.md) |
|
||||
| بنية ELF دون تشغيل | الأقسام والمقاطع والرموز ومعلومات إعادة التموضع الأصلية، وآليات الحماية المحتملة المستدلّ عليها بالفحص الثابت | pwntools يوفّره المستدعي على Linux x64؛ [تشخيص الملفات الثنائية](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -280,9 +280,9 @@ agent-env run ./my-env
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>هل أحتاج إلى Hopper أو Ghidra أو IDA؟</strong></summary>
|
||||
<summary><strong>هل أحتاج إلى Hopper أو Ghidra أو IDA أو Kuna؟</strong></summary>
|
||||
|
||||
يستخدم تحليل الشيفرة الأصلية المتعمق أحدها. يعمل الفحص الثابت لـ JavaScript و.NET دون محرك لتحليل الشيفرة الأصلية. يستطيع الإعداد تثبيت Hopper بعد الموافقة؛ أما Ghidra وIDA فيستخدمان تثبيتاتك الموجودة. راجع [إعداد الموفّرين](../installation.md#hopper).
|
||||
يستخدم تحليل الشيفرة الأصلية المتعمق أحدها. يعمل الفحص الثابت لـ JavaScript و.NET دون محرك لتحليل الشيفرة الأصلية. يستطيع الإعداد تثبيت Hopper بعد الموافقة؛ أما Ghidra وIDA وKuna فتستخدم تثبيتاتك الموجودة. راجع [إعداد الموفّرين](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Website](https://rea.tools/de/) · [Anleitungen](https://rea.tools/de/guides/) · [Fallstudien](https://rea.tools/de/showcase/)**
|
||||
|
||||
[Schnellstart](#schnellstart) · [So funktioniert REA](#so-funktioniert-rea) · [Was du analysieren kannst](#was-du-analysieren-kannst) · [Fallstudien](#fallstudien) · [RL-Umgebungen erstellen](#build-rl-environments) · [Häufige Fragen](#häufige-fragen) · [GNU-objdump- und Rizin-Tools](../reverse-engineering-tools.md) · [Dokumentation](#dokumentation)
|
||||
[Schnellstart](#schnellstart) · [So funktioniert REA](#so-funktioniert-rea) · [Was du analysieren kannst](#was-du-analysieren-kannst) · [Fallstudien](#fallstudien) · [RL-Umgebungen erstellen](#build-rl-environments) · [Häufige Fragen](#häufige-fragen) · [Dokumentation](#dokumentation)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@ Du hast in einer App eine Funktion entdeckt, die du in dein eigenes Produkt übe
|
||||
|
||||
REA verbindet deinen Agenten mit Werkzeugen zum Untersuchen nativer Binärdateien, von JavaScript- und Electron-Apps, .NET-Assemblies und Websites. Dieselben Werkzeuge kannst du auch im Terminal nutzen. Die Analyse läuft lokal; die Ergebnisse enthalten die Belege und Einschränkungen hinter jeder Schlussfolgerung.
|
||||
|
||||
Die Einrichtung registriert REA bei deinem Agenten und installiert passende Workflow-Anweisungen. Native Analysen nutzen eine vorhandene Installation von Hopper, Ghidra oder IDA; nach Zustimmung kann die Einrichtung Hopper installieren. Statische JavaScript-Analysen benötigen keine native Analyse-Engine.
|
||||
Die Einrichtung registriert REA bei deinem Agenten und installiert passende Workflow-Anweisungen. Native Analysen nutzen eine vorhandene Installation von Hopper, Ghidra, IDA oder Kuna; nach Zustimmung kann die Einrichtung Hopper installieren. Statische JavaScript-Analysen benötigen keine native Analyse-Engine.
|
||||
|
||||
> **[Besuche die REA-Website](https://rea.tools/de/)** für Einrichtungshinweise, bebilderte Anleitungen und echte Fallstudien.
|
||||
|
||||
@@ -151,7 +151,7 @@ REA benötigt Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) oder 26+ (>=26.12.1) so
|
||||
|
||||
| Ziel | Was REA zurückgibt | Voraussetzungen und Anleitung |
|
||||
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Native Binärdateien | Pseudocode, Assemblercode, Zeichenketten, Symbole, Aufrufe und Verweise | Hopper, Ghidra oder IDA; [native Analyse](../native-investigation.md) |
|
||||
| Native Binärdateien | Pseudocode, Assemblercode, Zeichenketten, Symbole, Aufrufe und Verweise | Hopper, Ghidra, IDA oder Kuna; [native Analyse](../native-investigation.md) |
|
||||
| Offline-ELF-Struktur | Sektionen, Segmente, ursprüngliche Symbole/Relokationen und mögliche Schutzmaßnahmen aus statischer Analyse | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; [Binärdiagnostik](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -190,6 +190,8 @@ REA benötigt Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) oder 26+ (>=26.12.1) so
|
||||
|
||||
Statische JavaScript- und .NET-Untersuchungen lesen die bereitgestellten Dateien, ohne die Anwendung auszuführen. Laufzeitaufzeichnungen führen das gewählte Ziel mit deinen Benutzerrechten aus oder interagieren damit; die jeweiligen Anleitungen beschreiben die Auswirkungen.
|
||||
|
||||
Für die Offline-Untersuchung nativer Binärdateien unterstützt REA auch GNU objdump und Rizin, die du selbst bereitstellst. Der [Leitfaden zu Reverse-Engineering-Tools](../reverse-engineering-tools.md) beschreibt die Einrichtung der Provider, CLI-Befehle und Einschränkungen der Evidence. REA installiert oder aktualisiert keinen der beiden Provider.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
Bei großen Binärdateien kannst du die Startfrist mit `REA_GHIDRA_STARTUP_TIMEOUT_MS` oder `REA_HOPPER_STARTUP_TIMEOUT_MS` erhöhen.
|
||||
@@ -278,9 +280,9 @@ Jeder Agent, der lokale MCP-Server unterstützt. Die Einrichtung konfiguriert di
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Brauche ich Hopper, Ghidra oder IDA?</strong></summary>
|
||||
<summary><strong>Brauche ich Hopper, Ghidra, IDA oder Kuna?</strong></summary>
|
||||
|
||||
Für tiefgehende native Analysen wird eines dieser Programme verwendet. Statische JavaScript- und .NET-Untersuchungen funktionieren ohne native Analyse-Engine. Die Einrichtung kann Hopper nach Zustimmung installieren; Ghidra und IDA nutzen deine vorhandenen Installationen. Siehe [Provider-Einrichtung](../installation.md#hopper).
|
||||
Für tiefgehende native Analysen wird eines dieser Programme verwendet. Statische JavaScript- und .NET-Untersuchungen funktionieren ohne native Analyse-Engine. Die Einrichtung kann Hopper nach Zustimmung installieren; Ghidra, IDA und Kuna nutzen deine vorhandenen Installationen. Siehe [Provider-Einrichtung](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
Το REA συνδέει τον πράκτορά σου με εργαλεία εξέτασης δυαδικών αρχείων με κώδικα μηχανής, εφαρμογών JavaScript και Electron, assemblies .NET και ιστοτόπων. Μπορείς να χρησιμοποιήσεις τα ίδια εργαλεία και από το τερματικό. Η ανάλυση εκτελείται τοπικά και τα αποτελέσματα περιλαμβάνουν τα τεκμήρια και τους περιορισμούς στους οποίους βασίζεται κάθε συμπέρασμα.
|
||||
|
||||
Η διαδικασία εγκατάστασης καταχωρίζει το REA στον agent σου και εγκαθιστά τις αντίστοιχες οδηγίες εργασίας. Για ανάλυση κώδικα μηχανής μπορείς να χρησιμοποιήσεις μια υπάρχουσα εγκατάσταση του Hopper, του Ghidra ή του IDA. Η διαδικασία εγκατάστασης μπορεί επίσης να εγκαταστήσει το Hopper, εφόσον το εγκρίνεις. Η στατική ανάλυση JavaScript δεν χρειάζεται μηχανή ανάλυσης κώδικα μηχανής.
|
||||
Η διαδικασία εγκατάστασης καταχωρίζει το REA στον agent σου και εγκαθιστά τις αντίστοιχες οδηγίες εργασίας. Για ανάλυση κώδικα μηχανής μπορείς να χρησιμοποιήσεις μια υπάρχουσα εγκατάσταση του Hopper, του Ghidra, του IDA ή του Kuna. Η διαδικασία εγκατάστασης μπορεί επίσης να εγκαταστήσει το Hopper, εφόσον το εγκρίνεις. Η στατική ανάλυση JavaScript δεν χρειάζεται μηχανή ανάλυσης κώδικα μηχανής.
|
||||
|
||||
> **[Επισκέψου τον ιστότοπο του REA](https://rea.tools/)** για οδηγίες εγκατάστασης, εικονογραφημένους οδηγούς και πραγματικές μελέτες περίπτωσης.
|
||||
|
||||
@@ -151,7 +151,7 @@ npx rea-agents@latest setup
|
||||
|
||||
| Στόχος | Τι επιστρέφει το REA | Απαιτήσεις και οδηγός |
|
||||
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Δυαδικά αρχεία με κώδικα μηχανής | Ψευδοκώδικα, κώδικα assembly, συμβολοσειρές, σύμβολα, κλήσεις και αναφορές | Hopper, Ghidra ή IDA· [ανάλυση κώδικα μηχανής](../native-investigation.md) |
|
||||
| Δυαδικά αρχεία με κώδικα μηχανής | Ψευδοκώδικα, κώδικα assembly, συμβολοσειρές, σύμβολα, κλήσεις και αναφορές | Hopper, Ghidra, IDA ή Kuna· [ανάλυση κώδικα μηχανής](../native-investigation.md) |
|
||||
| Δομή ELF χωρίς εκτέλεση | Ενότητες, τμήματα, αρχικά σύμβολα/εγγραφές μετεγκατάστασης και ενδείξεις πιθανών μέτρων προστασίας από στατική ανάλυση | pwntools που παρέχει ο χρήστης σε Linux x64· [διαγνωστικά δυαδικών αρχείων](../binary-diagnostics.md) |
|
||||
| Δυαδικά αρχεία Go | Ενσωματωμένη έκδοση μεταγλωττιστή, modules, αντικαταστάσεις και ρυθμίσεις μεταγλώττισης | Ενσωματωμένη στατική εξέταση ELF/PE/thin Mach-O· δεν απαιτείται εγκατάσταση του Go |
|
||||
| Δυαδικά αρχεία Rust | Ενσωματωμένα ονόματα, εκδόσεις, πηγές και σχέσεις εξάρτησης των crates από το cargo-auditable | Ενσωματωμένη στατική εξέταση ELF/PE/thin Mach-O· [δυαδικά αρχεία Rust](../rust-binaries.md) |
|
||||
@@ -282,9 +282,9 @@ agent-env run ./my-env
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Χρειάζομαι Hopper, Ghidra ή IDA;</strong></summary>
|
||||
<summary><strong>Χρειάζομαι Hopper, Ghidra, IDA ή Kuna;</strong></summary>
|
||||
|
||||
Η εις βάθος ανάλυση κώδικα μηχανής χρησιμοποιεί ένα από αυτά. Η στατική εξέταση JavaScript και .NET λειτουργεί χωρίς μηχανή ανάλυσης κώδικα μηχανής. Η διαδικασία εγκατάστασης μπορεί να εγκαταστήσει το Hopper μετά την έγκρισή σου· το Ghidra και το IDA χρησιμοποιούν τις υπάρχουσες εγκαταστάσεις σου. Δες τη [ρύθμιση παρόχων ανάλυσης](../installation.md#hopper).
|
||||
Η εις βάθος ανάλυση κώδικα μηχανής χρησιμοποιεί ένα από αυτά. Η στατική εξέταση JavaScript και .NET λειτουργεί χωρίς μηχανή ανάλυσης κώδικα μηχανής. Η διαδικασία εγκατάστασης μπορεί να εγκαταστήσει το Hopper μετά την έγκρισή σου· το Ghidra, το IDA και το Kuna χρησιμοποιούν τις υπάρχουσες εγκαταστάσεις σου. Δες τη [ρύθμιση παρόχων ανάλυσης](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Sitio web](https://rea.tools/es/) · [Guías](https://rea.tools/es/guides/) · [Casos prácticos](https://rea.tools/es/showcase/)**
|
||||
|
||||
[Inicio rápido](#inicio-rápido) · [Cómo funciona REA](#cómo-funciona-rea) · [Qué puedes analizar](#qué-puedes-analizar) · [Casos prácticos](#casos-prácticos) · [Crear entornos de RL](#build-rl-environments) · [Preguntas frecuentes](#preguntas-frecuentes) · [Herramientas GNU objdump y Rizin](../reverse-engineering-tools.md) · [Documentación](#documentación)
|
||||
[Inicio rápido](#inicio-rápido) · [Cómo funciona REA](#cómo-funciona-rea) · [Qué puedes analizar](#qué-puedes-analizar) · [Casos prácticos](#casos-prácticos) · [Crear entornos de RL](#build-rl-environments) · [Preguntas frecuentes](#preguntas-frecuentes) · [Documentación](#documentación)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
REA conecta tu agente con herramientas para inspeccionar binarios nativos, aplicaciones JavaScript y Electron, ensamblados .NET y sitios web. También puedes usar las mismas herramientas desde la terminal. El análisis se ejecuta localmente y los resultados incluyen las pruebas y limitaciones que sustentan cada conclusión.
|
||||
|
||||
La configuración registra REA con tu agente e instala las instrucciones de trabajo correspondientes. El análisis nativo puede usar Hopper, Ghidra o IDA ya instalados; la configuración puede instalar Hopper con tu aprobación. El análisis estático de JavaScript no requiere un motor de análisis nativo.
|
||||
La configuración registra REA con tu agente e instala las instrucciones de trabajo correspondientes. El análisis nativo puede usar Hopper, Ghidra, IDA o Kuna ya instalados; la configuración puede instalar Hopper con tu aprobación. El análisis estático de JavaScript no requiere un motor de análisis nativo.
|
||||
|
||||
> **[Visita el sitio web de REA](https://rea.tools/es/)** para encontrar instrucciones de configuración, guías ilustradas y casos reales.
|
||||
|
||||
@@ -151,7 +151,7 @@ REA requiere Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) o 26+ (>=26.12.1), adem
|
||||
|
||||
| Objetivo | Qué devuelve REA | Requisitos y guía |
|
||||
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Binarios nativos | Pseudocódigo, ensamblador, cadenas, símbolos, llamadas y referencias | Hopper, Ghidra o IDA; [análisis nativo](../native-investigation.md) |
|
||||
| Binarios nativos | Pseudocódigo, ensamblador, cadenas, símbolos, llamadas y referencias | Hopper, Ghidra, IDA o Kuna; [análisis nativo](../native-investigation.md) |
|
||||
| Estructura ELF sin ejecutar | Secciones, segmentos, símbolos/reubicaciones originales y posibles medidas de mitigación detectadas mediante análisis estático | pwntools proporcionado por quien llama, en Linux x64; [diagnóstico de binarios](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -190,6 +190,8 @@ REA requiere Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) o 26+ (>=26.12.1), adem
|
||||
|
||||
La inspección estática de JavaScript y .NET lee los archivos suministrados sin ejecutar la aplicación. La captura en ejecución inicia el objetivo seleccionado o interactúa con él con los permisos de tu usuario; cada guía describe sus efectos.
|
||||
|
||||
Para inspeccionar binarios nativos sin conexión, REA también admite GNU objdump y Rizin, que debes proporcionar por tu cuenta. La [guía de herramientas de ingeniería inversa](../reverse-engineering-tools.md) explica la configuración de los proveedores, los comandos de la CLI y las limitaciones de Evidence. REA no instala ni actualiza ninguno de estos proveedores.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
Para binarios grandes, aumenta el plazo de inicio mediante `REA_GHIDRA_STARTUP_TIMEOUT_MS` o `REA_HOPPER_STARTUP_TIMEOUT_MS`.
|
||||
@@ -278,9 +280,9 @@ Cualquier agente que admita servidores MCP locales. La configuración prepara lo
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>¿Necesito Hopper, Ghidra o IDA?</strong></summary>
|
||||
<summary><strong>¿Necesito Hopper, Ghidra, IDA o Kuna?</strong></summary>
|
||||
|
||||
El análisis nativo en profundidad utiliza uno de ellos. La inspección estática de JavaScript y .NET funciona sin un motor de análisis nativo. La configuración puede instalar Hopper después de tu aprobación; Ghidra e IDA usan las instalaciones que ya tienes. Consulta [configuración de proveedores](../installation.md#hopper).
|
||||
El análisis nativo en profundidad utiliza uno de ellos. La inspección estática de JavaScript y .NET funciona sin un motor de análisis nativo. La configuración puede instalar Hopper después de tu aprobación; Ghidra, IDA y Kuna usan las instalaciones que ya tienes. Consulta [configuración de proveedores](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[وبسایت](https://rea.tools/fa/) · [راهنماها](https://rea.tools/fa/guides/) · [نمونههای عملی](https://rea.tools/fa/showcase/)**
|
||||
|
||||
[شروع سریع](#شروع-سریع) · [REA چگونه کار میکند؟](#rea-چگونه-کار-میکند) · [چه چیزهایی را میتوان تحلیل کرد؟](#چه-چیزهایی-را-میتوان-تحلیل-کرد) · [نمونههای عملی](#نمونههای-عملی) · [ساخت محیطهای RL](#build-rl-environments) · [پرسشهای متداول](#پرسشهای-متداول) · [ابزارهای GNU objdump و Rizin](../reverse-engineering-tools.md) · [مستندات](#مستندات)
|
||||
[شروع سریع](#شروع-سریع) · [REA چگونه کار میکند؟](#rea-چگونه-کار-میکند) · [چه چیزهایی را میتوان تحلیل کرد؟](#چه-چیزهایی-را-میتوان-تحلیل-کرد) · [نمونههای عملی](#نمونههای-عملی) · [ساخت محیطهای RL](#build-rl-environments) · [پرسشهای متداول](#پرسشهای-متداول) · [مستندات](#مستندات)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
REA ایجنت شما را به ابزارهایی برای بررسی باینریهای بومی، برنامههای JavaScript و Electron، اسمبلیهای .NET و وبسایتها متصل میکند. همین ابزارها از ترمینال نیز قابل استفادهاند. تحلیل بهصورت محلی انجام میشود و نتایج شامل شواهد و محدودیتهای پشت هر نتیجهگیری هستند.
|
||||
|
||||
راهاندازی، REA را در ایجنت ثبت و دستورالعملهای متناظر را نصب میکند. تحلیل بومی میتواند از Hopper، Ghidra یا IDA موجود استفاده کند؛ نصب Hopper پس از تأیید شما ممکن است. تحلیل ایستای JavaScript به موتور تحلیل بومی نیاز ندارد.
|
||||
راهاندازی، REA را در ایجنت ثبت و دستورالعملهای متناظر را نصب میکند. تحلیل بومی میتواند از Hopper، Ghidra، IDA یا Kuna موجود استفاده کند؛ نصب Hopper پس از تأیید شما ممکن است. تحلیل ایستای JavaScript به موتور تحلیل بومی نیاز ندارد.
|
||||
|
||||
> برای دستورالعملهای راهاندازی، راهنماهای تصویری و مطالعات موردی واقعی، **[به وبسایت REA مراجعه کنید](https://rea.tools/fa/)**.
|
||||
|
||||
@@ -143,7 +143,7 @@ REA به Node.js 22.x (>=22.23.4)، 24.x (>=24.22.1) یا 26+ (>=26.12.1)، به
|
||||
|
||||
| هدف | خروجی REA | پیشنیازها و راهنما |
|
||||
| ---------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| باینریهای بومی | شبهکد، اسمبلی، رشتهها، نمادها، فراخوانیها و ارجاعات | Hopper، Ghidra یا IDA؛ [تحلیل بومی](../native-investigation.md) |
|
||||
| باینریهای بومی | شبهکد، اسمبلی، رشتهها، نمادها، فراخوانیها و ارجاعات | Hopper، Ghidra، IDA یا Kuna؛ [تحلیل بومی](../native-investigation.md) |
|
||||
| ساختار ELF آفلاین | بخشها، سگمنتها، نمادها و relocationهای اصلی و گزینههای احتمالی کاهش آسیبپذیری ایستا | pwntools تأمینشده توسط فراخواننده روی Linux x64؛ [تشخیص باینری](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -182,6 +182,8 @@ REA به Node.js 22.x (>=22.23.4)، 24.x (>=24.22.1) یا 26+ (>=26.12.1)، به
|
||||
|
||||
بررسی ایستای JavaScript و .NET فایلهای ارائهشده را بدون اجرای برنامه میخواند. ضبط زمان اجرا، هدف انتخابشده را با مجوزهای کاربری شما اجرا میکند یا با آن تعامل دارد؛ آثار این عملیات در راهنمای مربوط به هر نوع ضبط توضیح داده شدهاند.
|
||||
|
||||
برای بررسی آفلاین فایلهای باینری بومی، REA از GNU objdump و Rizin نیز پشتیبانی میکند؛ این ابزارها را باید خودتان فراهم کنید. [راهنمای ابزارهای مهندسی معکوس](../reverse-engineering-tools.md) تنظیم ارائهدهندگان، فرمانهای CLI و محدودیتهای Evidence را توضیح میدهد. REA هیچیک از این دو ارائهدهنده را نصب یا بهروزرسانی نمیکند.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
برای باینریهای بزرگ، مهلت شروع را با `REA_GHIDRA_STARTUP_TIMEOUT_MS` یا `REA_HOPPER_STARTUP_TIMEOUT_MS` افزایش دهید.
|
||||
@@ -268,9 +270,9 @@ REA محیطی آمادهٔ اجرا همراه با یک آزمون ساده ب
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary><strong>آیا به Hopper، Ghidra یا IDA نیاز دارم؟</strong></summary>
|
||||
<details><summary><strong>آیا به Hopper، Ghidra، IDA یا Kuna نیاز دارم؟</strong></summary>
|
||||
|
||||
تحلیل عمیق بومی به یکی از آنها نیاز دارد. بررسی ایستای JavaScript و .NET بدون موتور تحلیل بومی کار میکند. setup میتواند با تأیید شما Hopper را نصب کند؛ Ghidra و IDA از نصبهای موجود شما استفاده میکنند. [راهاندازی ارائهدهنده](../installation.md#hopper) را ببینید.
|
||||
تحلیل عمیق بومی به یکی از آنها نیاز دارد. بررسی ایستای JavaScript و .NET بدون موتور تحلیل بومی کار میکند. setup میتواند با تأیید شما Hopper را نصب کند؛ Ghidra، IDA و Kuna از نصبهای موجود شما استفاده میکنند. [راهاندازی ارائهدهنده](../installation.md#hopper) را ببینید.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Site web](https://rea.tools/fr/) · [Guides](https://rea.tools/fr/guides/) · [Études de cas](https://rea.tools/fr/showcase/)**
|
||||
|
||||
[Démarrage rapide](#démarrage-rapide) · [Comment fonctionne REA](#comment-fonctionne-rea) · [Ce que vous pouvez analyser](#ce-que-vous-pouvez-analyser) · [Études de cas](#études-de-cas) · [Créer des environnements RL](#build-rl-environments) · [Questions fréquentes](#questions-fréquentes) · [Outils GNU objdump et Rizin](../reverse-engineering-tools.md) · [Documentation](#documentation)
|
||||
[Démarrage rapide](#démarrage-rapide) · [Comment fonctionne REA](#comment-fonctionne-rea) · [Ce que vous pouvez analyser](#ce-que-vous-pouvez-analyser) · [Études de cas](#études-de-cas) · [Créer des environnements RL](#build-rl-environments) · [Questions fréquentes](#questions-fréquentes) · [Documentation](#documentation)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@ Vous avez repéré dans une application une fonctionnalité que vous aimeriez av
|
||||
|
||||
REA connecte votre agent à des outils d'inspection de binaires natifs, d'applications JavaScript et Electron, d'assemblys .NET et de sites web. Les mêmes outils sont aussi disponibles depuis votre terminal. L'analyse s'exécute localement, et chaque conclusion s'accompagne des preuves et des limites sur lesquelles elle repose.
|
||||
|
||||
Setup enregistre REA auprès de votre agent et installe les instructions de workflow correspondantes. L'analyse native peut utiliser une installation existante de Hopper, de Ghidra ou d'IDA ; Setup peut aussi installer Hopper après votre accord. L'analyse statique JavaScript ne nécessite aucun moteur d'analyse natif.
|
||||
Setup enregistre REA auprès de votre agent et installe les instructions de workflow correspondantes. L'analyse native peut utiliser une installation existante de Hopper, de Ghidra, d'IDA ou de Kuna ; Setup peut aussi installer Hopper après votre accord. L'analyse statique JavaScript ne nécessite aucun moteur d'analyse natif.
|
||||
|
||||
> **[Visitez le site web de REA](https://rea.tools/fr/)** pour les instructions d'installation, des guides illustrés et des études de cas réelles.
|
||||
|
||||
@@ -150,7 +150,7 @@ REA nécessite Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) ou 26+ (>=26.12.1), ai
|
||||
|
||||
| Cible | Ce que REA renvoie | Prérequis et guide |
|
||||
| ---------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Binaires natifs | Pseudo-code, assembleur, chaînes, symboles, appels et références | Hopper, Ghidra ou IDA ; [analyse native](../native-investigation.md) |
|
||||
| Binaires natifs | Pseudo-code, assembleur, chaînes, symboles, appels et références | Hopper, Ghidra, IDA ou Kuna ; [analyse native](../native-investigation.md) |
|
||||
| Structure ELF hors ligne | Sections, segments, symboles et relocations d'origine, et protections statiques candidates | pwntools fourni par l'utilisateur sous Linux x64 ; [diagnostics binaires](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -189,6 +189,8 @@ REA nécessite Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) ou 26+ (>=26.12.1), ai
|
||||
|
||||
L'inspection statique JavaScript et .NET lit les fichiers fournis sans exécuter l'application. La capture à l'exécution lance la cible choisie ou interagit avec elle avec vos permissions utilisateur ; chaque guide d'exécution décrit ses effets.
|
||||
|
||||
Pour inspecter les binaires natifs hors ligne, REA prend aussi en charge GNU objdump et Rizin, que vous devez fournir vous-même. Le [guide des outils de rétro-ingénierie](../reverse-engineering-tools.md) décrit la configuration des fournisseurs, les commandes CLI et les limites des Evidence. REA n’installe ni ne met à jour ces deux fournisseurs.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
Les formats natifs et les hôtes pris en charge varient selon le fournisseur. Consultez [la configuration de Hopper et Ghidra](../installation.md#hopper), le [guide IDA](../ida-provider.md), [Kuna](../kuna-provider.md) et [la prise en charge expérimentale de Ghidra sous Windows](../windows-ghidra-p0.md). Ghidra prend aussi en charge [l'analyse DOS 16 bits](../ghidra-dos.md). Pour les gros binaires, augmentez son délai de démarrage avec `REA_GHIDRA_STARTUP_TIMEOUT_MS` / `REA_HOPPER_STARTUP_TIMEOUT_MS`. Pour le choix du fournisseur, consultez le [guide CLI](../cli.md#choose-a-provider). Vérifiez la [disponibilité dans les versions publiées](../installation.md#released-package-and-main) pour les fonctionnalités ajoutées depuis la dernière version npm.
|
||||
@@ -275,9 +277,9 @@ Tout agent compatible avec les serveurs MCP locaux. Setup configure les [agents
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Ai-je besoin de Hopper, Ghidra ou IDA ?</strong></summary>
|
||||
<summary><strong>Ai-je besoin de Hopper, Ghidra, IDA ou Kuna ?</strong></summary>
|
||||
|
||||
L'analyse native approfondie utilise l'un d'eux. L'inspection statique JavaScript et .NET fonctionne sans moteur d'analyse native. Setup peut installer Hopper après votre accord ; Ghidra et IDA utilisent vos installations existantes. Consultez [la configuration des fournisseurs](../installation.md#hopper).
|
||||
L'analyse native approfondie utilise l'un d'eux. L'inspection statique JavaScript et .NET fonctionne sans moteur d'analyse native. Setup peut installer Hopper après votre accord ; Ghidra, IDA et Kuna utilisent vos installations existantes. Consultez [la configuration des fournisseurs](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Situs Web](https://rea.tools/id/) · [Panduan](https://rea.tools/id/guides/) · [Contoh Penggunaan](https://rea.tools/id/showcase/)**
|
||||
|
||||
[Mulai Cepat](#mulai-cepat) · [Cara Kerja REA](#cara-kerja-rea) · [Hal yang Dapat Anda Analisis](#hal-yang-dapat-anda-analisis) · [Contoh Penggunaan](#contoh-penggunaan) · [Membangun lingkungan RL](#build-rl-environments) · [FAQ](#faq) · [Alat GNU objdump dan Rizin](../reverse-engineering-tools.md) · [Dokumentasi](#dokumentasi)
|
||||
[Mulai Cepat](#mulai-cepat) · [Cara Kerja REA](#cara-kerja-rea) · [Hal yang Dapat Anda Analisis](#hal-yang-dapat-anda-analisis) · [Contoh Penggunaan](#contoh-penggunaan) · [Membangun lingkungan RL](#build-rl-environments) · [FAQ](#faq) · [Dokumentasi](#dokumentasi)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@ Melihat fitur dalam suatu aplikasi yang ingin Anda hadirkan di produk sendiri? M
|
||||
|
||||
REA menghubungkan agen Anda dengan berbagai alat untuk memeriksa biner native, aplikasi JavaScript dan Electron, assembly .NET, serta situs web. Anda juga dapat menggunakan alat yang sama dari terminal. Analisis dijalankan secara lokal, dan hasilnya mencakup bukti serta keterbatasan yang mendasari setiap kesimpulan.
|
||||
|
||||
Proses penyiapan mendaftarkan REA ke agen Anda dan memasang instruksi alur kerja yang sesuai. Analisis native dapat menggunakan instalasi Hopper, Ghidra, atau IDA yang sudah ada. Proses penyiapan juga dapat memasang Hopper secara opsional setelah mendapatkan persetujuan. Analisis JavaScript statis tidak memerlukan mesin analisis native.
|
||||
Proses penyiapan mendaftarkan REA ke agen Anda dan memasang instruksi alur kerja yang sesuai. Analisis native dapat menggunakan instalasi Hopper, Ghidra, IDA, atau Kuna yang sudah ada. Proses penyiapan juga dapat memasang Hopper secara opsional setelah mendapatkan persetujuan. Analisis JavaScript statis tidak memerlukan mesin analisis native.
|
||||
|
||||
> **[Kunjungi situs web REA](https://rea.tools/id/)** untuk mendapatkan petunjuk penyiapan, panduan bergambar, dan studi kasus nyata.
|
||||
|
||||
@@ -153,18 +153,18 @@ Alat tambahan dan dukungan sistem host bergantung pada target yang dianalisis:
|
||||
|
||||
| Target | Hasil yang diberikan REA | Persyaratan dan panduan |
|
||||
| -------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Biner native | Pseudocode, assembly, string, simbol, pemanggilan, dan referensi | Hopper, Ghidra, atau IDA; [analisis native](../native-investigation.md) |
|
||||
| Biner native | Pseudocode, assembly, string, simbol, pemanggilan, dan referensi | Hopper, Ghidra, IDA, atau Kuna; [analisis native](../native-investigation.md) |
|
||||
| Tata letak ELF offline | Bagian, segmen, simbol/relokasi asli, dan kandidat mitigasi statis | pwntools yang disediakan pemanggil pada Linux x64; [diagnostik biner](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
| Artefak WASM | Validasi, bagian, bentuk WAT import/ekspor yang tepat, dan WAT yang didekode | WABT 1.0.42 yang disediakan pemanggil; `inspect_wasm_artifact` |
|
||||
| Bytecode EVM | Selector dispatch, offset byte, argumen yang disimpulkan, dan sifat mutabilitas | Pembawa data raw/hex lokal; [panduan EVM offline](../evm-bytecode.md) |
|
||||
| Bytecode EVM | Selector dispatch, offset byte, argumen yang disimpulkan, dan sifat mutabilitas | Pembawa data raw/hex lokal di Linux x64; [panduan EVM offline](../evm-bytecode.md) |
|
||||
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
|
||||
| ELF notes | PT_NOTE/SHT_NOTE owners, types, GNU build-id and ABI-tag fields | Built-in static ELF inspection; [ELF notes](../elf-notes.md) |
|
||||
| Apple IPS crashes | .ips metadata, threads, images, registers and crash classes | Built-in static JSON inspection; [Apple IPS](../apple-ips.md) |
|
||||
| Linux kernel modules | .modinfo keys, __versions CRCs, this_module presence, and signature trailer | Built-in static ELF inspection; [kernel modules](../kernel-modules.md) |
|
||||
| Erlang BEAM | IFF chunks, atoms, exports, and tables | Built-in static BEAM inspection; [Erlang BEAM](../erlang-beam.md) |
|
||||
| Crash Linux yang direkam | Catatan mentah, register/sinyal setiap thread yang direkam, dan kandidat pemetaan opsional | pwntools yang disediakan pemanggil; GDB/pwndbg opsional; [crash yang direkam](../recorded-crashes.md) |
|
||||
| Crash Linux yang direkam | Catatan mentah, register/sinyal setiap thread yang direkam, dan kandidat pemetaan opsional | pwntools yang disediakan pemanggil di Linux x64; GDB/pwndbg opsional; [crash yang direkam](../recorded-crashes.md) |
|
||||
| Instalasi desktop | Kandidat runtime, berkas pendukung, penanda komponen, dan langkah berikutnya | Pemeriksaan direktori dan header terbatas;[Aplikasi desktop](../desktop-applications.md) |
|
||||
| JavaScript / Electron | Modul, impor, source map, rute, IPC, dan hubungan add-on native | Node.js dan npm; [analisis aplikasi](../javascript-application-workflows.md); Linux: procps `ps` |
|
||||
| Situs web | Struktur halaman, skrip, pengamatan jaringan, dan tangkapan layar yang diminta | Peramban berbasis Chrome; [analisis peramban](../browser-observation.md) |
|
||||
@@ -192,6 +192,8 @@ Alat tambahan dan dukungan sistem host bergantung pada target yang dianalisis:
|
||||
|
||||
Pemeriksaan JavaScript dan .NET statis membaca berkas yang disediakan tanpa menjalankan aplikasinya. Perekaman runtime menjalankan atau berinteraksi dengan target yang dipilih menggunakan izin pengguna Anda. Setiap panduan runtime menjelaskan dampaknya.
|
||||
|
||||
Untuk pemeriksaan biner native secara offline, REA juga mendukung GNU objdump dan Rizin yang Anda sediakan sendiri. [Panduan alat rekayasa balik](../reverse-engineering-tools.md) menjelaskan penyiapan penyedia, perintah CLI, dan keterbatasan Evidence. REA tidak menginstal atau memperbarui kedua penyedia tersebut.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
Format native dan dukungan sistem host berbeda-beda menurut penyedia. Lihat [penyiapan Hopper dan Ghidra](../installation.md#hopper), [panduan IDA](../ida-provider.md), [Kuna](../kuna-provider.md), dan [dukungan eksperimental Ghidra di Windows](../windows-ghidra-p0.md).
|
||||
@@ -286,11 +288,11 @@ Agen apa pun yang mendukung server MCP lokal dapat menggunakan REA. Proses penyi
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Apakah saya memerlukan Hopper, Ghidra, atau IDA?</strong></summary>
|
||||
<summary><strong>Apakah saya memerlukan Hopper, Ghidra, IDA, atau Kuna?</strong></summary>
|
||||
|
||||
Analisis native mendalam menggunakan salah satu dari ketiganya. Pemeriksaan JavaScript dan .NET statis dapat dilakukan tanpa mesin analisis native.
|
||||
Analisis native mendalam menggunakan salah satu dari keempatnya. Pemeriksaan JavaScript dan .NET statis dapat dilakukan tanpa mesin analisis native.
|
||||
|
||||
Proses penyiapan dapat memasang Hopper setelah memperoleh persetujuan. Ghidra dan IDA menggunakan instalasi yang sudah tersedia. Lihat [penyiapan penyedia](../installation.md#hopper).
|
||||
Proses penyiapan dapat memasang Hopper setelah memperoleh persetujuan. Ghidra, IDA, dan Kuna menggunakan instalasi yang sudah tersedia. Lihat [penyiapan penyedia](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Sito web](https://rea.tools/it/) · [Guide](https://rea.tools/it/guides/) · [Showcase](https://rea.tools/it/showcase/)**
|
||||
|
||||
[Avvio rapido](#avvio-rapido) · [Come funziona REA](#come-funziona-rea) · [Cosa puoi analizzare](#cosa-puoi-analizzare) · [Showcase](#showcase) · [Creare ambienti RL](#build-rl-environments) · [FAQ](#faq) · [Strumenti GNU objdump e Rizin](../reverse-engineering-tools.md) · [Documentazione](#documentazione)
|
||||
[Avvio rapido](#avvio-rapido) · [Come funziona REA](#come-funziona-rea) · [Cosa puoi analizzare](#cosa-puoi-analizzare) · [Showcase](#showcase) · [Creare ambienti RL](#build-rl-environments) · [FAQ](#faq) · [Documentazione](#documentazione)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@ Hai visto una funzionalità in un'app che vorresti nel tuo prodotto? Chiedi al t
|
||||
|
||||
REA collega il tuo agente a strumenti per ispezionare binari nativi, app JavaScript ed Electron, assembly .NET e siti web. Puoi usare gli stessi strumenti anche dal terminale. L'analisi viene eseguita localmente e i risultati includono le prove e i limiti dietro ogni conclusione.
|
||||
|
||||
La configurazione registra REA con il tuo agente e installa le istruzioni di workflow corrispondenti. L'analisi nativa può usare un'installazione esistente di Hopper, Ghidra o IDA; la configurazione può installare opzionalmente Hopper previa approvazione. L'analisi statica JavaScript non richiede alcun motore di analisi nativo.
|
||||
La configurazione registra REA con il tuo agente e installa le istruzioni di workflow corrispondenti. L'analisi nativa può usare un'installazione esistente di Hopper, Ghidra, IDA o Kuna; la configurazione può installare opzionalmente Hopper previa approvazione. L'analisi statica JavaScript non richiede alcun motore di analisi nativo.
|
||||
|
||||
> **[Visita il sito web di REA](https://rea.tools/it/)** per istruzioni di configurazione, guide illustrate e veri casi studio.
|
||||
|
||||
@@ -150,18 +150,18 @@ REA richiede Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) o 26+ (>=26.12.1), oltre
|
||||
|
||||
| Obiettivo | Cosa restituisce REA | Requisiti e guida |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Binari nativi | Pseudocodice, assembly, stringhe, simboli, chiamate e riferimenti | Hopper, Ghidra o IDA; [analisi nativa](../native-investigation.md) |
|
||||
| Binari nativi | Pseudocodice, assembly, stringhe, simboli, chiamate e riferimenti | Hopper, Ghidra, IDA o Kuna; [analisi nativa](../native-investigation.md) |
|
||||
| Layout ELF offline | Sezioni, segmenti, simboli/relocazioni originali e candidati mitigazioni statiche | pwntools fornito dal chiamante su Linux x64; [diagnostica binaria](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
| Artefatto WASM | Convalida, sezioni, forme WAT di import/export esatte e WAT decodificato | WABT 1.0.42 fornito dal chiamante; `inspect_wasm_artifact` |
|
||||
| Bytecode EVM | Selettori di dispatch, offset dei byte, argomenti inferiti e mutabilità | Carrier raw/hex locale; [guida EVM offline](../evm-bytecode.md) |
|
||||
| Bytecode EVM | Selettori di dispatch, offset dei byte, argomenti inferiti e mutabilità | Carrier raw/hex locale su Linux x64; [guida EVM offline](../evm-bytecode.md) |
|
||||
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
|
||||
| ELF notes | PT_NOTE/SHT_NOTE owners, types, GNU build-id and ABI-tag fields | Built-in static ELF inspection; [ELF notes](../elf-notes.md) |
|
||||
| Linux kernel modules | .modinfo keys, __versions CRCs, this_module presence, and signature trailer | Built-in static ELF inspection; [kernel modules](../kernel-modules.md) |
|
||||
| Erlang BEAM | IFF chunks, atoms, exports, and tables | Built-in static BEAM inspection; [Erlang BEAM](../erlang-beam.md) |
|
||||
| Apple IPS crashes | .ips metadata, threads, images, registers and crash classes | Built-in static JSON inspection; [Apple IPS](../apple-ips.md) |
|
||||
| Crash Linux registrati | Note grezze, registri/segnai di ogni thread registrato e candidati mapping opzionali | pwntools fornito dal chiamante; GDB/pwndbg opzionale; [crash registrati](../recorded-crashes.md) |
|
||||
| Crash Linux registrati | Note grezze, registri/segnai di ogni thread registrato e candidati mapping opzionali | pwntools fornito dal chiamante su Linux x64; GDB/pwndbg opzionale; [crash registrati](../recorded-crashes.md) |
|
||||
| Installazioni desktop | Runtime candidati, file di supporto, componenti e passi successivi | Ispezione limitata di directory e intestazioni;[Applicazioni desktop](../desktop-applications.md) |
|
||||
| JavaScript / Electron | Moduli, import, source map, route, IPC e relazioni con add-on nativi | Node.js e npm; [analisi delle applicazioni](../javascript-application-workflows.md); Linux: procps `ps` |
|
||||
| Siti web | Struttura della pagina, script, osservazioni di rete e screenshot richiesti | Un browser della famiglia Chrome; [analisi browser](../browser-observation.md) |
|
||||
@@ -189,6 +189,8 @@ REA richiede Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) o 26+ (>=26.12.1), oltre
|
||||
|
||||
L'ispezione statica di JavaScript e .NET legge i file forniti senza eseguire l'applicazione. La cattura a runtime esegue o interagisce con il bersaglio selezionato usando i tuoi permessi utente; ogni guida runtime descrive i suoi effetti.
|
||||
|
||||
Per ispezionare offline i binari nativi, REA supporta anche GNU objdump e Rizin, che devi fornire autonomamente. La [guida agli strumenti di reverse engineering](../reverse-engineering-tools.md) descrive la configurazione dei provider, i comandi CLI e i limiti di Evidence. REA non installa né aggiorna questi due provider.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
I formati nativi e il supporto host variano in base al provider. Vedi la [configurazione di Hopper e Ghidra](../installation.md#hopper), la [guida IDA](../ida-provider.md), [Kuna](../kuna-provider.md) e il [supporto sperimentale Windows Ghidra](../windows-ghidra-p0.md). Ghidra supporta anche l'[analisi DOS a 16 bit](../ghidra-dos.md). Per binari di grandi dimensioni, aumenta il timeout di avvio con `REA_GHIDRA_STARTUP_TIMEOUT_MS` / `REA_HOPPER_STARTUP_TIMEOUT_MS`. Per la selezione del provider, vedi la [guida CLI](../cli.md#choose-a-provider). Controlla la [disponibilità delle release](../installation.md#released-package-and-main) per le funzionalità aggiunte dall'ultima release npm.
|
||||
@@ -275,9 +277,9 @@ Qualsiasi agente che supporti server MCP locali. La configurazione configura gli
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Ho bisogno di Hopper, Ghidra o IDA?</strong></summary>
|
||||
<summary><strong>Ho bisogno di Hopper, Ghidra, IDA o Kuna?</strong></summary>
|
||||
|
||||
L'analisi nativa profonda ne usa uno. L'ispezione statica di JavaScript e .NET funziona senza un motore di analisi nativo. La configurazione può installare Hopper previa approvazione; Ghidra e IDA usano le tue installazioni esistenti. Vedi [configurazione provider](../installation.md#hopper).
|
||||
L'analisi nativa profonda ne usa uno. L'ispezione statica di JavaScript e .NET funziona senza un motore di analisi nativo. La configurazione può installare Hopper previa approvazione; Ghidra, IDA e Kuna usano le tue installazioni esistenti. Vedi [configurazione provider](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[ウェブサイト](https://rea.tools/ja/) · [ガイド](https://rea.tools/ja/guides/) · [事例](https://rea.tools/ja/showcase/)**
|
||||
|
||||
[クイックスタート](#クイックスタート) · [REA の仕組み](#rea-の仕組み) · [分析できる対象](#分析できる対象) · [事例](#事例) · [RL 環境を構築する](#build-rl-environments) · [よくある質問](#よくある質問) · [GNU objdump・Rizin ツール](../reverse-engineering-tools.md) · [ドキュメント](#ドキュメント)
|
||||
[クイックスタート](#クイックスタート) · [REA の仕組み](#rea-の仕組み) · [分析できる対象](#分析できる対象) · [事例](#事例) · [RL 環境を構築する](#build-rl-environments) · [よくある質問](#よくある質問) · [ドキュメント](#ドキュメント)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
REA はエージェントを分析ツールにつなぎ、ネイティブバイナリ、JavaScript や Electron のアプリ、.NET アセンブリ、ウェブサイトを調べられるようにします。同じツールをターミナルからも使えます。分析はローカルで実行され、結果には各結論を裏付ける根拠と制限事項が含まれます。
|
||||
|
||||
セットアップはエージェントに REA を登録し、対応するワークフロー指示をインストールします。ネイティブ解析には既存の Hopper、Ghidra、IDA を使用でき、承認すれば Hopper をインストールできます。静的 JavaScript 解析にネイティブ解析エンジンは不要です。
|
||||
セットアップはエージェントに REA を登録し、対応するワークフロー指示をインストールします。ネイティブ解析には既存の Hopper、Ghidra、IDA、Kuna を使用でき、承認すれば Hopper をインストールできます。静的 JavaScript 解析にネイティブ解析エンジンは不要です。
|
||||
|
||||
> **[REA のウェブサイト](https://rea.tools/ja/)**で、セットアップ手順、図解ガイド、実際の事例を確認できます。
|
||||
|
||||
@@ -151,7 +151,7 @@ REA には Node.js 22.x(>=22.23.4)、24.x(>=24.22.1)、または 26+ (>=
|
||||
|
||||
| 対象 | REA が返すもの | 要件とガイド |
|
||||
| -------------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| ネイティブバイナリ | 疑似コード、アセンブリ、文字列、シンボル、呼び出し、参照 | Hopper、Ghidra、または IDA;[ネイティブ分析](../native-investigation.md) |
|
||||
| ネイティブバイナリ | 疑似コード、アセンブリ、文字列、シンボル、呼び出し、参照 | Hopper、Ghidra、IDA、または Kuna;[ネイティブ分析](../native-investigation.md) |
|
||||
| オフライン ELF レイアウト | セクション、セグメント、元のシンボル/再配置情報、静的解析によるセキュリティ対策の候補 | Linux x64 で利用者が用意する pwntools;[バイナリ診断](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -190,6 +190,8 @@ REA には Node.js 22.x(>=22.23.4)、24.x(>=24.22.1)、または 26+ (>=
|
||||
|
||||
静的な JavaScript と .NET の検査は、指定されたファイルを読み取り、アプリケーションを実行しません。実行時キャプチャは、あなたのユーザー権限で対象を実行したり、対象とやり取りしたりします。それぞれの実行時ガイドに、どのような操作が行われるかを記載しています。
|
||||
|
||||
ネイティブバイナリのオフライン検査では、利用者が用意した GNU objdump と Rizin も使用できます。[リバースエンジニアリングツールのガイド](../reverse-engineering-tools.md)では、プロバイダーのセットアップ、CLI コマンド、Evidence の制約を説明しています。REA はどちらのプロバイダーもインストールや更新を行いません。
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
大きなバイナリでは `REA_GHIDRA_STARTUP_TIMEOUT_MS` または `REA_HOPPER_STARTUP_TIMEOUT_MS` でプロバイダーの起動期限を延長できます。
|
||||
@@ -280,9 +282,9 @@ REA は実行可能な環境と、起動して応答することを確認する
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Hopper、Ghidra、IDA は必要ですか?</strong></summary>
|
||||
<summary><strong>Hopper、Ghidra、IDA、Kuna は必要ですか?</strong></summary>
|
||||
|
||||
深いネイティブ分析には、そのいずれかを使います。静的な JavaScript と .NET の検査には、ネイティブ分析エンジンは必要ありません。セットアップは承認後に Hopper をインストールできます。Ghidra と IDA は既存のインストールを使います。[プロバイダーのセットアップ](../installation.md#hopper)を参照してください。
|
||||
深いネイティブ分析には、そのいずれかを使います。静的な JavaScript と .NET の検査には、ネイティブ分析エンジンは必要ありません。セットアップは承認後に Hopper をインストールできます。Ghidra、IDA、Kuna は既存のインストールを使います。[プロバイダーのセットアップ](../installation.md#hopper)を参照してください。
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
REA는 에이전트를 분석 도구에 연결해 네이티브 바이너리, JavaScript와 Electron 앱, .NET 어셈블리, 웹사이트를 검사할 수 있게 합니다. 터미널에서도 같은 도구를 사용할 수 있습니다. 분석은 로컬에서 실행되며, 결과에는 각 결론의 근거와 한계가 포함됩니다.
|
||||
|
||||
설정 과정은 에이전트에 REA를 등록하고 해당 버전에 맞는 워크플로 지침을 설치합니다. 네이티브 분석에는 기존 Hopper, Ghidra 또는 IDA 설치를 사용할 수 있습니다. 승인하면 설정 과정에서 Hopper를 설치할 수도 있습니다. 정적 JavaScript 분석에는 네이티브 분석 엔진이 필요하지 않습니다.
|
||||
설정 과정은 에이전트에 REA를 등록하고 해당 버전에 맞는 워크플로 지침을 설치합니다. 네이티브 분석에는 기존 Hopper, Ghidra, IDA 또는 Kuna 설치를 사용할 수 있습니다. 승인하면 설정 과정에서 Hopper를 설치할 수도 있습니다. 정적 JavaScript 분석에는 네이티브 분석 엔진이 필요하지 않습니다.
|
||||
|
||||
> <strong>[REA 웹사이트](https://rea.tools/ko/)</strong>에서 설정 방법, 그림으로 설명한 가이드, 실제 사례를 확인하세요.
|
||||
|
||||
@@ -151,7 +151,7 @@ REA에는 Node.js 22.x(>=22.23.4), 24.x(>=24.22.1) 또는 26+ (>=26.12.1)와 npm
|
||||
|
||||
| 대상 | REA가 반환하는 내용 | 요구 사항 및 가이드 |
|
||||
| ---------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 네이티브 바이너리 | 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조 | Hopper, Ghidra 또는 IDA; [네이티브 분석](../native-investigation.md) |
|
||||
| 네이티브 바이너리 | 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조 | Hopper, Ghidra, IDA 또는 Kuna; [네이티브 분석](../native-investigation.md) |
|
||||
| 오프라인 ELF 레이아웃 | 섹션, 세그먼트, 원본 심볼/재배치 정보, 정적 분석으로 얻은 보안 완화 기법 후보 | Linux x64에서 호출자가 제공하는 pwntools; [바이너리 진단](../binary-diagnostics.md) |
|
||||
| Go 바이너리 | 내장된 컴파일러 버전, 모듈, `replace` 지시어, 빌드 설정 | REA 내장 ELF/PE/thin Mach-O 정적 검사; Go 설치 불필요 |
|
||||
| Rust 바이너리 | cargo-auditable이 내장한 크레이트 이름, 버전, 소스, 의존성 관계 | REA 내장 ELF/PE/thin Mach-O 정적 검사; [Rust 바이너리](../rust-binaries.md) |
|
||||
@@ -280,9 +280,9 @@ REA는 실행 가능한 환경과 시작 및 응답 여부를 확인하는 기
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Hopper, Ghidra 또는 IDA가 필요한가요?</strong></summary>
|
||||
<summary><strong>Hopper, Ghidra, IDA 또는 Kuna가 필요한가요?</strong></summary>
|
||||
|
||||
심층 네이티브 분석에는 이 중 하나를 사용합니다. 정적 JavaScript 및 .NET 검사에는 네이티브 분석 엔진이 필요하지 않습니다. 설정 과정에서 승인 후 Hopper를 설치할 수 있으며, Ghidra와 IDA는 기존 설치를 사용합니다. [제공자 설정](../installation.md#hopper)을 참고하세요.
|
||||
심층 네이티브 분석에는 이 중 하나를 사용합니다. 정적 JavaScript 및 .NET 검사에는 네이티브 분석 엔진이 필요하지 않습니다. 설정 과정에서 승인 후 Hopper를 설치할 수 있으며, Ghidra, IDA, Kuna는 기존 설치를 사용합니다. [제공자 설정](../installation.md#hopper)을 참고하세요.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
Native binaries, JavaScript, Electron apps, .NET assemblies, websites എന്നിവ പരിശോധിക്കുന്നതിനുള്ള tools-ലേക്ക് REA നിങ്ങളുടെ agent-നെ ബന്ധിപ്പിക്കുന്നു. ഇതേ tools നിങ്ങളുടെ terminal-ൽ നിന്നും ഉപയോഗിക്കാം. വിശകലനം local ആയി നടക്കുന്നു; ഓരോ നിഗമനത്തിനും പിന്നിലെ തെളിവുകളും പരിമിതികളും ഫലങ്ങളിൽ ഉൾപ്പെടുന്നു.
|
||||
|
||||
Setup നിങ്ങളുടെ agent-ിൽ REA രജിസ്റ്റർ ചെയ്യുകയും അനുയോജ്യമായ workflow നിർദ്ദേശങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്യുകയും ചെയ്യുന്നു. Native analysis-നായി നിലവിലുള്ള Hopper, Ghidra, അല്ലെങ്കിൽ IDA installation ഉപയോഗിക്കാം; അനുമതി നൽകിയാൽ setup-ന് Hopper ഇൻസ്റ്റാൾ ചെയ്യാനും കഴിയും. Static JavaScript analysis-ന് native analysis engine ആവശ്യമില്ല.
|
||||
Setup നിങ്ങളുടെ agent-ിൽ REA രജിസ്റ്റർ ചെയ്യുകയും അനുയോജ്യമായ workflow നിർദ്ദേശങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്യുകയും ചെയ്യുന്നു. Native analysis-നായി നിലവിലുള്ള Hopper, Ghidra, IDA, അല്ലെങ്കിൽ Kuna installation ഉപയോഗിക്കാം; അനുമതി നൽകിയാൽ setup-ന് Hopper ഇൻസ്റ്റാൾ ചെയ്യാനും കഴിയും. Static JavaScript analysis-ന് native analysis engine ആവശ്യമില്ല.
|
||||
|
||||
> **[REA വെബ്സൈറ്റ് സന്ദർശിക്കുക](https://rea.tools/)** — setup നിർദ്ദേശങ്ങൾക്കും ചിത്രങ്ങളോടുകൂടിയ ഗൈഡുകൾക്കും യഥാർത്ഥ case study-കൾക്കും.
|
||||
|
||||
@@ -151,7 +151,7 @@ REA-യ്ക്ക് Node.js 22.x (>=22.23.4), 24.x (>=24.22.1), അല്ല
|
||||
|
||||
| Target | REA നൽകുന്ന ഫലങ്ങൾ | ആവശ്യകതകളും ഗൈഡും |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Native binaries | Pseudocode, assembly, strings, symbols, calls, references | Hopper, Ghidra അല്ലെങ്കിൽ IDA; [native analysis](../native-investigation.md) |
|
||||
| Native binaries | Pseudocode, assembly, strings, symbols, calls, references | Hopper, Ghidra, IDA അല്ലെങ്കിൽ Kuna; [native analysis](../native-investigation.md) |
|
||||
| Offline ELF layout | Sections, segments, യഥാർത്ഥ symbols/relocations, static mitigation candidates | Linux x64-ൽ caller നൽകുന്ന pwntools; [binary diagnostics](../binary-diagnostics.md) |
|
||||
| Go binaries | ഉൾച്ചേർത്ത compiler version, modules, replacements, build settings | Built-in static ELF/PE/thin Mach-O പരിശോധന; Go installation ആവശ്യമില്ല |
|
||||
| Rust binaries | ഉൾച്ചേർത്ത cargo-auditable crate പേരുകൾ, versions, sources, dependency edges | Built-in static ELF/PE/thin Mach-O പരിശോധന; [Rust binaries](../rust-binaries.md) |
|
||||
@@ -284,9 +284,9 @@ Local MCP servers പിന്തുണയ്ക്കുന്ന ഏത് age
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Hopper, Ghidra അല്ലെങ്കിൽ IDA ആവശ്യമാണോ?</strong></summary>
|
||||
<summary><strong>Hopper, Ghidra, IDA അല്ലെങ്കിൽ Kuna ആവശ്യമാണോ?</strong></summary>
|
||||
|
||||
ആഴത്തിലുള്ള native analysis-ന് ഇവയിൽ ഒന്ന് ആവശ്യമാണ്. Static JavaScript, .NET പരിശോധനകൾ native analysis engine ഇല്ലാതെയും പ്രവർത്തിക്കും. അനുമതി ലഭിച്ചാൽ setup-ന് Hopper ഇൻസ്റ്റാൾ ചെയ്യാം; Ghidra, IDA എന്നിവയ്ക്കായി നിങ്ങളുടെ നിലവിലുള്ള installations ഉപയോഗിക്കുന്നു. [Provider setup](../installation.md#hopper) കാണുക.
|
||||
ആഴത്തിലുള്ള native analysis-ന് ഇവയിൽ ഒന്ന് ആവശ്യമാണ്. Static JavaScript, .NET പരിശോധനകൾ native analysis engine ഇല്ലാതെയും പ്രവർത്തിക്കും. അനുമതി ലഭിച്ചാൽ setup-ന് Hopper ഇൻസ്റ്റാൾ ചെയ്യാം; Ghidra, IDA, Kuna എന്നിവയ്ക്കായി നിങ്ങളുടെ നിലവിലുള്ള installations ഉപയോഗിക്കുന്നു. [Provider setup](../installation.md#hopper) കാണുക.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Strona internetowa](https://rea.tools/pl/) · [Przewodniki](https://rea.tools/pl/guides/) · [Przykłady zastosowań](https://rea.tools/pl/showcase/)**
|
||||
|
||||
[Szybki start](#szybki-start) · [Jak działa REA](#jak-działa-rea) · [Co możesz analizować](#co-możesz-analizować) · [Przykłady zastosowań](#przykłady-zastosowań) · [Tworzenie środowisk RL](#build-rl-environments) · [FAQ](#faq) · [Narzędzia GNU objdump i Rizin](../reverse-engineering-tools.md) · [Dokumentacja](#dokumentacja)
|
||||
[Szybki start](#szybki-start) · [Jak działa REA](#jak-działa-rea) · [Co możesz analizować](#co-możesz-analizować) · [Przykłady zastosowań](#przykłady-zastosowań) · [Tworzenie środowisk RL](#build-rl-environments) · [FAQ](#faq) · [Dokumentacja](#dokumentacja)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@ Widzisz w aplikacji funkcję, którą chcesz mieć we własnym produkcie? Popro
|
||||
|
||||
REA łączy Twojego agenta z narzędziami do analizy natywnych plików binarnych, aplikacji JavaScript i Electron, zestawów .NET oraz stron internetowych. Z tych samych narzędzi możesz korzystać w terminalu. Analiza odbywa się lokalnie, a wyniki zawierają dowody i ograniczenia stojące za każdym wnioskiem.
|
||||
|
||||
Konfigurator rejestruje REA w Twoim agencie i instaluje pasujące instrukcje pracy. Analiza kodu natywnego może korzystać z istniejącej instalacji Hoppera lub Ghidry; konfigurator może też zainstalować Hoppera po uzyskaniu zgody. Statyczna analiza JavaScript nie wymaga żadnego z tych silników.
|
||||
Konfigurator rejestruje REA w Twoim agencie i instaluje pasujące instrukcje pracy. Analiza kodu natywnego może korzystać z istniejącej instalacji Hoppera, Ghidry, IDA lub Kuna; konfigurator może też zainstalować Hoppera po uzyskaniu zgody. Statyczna analiza JavaScript nie wymaga żadnego z tych silników.
|
||||
|
||||
> **[Odwiedź stronę REA](https://rea.tools/pl/)**, aby znaleźć instrukcje konfiguracji, ilustrowane przewodniki i rzeczywiste studia przypadków.
|
||||
|
||||
@@ -151,7 +151,7 @@ REA wymaga Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) lub 26+ (>=26.12.1) oraz n
|
||||
|
||||
| Cel | Co zwraca REA | Wymagania i przewodnik |
|
||||
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Natywne pliki binarne | Pseudokod, kod asemblera, ciągi znaków, symbole, wywołania i odwołania | Hopper, Ghidra lub IDA; [analiza kodu natywnego](../native-investigation.md) |
|
||||
| Natywne pliki binarne | Pseudokod, kod asemblera, ciągi znaków, symbole, wywołania i odwołania | Hopper, Ghidra, IDA lub Kuna; [analiza kodu natywnego](../native-investigation.md) |
|
||||
| Układ pliku ELF w trybie offline | Sekcje, segmenty, oryginalne symbole/relokacje i potencjalne mechanizmy zabezpieczeń wskazane przez analizę statyczną | pwntools dostarczone przez użytkownika w systemie Linux x64; [diagnostyka plików binarnych](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -190,6 +190,8 @@ REA wymaga Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) lub 26+ (>=26.12.1) oraz n
|
||||
|
||||
Statyczna analiza JavaScript i .NET odczytuje dostarczone pliki bez uruchamiania aplikacji. Przechwytywanie w czasie wykonywania uruchamia wybrany cel lub wchodzi z nim w interakcje z uprawnieniami Twojego użytkownika; skutki opisano w odpowiednich przewodnikach.
|
||||
|
||||
Do analizy offline natywnych plików binarnych REA obsługuje również GNU objdump i Rizin, które musisz dostarczyć samodzielnie. [Przewodnik po narzędziach inżynierii wstecznej](../reverse-engineering-tools.md) opisuje konfigurację dostawców, polecenia CLI i ograniczenia Evidence. REA nie instaluje ani nie aktualizuje żadnego z tych dostawców.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
Dla dużych plików zwiększ czas uruchomienia przez `REA_GHIDRA_STARTUP_TIMEOUT_MS` lub `REA_HOPPER_STARTUP_TIMEOUT_MS`.
|
||||
@@ -278,9 +280,9 @@ Każdy agent obsługujący lokalne serwery MCP. Konfigurator konfiguruje [obsłu
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Czy potrzebuję Hoppera, Ghidry lub IDA?</strong></summary>
|
||||
<summary><strong>Czy potrzebuję Hoppera, Ghidry, IDA lub Kuna?</strong></summary>
|
||||
|
||||
Dogłębna analiza kodu natywnego używa jednego z nich. Statyczna analiza JavaScript i .NET działa bez silnika analizy natywnej. Konfigurator może zainstalować Hoppera po uzyskaniu zgody; Ghidra i IDA korzystają z istniejących instalacji. Zobacz [konfigurację dostawców analizy](../installation.md#hopper).
|
||||
Dogłębna analiza kodu natywnego używa jednego z nich. Statyczna analiza JavaScript i .NET działa bez silnika analizy natywnej. Konfigurator może zainstalować Hoppera po uzyskaniu zgody; Ghidra, IDA i Kuna korzystają z istniejących instalacji. Zobacz [konfigurację dostawców analizy](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Site](https://rea.tools/pt-BR/) · [Guias](https://rea.tools/pt-BR/guides/) · [Casos de uso](https://rea.tools/pt-BR/showcase/)**
|
||||
|
||||
[Início rápido](#início-rápido) · [Como o REA funciona](#como-o-rea-funciona) · [O que você pode analisar](#o-que-você-pode-analisar) · [Casos de uso](#casos-de-uso) · [Criar ambientes de RL](#build-rl-environments) · [Perguntas frequentes](#perguntas-frequentes) · [Ferramentas GNU objdump e Rizin](../reverse-engineering-tools.md) · [Documentação](#documentação)
|
||||
[Início rápido](#início-rápido) · [Como o REA funciona](#como-o-rea-funciona) · [O que você pode analisar](#o-que-você-pode-analisar) · [Casos de uso](#casos-de-uso) · [Criar ambientes de RL](#build-rl-environments) · [Perguntas frequentes](#perguntas-frequentes) · [Documentação](#documentação)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@ Viu uma funcionalidade em um aplicativo que gostaria de ter no seu próprio prod
|
||||
|
||||
O REA conecta seu agente a ferramentas para inspecionar binários nativos, aplicativos JavaScript e Electron, assemblies .NET e sites. Você também pode usar as mesmas ferramentas pelo terminal. A análise acontece localmente, e os resultados incluem as evidências e limitações por trás de cada conclusão.
|
||||
|
||||
A configuração registra o REA no seu agente e instala as instruções de trabalho correspondentes. A análise nativa pode usar Hopper, Ghidra ou IDA já instalados; o Hopper pode ser instalado após sua aprovação. A análise estática de JavaScript não precisa de um mecanismo de análise nativa.
|
||||
A configuração registra o REA no seu agente e instala as instruções de trabalho correspondentes. A análise nativa pode usar Hopper, Ghidra, IDA ou Kuna já instalados; o Hopper pode ser instalado após sua aprovação. A análise estática de JavaScript não precisa de um mecanismo de análise nativa.
|
||||
|
||||
> **[Visite o site do REA](https://rea.tools/pt-BR/)** para instruções de configuração, guias ilustrados e estudos de caso reais.
|
||||
|
||||
@@ -151,7 +151,7 @@ O REA requer Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) ou 26+ (>=26.12.1), alé
|
||||
|
||||
| Alvo | O que o REA retorna | Requisitos e guia |
|
||||
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Binários nativos | Pseudocódigo, assembly, strings, símbolos, chamadas e referências | Hopper, Ghidra ou IDA; [análise nativa](../native-investigation.md) |
|
||||
| Binários nativos | Pseudocódigo, assembly, strings, símbolos, chamadas e referências | Hopper, Ghidra, IDA ou Kuna; [análise nativa](../native-investigation.md) |
|
||||
| Estrutura ELF sem execução | Seções, segmentos, símbolos/relocações originais e possíveis mecanismos de mitigação identificados por análise estática | pwntools fornecido pelo chamador no Linux x64; [diagnóstico de binários](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -190,6 +190,8 @@ O REA requer Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) ou 26+ (>=26.12.1), alé
|
||||
|
||||
A inspeção estática de JavaScript e .NET lê os arquivos fornecidos sem executar o aplicativo. A captura em execução inicia o alvo selecionado ou interage com ele usando as permissões do seu usuário; cada guia descreve seus efeitos.
|
||||
|
||||
Para inspecionar binários nativos offline, o REA também oferece suporte ao GNU objdump e ao Rizin, que você deve fornecer por conta própria. O [guia de ferramentas de engenharia reversa](../reverse-engineering-tools.md) descreve a configuração dos provedores, os comandos da CLI e as limitações de Evidence. O REA não instala nem atualiza nenhum desses provedores.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
Para binários grandes, aumente o prazo de inicialização com `REA_GHIDRA_STARTUP_TIMEOUT_MS` ou `REA_HOPPER_STARTUP_TIMEOUT_MS`.
|
||||
@@ -278,9 +280,9 @@ Qualquer agente que ofereça suporte a servidores MCP locais. A configuração p
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Preciso do Hopper, Ghidra ou IDA?</strong></summary>
|
||||
<summary><strong>Preciso do Hopper, Ghidra, IDA ou Kuna?</strong></summary>
|
||||
|
||||
A análise nativa aprofundada usa um desses motores. A inspeção estática de JavaScript e .NET funciona sem um motor de análise nativa. A configuração pode instalar o Hopper após aprovação; Ghidra e IDA usam as instalações existentes. Consulte [configuração dos provedores](../installation.md#hopper).
|
||||
A análise nativa aprofundada usa um desses motores. A inspeção estática de JavaScript e .NET funciona sem um motor de análise nativa. A configuração pode instalar o Hopper após aprovação; Ghidra, IDA e Kuna usam as instalações existentes. Consulte [configuração dos provedores](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ Ai văzut într-o aplicație o funcționalitate pe care ai vrea să o incluzi î
|
||||
|
||||
REA conectează agentul tău la unelte pentru inspectarea fișierelor binare native, a aplicațiilor JavaScript și Electron, a ansamblurilor .NET și a site-urilor web. Poți folosi aceleași unelte și din terminal. Analiza rulează local, iar rezultatele includ dovezile și limitările care stau la baza fiecărei concluzii.
|
||||
|
||||
Programul de configurare înregistrează REA în agentul tău și instalează instrucțiunile corespunzătoare pentru fluxul de lucru. Analiza nativă poate folosi o instalare existentă de Hopper, Ghidra sau IDA; programul de configurare poate instala opțional Hopper, cu aprobarea ta. Analiza statică JavaScript nu necesită un motor de analiză nativă.
|
||||
Programul de configurare înregistrează REA în agentul tău și instalează instrucțiunile corespunzătoare pentru fluxul de lucru. Analiza nativă poate folosi o instalare existentă de Hopper, Ghidra, IDA sau Kuna; programul de configurare poate instala opțional Hopper, cu aprobarea ta. Analiza statică JavaScript nu necesită un motor de analiză nativă.
|
||||
|
||||
> **[Vizitează site-ul REA](https://rea.tools/)** pentru instrucțiuni de configurare, ghiduri ilustrate și studii de caz reale.
|
||||
|
||||
@@ -187,7 +187,7 @@ Uneltele suplimentare și platformele acceptate depind de ținta analizată:
|
||||
| Țintă | Ce returnează REA | Cerințe și ghid |
|
||||
| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Aplicații desktop instalate | Componente de execuție candidate, fișiere auxiliare, indicii despre componente și următoarele verificări | Inspectare integrată a directoarelor și antetelor, cu limite de resurse; [aplicații desktop](../desktop-applications.md) |
|
||||
| Fișiere binare native | Pseudocod, cod de asamblare, șiruri de caractere, simboluri, apeluri și referințe | Hopper, Ghidra sau IDA; [analiză nativă](../native-investigation.md) |
|
||||
| Fișiere binare native | Pseudocod, cod de asamblare, șiruri de caractere, simboluri, apeluri și referințe | Hopper, Ghidra, IDA sau Kuna; [analiză nativă](../native-investigation.md) |
|
||||
| Structura ELF, offline | Secțiuni, segmente, simboluri și relocări originale, precum și indicii statice despre mecanismele de protecție | pwntools furnizat de utilizator, pe Linux x64; [diagnosticarea binarelor](../binary-diagnostics.md) |
|
||||
| Fișiere binare Go | Versiunea compilatorului încorporată în fișier, modulele, înlocuirile și setările de compilare | Inspectare statică integrată a fișierelor ELF/PE/Mach-O cu o singură arhitectură; nu necesită instalarea Go |
|
||||
| Obiecte de cod GPU | Ținte CUDA/HIP, parametri și resurse selectate ale kernelurilor GPU, textul PTX păstrat | Inspectare statică integrată a fișierelor ELF/PE/fatbin/CUBIN/PTX; [obiecte de cod GPU](../gpu-code-objects.md) |
|
||||
@@ -342,11 +342,11 @@ poți folosi [înregistrarea manuală MCP](../installation.md#mcp-registry).
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Am nevoie de Hopper, Ghidra sau IDA?</strong></summary>
|
||||
<summary><strong>Am nevoie de Hopper, Ghidra, IDA sau Kuna?</strong></summary>
|
||||
|
||||
Analiza nativă aprofundată folosește unul dintre aceste instrumente. Inspectarea
|
||||
statică JavaScript și .NET funcționează fără un motor de analiză nativă.
|
||||
Programul de configurare poate instala Hopper după aprobare; pentru Ghidra și IDA
|
||||
Programul de configurare poate instala Hopper după aprobare; pentru Ghidra, IDA și Kuna
|
||||
folosește instalările existente. Consultă [configurarea motoarelor de analiză](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Сайт](https://rea.tools/ru/) · [Руководства](https://rea.tools/ru/guides/) · [Примеры](https://rea.tools/ru/showcase/)**
|
||||
|
||||
[Быстрый старт](#быстрый-старт) · [Как работает REA](#как-работает-rea) · [Что можно анализировать](#что-можно-анализировать) · [Примеры](#примеры) · [Создание RL-окружений](#build-rl-environments) · [Частые вопросы](#частые-вопросы) · [Инструменты GNU objdump и Rizin](../reverse-engineering-tools.md) · [Документация](#документация)
|
||||
[Быстрый старт](#быстрый-старт) · [Как работает REA](#как-работает-rea) · [Что можно анализировать](#что-можно-анализировать) · [Примеры](#примеры) · [Создание RL-окружений](#build-rl-environments) · [Частые вопросы](#частые-вопросы) · [Документация](#документация)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
REA подключает вашего агента к инструментам для исследования нативных бинарных файлов, приложений JavaScript и Electron, сборок .NET и сайтов. Те же инструменты доступны в терминале. Анализ выполняется локально, а результаты содержат данные и ограничения, на которых основан каждый вывод.
|
||||
|
||||
Настройка регистрирует REA у агента и устанавливает соответствующие инструкции. Нативный анализ использует установленный Hopper, Ghidra или IDA; Hopper можно установить после одобрения. Статическому анализу JavaScript нативный движок не нужен.
|
||||
Настройка регистрирует REA у агента и устанавливает соответствующие инструкции. Нативный анализ использует установленный Hopper, Ghidra, IDA или Kuna; Hopper можно установить после одобрения. Статическому анализу JavaScript нативный движок не нужен.
|
||||
|
||||
> **[Посетите сайт REA](https://rea.tools/ru/)**: там есть инструкции по настройке, иллюстрированные руководства и реальные исследования.
|
||||
|
||||
@@ -151,7 +151,7 @@ REA требует Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) или 26+ (>=26.1
|
||||
|
||||
| Цель | Что возвращает REA | Требования и руководство |
|
||||
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Нативные бинарные файлы | Псевдокод, ассемблер, строки, символы, вызовы и ссылки | Hopper, Ghidra или IDA; [нативный анализ](../native-investigation.md) |
|
||||
| Нативные бинарные файлы | Псевдокод, ассемблер, строки, символы, вызовы и ссылки | Hopper, Ghidra, IDA или Kuna; [нативный анализ](../native-investigation.md) |
|
||||
| Структура ELF без запуска | Секции, сегменты, исходные символы/релокации и возможные механизмы защиты по данным статического анализа | pwntools, предоставленный вызывающей стороной, в Linux x64; [диагностика бинарных файлов](../binary-diagnostics.md) |
|
||||
| Байт-код EVM | Селекторы диспетчеризации, смещения байтов, предполагаемые аргументы и изменяемость состояния | Локальные необработанные байты или шестнадцатеричное представление в Linux x64; [руководство по EVM без запуска](../evm-bytecode.md) |
|
||||
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
|
||||
@@ -190,6 +190,8 @@ REA требует Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) или 26+ (>=26.1
|
||||
|
||||
Статическое исследование JavaScript и .NET читает предоставленные файлы, не запуская приложение. Захват во время выполнения запускает выбранную цель или взаимодействует с ней с правами вашего пользователя; соответствующие руководства описывают последствия.
|
||||
|
||||
Для автономного анализа нативных бинарных файлов REA также поддерживает GNU objdump и Rizin, которые пользователь предоставляет самостоятельно. В [руководстве по инструментам обратной разработки](../reverse-engineering-tools.md) описаны настройка провайдеров, команды CLI и ограничения Evidence. REA не устанавливает и не обновляет ни один из этих провайдеров.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
Для больших файлов увеличьте срок запуска через `REA_GHIDRA_STARTUP_TIMEOUT_MS` или `REA_HOPPER_STARTUP_TIMEOUT_MS`.
|
||||
@@ -278,9 +280,9 @@ REA экспортирует готовое к запуску окружение
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Нужны ли мне Hopper, Ghidra или IDA?</strong></summary>
|
||||
<summary><strong>Нужны ли мне Hopper, Ghidra, IDA или Kuna?</strong></summary>
|
||||
|
||||
Углублённый нативный анализ использует один из этих инструментов. Статическое исследование JavaScript и .NET работает без движка нативного анализа. Настройка может установить Hopper после подтверждения; Ghidra и IDA используют существующие установки. См. [настройку провайдеров](../installation.md#hopper).
|
||||
Углублённый нативный анализ использует один из этих инструментов. Статическое исследование JavaScript и .NET работает без движка нативного анализа. Настройка может установить Hopper после подтверждения; Ghidra, IDA и Kuna используют существующие установки. См. [настройку провайдеров](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[เว็บไซต์](https://rea.tools/th/) · [คู่มือ](https://rea.tools/th/guides/) · [ตัวอย่างการใช้งาน](https://rea.tools/th/showcase/)**
|
||||
|
||||
[เริ่มต้นอย่างรวดเร็ว](#เริ่มต้นอย่างรวดเร็ว) · [REA ทำงานอย่างไร](#rea-ทำงานอย่างไร) · [สิ่งที่วิเคราะห์ได้](#สิ่งที่วิเคราะห์ได้) · [ตัวอย่างการใช้งาน](#ตัวอย่างการใช้งาน) · [สร้างสภาพแวดล้อม RL](#build-rl-environments) · [คำถามที่พบบ่อย](#คำถามที่พบบ่อย) · [เครื่องมือ GNU objdump และ Rizin](../reverse-engineering-tools.md) · [เอกสาร](#เอกสาร)
|
||||
[เริ่มต้นอย่างรวดเร็ว](#เริ่มต้นอย่างรวดเร็ว) · [REA ทำงานอย่างไร](#rea-ทำงานอย่างไร) · [สิ่งที่วิเคราะห์ได้](#สิ่งที่วิเคราะห์ได้) · [ตัวอย่างการใช้งาน](#ตัวอย่างการใช้งาน) · [สร้างสภาพแวดล้อม RL](#build-rl-environments) · [คำถามที่พบบ่อย](#คำถามที่พบบ่อย) · [เอกสาร](#เอกสาร)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
REA เชื่อมเอเจนต์ของคุณกับเครื่องมือสำหรับตรวจสอบไบนารีเนทีฟ แอป JavaScript และ Electron แอสเซมบลี .NET และเว็บไซต์ คุณใช้เครื่องมือเดียวกันจากเทอร์มินัลได้ การวิเคราะห์ทำงานบนเครื่องของคุณ และผลลัพธ์มีทั้งหลักฐานและข้อจำกัดที่ประกอบแต่ละข้อสรุป
|
||||
|
||||
การตั้งค่าลงทะเบียน REA กับเอเจนต์และติดตั้งคำแนะนำการทำงานที่ตรงกัน การวิเคราะห์เนทีฟใช้ Hopper, Ghidra หรือ IDA ที่มีอยู่ได้ และติดตั้ง Hopper ได้เมื่อคุณอนุมัติ การวิเคราะห์ JavaScript แบบสแตติกไม่ต้องใช้เอนจินวิเคราะห์เนทีฟ
|
||||
การตั้งค่าลงทะเบียน REA กับเอเจนต์และติดตั้งคำแนะนำการทำงานที่ตรงกัน การวิเคราะห์เนทีฟใช้ Hopper, Ghidra, IDA หรือ Kuna ที่มีอยู่ได้ และติดตั้ง Hopper ได้เมื่อคุณอนุมัติ การวิเคราะห์ JavaScript แบบสแตติกไม่ต้องใช้เอนจินวิเคราะห์เนทีฟ
|
||||
|
||||
> **[เยี่ยมชมเว็บไซต์ REA](https://rea.tools/th/)** เพื่อดูคำแนะนำการตั้งค่า คู่มือพร้อมภาพประกอบ และกรณีศึกษาจริง
|
||||
|
||||
@@ -151,7 +151,7 @@ REA ต้องใช้ Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) หรื
|
||||
|
||||
| เป้าหมาย | สิ่งที่ REA ส่งกลับ | ข้อกำหนดและคู่มือ |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| ไบนารีเนทีฟ | โค้ดเทียม แอสเซมบลี สตริง สัญลักษณ์ การเรียก และการอ้างอิง | Hopper, Ghidra หรือ IDA; [การวิเคราะห์เนทีฟ](../native-investigation.md) |
|
||||
| ไบนารีเนทีฟ | โค้ดเทียม แอสเซมบลี สตริง สัญลักษณ์ การเรียก และการอ้างอิง | Hopper, Ghidra, IDA หรือ Kuna; [การวิเคราะห์เนทีฟ](../native-investigation.md) |
|
||||
| โครงสร้าง ELF แบบออฟไลน์ | เซกชัน เซกเมนต์ สัญลักษณ์/รีโลเคชันต้นฉบับ และตัวเลือกกลไกป้องกันที่พบจากการวิเคราะห์แบบสถิต | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; [การวินิจฉัยไบนารี](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -190,6 +190,8 @@ REA ต้องใช้ Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) หรื
|
||||
|
||||
การตรวจสอบ JavaScript และ .NET แบบสถิตอ่านไฟล์ที่ให้มาโดยไม่รันแอปพลิเคชัน การบันทึกขณะทำงานจะรันหรือโต้ตอบกับเป้าหมายที่เลือกโดยใช้สิทธิ์ของผู้ใช้คุณ คู่มือการทำงานแต่ละฉบับอธิบายผลที่เกิดขึ้นไว้
|
||||
|
||||
สำหรับการตรวจสอบไบนารีเนทีฟแบบออฟไลน์ REA ยังรองรับ GNU objdump และ Rizin ที่ผู้ใช้ต้องจัดหาเอง [คู่มือเครื่องมือวิศวกรรมย้อนกลับ](../reverse-engineering-tools.md) อธิบายการตั้งค่าผู้ให้บริการ คำสั่ง CLI และข้อจำกัดของ Evidence โดย REA จะไม่ติดตั้งหรืออัปเดตผู้ให้บริการทั้งสองนี้
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
สำหรับไบนารีขนาดใหญ่ เพิ่มเวลารอเริ่มต้นด้วย `REA_GHIDRA_STARTUP_TIMEOUT_MS` หรือ `REA_HOPPER_STARTUP_TIMEOUT_MS`
|
||||
@@ -278,9 +280,9 @@ REA ส่งออกสภาพแวดล้อมที่รันได
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>จำเป็นต้องมี Hopper, Ghidra หรือ IDA หรือไม่?</strong></summary>
|
||||
<summary><strong>จำเป็นต้องมี Hopper, Ghidra, IDA หรือ Kuna หรือไม่?</strong></summary>
|
||||
|
||||
การวิเคราะห์เนทีฟเชิงลึกต้องใช้หนึ่งในเครื่องมือเหล่านี้ การตรวจสอบ JavaScript และ .NET แบบสถิตทำงานได้โดยไม่มีเอนจินวิเคราะห์เนทีฟ ขั้นตอนตั้งค่าสามารถติดตั้ง Hopper หลังได้รับอนุมัติ ส่วน Ghidra และ IDA ใช้การติดตั้งที่คุณมีอยู่แล้ว ดู[การตั้งค่าผู้ให้บริการวิเคราะห์](../installation.md#hopper)
|
||||
การวิเคราะห์เนทีฟเชิงลึกต้องใช้หนึ่งในเครื่องมือเหล่านี้ การตรวจสอบ JavaScript และ .NET แบบสถิตทำงานได้โดยไม่มีเอนจินวิเคราะห์เนทีฟ ขั้นตอนตั้งค่าสามารถติดตั้ง Hopper หลังได้รับอนุมัติ ส่วน Ghidra, IDA และ Kuna ใช้การติดตั้งที่คุณมีอยู่แล้ว ดู[การตั้งค่าผู้ให้บริการวิเคราะห์](../installation.md#hopper)
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ Bir uygulamada kendi ürününüze eklemek istediğiniz bir özellik mi gördün
|
||||
|
||||
REA, ajanınızı yerel makine kodu içeren ikili dosyaları, JavaScript ve Electron uygulamalarını, .NET derlemelerini ve web sitelerini inceleyen araçlara bağlar. Aynı araçları terminalden de kullanabilirsiniz. Analiz yerel olarak çalışır; sonuçlar her çıkarımın dayandığı kanıtları ve sınırlamaları içerir.
|
||||
|
||||
Kurulum, REA'yı ajanınıza kaydeder ve uyumlu iş akışı talimatlarını yükler. Yerel makine kodu analizi mevcut bir Hopper, Ghidra veya IDA kurulumunu kullanabilir; kurulum işlemi, onayınızla isteğe bağlı olarak Hopper da yükleyebilir. Statik JavaScript analizi bu yerel analiz motorlarından hiçbirine ihtiyaç duymaz.
|
||||
Kurulum, REA'yı ajanınıza kaydeder ve uyumlu iş akışı talimatlarını yükler. Yerel makine kodu analizi mevcut bir Hopper, Ghidra, IDA veya Kuna kurulumunu kullanabilir; kurulum işlemi, onayınızla isteğe bağlı olarak Hopper da yükleyebilir. Statik JavaScript analizi bu yerel analiz motorlarından hiçbirine ihtiyaç duymaz.
|
||||
|
||||
> Kurulum talimatları, görselli rehberler ve gerçek örnek çalışmalar için **[REA web sitesini ziyaret edin](https://rea.tools/tr/)**.
|
||||
|
||||
@@ -149,7 +149,7 @@ REA; Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) veya 26+ (>=26.12.1) ve npm gere
|
||||
|
||||
| Hedef | REA'nın döndürdükleri | Gereksinimler ve rehber |
|
||||
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Yerel makine kodu içeren ikili dosyalar | Sözde kod, assembly kodu, dizeler, semboller, çağrılar ve referanslar | Hopper, Ghidra veya IDA; [yerel kod analizi](../native-investigation.md) |
|
||||
| Yerel makine kodu içeren ikili dosyalar | Sözde kod, assembly kodu, dizeler, semboller, çağrılar ve referanslar | Hopper, Ghidra, IDA veya Kuna; [yerel kod analizi](../native-investigation.md) |
|
||||
| Çevrimdışı ELF yapısı | Bölümler, segmentler, özgün semboller/yeniden konumlandırmalar ve statik analizden olası güvenlik önlemleri | Linux x64 üzerinde çağıranın sağladığı pwntools; [ikili dosya tanılama](../binary-diagnostics.md) |
|
||||
| Go ikili dosyaları | Gömülü compiler sürümü, modüller, replacement'lar ve build ayarları | Yerleşik statik ELF/PE/thin Mach-O incelemesi; Go kurulumu gerekmez |
|
||||
| Rust ikili dosyaları | Gömülü cargo-auditable crate adları, sürümleri, kaynakları ve bağımlılık ilişkileri | Yerleşik statik ELF/PE/thin Mach-O incelemesi; [Rust ikili dosyaları](../rust-binaries.md) |
|
||||
@@ -274,9 +274,9 @@ Yerel MCP sunucularını destekleyen her ajan REA'yı kullanabilir. Kurulum, [de
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Hopper, Ghidra veya IDA gerekiyor mu?</strong></summary>
|
||||
<summary><strong>Hopper, Ghidra, IDA veya Kuna gerekiyor mu?</strong></summary>
|
||||
|
||||
Derin yerel kod analizi bunlardan birini kullanır. Statik JavaScript ve .NET incelemesi yerel analiz motoru olmadan çalışır. Kurulum onaydan sonra Hopper yükleyebilir; Ghidra ve IDA mevcut kurulumlarınızı kullanır. [Sağlayıcı kurulumuna](../installation.md#hopper) bakın.
|
||||
Derin yerel kod analizi bunlardan birini kullanır. Statik JavaScript ve .NET incelemesi yerel analiz motoru olmadan çalışır. Kurulum onaydan sonra Hopper yükleyebilir; Ghidra, IDA ve Kuna mevcut kurulumlarınızı kullanır. [Sağlayıcı kurulumuna](../installation.md#hopper) bakın.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Сайт](https://rea.tools/uk/) · [Посібники](https://rea.tools/uk/guides/) · [Приклади](https://rea.tools/uk/showcase/)**
|
||||
|
||||
[Швидкий старт](#швидкий-старт) · [Як працює REA](#як-працює-rea) · [Що можна аналізувати](#що-можна-аналізувати) · [Приклади](#приклади) · [Створення RL-середовищ](#build-rl-environments) · [Поширені запитання](#поширені-запитання) · [Інструменти GNU objdump і Rizin](../reverse-engineering-tools.md) · [Документація](#документація)
|
||||
[Швидкий старт](#швидкий-старт) · [Як працює REA](#як-працює-rea) · [Що можна аналізувати](#що-можна-аналізувати) · [Приклади](#приклади) · [Створення RL-середовищ](#build-rl-environments) · [Поширені запитання](#поширені-запитання) · [Документація](#документація)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
REA підключає вашого агента до інструментів дослідження нативних бінарних файлів, застосунків JavaScript і Electron, збірок .NET та сайтів. Ті самі інструменти можна використовувати з термінала. Аналіз виконується локально, а результати містять підтвердження й обмеження, на яких ґрунтується кожен висновок.
|
||||
|
||||
Налаштування реєструє REA в агенті та встановлює відповідні інструкції. Нативний аналіз використовує наявний Hopper, Ghidra або IDA; Hopper можна встановити після схвалення. Статичний аналіз JavaScript не потребує нативного рушія.
|
||||
Налаштування реєструє REA в агенті та встановлює відповідні інструкції. Нативний аналіз використовує наявний Hopper, Ghidra, IDA або Kuna; Hopper можна встановити після схвалення. Статичний аналіз JavaScript не потребує нативного рушія.
|
||||
|
||||
> **[Відвідайте сайт REA](https://rea.tools/uk/)**, щоб знайти інструкції налаштування, ілюстровані посібники та реальні дослідження.
|
||||
|
||||
@@ -151,7 +151,7 @@ REA потребує Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) або 26+ (>=26
|
||||
|
||||
| Ціль | Що повертає REA | Вимоги й посібник |
|
||||
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Нативні бінарні файли | Псевдокод, асемблерний код, рядки, символи, виклики й посилання | Hopper, Ghidra або IDA; [нативний аналіз](../native-investigation.md) |
|
||||
| Нативні бінарні файли | Псевдокод, асемблерний код, рядки, символи, виклики й посилання | Hopper, Ghidra, IDA або Kuna; [нативний аналіз](../native-investigation.md) |
|
||||
| Структура ELF без запуску | Секції, сегменти, початкові символи/релокації та можливі захисні механізми за даними статичного аналізу | pwntools, наданий стороною, що викликає інструмент, у Linux x64; [діагностика бінарних файлів](../binary-diagnostics.md) |
|
||||
| PE certificates | Authenticode WIN_CERTIFICATE entries and PKCS#7 signer/X.509 identity fields | Built-in static PE inspection; [PE certificates](../pe-certificates.md) |
|
||||
| PE imports | Import and delay-load DLL names, ordinals, IAT RVAs and pefile import hash | Built-in static PE inspection; [PE imports](../pe-imports.md) |
|
||||
@@ -190,6 +190,8 @@ REA потребує Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) або 26+ (>=26
|
||||
|
||||
Статична перевірка JavaScript і .NET читає надані файли, не запускаючи застосунок. Захоплення під час виконання запускає вибрану ціль або взаємодіє з нею з правами вашого користувача; відповідні посібники описують його вплив.
|
||||
|
||||
Для автономного аналізу нативних бінарних файлів REA також підтримує GNU objdump і Rizin, які користувач надає самостійно. [Посібник з інструментів зворотної розробки](../reverse-engineering-tools.md) описує налаштування провайдерів, команди CLI та обмеження Evidence. REA не встановлює й не оновлює жодного з цих провайдерів.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
Для великих файлів збільште час запуску через `REA_GHIDRA_STARTUP_TIMEOUT_MS` або `REA_HOPPER_STARTUP_TIMEOUT_MS`.
|
||||
@@ -278,9 +280,9 @@ REA експортує готове до запуску середовище з
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Чи потрібні мені Hopper, Ghidra або IDA?</strong></summary>
|
||||
<summary><strong>Чи потрібні мені Hopper, Ghidra, IDA або Kuna?</strong></summary>
|
||||
|
||||
Поглиблений нативний аналіз використовує один із цих інструментів. Статична перевірка JavaScript і .NET працює без рушія нативного аналізу. Налаштування може встановити Hopper після схвалення; Ghidra й IDA використовують наявні встановлення. Дивіться [налаштування провайдерів](../installation.md#hopper).
|
||||
Поглиблений нативний аналіз використовує один із цих інструментів. Статична перевірка JavaScript і .NET працює без рушія нативного аналізу. Налаштування може встановити Hopper після схвалення; Ghidra, IDA й Kuna використовують наявні встановлення. Дивіться [налаштування провайдерів](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ Kisi app mein aisa feature dekha jo aap apne product mein chahte hain? Apne agen
|
||||
|
||||
REA aapke agent ko native binaries, JavaScript aur Electron apps, .NET assemblies aur websites inspect karne wale tools se jorta hai. Yehi tools terminal se bhi use kar sakte hain. Analysis local machine par hota hai, aur har natije ke saath uske saboot aur limitations bhi milti hain.
|
||||
|
||||
Setup REA ko aapke agent ke saath register karta hai aur uske mutabiq workflow instructions install karta hai. Native analysis ke liye pehle se installed Hopper, Ghidra ya IDA use ho sakta hai; aapki approval par setup Hopper bhi install kar sakta hai. Static JavaScript analysis ke liye native analysis engine ki zaroorat nahi.
|
||||
Setup REA ko aapke agent ke saath register karta hai aur uske mutabiq workflow instructions install karta hai. Native analysis ke liye pehle se installed Hopper, Ghidra, IDA ya Kuna use ho sakta hai; aapki approval par setup Hopper bhi install kar sakta hai. Static JavaScript analysis ke liye native analysis engine ki zaroorat nahi.
|
||||
|
||||
> Setup instructions, tasveeron ke saath guides aur asli case studies ke liye **[REA ki website dekhein](https://rea.tools/)**.
|
||||
|
||||
@@ -187,7 +187,7 @@ Mazeed tools aur host support target par depend karte hain:
|
||||
| Target | REA kya wapas deta hai | Zarooriyat aur guide |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Desktop installations | Runtime candidates, supporting files, component markers aur agle probes | Built-in bounded directory/header inspection; [desktop applications](../desktop-applications.md) |
|
||||
| Native binaries | Pseudocode, assembly, strings, symbols, calls aur references | Hopper, Ghidra ya IDA; [native analysis](../native-investigation.md) |
|
||||
| Native binaries | Pseudocode, assembly, strings, symbols, calls aur references | Hopper, Ghidra, IDA ya Kuna; [native analysis](../native-investigation.md) |
|
||||
| Offline ELF layout | Sections, segments, original symbols/relocations aur static mitigation candidates | Linux x64 par aapka diya hua pwntools; [binary diagnostics](../binary-diagnostics.md) |
|
||||
| Go binaries | Embedded compiler version, modules, replacements aur build settings | Built-in static ELF/PE/thin Mach-O inspection; Go install karna zaroori nahi |
|
||||
| GPU code objects | CUDA/HIP targets, selected kernel parameters aur resources, retained PTX text | Built-in static ELF/PE/fatbin/CUBIN/PTX inspection; [GPU code objects](../gpu-code-objects.md) |
|
||||
@@ -342,11 +342,11 @@ use kar sakte hain.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Kya mujhe Hopper, Ghidra ya IDA chahiye?</strong></summary>
|
||||
<summary><strong>Kya mujhe Hopper, Ghidra, IDA ya Kuna chahiye?</strong></summary>
|
||||
|
||||
Deep native analysis in mein se ek use karta hai. Static JavaScript aur .NET
|
||||
inspection native analysis engine ke baghair kaam karti hai. Approval ke baad
|
||||
setup Hopper install kar sakta hai; Ghidra aur IDA ke liye aapki existing
|
||||
setup Hopper install kar sakta hai; Ghidra, IDA aur Kuna ke liye aapki existing
|
||||
installations use hoti hain. [Provider setup](../installation.md#hopper) dekhein.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[Trang web](https://rea.tools/vi/) · [Hướng dẫn](https://rea.tools/vi/guides/) · [Các nghiên cứu điển hình](https://rea.tools/vi/showcase/)**
|
||||
|
||||
[Bắt đầu nhanh](#bắt-đầu-nhanh) · [Cách REA hoạt động](#cách-rea-hoạt-động) · [Những gì bạn có thể phân tích](#những-gì-bạn-có-thể-phân-tích) · [Các nghiên cứu điển hình](#các-nghiên-cứu-điển-hình) · [Xây dựng môi trường RL](#build-rl-environments) · [Câu hỏi thường gặp](#câu-hỏi-thường-gặp) · [Công cụ GNU objdump và Rizin](../reverse-engineering-tools.md) · [Tài liệu](#tài-liệu)
|
||||
[Bắt đầu nhanh](#bắt-đầu-nhanh) · [Cách REA hoạt động](#cách-rea-hoạt-động) · [Những gì bạn có thể phân tích](#những-gì-bạn-có-thể-phân-tích) · [Các nghiên cứu điển hình](#các-nghiên-cứu-điển-hình) · [Xây dựng môi trường RL](#build-rl-environments) · [Câu hỏi thường gặp](#câu-hỏi-thường-gặp) · [Tài liệu](#tài-liệu)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@ Bạn thấy một tính năng trong ứng dụng và muốn đưa nó vào sả
|
||||
|
||||
REA kết nối tác nhân của bạn với các công cụ kiểm tra tệp nhị phân mã máy, ứng dụng JavaScript và Electron, assembly .NET và trang web. Bạn cũng có thể dùng các công cụ đó từ terminal. Việc phân tích chạy cục bộ; kết quả bao gồm bằng chứng và giới hạn làm cơ sở cho từng kết luận.
|
||||
|
||||
Thiết lập đăng ký REA với tác nhân và cài hướng dẫn công việc tương ứng. Phân tích native dùng Hopper, Ghidra hoặc IDA có sẵn; có thể cài Hopper sau khi bạn chấp thuận. Phân tích tĩnh JavaScript không cần công cụ phân tích native.
|
||||
Thiết lập đăng ký REA với tác nhân và cài hướng dẫn công việc tương ứng. Phân tích native dùng Hopper, Ghidra, IDA hoặc Kuna có sẵn; có thể cài Hopper sau khi bạn chấp thuận. Phân tích tĩnh JavaScript không cần công cụ phân tích native.
|
||||
|
||||
> **[Truy cập trang web REA](https://rea.tools/vi/)** để xem cách thiết lập, hướng dẫn có hình minh họa và các nghiên cứu điển hình thực tế.
|
||||
|
||||
@@ -151,7 +151,7 @@ REA yêu cầu Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) hoặc 26+ (>=26.12.1)
|
||||
|
||||
| Mục tiêu | REA trả về gì | Yêu cầu và hướng dẫn |
|
||||
| --------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Tệp nhị phân mã máy | Mã giả, hợp ngữ, chuỗi, ký hiệu, lời gọi và tham chiếu | Hopper, Ghidra hoặc IDA; [phân tích mã máy](../native-investigation.md) |
|
||||
| Tệp nhị phân mã máy | Mã giả, hợp ngữ, chuỗi, ký hiệu, lời gọi và tham chiếu | Hopper, Ghidra, IDA hoặc Kuna; [phân tích mã máy](../native-investigation.md) |
|
||||
| Bố cục ELF ngoại tuyến | Các section, segment, ký hiệu/thông tin tái định vị gốc và các biện pháp giảm thiểu có thể có từ phân tích tĩnh | pwntools do bên gọi cung cấp trên Linux x64; [chẩn đoán tệp nhị phân](../binary-diagnostics.md) |
|
||||
| Bytecode EVM | Bộ chọn điều phối, độ lệch byte, tham số suy luận và khả năng thay đổi trạng thái | Đầu vào cục bộ chứa byte thô hoặc dạng thập lục phân trên Linux x64; [hướng dẫn EVM ngoại tuyến](../evm-bytecode.md) |
|
||||
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
|
||||
@@ -190,6 +190,8 @@ REA yêu cầu Node.js 22.x (>=22.23.4), 24.x (>=24.22.1) hoặc 26+ (>=26.12.1)
|
||||
|
||||
Kiểm tra tĩnh JavaScript và .NET đọc các tệp được cung cấp mà không chạy ứng dụng. Ghi lại khi chạy sẽ khởi chạy hoặc tương tác với mục tiêu đã chọn bằng quyền người dùng của bạn; từng hướng dẫn mô tả tác động của nó.
|
||||
|
||||
Để kiểm tra tệp nhị phân native ngoại tuyến, REA cũng hỗ trợ GNU objdump và Rizin do bạn tự cung cấp. [Hướng dẫn công cụ dịch ngược](../reverse-engineering-tools.md) trình bày cách thiết lập nhà cung cấp, các lệnh CLI và giới hạn của Evidence. REA không cài đặt hoặc cập nhật hai nhà cung cấp này.
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
Với tệp nhị phân lớn, tăng hạn khởi động bằng `REA_GHIDRA_STARTUP_TIMEOUT_MS` hoặc `REA_HOPPER_STARTUP_TIMEOUT_MS`.
|
||||
@@ -278,9 +280,9 @@ Bất kỳ tác nhân nào hỗ trợ máy chủ MCP cục bộ. Quá trình thi
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Tôi có cần Hopper, Ghidra hoặc IDA không?</strong></summary>
|
||||
<summary><strong>Tôi có cần Hopper, Ghidra, IDA hoặc Kuna không?</strong></summary>
|
||||
|
||||
Phân tích mã máy chuyên sâu sử dụng một trong những công cụ đó. Kiểm tra tĩnh JavaScript và .NET hoạt động mà không cần bộ máy phân tích mã máy. Quá trình thiết lập có thể cài Hopper sau khi được chấp thuận; Ghidra và IDA dùng bản cài đặt sẵn có. Xem [thiết lập trình phân tích](../installation.md#hopper).
|
||||
Phân tích mã máy chuyên sâu sử dụng một trong những công cụ đó. Kiểm tra tĩnh JavaScript và .NET hoạt động mà không cần bộ máy phân tích mã máy. Quá trình thiết lập có thể cài Hopper sau khi được chấp thuận; Ghidra, IDA và Kuna dùng bản cài đặt sẵn có. Xem [thiết lập trình phân tích](../installation.md#hopper).
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**[網站](https://rea.tools/zh-TW/) · [指南](https://rea.tools/zh-TW/guides/) · [案例](https://rea.tools/zh-TW/showcase/)**
|
||||
|
||||
[快速開始](#快速開始) · [REA 的工作原理](#rea-的工作原理) · [可以分析什麼](#可以分析什麼) · [案例](#案例) · [建立 RL 環境](#build-rl-environments) · [常見問題](#常見問題) · [GNU objdump 與 Rizin 工具](../reverse-engineering-tools.md) · [文件](#文件)
|
||||
[快速開始](#快速開始) · [REA 的工作原理](#rea-的工作原理) · [可以分析什麼](#可以分析什麼) · [案例](#案例) · [建立 RL 環境](#build-rl-environments) · [常見問題](#常見問題) · [文件](#文件)
|
||||
|
||||
<code>npx rea-agents setup</code>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
REA 將 AI 代理連接到分析工具,用於檢查原生二進位檔案、JavaScript 和 Electron 應用、.NET 程式集以及網站。你也可以在終端中使用同樣的工具。分析在本機執行,結果包含支撐各項結論的證據和相關限制。
|
||||
|
||||
設定流程會向 AI 代理註冊 REA,並安裝對應的工作流程指引。原生分析可以使用已有的 Hopper、Ghidra 或 IDA;設定流程也可以在你核准後安裝 Hopper。靜態 JavaScript 分析不需要原生分析引擎。
|
||||
設定流程會向 AI 代理註冊 REA,並安裝對應的工作流程指引。原生分析可以使用已有的 Hopper、Ghidra、IDA 或 Kuna;設定流程也可以在你核准後安裝 Hopper。靜態 JavaScript 分析不需要原生分析引擎。
|
||||
|
||||
> **[訪問 REA 網站](https://rea.tools/zh-TW/)**,查看設定說明、圖解指南和真實案例。
|
||||
|
||||
@@ -149,7 +149,7 @@ REA 需要 Node.js 22.x(>=22.23.4)、24.x(>=24.22.1)或 26+ (>=26.12.1)
|
||||
|
||||
| 目標 | REA 返回的內容 | 要求與指南 |
|
||||
| --------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| 原生二進位檔案 | 偽程式碼、組合語言、字串、符號、呼叫和引用 | Hopper、Ghidra 或 IDA;[原生分析](../native-investigation.md) |
|
||||
| 原生二進位檔案 | 偽程式碼、組合語言、字串、符號、呼叫和引用 | Hopper、Ghidra、IDA 或 Kuna;[原生分析](../native-investigation.md) |
|
||||
| 離線 ELF 佈局 | 節、段、原始符號/重定位資訊及靜態防護機制候選項 | Linux x64 上由呼叫方提供的 pwntools;[二進位診斷](../binary-diagnostics.md) |
|
||||
| Go 二進位檔案 | 內嵌編譯器版本、模組、替換項和建置設定 | 內建靜態 ELF/PE/thin Mach-O 檢查;無需安裝 Go |
|
||||
| WASM 工件 | 驗證、節、精確的匯入/匯出 WAT 形式及解碼後的 WAT | 呼叫方提供的 WABT 1.0.42;`inspect_wasm_artifact` |
|
||||
@@ -188,6 +188,8 @@ REA 需要 Node.js 22.x(>=22.23.4)、24.x(>=24.22.1)或 26+ (>=26.12.1)
|
||||
|
||||
靜態 JavaScript 和 .NET 檢查讀取提供的檔案,不執行應用。執行階段擷取會以你的使用者權限執行目標或與之互動;各執行階段指南說明瞭具體影響。
|
||||
|
||||
若要離線檢查原生二進位檔,REA 也支援由呼叫端自行提供的 GNU objdump 和 Rizin。[逆向工程工具指南](../reverse-engineering-tools.md)說明了分析提供者的設定、CLI 指令及 Evidence 的限制。REA 不會安裝或更新這兩個分析提供者。
|
||||
|
||||
<a id="choosing-a-deep-analysis-provider"></a>
|
||||
|
||||
大型二進位檔可透過 `REA_GHIDRA_STARTUP_TIMEOUT_MS` 或 `REA_HOPPER_STARTUP_TIMEOUT_MS` 延長提供者啟動期限。
|
||||
@@ -278,9 +280,9 @@ REA 匯出可直接執行的環境,並附帶基本測試,檢查環境能否
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>需要 Hopper、Ghidra 或 IDA 嗎?</strong></summary>
|
||||
<summary><strong>需要 Hopper、Ghidra、IDA 或 Kuna 嗎?</strong></summary>
|
||||
|
||||
深入的原生分析需要其中一個引擎。靜態 JavaScript 和 .NET 檢查不需要原生分析引擎。設定流程可以在你核准後安裝 Hopper;Ghidra 和 IDA 則使用已有安裝。見[提供者設定](../installation.md#hopper)。
|
||||
深入的原生分析需要其中一個引擎。靜態 JavaScript 和 .NET 檢查不需要原生分析引擎。設定流程可以在你核准後安裝 Hopper;Ghidra、IDA 和 Kuna 則使用已有安裝。見[提供者設定](../installation.md#hopper)。
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
REA 将智能体连接到分析工具,用于检查原生二进制文件、JavaScript 和 Electron 应用、.NET 程序集以及网站。你也可以在终端中使用同样的工具。分析在本机运行,结果包含支撑各项结论的证据和相关限制。
|
||||
|
||||
设置流程会向智能体注册 REA,并安装匹配的工作流指引。原生分析可以使用已有的 Hopper、Ghidra 或 IDA;设置流程也可以在你批准后安装 Hopper。静态 JavaScript 分析不需要原生分析引擎。
|
||||
设置流程会向智能体注册 REA,并安装匹配的工作流指引。原生分析可以使用已有的 Hopper、Ghidra、IDA 或 Kuna;设置流程也可以在你批准后安装 Hopper。静态 JavaScript 分析不需要原生分析引擎。
|
||||
|
||||
> **[访问 REA 网站](https://rea.tools/zh-CN/)**,查看设置说明、图解指南和真实案例。
|
||||
|
||||
@@ -149,7 +149,7 @@ REA 需要 Node.js 22.x(>=22.23.4)、24.x(>=24.22.1)或 26+ (>=26.12.1)
|
||||
|
||||
| 目标 | REA 返回的内容 | 要求与指南 |
|
||||
| --------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| 原生二进制文件 | 伪代码、汇编、字符串、符号、调用和引用 | Hopper、Ghidra 或 IDA;[原生分析](../native-investigation.md) |
|
||||
| 原生二进制文件 | 伪代码、汇编、字符串、符号、调用和引用 | Hopper、Ghidra、IDA 或 Kuna;[原生分析](../native-investigation.md) |
|
||||
| 离线 ELF 布局 | 节、段、原始符号/重定位信息及静态防护机制候选项 | Linux x64 上由调用方提供的 pwntools;[二进制诊断](../binary-diagnostics.md) |
|
||||
| Go 二进制文件 | 内嵌编译器版本、模块、替换项和构建设置 | 内置静态 ELF/PE/thin Mach-O 检查;无需安装 Go |
|
||||
| WASM 工件 | 验证、节、精确的导入/导出 WAT 形式及解码后的 WAT | 调用方提供的 WABT 1.0.42;`inspect_wasm_artifact` |
|
||||
@@ -278,9 +278,9 @@ REA 导出可直接运行的环境,并附带基本测试,检查环境能否
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>需要 Hopper、Ghidra 或 IDA 吗?</strong></summary>
|
||||
<summary><strong>需要 Hopper、Ghidra、IDA 或 Kuna 吗?</strong></summary>
|
||||
|
||||
深入的原生分析需要其中一个引擎。静态 JavaScript 和 .NET 检查不需要原生分析引擎。设置流程可以在你批准后安装 Hopper;Ghidra 和 IDA 则使用已有安装。见[提供方设置](../installation.md#hopper)。
|
||||
深入的原生分析需要其中一个引擎。静态 JavaScript 和 .NET 检查不需要原生分析引擎。设置流程可以在你批准后安装 Hopper;Ghidra、IDA 和 Kuna 则使用已有安装。见[提供方设置](../installation.md#hopper)。
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ cannot. This increment adds the view kind only; serving from the state, loading
|
||||
another state through the AgentEnv data plane and modelling write effects are
|
||||
later increments.
|
||||
|
||||
Safe `HEAD`, `OPTIONS` and `TRACE` tools have recorded views with reason
|
||||
`method-replay`; state rendering currently applies only to `GET` reads.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Accept `inspect_web_network_capture` HAR parents and
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Implementation plan
|
||||
|
||||
1. **Sorted creates.** Placed creates whose confirming read was a whole listing in collection order may be placed
|
||||
again; narrowing keeps the sorts a later listing follows and adds those its items show, the type's id field last.
|
||||
2. **Listed references.** `referenceRule` reads a sent list of ids; `many` on the reference rule and its schema;
|
||||
`referencedValue` maps each id; the create merge lets an empty reference agree and frees the members it fixed.
|
||||
3. **Hidden bodies.** Scenario records give a request with a body Playwright did not expose, and no `Content-Type`, a
|
||||
`bodySize` of 0.
|
||||
4. **Toggles.** `toggledRules` turns a plan's `set` and a later call's opposite `set` into `toggle`; the rule's schema,
|
||||
serving, later-call checks and the action verdict.
|
||||
5. **Skill, tests and docs.**
|
||||
@@ -0,0 +1,41 @@
|
||||
# Serve sorted creates, listed references and toggles
|
||||
|
||||
Issue: https://github.com/morluto/rea/issues/4933
|
||||
|
||||
## Outcome
|
||||
|
||||
Over 148 recorded captures (the 130 measured before and 18 from a fresh recording round), #7539 withholds 302 of 694
|
||||
write plans. A short diagnosis of the largest clusters found three gaps REA could close:
|
||||
|
||||
- **A create's sort learned too late.** Grafana lists folders by title. A recording's first scratch folder sorted
|
||||
after the one seeded folder, so the plan placed creates last; the second sorted before the first, the list after it
|
||||
contradicted the plan, and the update and delete after that went unconfirmed.
|
||||
- **Lists of references.** Homebox creates an item from `parentId` and `tagIds` and answers with the parent and tag
|
||||
objects. REA modelled a parent but not a list of tags, and a create that sent `null` and `[]` disagreed with one that
|
||||
named both.
|
||||
- **Toggles.** Miniflux stars and unstars an entry with a body-less `PUT /v1/entries/{id}/bookmark`. Chromium exposes
|
||||
no body for it, which REA read as unusable, and an action flipping a flag back was taken to contradict the call that
|
||||
set it.
|
||||
|
||||
## Behaviour
|
||||
|
||||
- **Sorted creates.** A create a whole listing in collection order placed last is placed again by a field a later such
|
||||
listing shows it sorted by, the type's id field last. A sort an earlier such listing did not follow stays ruled out,
|
||||
though the entity that showed it is gone. A create another read placed keeps its place.
|
||||
- **Listed references.** A field holding one object per id a sent list names, in that order, is a `reference` with
|
||||
`many`. A create that sent the member as `null` or `[]` and stored the field so agrees with one that named entities,
|
||||
whichever create first showed the reference;
|
||||
serving stores the entities a call names, or the empty value as that create did. A `null` id stays refused where
|
||||
no recorded create sent one, and a call leaving the member out stores no field where the observed create showed
|
||||
none.
|
||||
- **Hidden bodies.** A scenario request whose body Playwright did not expose and that names no `Content-Type` sent no
|
||||
body.
|
||||
- **Toggles.** An item action a later call shows flipping back a boolean an earlier call set, when no call found it
|
||||
already set, has a `toggle` rule: serving flips the field, refusing an entity that holds no boolean there.
|
||||
- **Skill.** Recordings run an action twice in a row on one object, reading it back after each (skill 55).
|
||||
|
||||
Plans and views that need none of this are unchanged.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- No write of the 148 captures goes from served to withheld, and no view changes.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Place a create again by the sort a later whole listing shows.
|
||||
- [x] Learn and serve references a sent list of ids names, and let an empty reference agree.
|
||||
- [x] Treat a hidden request body without a `Content-Type` as absent.
|
||||
- [x] Learn, check and serve toggles.
|
||||
- [x] Ask recordings to run an action twice on one object.
|
||||
- [x] Add view, serving, record and unit tests.
|
||||
- [x] Document the rules.
|
||||
- [x] Measure the recorded captures.
|
||||
- [x] Run static, formatting, documentation and test gates.
|
||||
@@ -0,0 +1,88 @@
|
||||
# Verification
|
||||
|
||||
Executed on macOS with Node v24.22.1 on this branch and on #7539 at `30e2a582`; the census and the base reproduction
|
||||
were repeated after merging #7539 at `2817665d`, `174a0ff2`, `5691f97f` (which merges main with #7332)
|
||||
and `3b800a10`.
|
||||
|
||||
## Diagnosis
|
||||
|
||||
Over 148 recorded captures, #7539 withholds 302 of 694 write plans. The largest clusters: Homebox item writes (36),
|
||||
unconfirmed deletes (23), Grafana's feature-flag evaluation calls (15, which change no state), Linkding renumbering
|
||||
bundles after a delete (7) and Miniflux's bookmark toggle (5).
|
||||
|
||||
- **Grafana.** A fresh recording created "Scratch Pier 3", which the list after it showed after the one seeded folder,
|
||||
then "Scratch Meadow Notes 4", which the list after it showed before the first, by title. The create plan had settled
|
||||
on `last` when the first list confirmed it, so the second list contradicted it, and the folder update and delete
|
||||
after it went unconfirmed.
|
||||
- **Homebox.** Item creates send `parentId` and `tagIds` and answer with `parent` and `tags` objects. The recording
|
||||
that created one item with neither (`null` and `[]`) and one with both was withheld: `tags` had no rule, and the
|
||||
first create fixed both members to their empty values.
|
||||
- **Miniflux.** `PUT /v1/entries/{id}/bookmark` sends no body and answers `204`. Chromium exposes no body for it and
|
||||
the request names no `Content-Type`; REA read the body as unusable. Across the captures, every `POST`, `PUT` or
|
||||
`PATCH` whose body was captured names `content-type` among its request header names (835 of 835).
|
||||
|
||||
## Gates
|
||||
|
||||
- `npm run -s check:fast`, `format:check`, `knip`, `scan:todos`, `docs:check`, `verify:test-discovery`,
|
||||
`mcp-catalog:check` and `jscpd`: passed.
|
||||
- `npx vitest run --project domain --project services`: 11,886 passed, 6 skipped, merged with `3b800a10`. An earlier run of the suite failed a
|
||||
`SetupRegistrationPrewarm` runner test whose child process outran its 5-second timeout; alone it passes on this
|
||||
branch and on #7539 (3.0 to 4.7 seconds).
|
||||
- `npm run -s test:focused --` the environment build, export and serve CLI boundaries, the analysis-view CLI and MCP
|
||||
boundaries and the environment serve MCP boundary: 7 files, 81 passed. `outputSchemaProfile`, `toolSchemaValidity`,
|
||||
`mcpSchemaValidation`, `outputSchemaSemanticConstraints` and `analysisViewMcp`: 5 files, 54 passed; the compact
|
||||
catalog stays under its frame.
|
||||
|
||||
## Tests
|
||||
|
||||
- View: a create placed last, then a create a later whole listing shows before it by title, learns `title` ascending
|
||||
and its delete is served; an item create naming its parent and tags by id, after one naming none, learns
|
||||
`reference` rules for `parent` and for `tags` (`many`) and is served; a body-less action two calls show starring
|
||||
then unstarring an entry learns `toggle` and is served, and is not when its calls flip the flag one way only or a
|
||||
later call leaves it unchanged.
|
||||
- Serving: a create stores the parent and the tags its ids name, in the order sent; a create leaving out both, or
|
||||
sending them as `null` and `[]`, stores `null` and `[]`; a tag the environment does not hold is refused, and so is a
|
||||
`null` shelf where every recorded create named one; an entry the recording never starred flips on each call.
|
||||
- Records: a hidden request body is absent when the request names no `Content-Type`, and stays unusable when it names
|
||||
one.
|
||||
- The nine behaviour tests fail on #7539 at `30e2a582`, `2817665d`, `174a0ff2`, `5691f97f` and `3b800a10`; the three that guard toggles and `null` ids
|
||||
pass there too.
|
||||
|
||||
## Write plans and views over recorded captures
|
||||
|
||||
The 148 captures, built by #7539 and by this branch: 694 plans, 392 served and 399, both at `30e2a582` and after
|
||||
merging `2817665d`, `174a0ff2`, `5691f97f` and
|
||||
`3b800a10`.
|
||||
|
||||
- No write goes from served to withheld, and no served plan changes. Newly served: Grafana's folder create, update and
|
||||
delete in a fresh recording; Homebox's item create in another; Miniflux's bookmark toggle in three recordings.
|
||||
- Five withheld plans explain more. Two Miniflux recordings learn the toggle but stay withheld: a list of starred
|
||||
entries with no `order` parameter lists them by `published_at`, which REA answers in state order. Linkding's
|
||||
unarchive learns its body-less call and stays `unconfirmed`, seen once. Two Homebox item writes learn their tag
|
||||
references and stay withheld for other members.
|
||||
- Views are unchanged: 3,188 views across the captures.
|
||||
|
||||
## Review round
|
||||
|
||||
Greptile's review of `4e777d28` raised five findings. Two were in this branch's code and are fixed:
|
||||
|
||||
- A sort an earlier whole listing ruled out could come back from a later listing once the entity that ruled it out was
|
||||
deleted, and a create's retry could adopt it. Each create now keeps the sorts its whole listings did not follow.
|
||||
- A create sending a reference's member as `null` after a later create added the reference, the first having shown no
|
||||
such field, was withheld: the empty-reference agreement now applies there too.
|
||||
|
||||
Both tests fail on `4e777d28` and on #7539 at `174a0ff2`; the census is unchanged. The other three were in #7332's and
|
||||
#7539's code: `308aebf0` (#7332), already here, covers the made-object count, and #7539's `174a0ff2`, merged here,
|
||||
fixes the update default and the read clock spelling.
|
||||
|
||||
Greptile's review of `f7c1bfe9` raised one more, fixed: once a later create sent a reference's member as `null`, a
|
||||
served create leaving the member out stored `null`, though the create the plan observes left it out and stored no such
|
||||
field. Serving now leaves the field out there, and still stores `null` for a call that sends it; the serving test fails
|
||||
on `f7c1bfe9`. The census is unchanged.
|
||||
|
||||
## Not verified
|
||||
|
||||
- No environment was rebuilt and run with agents for this branch, and no recording was made with skill 55.
|
||||
- The order an application gives a list read with no sort parameter (Miniflux's `published_at`) when it is not state
|
||||
order.
|
||||
- The rest of the Homebox cluster: `assetId` numbering and item updates; Linkding renumbering bundles after a delete.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Implementation plan
|
||||
|
||||
1. **Update members.** `refinedBody` keeps only the required members a later update also sent.
|
||||
2. **Numbered unless sent.** `sent` on sequence rules and their schema; the create merge adopts it for an echoed member
|
||||
and a sequence from a call that left the member out; serving and replay take the sent value when there is one.
|
||||
3. **Cleared by a PUT.** `explainUpdate` records a `PUT`'s left-out member cleared to an empty value as a default;
|
||||
update refinement keeps defaults from later calls; `updatedFields` applies them to members a call leaves out.
|
||||
4. **Update clocks.** `restampedFields` respells clocks from the first later read as it does nested clocks.
|
||||
5. **Skill, tests and docs.**
|
||||
@@ -0,0 +1,56 @@
|
||||
# Serve writes whose calls send different members
|
||||
|
||||
Issue: https://github.com/morluto/rea/issues/4933
|
||||
|
||||
## Outcome
|
||||
|
||||
A fresh recording round of seven applications, main against #7332, showed the recording skill now varies what the two
|
||||
creates and two updates of a type send, as it asks. Where the second call left out a member the first sent, REA
|
||||
withheld the write:
|
||||
|
||||
- **Updates.** An update plan required every member its first call sent and never narrowed that, so EspoCRM's second
|
||||
contact update, which changed only an email address, was refused in both recordings of the branch.
|
||||
- **Members numbered when left out.** Linkding stores a bundle's `order` as sent, or one past the others when a call
|
||||
leaves it out. One create showed the first and another the second, which the create merge took as a disagreement.
|
||||
|
||||
The same recordings and the 130 earlier captures showed two more update gaps:
|
||||
|
||||
- **Whole-object PUTs.** Paperless clears a tag's, correspondent's or document type's `owner` when a `PUT` leaves it
|
||||
out, and Homebox an item's `assetId`, so those updates were `unexplained-change`.
|
||||
- **Update clocks read at another precision.** Vikunja answers a task update with `done_at` to the nanosecond while its
|
||||
reads spell it to the second, so the read after the update contradicted it.
|
||||
|
||||
The round also found two creates of EspoCRM contacts in one second, which a list sorted newest first shows in an order
|
||||
the application breaks ties in. The skill now spaces creates.
|
||||
|
||||
## Behaviour
|
||||
|
||||
- **Update members.** A later update narrows the plan's required members to those every call sent.
|
||||
- **Numbered unless sent.** A member one create sent and stored as sent, and another left out and the application
|
||||
numbered one past the others, is a `sequence` with `sent`, in either order: serving stores the value a call sends,
|
||||
else the next number, and a later call that sends it must have stored what it sent. The next number follows the
|
||||
largest value any call took, a deleted entity's included, in replay as in serving.
|
||||
- **Cleared by a PUT.** A field a `PUT` left out that the application cleared to an empty value (`""`, `null`, `false`,
|
||||
`[]` or `{}`) is that member's default (`body.defaults`) when every call that left it out stored that value, as its
|
||||
answer shows it or, where the answer leaves the member out, the read after it: serving stores it for an update that
|
||||
leaves the member out. Calls that left it out and stored it otherwise withhold the plan.
|
||||
- **Update clocks.** The state holds an update's clock as the first read of the entity after it spells the same instant
|
||||
at a coarser precision in the same zone and separator, as it already does for nested clocks: replay and serving store
|
||||
every update's clocks in the spelling of the read the plan keeps as `observation.read`, so a later update whose read
|
||||
spells them otherwise contradicts the plan, while answers keep the update's own. A create's clocks stay as answered,
|
||||
as serving makes them.
|
||||
- **Skill.** Recordings leave more than a second between two creates, as between a create and its first edit.
|
||||
|
||||
Plans and views that need none of this are unchanged.
|
||||
|
||||
## Not covered
|
||||
|
||||
- Vikunja numbers tasks per project. Creates into projects the recording did not list cannot be numbered, so its task
|
||||
creates stay withheld.
|
||||
- Linkding renumbers bundles' `order` after a delete, which no rule models.
|
||||
- Homebox item creates expand sent tag ids into tag objects and pin `parentId`; they stay withheld.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- No write tool of the recorded captures goes from served to withheld.
|
||||
- The writes the diagnosis named are served where their recordings show nothing else against them.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Narrow an update plan's required members to those every call sent.
|
||||
- [x] Serve a member the value a call sends, else the next number, when calls showed both.
|
||||
- [x] Learn and serve the value a `PUT` stores for a member it leaves out.
|
||||
- [x] Hold an update's clock as the read after it spells it.
|
||||
- [x] Ask recordings to space creates.
|
||||
- [x] Add view, serving and unit tests.
|
||||
- [x] Document the rules.
|
||||
- [x] Measure the recorded captures.
|
||||
- [x] Run static, formatting, documentation and test gates.
|
||||
@@ -0,0 +1,95 @@
|
||||
# Verification
|
||||
|
||||
Executed on macOS with Node v24.22.1 on this branch, on #7332 at `7d01a5d5` (main `5aa23c3d`), and on Ubuntu 24.04 VMs
|
||||
with snap Chromium for the recording round.
|
||||
|
||||
## Diagnosis
|
||||
|
||||
Claude Code (`claude-sonnet-5-5`) built an environment of each of seven applications from the same prompt, once with
|
||||
REA main `5aa23c3d` (skill 50) and once with #7332 at `7d01a5d5` (skill 53). Each bundle's write tasks ran with
|
||||
`fireworks_ai/gpt-oss-120b` and `fireworks_ai/glm-5p3-flash`, which scored alike:
|
||||
|
||||
| Application | Write tasks | Main | #7332 |
|
||||
| ----------- | ----------- | ------- | ------- |
|
||||
| Miniflux | 3 | 3/3 | 3/3 |
|
||||
| Grafana | 2 | 2/2 | 2/2 |
|
||||
| Vikunja | 3 + 2 | 0/3 0/2 | 1/3 2/2 |
|
||||
| Paperless | 3 | 1/3 | 2/3 |
|
||||
| Linkding | 2 | 0/2 | 2/2 |
|
||||
| Homebox | 2 | 2/2 | 0/2 |
|
||||
| EspoCRM | 3 | 1/3 | 0/3 |
|
||||
| Total | 20 | 9/20 | 12/20 |
|
||||
|
||||
Served writes were 14 and 25. Recorded again, Homebox and EspoCRM gave main 2/2 and 1/3 and #7332 2/2 and 3/3: the
|
||||
first losses were the agents' runs, not REA. Built with both versions, none of the 18 recordings served fewer writes
|
||||
with #7332 (44 and 53 in all).
|
||||
|
||||
Replaying #7332's recordings with failing checks and refusals logged gave the causes this branch takes: EspoCRM's
|
||||
second contact update left out `addressCity` and was refused for lacking a required member (both recordings); Linkding's
|
||||
second bundle create left `order` to the application, which the merge took as disagreeing with the first create's
|
||||
echo; Vikunja's task update stamped `done_at` to the nanosecond where the read after it showed seconds. Over the
|
||||
earlier captures, 14 withheld updates were `PUT`s whose application cleared a member they left out (Paperless `owner`,
|
||||
Homebox `assetId`).
|
||||
|
||||
## Gates
|
||||
|
||||
- `npm run -s check:fast`, `format:check`, `scan:todos`, `docs:check`, `verify:test-discovery`, `mcp-catalog:check` and
|
||||
`jscpd`: passed. `npx knip` reports `staticFileUrlPath`, `ObjcClassImportBindingCoverage` and
|
||||
`AndroidManifestComponentInventory`, as main `5aa23c3d` does.
|
||||
- `npx vitest run --project domain --project services`: 11,694 passed, 8 failed (`appleApplication.test.ts`), which fail
|
||||
the same way on main `5aa23c3d`.
|
||||
- `npm run -s test:focused --` the environment build, export and serve CLI boundaries, the analysis-view CLI and MCP
|
||||
boundaries and the environment serve MCP boundary: 80 passed. `outputSchemaProfile`, `toolSchemaValidity`,
|
||||
`mcpSchemaValidation`, `outputSchemaSemanticConstraints` and `analysisViewMcp`: 54 passed; the compact catalog stays
|
||||
under its frame.
|
||||
- The seven new view and serving tests fail on #7332 at `7d01a5d5` and pass here.
|
||||
|
||||
## Write plans over recorded captures
|
||||
|
||||
The 130 captures #7332 measured and the round's 18 recordings, built by #7332 at `7d01a5d5` and by this branch: 694
|
||||
plans, 386 served and 398. No write goes from served to withheld and every view is unchanged. Newly served:
|
||||
|
||||
- Paperless correspondent, document type and tag updates in four recordings, whose `PUT` clears `owner`.
|
||||
- EspoCRM's contact update and Linkding's bundle create in #7332's recordings of the round.
|
||||
- Grafana's folder update and delete in a fresh recording whose second update sent fewer members.
|
||||
- Homebox's item update in the published capture, whose `PUT` clears `assetId`.
|
||||
|
||||
Vikunja's task update reads back confirmed, but stays withheld: the task creates before it are not modelled (per-project
|
||||
numbers), so their entities carry the creates' answer spellings into later reads.
|
||||
|
||||
## Review round
|
||||
|
||||
- Greptile's first review: a `sequence` with `sent` now accepts a value a later create sent, whichever create came
|
||||
first; a default must agree with every update that left its member out, else the plan is withheld; and serving
|
||||
stores an update's clocks as the update plan's read-back spells them (`observation.read`). Their four tests fail on
|
||||
`6300ec80`. #7332's made-object clock check, merged in, has its test there.
|
||||
- Gates as above: `domain` + `services` 11,699 passed, 8 failed (main's `appleApplication.test.ts`); focused boundaries
|
||||
80 passed; the five MCP schema files 54 passed. The census stays at 694 plans and 398 served, with no plan or view
|
||||
changing.
|
||||
|
||||
Greptile's review after main `21b19270` was merged in (`467ac78f`) raised three more, fixed:
|
||||
|
||||
- A member a call left out and the application stored a fixed value for (`body.defaults`) is no longer turned into a
|
||||
`sequence` with `sent` by a later call that left it out and got the next number.
|
||||
- Serving stores an update's clock at a coarser read's precision from the answer's own digits, so an answer to the
|
||||
nanosecond read back to the microsecond keeps its microseconds.
|
||||
- A `PUT` that names a `reference` field's entity by its member supplies that field: it is not checked against, or
|
||||
given, the default a `PUT` that left the field out showed, whichever of the two calls came first.
|
||||
|
||||
Their tests fail on `467ac78f`, and the reference case with the clearing call first on `7030ca4d`. Gates pass but
|
||||
`knip`, whose one finding main `21b19270` reports too; `domain` + `services` 12,046 passed; focused boundaries 82 passed; the five MCP schema files 55 passed. Over the 148 captures, main
|
||||
serves 380 writes and this branch 392, with no plan or view changing from `467ac78f`.
|
||||
|
||||
Greptile's review of `b56f8924` raised two more on numbered members, fixed: a member a call sent empty (`""`) is no
|
||||
longer filled in for a call that leaves it out when a `sequence` with `sent` numbers it; and a later create the
|
||||
application numbered at or below a value an earlier create sent (9 sent and deleted, then 2) no longer turns the echo
|
||||
into a numbered `sequence`, since serving counts past every value a call sent. Their tests fail on `b56f8924`; gates
|
||||
pass but `knip` (main's finding), `domain` + `services` 12,048 passed, and the census is unchanged. Greptile's next
|
||||
review found that check counting values sent in other collections, which withheld a create numbered within its own
|
||||
collection; the check now counts them in the sequence's scope, and its test fails on `d4922b3d`.
|
||||
|
||||
## Not verified
|
||||
|
||||
- No recording round ran with this branch, so its write tasks are not measured.
|
||||
- The skill's spacing of creates.
|
||||
- Vikunja per-project task numbers, Linkding's renumbering after a delete and Homebox item creates, which stay withheld.
|
||||
+65
-14
@@ -301,8 +301,9 @@ Turbo caches deterministic preparation and static checks, but `test:run` always
|
||||
executes. Repository files do not fully describe installed tool contents or host
|
||||
state. A previous test pass therefore cannot replace current validation, even
|
||||
when the source tree is unchanged. `check:pr` also runs the fast Python producer
|
||||
suite; CI runs it in the static job for code changes. These producer tests do not
|
||||
establish real LLDB engine coverage.
|
||||
suite. Fast CI runs it from the selected Python job after installing dependencies
|
||||
and preparing the compiled runtime; full qualification runs it from the deep
|
||||
static job. These producer tests do not establish real LLDB engine coverage.
|
||||
|
||||
Vitest's persistent compile cache remains disabled. The `cliTest` fixture shares
|
||||
a temporary Node compile cache among its fresh CLI subprocesses. The worker
|
||||
@@ -480,6 +481,18 @@ and retain representative compiled CLI parity checks. Every distinct source
|
||||
scenario still runs through the public workflow; session-lifecycle scenarios
|
||||
need their own sessions and cleanup assertions.
|
||||
|
||||
Complete-inline-Evidence conformance uses
|
||||
`scripts/lib/mcp-verification-environment.mjs`: a finite 65,536-element
|
||||
allowance selected by the application harness, file-owned CLI/MCP session and
|
||||
artifact verifiers.
|
||||
Explicit harness environment selections take precedence. This keeps canonical
|
||||
workflow assertions reachable for large retained observations. Admission-policy
|
||||
tests launch the public server with the resource setting unset or explicitly
|
||||
selected, including the default structured-input boundary and continued-service
|
||||
checks. Downstream capacity fixtures select enough finite transport allowance
|
||||
to reach their original memory, depth, cycle or representation boundary; retain
|
||||
those stronger assertions.
|
||||
|
||||
When a matrix already holds a named tool definition from live `tools/list`,
|
||||
pass that definition through the SDK's `toolDefinition` call option. This keeps
|
||||
the selected output-schema validation without eagerly compiling unrelated
|
||||
@@ -839,8 +852,15 @@ Native, provider, fixture, SQLite compatibility, and website lanes wait for
|
||||
the fast static checks (typecheck, built lint, and format) to succeed before
|
||||
allocating their runners. Knip, duplication, architecture guards, test
|
||||
discovery, and the Python producer run in the separate full-tier deep static
|
||||
job and do not gate provider admission. Portable test shards and documentation
|
||||
checks remain independent of static results, so they can still provide
|
||||
job and do not gate provider admission. On the fast tier, changes to Python
|
||||
bridges, analysis-efficiency inputs, or the Python test runner select a separate
|
||||
required Python job. That job installs locked dependencies and prepares the
|
||||
compiled runtime before the suite, because analysis-efficiency checks import
|
||||
built process modules. Bridge tests are discovered from the source tree. The
|
||||
mitmproxy, native, and pwndbg families must each contain a test module and
|
||||
execute at least one non-skipped case or subtest. A parent case with only skipped
|
||||
subtests does not satisfy this requirement. A newly added failing test fails the job.
|
||||
Portable test shards and documentation checks remain independent of static results, so they can still provide
|
||||
diagnostic feedback. The required gate rejects skipped selected lanes when
|
||||
static checks fail; on the full tier it also requires the deep static job.
|
||||
Passing revisions retain all selected coverage. This ordering reduces peak
|
||||
@@ -1558,30 +1578,44 @@ initial proposal measures only leaf producer-test omissions; it does not promise
|
||||
the savings of a broader affected-test planner.
|
||||
|
||||
`scripts/ci/plan.mjs` selects lanes using the ownership table in
|
||||
`scripts/ci/scopes.mjs`. Provider implementation changes run their real-provider
|
||||
verifiers and the Linux x64 installed-package/Inspector baseline. The `apple`
|
||||
scope owns the Apple artifact lane; the `package` scope owns the multi-host
|
||||
`scripts/ci/scopes.mjs`. Each lane record owns its path and test selection
|
||||
rules and required fast/full jobs; workflow contract tests verify the mapped jobs.
|
||||
Provider implementation changes run their real-provider verifiers and the Linux
|
||||
x64 installed-package/Inspector baseline. The `apple` scope owns the Apple artifact lane; the `package` scope owns the multi-host
|
||||
package matrix and the Windows curated lane, including Windows native controls,
|
||||
Inspector, setup, configuration and packaging entrypoints. Runtime sources under
|
||||
`src/` or `bridge/` without an owner, and the authored skill, run the Linux suite
|
||||
and the Linux x64 installed-package/Inspector baseline only. Test-only changes
|
||||
run the Linux suite without native package verification, except test files that
|
||||
the Apple or Windows curated lanes invoke explicitly, which also select that
|
||||
lane. Edits to verifier entrypoints run only by manual, licensed or self-hosted
|
||||
lane. Packet-capture and signal-recording tests and their producers select the
|
||||
corresponding real-tool lane; both also run in full qualification. The shared
|
||||
Linux resource-limit source and its tests select both. Each lane requires
|
||||
its Linux kernel resource-limit cases and all seven descriptor-cleanup cases to
|
||||
pass in the focused Vitest report. A missing report, missing case, skipped case,
|
||||
or duplicate identity fails the lane; unrelated host-specific skips remain
|
||||
allowed. These tests use synthetic producers. The separate real TShark or
|
||||
sigrok verifier establishes the actual-tool observation. Edits to verifier entrypoints run only by manual, licensed or self-hosted
|
||||
workflows run static checks and the Linux suite. Website changes run website
|
||||
checks. Provider workflow changes validate the workflow and run that provider's
|
||||
verifier. Changes under `bridge/ghidra/` also select the `ghidra_bridge` lane,
|
||||
which compiles the packaged bridge sources against the pinned Ghidra 12.1.4
|
||||
jars with `npm run verify:ghidra:bridge-sources`. It never launches Ghidra or
|
||||
imports a target, so a missing import fails the PR instead of every Ghidra
|
||||
session. The launcher, compiler and package checks share named required source
|
||||
jars with `npm run verify:ghidra:bridge-sources`. That compile step never
|
||||
launches Ghidra or imports a target, so a missing import fails the PR instead
|
||||
of every Ghidra session. The launcher, compiler and package checks share named required source
|
||||
roles. The manifest must match the complete Java cohort, so deleting a helper
|
||||
or adding an unregistered dependency cannot silently change the shipped set.
|
||||
The preflight reuses the provider's Java Properties parser with the pinned Node
|
||||
toolchain's native type stripping, without an npm install or runtime build.
|
||||
The shared release policy owns the verified version and JDK major. CI checks
|
||||
the archive pin before downloading and verifies the extracted SDK version;
|
||||
changes to these source owners also select the compile lane.
|
||||
changes to these source owners also select the compile lane. After compiling,
|
||||
the lane launches headless Ghidra on source-owned instruction bytes with
|
||||
`-noanalysis`. The ARM/Thumb probe sets each instruction's mode explicitly and
|
||||
checks the bridge's decoder-context readback. The decode probes check that
|
||||
`ARM:LE:32:Cortex`, `ARM:LE:32:v8-m` and `Xtensa:LE:32:default` decode their
|
||||
bytes from each language's default context. The bytes are never executed, and
|
||||
edits to those probe scripts also select the lane.
|
||||
Manual-provider/Android workflow changes run workflow validation only.
|
||||
The four-version SQLite compatibility matrix has its own `sqlite` scope for
|
||||
SQLite implementation, contracts, CLI/MCP registration, fixtures, and shared
|
||||
@@ -1729,6 +1763,10 @@ The Apple artifact CLI/MCP lane uses one `macos-15` job to avoid adding demand
|
||||
for scarce macOS runner capacity. It runs the artifact-format and metadata
|
||||
verifiers, followed by one consolidated focused invocation containing all
|
||||
existing native and process-boundary regression paths.
|
||||
The real native provenance verifier checks CLI/MCP agreement on complete
|
||||
per-slice encryption absence. The encryption CLI regression builds a universal
|
||||
image, marks its owned arm64 command with `cryptid=1`, and compares the reported
|
||||
range with `otool`; this verifies declared metadata, not actual FairPlay data.
|
||||
|
||||
The Linux source-test shards download a shared runtime and generated test
|
||||
metadata snapshot produced by the build job with `npm run test:prepare`. The
|
||||
@@ -1831,8 +1869,8 @@ Portable owner-based test selection remains observational. Its reports compare
|
||||
proposed omissions with the full run; incomplete or skipped observations do not
|
||||
establish that fewer tests would preserve regression detection.
|
||||
|
||||
The nine automatic browser, binary-layout, EVM, JavaScript-recovery,
|
||||
recorded-crash, web and environment-bundle provider lanes download
|
||||
The automatic browser, binary-layout, EVM, JavaScript-recovery, packet-capture,
|
||||
signal-recording, recorded-crash, web and environment-bundle provider lanes download
|
||||
`rea-build-cache` from their own run after the build and static jobs succeed. Their existing build commands still
|
||||
validate task hashes and rebuild mismatched inputs; provider observations always
|
||||
run. Provider-workflow-only edits also admit the build without enabling source
|
||||
@@ -1950,6 +1988,19 @@ unknown chunks, depth limits and extracted child digests. The optional
|
||||
Neither optional toolchain is a base-lane prerequisite. See
|
||||
[firmware analysis](firmware-analysis.md) for limits and unverified formats.
|
||||
|
||||
`npm run verify:esp-images` requires a Clang with the RISC-V target and
|
||||
`ld.lld` (`REA_RISCV_CLANG`, `REA_RISCV_LLD`) and a Python that runs esptool
|
||||
and espsecure (`REA_ESPTOOL_PYTHON`). It builds ESP32-C3 app and bootloader
|
||||
ELF files from `tests/conformance/esp/`, converts them with `esptool
|
||||
elf2image`, including `--secure-pad-v2`, `--ram-only-header` and
|
||||
`--pad-to-size`, signs one with RSA, ECDSA P-256 and P-384 keys, and compares
|
||||
REA's facts with `esptool image-info` and `espsecure signature-info-v2`. It
|
||||
compares extracted segments and signature blocks with the producer's bytes,
|
||||
and derives malformed images and ESP8266 v1 and v3 images. It checks each
|
||||
tool before building and warns when esptool is not the pinned v5.6.0.
|
||||
`REA_XTENSA_ESP32_GCC` adds an ESP32 Xtensa build. See
|
||||
[ESP images](esp-image.md).
|
||||
|
||||
### JavaScript source recovery
|
||||
|
||||
Build once with `npm run build:cached`, then run `npm run verify:javascript:recovery`.
|
||||
|
||||
+7
-3
@@ -9,14 +9,18 @@ The same domain header/table facts and artifact reader serve CLI and MCP.
|
||||
The root is an archive with unknown executable architecture. The header's CPU,
|
||||
OS, type, compression, load address and entry address are declarations, not proof of
|
||||
compatible or executable payloads. Raw numeric identifiers remain available
|
||||
alongside names; unrecognized identifiers have the name `unknown`.
|
||||
alongside names. Type names cover every image type in the pinned
|
||||
`include/image.h`, using U-Boot's `mkimage -T` names; `IH_TYPE_LOADABLE` (22)
|
||||
has none and is named `loadable`. Unrecognized identifiers have the name
|
||||
`unknown`.
|
||||
|
||||
The header's CRC32 and the declared payload's CRC32 must verify before a
|
||||
successful inventory. `payload.bin` contains the complete stored payload.
|
||||
Multi-file images also expose `image-0.bin`, `image-1.bin`, and so on. These
|
||||
component names are generated from table order. Components follow the zero-terminated big-endian size table, with four-byte
|
||||
padding after every nonfinal component. Their physical source ranges and
|
||||
content hashes retain precise provenance. Extraction writes the complete
|
||||
padding after every nonfinal component. Script images (`boot.scr`) carry the
|
||||
same table, so their script text is `image-0.bin`. Component physical source
|
||||
ranges and content hashes retain precise provenance. Extraction writes the complete
|
||||
payload and every component, so multi-file output can approach twice the input
|
||||
size. Compressed payloads remain compressed.
|
||||
|
||||
|
||||
@@ -119,6 +119,6 @@ Then rerun this installer.",implemented,verified by shell branch inspection
|
||||
90.5,@modelcontextprotocol/server:tool input validation,Caller sends arguments that violate a declared tool schema,"Canonical invalid_request with the SDK diagnostic plus recovery.kind=inspect_input_contract and a bounded instruction to read the advertised schema or call tools/list",Keeps field/type correction while telling the agent how to recover; diagnostics over 4 KiB stay on the existing retained-error path,Normalize ordinary validation failures and retain oversized diagnostics,implemented,verified by real in-memory and stdio MCP client/server calls with wrong argument types
|
||||
90.6,incur:unknown CLI command,Caller enters an unknown REA command,"'COMMAND' is not a command for 'rea'. Suggested command: rea --help",Low risk; identifies input and exact discovery action,Keep framework-generated copy,unchanged,verified by real packaged dispatcher invocation
|
||||
90.7,src/ghidra/GhidraProviderClient.ts:projectPrimarySessionError,One procedure's decompile reaches REA_GHIDRA_DECOMPILE_TIMEOUT_SECONDS,"Ghidra decompilation of {entry} exceeded the {N}-second limit set by REA_GHIDRA_DECOMPILE_TIMEOUT_SECONDS. Only this procedure's decompilation was stopped; the Ghidra session remains usable.",Low risk; names the setting and keeps the session,Keep current copy,implemented,provider projection test and real-provider lane
|
||||
91,src/application/binaryDiagnostics/ByteEntropyService.ts,Invalid file or window,"Expected a regular file.; Selected file could not be found.; Selected byte window starts beyond the end of the file.; Selected byte window extends beyond the end of the file.; File size exceeds exact numeric offset representation.",Invalid selection cannot produce complete entropy Evidence,Choose a readable regular file and a window within its byte size,implemented,entropy service and MCP boundary tests
|
||||
91,src/application/binaryDiagnostics/ByteEntropyService.ts (issues); src/domain/analysisErrorPresentation.ts (recovery),Invalid file or window,Expected a regular file.; Selected file could not be found.; Selected byte window starts beyond the end of the file.; Selected byte window extends beyond the end of the file.; File size exceeds exact numeric offset representation.,Invalid selection cannot produce complete entropy Evidence,"Read the declared input schema or CLI usage for inspect_byte_entropy; if using MCP and the catalog may be stale, call tools/list. Correct the listed fields, then retry. Do not repeat the unchanged call.",unchanged,Executed CLI/stdio MCP: path/offset/length refusals and tiny + system-binary controls; shared canonical recovery; service/MCP tests check classification and fields; remaining listed errors source-inspected
|
||||
92,src/domain/analysisView/byteEntropyView.ts,Non-summary entropy view,Byte entropy Evidence supports the summary view; retrieve parent Evidence for the complete block series.,Unsupported view selection,Use the summary view or retrieve complete parent Evidence,implemented,typed input rejection
|
||||
93,src/windows/WindowsNativeLoader.ts:load refused,Windows refuses to load the digest-verified native addon (for example Smart App Control or App Control policy),"REA Windows native controls are unavailable: Windows refused to load the verified native/windows/build/rea-windows-x64.node: {OS error} The file matched the package manifest, so restoring or reinstalling it will not help. ...",Previous artifact copy told users to restore or rebuild files that were already intact,"Name the OS refusal, say restoring cannot help, state that Ghidra and JADX need native controls while setup can still register clients, and point to a policy-allowed host or a maintainer-signed build",implemented,simulated loader refusal unit test; real Smart App Control block not reproduced
|
||||
|
@@ -93,8 +93,10 @@ whose section attribution is unknown prevent a complete debug-name claim, even
|
||||
when module names were decoded. They do not establish that the name section is
|
||||
malformed. Exact warnings retain their producing tool and text. Older portable
|
||||
reports retain their original strict command profile; missing metadata coverage
|
||||
is `unknown` and missing warning history is `null`. The raw custom section
|
||||
remains in the decoded WAT. An uninterpretable name section leaves complete
|
||||
is `unknown` and missing warning history is `null`. Decoded WAT retains readable
|
||||
custom sections; WABT omits a section whose name is invalid UTF-8. In that case
|
||||
REA verifies the selected bytes, retains the section range and exact producer
|
||||
diagnostic, and leaves its identity and debug-name coverage unknown. An uninterpretable name section leaves complete
|
||||
debug-name coverage unknown. Module names decoded before a later metadata
|
||||
failure remain available for exact objdump framing, including names containing
|
||||
newlines or NUL; those partial observations do not establish complete optional
|
||||
|
||||
@@ -72,7 +72,15 @@ are rejected before materialization. Prototype-named members such as
|
||||
`__proto__` are preserved as ordinary own JSON members without prototype
|
||||
mutation. Original capture files remain unchanged.
|
||||
REA owns specific schema corrections because pinned upstream schemas omit
|
||||
object types and use the unrecognized `min` keyword. Following
|
||||
object types and use the unrecognized `min` keyword. The pinned schema also
|
||||
checks `request.url` as an RFC 3986 `uri`, while HAR 1.2 defines it only as the
|
||||
absolute request URL. REA additionally admits a URL that WHATWG URL
|
||||
serialization reproduces unchanged, which is how browsers record and send it,
|
||||
for example with an unescaped `|` or `{` in the query. Every URL the RFC 3986
|
||||
check accepts stays admitted, even when WHATWG would rewrite it, such as an
|
||||
uppercase host. Spellings that fail the RFC 3986 check and that WHATWG would
|
||||
rewrite, such as a backslash authority, a tab or a space, still fail.
|
||||
Following
|
||||
[HAR 1.2](https://github.com/ahmadnassri/har-spec/blob/81adb2fcf845e81ff3de728cf6829a0e6ad63e95/versions/1.2.md#timings),
|
||||
`timings` must be an object with nonnegative `send`, `wait` and `receive`;
|
||||
optional `blocked`, `dns`, `connect` and `ssl` may be absent, `-1`, or
|
||||
@@ -689,7 +697,8 @@ with a `value` or `absent: true`), and serving replays calls matching them and
|
||||
calls asking for fields the checked lines do not show.
|
||||
Otherwise the tool is a recorded view
|
||||
with reason `envelope-varies`, `fields-differ` or `list-differs`; the other
|
||||
reasons are `query-body` (a query `POST`, or one the capture shows only reading), `no-init-recording`,
|
||||
reasons are `query-body` (a query `POST`, or one the capture shows only reading),
|
||||
`method-replay` (a safe `HEAD`, `OPTIONS` or `TRACE` call), `no-init-recording`,
|
||||
`body-unusable`, `no-identity` (an item read without a proved identity),
|
||||
`path-varies` (another read under more than one path, as a template with a
|
||||
parameter before its end), `query-varies` (another read of one path under
|
||||
@@ -739,7 +748,9 @@ one-element array member) that a later item read of a type first shows (served
|
||||
only with the path values its recorded call sent, unless it creates into the
|
||||
type's own collection, whose path has no parameters, and a `path` rule stores
|
||||
each of its path values), and otherwise `none` with reason `no-state-target`. A plan is built from the tool's first successful call: its
|
||||
request body must be a usable JSON object (as response bodies are usable), and
|
||||
request body must be a usable JSON object (as response bodies are usable), or
|
||||
absent for an item action (a scenario request is absent when Playwright exposed
|
||||
no body and it names no `Content-Type`, which the bodies browsers send carry), and
|
||||
the written entity must show in that call's response or in a later read before
|
||||
the next write. Each field of a created entity gets the first rule that
|
||||
explains it: generated `identity` (a sequence, UUID or token, by the recorded
|
||||
@@ -779,15 +790,19 @@ with the entity leaves out a field only later reads showed, which no initial
|
||||
entity holds, when the entity does not hold it, as Vikunja's reads of tasks it
|
||||
did not create show no `subscription`. A `reference` is an object
|
||||
holding fields of the
|
||||
entity a sent member names, as the state holds it (a parent beside `parentId`):
|
||||
entity a sent member names, as the state holds it (a parent beside `parentId`),
|
||||
or a list of them, one per id a sent list names, in its order (`many`, tags
|
||||
beside `tagIds`):
|
||||
the member is accepted with any value, serving looks the entity up and refuses a
|
||||
call naming one the environment does not hold or holds in more than one
|
||||
collection, and the field is absent, from the entity and the create's answer,
|
||||
when the call does not send the member. An id naming entities of one type in
|
||||
several collections teaches no reference. Each later create widens its plan
|
||||
when, explained on its own, it agrees with it: both calls show the same fields
|
||||
but for a reference whose member a call without it did not send (one an earlier
|
||||
create added stays), every field both rule they rule alike (an echo one showed
|
||||
but for a reference whose member a call without it did not send, or sent as
|
||||
`null` or `[]` and stored so (one an earlier create added stays, and a call may
|
||||
send the member empty as that create did; one leaving it out stores no such field
|
||||
when the create the plan observes showed none), every field both rule they rule alike (an echo one showed
|
||||
sorted stays sorted, unless a call stored its strings out of order as sent),
|
||||
and a field neither rules holds one value, unless the later call's rule for it
|
||||
spells the earlier calls' value too: a `composed` or `template` string, or a
|
||||
@@ -797,7 +812,14 @@ clocks and own members, and a count only the later call shows starts at the
|
||||
first object's value; a later create's made object must hold clocks its own
|
||||
request stamped, in the rule's format. Members either call sent are accepted, only those every call sent are
|
||||
required, and an echoed member a call left out takes the value that call stored
|
||||
(`body.defaults`). A member a create sent empty (`""`, `null`, `false`, `[]` or
|
||||
(`body.defaults`). A member one call sent and stored as sent, and another left
|
||||
out and the application numbered one past the others, takes the value a call
|
||||
sends, else that number (a `sequence` with `sent`), whichever call came first,
|
||||
unless a call that left it out stored a fixed value (its `body.defaults`) or
|
||||
the number a later call was given is not above every value an earlier create
|
||||
sent in the sequence's scope (the type, or the later call's collection); an empty value a call sent is not applied to a call that leaves it out;
|
||||
a later call that sends it must have stored what it sent, and the next number
|
||||
follows the largest value any call took, a deleted entity's included. A member a create sent empty (`""`, `null`, `false`, `[]` or
|
||||
`{}`), as a form sends a field left as it was, is not required: a call that
|
||||
leaves it out is applied as sending that value (`body.blank`), unless a call
|
||||
that left it out showed a default, which it then keeps. A call may send it as any
|
||||
@@ -860,13 +882,28 @@ is unchanged) must be a clock, a nested clock, an increment, a slug, a fresh `un
|
||||
value, a `stamp` of the acting user, a value `derived` from the one member it
|
||||
stores nowhere, a `reference` to the entity a sent member names (kept by a call that names the entity the field already repeats), a `composed` string whose parts read members it stored as sent
|
||||
or fields it left as they were and spell the value before the call too, or for
|
||||
an item action a `set` of a scalar to the value it showed, or the plan is
|
||||
an item action a `set` of a scalar to the value it showed (a `toggle` once a
|
||||
later call flips back the boolean an earlier one set, when no call found it set
|
||||
already), or, for a `PUT`, a
|
||||
member it left out that the application cleared to an empty value, which calls
|
||||
that leave it out then store (`body.defaults`) as long as every call that left
|
||||
it out stored that value (a call naming a `reference` field's entity by its
|
||||
member does not leave the field out), or the plan is
|
||||
`unexplained-change`; an increment, slug, stamp, derived
|
||||
value or set must hold for every call of the tool, and an action is served
|
||||
only once a call found what it sets already set. A write is served only
|
||||
value, set or toggle must hold for every call of the tool, and an action is
|
||||
served only once a call found what it sets already set, or flipped back what it
|
||||
toggles. A write is served only
|
||||
with the query its first call sent, which serving applies to a call that
|
||||
leaves a parameter out and the catalog advertises as required. Every member the first call sent is required, except by `PATCH` and
|
||||
`POST` updates and members a create sent empty.
|
||||
leaves a parameter out and the catalog advertises as required. Every member every call sent is required, except by `PATCH` and
|
||||
`POST` updates and members a create sent empty. The state holds an update's
|
||||
clock as the first read of the entity after it spells the same instant at a
|
||||
coarser precision in the same zone and separator: replay and serving store every
|
||||
update's clocks in the spelling of the read the plan keeps as
|
||||
`observation.read`, so a later update whose read spells them otherwise
|
||||
contradicts the plan, while answers keep the update's own; a create's clocks
|
||||
stay as answered. A `PUT` default must agree with what every call that left the
|
||||
member out stored, as its answer shows it or, where the answer leaves it out,
|
||||
the read after the call.
|
||||
|
||||
A read on a line `query` answers is checked against the query evaluated over
|
||||
the replayed state. It covers the collection only when every parameter sorts or
|
||||
@@ -899,7 +936,10 @@ contradicted it; otherwise its `reason` is the first of its build reason
|
||||
(`no-call`, `body-unusable`, `no-observation`, `unexplained-change`),
|
||||
`contradicted` (with `contradicted_by`), `side-effect`, `unconfirmed` and `incomplete-entities` (an update or delete that answers with the entity, when no initial entity holds every field its recorded answer shows but those only later reads showed, counting for an update the fields its rules write, so it could answer only for entities the environment created). An otherwise served plan whose learned rules generate clock values is withheld with `unknown-clock` when no global clock start is established; its learned rules and confirming reads remain retained.
|
||||
`checked_record_ordinals` lists the confirming reads, `insert` places created
|
||||
entities (sorted by a field the collection's recorded order shows, else last),
|
||||
entities (sorted by a field the collection's recorded order shows, else last;
|
||||
a create a whole listing in collection order placed last is placed again by a
|
||||
field a later such listing shows it sorted by and no earlier one ruled out, the
|
||||
type's id field last),
|
||||
and `write_clock` is the end of the last timed record, to the next second, when
|
||||
all request completions are known; otherwise it is null. An
|
||||
update that writes the field its type's creates are sorted by moves its entity
|
||||
|
||||
@@ -31,10 +31,11 @@ zero-based UTF-16 column. The MCP arguments are:
|
||||
|
||||
The URL supplies the context for resolving `sources` and `sourceRoot` using the
|
||||
ECMA-426 URL parsing rule; it is not an instruction to fetch. Repeated path
|
||||
separators remain part of the resolved URL identity. A non-null `sourceRoot`
|
||||
separators remain part of the resolved URL identity. A non-empty `sourceRoot`
|
||||
prefixes each source, adding `/` only when the root does not already end with
|
||||
one. An empty root therefore prefixes `/`; a null or omitted root adds no
|
||||
prefix. Absolute virtual or file contexts can be selected as well. The map/script association is caller-selected: a declaration or local map
|
||||
one. An empty, null or omitted root adds no prefix. webpack 5 and tsc maps
|
||||
(`"sourceRoot": ""`) therefore resolve against the map URL, as Chrome, Firefox
|
||||
and the pinned codec do. Absolute virtual or file contexts can be selected as well. The map/script association is caller-selected: a declaration or local map
|
||||
does not prove deployment authenticity or execution. Use
|
||||
[import tracing](website-module-trace.md) to inspect outgoing native module edges.
|
||||
|
||||
@@ -101,8 +102,11 @@ run token while process release is unconfirmed, and the directory until removal
|
||||
succeeds. A later successful retry settles every error bound to that command;
|
||||
historical failure diagnostics remain available.
|
||||
|
||||
Complete evidence is bounded by a 4 MiB map, 32 MiB codec reply, 262144 decoded
|
||||
rows/segments and 64 nested section levels. Those structural budgets and the
|
||||
Complete evidence is bounded by a 4 MiB map, 32 MiB codec reply and a shared
|
||||
262144-record decoder budget. Generated rows, mapping segments, leaf maps,
|
||||
source and name declarations, `sourcesContent` entries and indexed sections all
|
||||
consume this budget. Generated rows and mapping segments also each have a
|
||||
262144 limit; indexed maps allow at most 64 nested section levels. Those budgets and the
|
||||
192 MiB codec heap have no runtime override. Exceeding a budget returns an explicit
|
||||
failure, without partial results. The existing 32 MiB manifest and 16 MiB selected
|
||||
script boundaries also apply. No global toolchain or browser configuration changes
|
||||
|
||||
@@ -19,12 +19,13 @@ additional permission flag or degraded mode is required.
|
||||
- a 64-bit full JDK inside that installation's declared Java range (JDK 21 or newer, with no maximum, for current 12.1 releases);
|
||||
- an explicit native, non-managed x86, x86-64, ARMNT (Thumb-2) or ARM64 PE application/DLL, or a
|
||||
[raw NMOS 6502 image](raw-binary.md#nmos-6502) with a caller-supplied entry; and
|
||||
- the 26 read-only Ghidra inventory, memory, and function-analysis operations.
|
||||
- the 27 read-only Ghidra inventory, memory, and function-analysis operations.
|
||||
|
||||
Loaded memory reads and file offsets preserve Ghidra's observed source mappings.
|
||||
PE load-image inspection returns an explicit unsupported attestation status.
|
||||
Independent verification covers admitted DOS MZ, explicit COM, and explicit
|
||||
[raw-binary imports](raw-binary.md) on their supported hosts, including the
|
||||
Independent verification covers admitted DOS MZ, explicit COM, explicit
|
||||
[raw-binary imports](raw-binary.md), and explicit
|
||||
[GameCube DOL images](ghidra-dol.md) on their supported hosts, including the
|
||||
admitted raw NMOS 6502 mapping on Windows. Windows P0 admission remains limited
|
||||
to native PE and raw NMOS 6502 images. For x64 PE
|
||||
NativeAOT RTR 9.1, the read-only snapshot parser can report metadata through
|
||||
|
||||
Generated
+1
@@ -61,6 +61,7 @@
|
||||
"@stryker-mutator/core": "10.0.0",
|
||||
"@stryker-mutator/typescript-checker": "10.0.0",
|
||||
"@stryker-mutator/vitest-runner": "10.0.0",
|
||||
"@toon-format/toon": "2.3.1",
|
||||
"@types/cross-spawn": "6.0.6",
|
||||
"@types/node": "26.6.4",
|
||||
"@types/semver": "7.7.1",
|
||||
|
||||
+5
-1
@@ -152,7 +152,7 @@
|
||||
"test": "npm run test:with-build",
|
||||
"test:with-build": "npm run test:prepare && vitest run",
|
||||
"test:run": "vitest run",
|
||||
"test:python": "python3 -m unittest bridge/native/test_rea_lldb_tracer.py bridge/pwndbg/test_core_context.py bridge/mitmproxy/test_capture.py -v && python3 -m unittest discover -s tests/support/analysis-efficiency -p 'test_*.py' -v",
|
||||
"test:python": "python3 scripts/run-python-tests.py",
|
||||
"test:local": "node scripts/run-development-tests.mjs local",
|
||||
"test:fast": "node scripts/ci/test-group.mjs source",
|
||||
"test:built": "node scripts/ci/test-group.mjs built",
|
||||
@@ -184,6 +184,7 @@
|
||||
"typecheck": "node scripts/run-typescript.mjs --noEmit",
|
||||
"verify:test-temp-hygiene": "npm run test:prepare && node scripts/verify-test-temp-hygiene.mjs",
|
||||
"verify:hopper": "npm run verify:fixtures && npm run build:cached && node scripts/verify-real-hopper.mjs",
|
||||
"verify:hopper:callers": "npm run build:cached && node scripts/verify-real-hopper-callers.mjs",
|
||||
"verify:hopper:deadlines": "npm run verify:fixtures && npm run build:cached && node scripts/verify-real-hopper-deadlines.mjs",
|
||||
"verify:hopper:fat": "npm run build:cached && node scripts/verify-real-hopper-fat.mjs",
|
||||
"verify:hopper:fat64": "npm run build:cached && node scripts/verify-real-hopper-fat.mjs --fat64",
|
||||
@@ -239,6 +240,7 @@
|
||||
"verify:managed": "npm run build:cached && node scripts/verify/managed/conformance.mjs",
|
||||
"verify:firmware": "npm run build:cached && node scripts/verify/firmware/analysis.mjs",
|
||||
"verify:devicetree": "npm run build:cached && node scripts/verify/firmware/devicetree.mjs",
|
||||
"verify:esp-images": "npm run build:cached && node scripts/verify/firmware/esp-image.mjs",
|
||||
"fixtures:firmware": "node scripts/fixtures/firmware/generate.mjs",
|
||||
"verify:android": "npm run build:cached && node scripts/verify/android/analysis.mjs",
|
||||
"verify:jeb": "npm run build:cached && node scripts/verify-jeb.mjs",
|
||||
@@ -308,6 +310,7 @@
|
||||
"verify:agentenv:environment": "npm run build:cached && node scripts/verify-agentenv-environment.mjs",
|
||||
"verify:web:http3": "npm run build:cached && node scripts/verify-http3-network-captures.mjs",
|
||||
"verify:binary:layout": "npm run build:cached && node scripts/verify-binary-layout.mjs",
|
||||
"verify:bun:standalone": "npm run build:cached && node scripts/verify-bun-standalone.mjs",
|
||||
"verify:go:binary": "npm run build:cached && node scripts/verify-go-binary.mjs",
|
||||
"verify:il2cpp:metadata": "npm run build:cached && node scripts/verify-il2cpp-metadata.mjs",
|
||||
"verify:wasm:package": "npm run build:cached && node scripts/verify-packaged-wasm-artifact.mjs",
|
||||
@@ -398,6 +401,7 @@
|
||||
"@stryker-mutator/core": "10.0.0",
|
||||
"@stryker-mutator/typescript-checker": "10.0.0",
|
||||
"@stryker-mutator/vitest-runner": "10.0.0",
|
||||
"@toon-format/toon": "2.3.1",
|
||||
"@types/cross-spawn": "6.0.6",
|
||||
"@types/node": "26.6.4",
|
||||
"@types/semver": "7.7.1",
|
||||
|
||||
+22
-19
@@ -4,13 +4,11 @@ import { matchesGlob } from "node:path";
|
||||
import {
|
||||
CI_FLAGS as flags,
|
||||
MANUAL_VERIFIERS,
|
||||
SCOPES,
|
||||
CI_LANES,
|
||||
WINDOWS_EXECUTABLE_SELECTION_INPUTS,
|
||||
} from "./scopes.mjs";
|
||||
import { planTestSelection } from "./test-selection.mjs";
|
||||
|
||||
// Test files select the host/runtime lanes that execute their focused suites.
|
||||
const HOST_TEST_OWNERS = ["apple", "package", "sqlite"];
|
||||
// Actionlint validates workflow syntax only. The semantic suite asserts these
|
||||
// workflows' release, publication and self-hosted runner safeguards.
|
||||
const GUARDED_WORKFLOWS = new Set([
|
||||
@@ -111,6 +109,10 @@ function classifyPackage(base, head) {
|
||||
selected.reverse_tools = true;
|
||||
continue;
|
||||
}
|
||||
if (script === "test:python") {
|
||||
selected.python = true;
|
||||
continue;
|
||||
}
|
||||
if (script === "test:sqlite" || script === "test:sqlite:run") {
|
||||
selected.sqlite = true;
|
||||
continue;
|
||||
@@ -145,11 +147,11 @@ function classifyPackage(base, head) {
|
||||
const scriptOwners =
|
||||
simple &&
|
||||
entries.every((entry) =>
|
||||
Object.values(SCOPES).some((patterns) => matchesAny(entry, patterns)),
|
||||
Object.values(CI_LANES).some(({ paths }) => matchesAny(entry, paths)),
|
||||
)
|
||||
? Object.entries(SCOPES)
|
||||
.filter(([, patterns]) =>
|
||||
entries.some((entry) => matchesAny(entry, patterns)),
|
||||
? Object.entries(CI_LANES)
|
||||
.filter(([, { paths }]) =>
|
||||
entries.some((entry) => matchesAny(entry, paths)),
|
||||
)
|
||||
.map(([owner]) => owner)
|
||||
: [];
|
||||
@@ -215,7 +217,12 @@ if (tier === "reused") {
|
||||
file,
|
||||
WINDOWS_EXECUTABLE_SELECTION_INPUTS,
|
||||
);
|
||||
if (matchesAny(file, SCOPES.reverse_tools)) selected.reverse_tools = true;
|
||||
for (const [
|
||||
owner,
|
||||
{ paths, earlyAll, earlyInputs = [] },
|
||||
] of Object.entries(CI_LANES))
|
||||
if (matchesAny(file, earlyAll ? paths : earlyInputs))
|
||||
selected[owner] = true;
|
||||
if (
|
||||
/^(README(?:_[^/]+)?\.md|AGENTS\.md|CONTRIBUTING\.md|CHANGELOG\.md|SECURITY\.md|native\/windows\/README\.md|\.github\/pull_request_template\.md)$/.test(
|
||||
file,
|
||||
@@ -229,13 +236,13 @@ if (tier === "reused") {
|
||||
file.startsWith("docs/") &&
|
||||
(/\.(?:[cm]?[jt]s|[jt]sx)$/u.test(file) ||
|
||||
file.endsWith("/package.json"));
|
||||
selected.website ||= matchesAny(file, SCOPES.website);
|
||||
selected.website ||= matchesAny(file, CI_LANES.website.paths);
|
||||
continue;
|
||||
}
|
||||
if (/^(src|tests)\/.*\.(?:test|spec)\.[cm]?[jt]sx?$/.test(file)) {
|
||||
selected.code = true;
|
||||
for (const owner of HOST_TEST_OWNERS)
|
||||
selected[owner] ||= matchesAny(file, SCOPES[owner]);
|
||||
for (const [owner, { paths, testInputs }] of Object.entries(CI_LANES))
|
||||
if (testInputs && matchesAny(file, paths)) selected[owner] = true;
|
||||
continue;
|
||||
}
|
||||
if (matchesAny(file, MANUAL_VERIFIERS)) {
|
||||
@@ -255,19 +262,15 @@ if (tier === "reused") {
|
||||
if (tier !== "full" && SHARED_BOUNDARY.test(file)) {
|
||||
selected.code = true;
|
||||
selected.runtime = true;
|
||||
const owners = Object.entries(SCOPES)
|
||||
.filter(([, patterns]) =>
|
||||
patterns.some((pattern) => matchesGlob(file, pattern)),
|
||||
)
|
||||
const owners = Object.entries(CI_LANES)
|
||||
.filter(([, { paths }]) => matchesAny(file, paths))
|
||||
.map(([owner]) => owner);
|
||||
if (owners.length === 1) selected[owners[0]] = true;
|
||||
reasons.push(`Shared boundary on fast tier: ${file}`);
|
||||
continue;
|
||||
}
|
||||
const owners = Object.entries(SCOPES)
|
||||
.filter(([, patterns]) =>
|
||||
patterns.some((pattern) => matchesGlob(file, pattern)),
|
||||
)
|
||||
const owners = Object.entries(CI_LANES)
|
||||
.filter(([, { paths }]) => matchesAny(file, paths))
|
||||
.map(([owner]) => owner);
|
||||
for (const owner of owners) selected[owner] = true;
|
||||
if (
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { isAbsolute, relative, resolve, sep } from "node:path";
|
||||
|
||||
const resources = [
|
||||
"enforces both address-space limits before any producer allocation",
|
||||
"preserves lower inherited file/CPU limits in the real launch",
|
||||
];
|
||||
const descriptors = [
|
||||
"capture",
|
||||
"tool",
|
||||
"limiter",
|
||||
"kernel",
|
||||
"field-tool",
|
||||
"field-limiter",
|
||||
"field-kernel",
|
||||
].map(
|
||||
(member) =>
|
||||
`retains failed ${member} descriptors and retries them before further acquisition and shutdown`,
|
||||
);
|
||||
const requirements = {
|
||||
packet: {
|
||||
"tests/boundary/captures/resourceLimits.test.ts": [
|
||||
...resources,
|
||||
"reports a real kernel file-limit termination with its effective ceiling",
|
||||
],
|
||||
"tests/boundary/captures/captureDescriptorCleanup.test.ts": descriptors,
|
||||
},
|
||||
signal: {
|
||||
"tests/boundary/signals/resourceLimits.test.ts": resources,
|
||||
"tests/boundary/signals/recordingDescriptorCleanup.test.ts": descriptors,
|
||||
},
|
||||
};
|
||||
|
||||
const [lane, reportPath] = process.argv.slice(2);
|
||||
if (!Object.hasOwn(requirements, lane ?? "") || !reportPath)
|
||||
throw new Error(
|
||||
"Expected provider test lane (packet or signal) and report path",
|
||||
);
|
||||
const root = resolve(process.cwd());
|
||||
const rootPrefix = `${root}${sep}`;
|
||||
const reportFile = resolve(root, reportPath);
|
||||
if (!reportFile.startsWith(rootPrefix)) {
|
||||
const failure = { code: "report_path_outside_checkout" };
|
||||
throw Object.assign(new Error(JSON.stringify(failure)), failure);
|
||||
}
|
||||
const report = JSON.parse(await readFile(reportFile, "utf8"));
|
||||
if (report?.success !== true || !Array.isArray(report.testResults))
|
||||
throw new Error(
|
||||
"Provider test report is missing a successful test inventory",
|
||||
);
|
||||
for (const [path, cases] of Object.entries(requirements[lane])) {
|
||||
const matches = report.testResults.filter((file) => {
|
||||
if (typeof file?.name !== "string") return false;
|
||||
const filePath = relative(process.cwd(), resolve(file.name));
|
||||
return !isAbsolute(filePath) && filePath.split(sep).join("/") === path;
|
||||
});
|
||||
if (matches.length !== 1 || !Array.isArray(matches[0].assertionResults))
|
||||
throw new Error(`Expected exactly one provider test result for ${path}`);
|
||||
for (const name of cases) {
|
||||
const results = matches[0].assertionResults.filter(
|
||||
(test) => test?.fullName === name,
|
||||
);
|
||||
if (results.length !== 1 || results[0].status !== "passed")
|
||||
throw new Error(`Required provider test did not pass: ${path}: ${name}`);
|
||||
}
|
||||
}
|
||||
console.log(`Required ${lane} resource and cleanup cases passed`);
|
||||
+3
-18
@@ -1,4 +1,4 @@
|
||||
import { CI_FLAGS } from "./scopes.mjs";
|
||||
import { CI_FLAGS, CI_LANES } from "./scopes.mjs";
|
||||
import { recordQualification } from "./qualification.mjs";
|
||||
|
||||
const jobs = JSON.parse(process.env.CI_JOBS);
|
||||
@@ -30,23 +30,8 @@ if (outputs.tier === "full" && selectedScopes.length !== CI_FLAGS.length)
|
||||
throw new Error("Full qualification requires every canonical CI scope");
|
||||
const required = reused ? ["changes"] : ["changes", "static", "test"];
|
||||
if (outputs.tier === "full") required.push("static-deep");
|
||||
const lanes = {
|
||||
code: [
|
||||
"build",
|
||||
"test-shard",
|
||||
...(outputs.tier === "fast" ? ["test-source"] : []),
|
||||
],
|
||||
reverse_tools: ["reverse-tools-quality"],
|
||||
runtime: ["windows-native-build", "package-e2e"],
|
||||
package: ["windows-curated"],
|
||||
sqlite: ["sqlite-runtime"],
|
||||
apple: ["apple-artifacts"],
|
||||
fixtures: ["conformance-fixtures"],
|
||||
readiness: ["reconstruction-readiness"],
|
||||
docs: ["docs"],
|
||||
workflows: ["static"],
|
||||
};
|
||||
for (const scope of selectedScopes) required.push(...(lanes[scope] ?? [scope]));
|
||||
for (const scope of selectedScopes)
|
||||
required.push(...CI_LANES[scope].required[outputs.tier]);
|
||||
const failed = [...new Set(required)].filter(
|
||||
(name) => jobs[name]?.result !== "success",
|
||||
);
|
||||
|
||||
+118
-13
@@ -8,10 +8,58 @@ export const WINDOWS_EXECUTABLE_SELECTION_INPUTS = [
|
||||
"tests/boundary/process/windowsExecutableSelection.test.ts",
|
||||
];
|
||||
|
||||
// Inputs whose changes must select both real capture lanes, even at shared boundaries.
|
||||
const CAPTURE_SHARED_INPUTS = [
|
||||
"src/process/LinuxResourceLimits*",
|
||||
"scripts/ci/require-provider-tests.mjs",
|
||||
];
|
||||
|
||||
// Ownership of the native-host, real-provider and website verification lanes.
|
||||
// Shared build inputs are classified once in plan.mjs rather than repeated in
|
||||
// every workflow.
|
||||
export const SCOPES = {
|
||||
const PATH_SCOPES = {
|
||||
python: [
|
||||
"bridge/**/*.py",
|
||||
"tests/support/analysis-efficiency/**",
|
||||
"scripts/run-python-tests.py",
|
||||
],
|
||||
packet_capture: [
|
||||
"tests/boundary/captures/**",
|
||||
"tests/boundary/cli/captureCleanup.test.ts",
|
||||
"tests/boundary/mcp/packetCaptureMcp.test.ts",
|
||||
"tests/boundary/pcap/**",
|
||||
"src/captures/**",
|
||||
"src/pcap/**",
|
||||
"src/domain/pcap/**",
|
||||
"src/domain/analysisView/pcapCaptureView.ts",
|
||||
"src/application/pcap/**",
|
||||
"src/contracts/pcap/**",
|
||||
"src/server/registerPcapTools.ts",
|
||||
"src/domain/captures/**",
|
||||
"src/application/captures/**",
|
||||
"src/contracts/captures/**",
|
||||
"src/composition/captures.ts",
|
||||
"src/cli/captureCommands.ts",
|
||||
"src/server/registerCaptureTools.ts",
|
||||
...CAPTURE_SHARED_INPUTS,
|
||||
"scripts/verify-packet-capture.mjs",
|
||||
".github/workflows/real-packet-capture.yml",
|
||||
],
|
||||
signal_recording: [
|
||||
"tests/boundary/signals/**",
|
||||
"tests/boundary/cli/signalCleanup.test.ts",
|
||||
"tests/boundary/mcp/signalRecordingMcp.test.ts",
|
||||
"src/signals/**",
|
||||
"src/domain/signals/**",
|
||||
"src/application/signals/**",
|
||||
"src/contracts/signals/**",
|
||||
"src/composition/signals.ts",
|
||||
"src/cli/signalCommands.ts",
|
||||
"src/server/registerSignalTools.ts",
|
||||
...CAPTURE_SHARED_INPUTS,
|
||||
"scripts/verify-signal-recording.mjs",
|
||||
".github/workflows/real-signal-recording.yml",
|
||||
],
|
||||
readiness: [
|
||||
"tests/conformance/readiness/**",
|
||||
"scripts/verify-reconstruction-readiness.mjs",
|
||||
@@ -107,6 +155,7 @@ export const SCOPES = {
|
||||
"tests/boundary/providers/native/nativeSignatureTargetBinding.test.ts",
|
||||
"tests/boundary/cli/nativeSignatureCli.test.ts",
|
||||
"tests/boundary/cli/nativeMachoArm64_32Cli.test.ts",
|
||||
"tests/boundary/cli/nativeMachoEncryptionCli.test.ts",
|
||||
"tests/boundary/mcp/nativeSignatureTargetBindingMcp.test.ts",
|
||||
"src/process/capture/FilesystemSnapshot.test.ts",
|
||||
"tests/process-global/filesystemSnapshotFallbackCancellation.test.ts",
|
||||
@@ -552,6 +601,8 @@ export const SCOPES = {
|
||||
"src/ghidra/GhidraJavaProperties.ts",
|
||||
"src/ghidra/GhidraReleasePolicy.ts",
|
||||
"scripts/verify-ghidra-bridge-sources.mjs",
|
||||
"tests/conformance/ghidra/ReaArmContextProbe.java",
|
||||
"tests/conformance/ghidra/ReaDecodeProbe.java",
|
||||
".github/workflows/ghidra-bridge-sources.yml",
|
||||
],
|
||||
website: [
|
||||
@@ -564,19 +615,73 @@ export const SCOPES = {
|
||||
],
|
||||
};
|
||||
|
||||
export const CI_FLAGS = [
|
||||
...new Set([
|
||||
"code",
|
||||
"runtime",
|
||||
"package",
|
||||
"apple",
|
||||
"fixtures",
|
||||
"readiness",
|
||||
"docs",
|
||||
"workflows",
|
||||
...Object.keys(SCOPES),
|
||||
// Each lane owns its path inputs, selection policy, and required jobs. The
|
||||
// workflow stays explicit; contract tests bind it to this registry.
|
||||
const sameJobs = (paths, jobs, selection = {}) => ({
|
||||
paths,
|
||||
required: { fast: jobs, full: jobs },
|
||||
...selection,
|
||||
});
|
||||
export const CI_LANES = {
|
||||
code: {
|
||||
paths: [],
|
||||
required: {
|
||||
fast: ["build", "test-shard", "test-source"],
|
||||
full: ["build", "test-shard"],
|
||||
},
|
||||
},
|
||||
runtime: sameJobs([], ["windows-native-build", "package-e2e"]),
|
||||
package: sameJobs(PATH_SCOPES.package, ["windows-curated"], {
|
||||
testInputs: true,
|
||||
}),
|
||||
apple: sameJobs(PATH_SCOPES.apple, ["apple-artifacts"], { testInputs: true }),
|
||||
fixtures: sameJobs([], ["conformance-fixtures"]),
|
||||
readiness: sameJobs(PATH_SCOPES.readiness, ["reconstruction-readiness"]),
|
||||
docs: sameJobs([], ["docs"]),
|
||||
workflows: sameJobs([], ["static"]),
|
||||
python: {
|
||||
paths: PATH_SCOPES.python,
|
||||
earlyAll: true,
|
||||
required: { fast: ["python"], full: ["static-deep"] },
|
||||
},
|
||||
packet_capture: sameJobs(PATH_SCOPES.packet_capture, ["packet_capture"], {
|
||||
testInputs: true,
|
||||
earlyInputs: CAPTURE_SHARED_INPUTS,
|
||||
}),
|
||||
signal_recording: sameJobs(
|
||||
PATH_SCOPES.signal_recording,
|
||||
["signal_recording"],
|
||||
{ testInputs: true, earlyInputs: CAPTURE_SHARED_INPUTS },
|
||||
),
|
||||
reverse_tools: sameJobs(
|
||||
PATH_SCOPES.reverse_tools,
|
||||
["reverse-tools-quality"],
|
||||
{ earlyAll: true },
|
||||
),
|
||||
sqlite: sameJobs(PATH_SCOPES.sqlite, ["sqlite-runtime"], {
|
||||
testInputs: true,
|
||||
}),
|
||||
browser: sameJobs(PATH_SCOPES.browser, ["browser"]),
|
||||
binary_layout: sameJobs(PATH_SCOPES.binary_layout, ["binary_layout"]),
|
||||
evm: sameJobs(PATH_SCOPES.evm, ["evm"]),
|
||||
apk_signature: sameJobs(PATH_SCOPES.apk_signature, ["apk_signature"]),
|
||||
javascript_recovery: sameJobs(PATH_SCOPES.javascript_recovery, [
|
||||
"javascript_recovery",
|
||||
]),
|
||||
];
|
||||
recorded_crash: sameJobs(PATH_SCOPES.recorded_crash, ["recorded_crash"]),
|
||||
web_network: sameJobs(PATH_SCOPES.web_network, ["web_network"]),
|
||||
web_runtime: sameJobs(PATH_SCOPES.web_runtime, ["web_runtime"]),
|
||||
web_source_map: sameJobs(PATH_SCOPES.web_source_map, ["web_source_map"]),
|
||||
agentenv: sameJobs(PATH_SCOPES.agentenv, ["agentenv"]),
|
||||
nativeaot: sameJobs(PATH_SCOPES.nativeaot, ["nativeaot"]),
|
||||
ghidra_bridge: sameJobs(PATH_SCOPES.ghidra_bridge, ["ghidra_bridge"]),
|
||||
website: sameJobs(PATH_SCOPES.website, ["website"]),
|
||||
};
|
||||
// An input owner omitted from the registry must never silently lose a lane.
|
||||
for (const [name, paths] of Object.entries(PATH_SCOPES))
|
||||
if (!Object.hasOwn(CI_LANES, name) || CI_LANES[name].paths !== paths)
|
||||
throw new Error(`CI lane registry does not own input scope: ${name}`);
|
||||
export const CI_FLAGS = Object.keys(CI_LANES);
|
||||
|
||||
// Verifier entrypoints that only manual, licensed, or self-hosted workflows
|
||||
// run. No selected CI lane executes them, so their edits need only the static
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DebugType>none</DebugType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.NET.HostModel">
|
||||
<HintPath>$(MSBuildSDKsPath)/../Microsoft.NET.HostModel.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration><packageSources><clear /></packageSources></configuration>
|
||||
@@ -0,0 +1,92 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Buffers.Binary;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
using Microsoft.NET.HostModel.AppHost;
|
||||
using Microsoft.NET.HostModel.Bundle;
|
||||
|
||||
// Trusted fixture generator only. Generated hosts are inspected, never executed.
|
||||
if (args.Length is < 2 or > 3)
|
||||
throw new ArgumentException("Expected apphost template, absent output directory, and optional windows/linux/osx target");
|
||||
var targetOS = (args.ElementAtOrDefault(2) ?? "windows") switch
|
||||
{
|
||||
"windows" => OSPlatform.Windows,
|
||||
"linux" => OSPlatform.Linux,
|
||||
"osx" => OSPlatform.OSX,
|
||||
_ => throw new ArgumentException("Target OS must be windows, linux or osx"),
|
||||
};
|
||||
var hostName = targetOS == OSPlatform.Windows ? "Probe.exe" : "Probe";
|
||||
var template = Path.GetFullPath(args[0]);
|
||||
var output = Path.GetFullPath(args[1]);
|
||||
if (Directory.Exists(output)) throw new IOException("Output directory must be absent");
|
||||
Directory.CreateDirectory(output);
|
||||
var assembly = typeof(Program).Assembly.Location;
|
||||
var resource = Path.Combine(output, "resource.txt");
|
||||
File.WriteAllText(resource, string.Concat(Enumerable.Repeat("owned compressed fixture content\n", 4096)));
|
||||
foreach (var (version, compress) in new[] { (new Version(3, 1), false), (new Version(5, 0), false), (new Version(8, 0), false), (new Version(8, 0), true) })
|
||||
{
|
||||
var label = $"net{version.Major}-{(compress ? "compressed" : "plain")}";
|
||||
var directory = Path.Combine(output, label);
|
||||
Directory.CreateDirectory(directory);
|
||||
var host = Path.Combine(directory, targetOS == OSPlatform.Windows ? "template.exe" : "template");
|
||||
HostWriter.CreateAppHost(template, host, "BundleFixture.dll");
|
||||
var bundler = new Bundler(hostName, directory,
|
||||
BundleOptions.BundleOtherFiles | (compress ? BundleOptions.EnableCompression : BundleOptions.None),
|
||||
targetOS, Architecture.X64, version, appAssemblyName: "BundleFixture");
|
||||
var inputs = new Dictionary<string, string>
|
||||
{
|
||||
["BundleFixture.dll"] = assembly,
|
||||
["BundleFixture.deps.json"] = Path.ChangeExtension(assembly, ".deps.json"),
|
||||
["BundleFixture.runtimeconfig.json"] = Path.ChangeExtension(assembly, ".runtimeconfig.json"),
|
||||
["data/resource.txt"] = resource,
|
||||
};
|
||||
var generated = bundler.GenerateBundle(new[] {
|
||||
new FileSpec(host, hostName),
|
||||
new FileSpec(assembly, "BundleFixture.dll"),
|
||||
new FileSpec(Path.ChangeExtension(assembly, ".deps.json"), "BundleFixture.deps.json"),
|
||||
new FileSpec(Path.ChangeExtension(assembly, ".runtimeconfig.json"), "BundleFixture.runtimeconfig.json"),
|
||||
new FileSpec(resource, "data/resource.txt"),
|
||||
});
|
||||
File.WriteAllText(Path.Combine(directory, "oracle.json"), JsonSerializer.Serialize(Observe(generated, inputs), new JsonSerializerOptions { WriteIndented = true }));
|
||||
Console.WriteLine(generated);
|
||||
}
|
||||
|
||||
// Independent positive-fixture oracle: .NET's BinaryReader owns its string/number framing.
|
||||
static object Observe(string path, Dictionary<string, string> inputs)
|
||||
{
|
||||
var bytes = File.ReadAllBytes(path);
|
||||
var signature = Convert.FromHexString("8b1202b96a612038727b930214d7a03213f5b9e6efae3318ee3b2dce24b36aae");
|
||||
var marker = bytes.AsSpan().IndexOf(signature);
|
||||
if (marker < 8) throw new InvalidDataException("Generated host has no bundle marker");
|
||||
var header = BinaryPrimitives.ReadInt64LittleEndian(bytes.AsSpan(marker - 8, 8));
|
||||
using var stream = new MemoryStream(bytes);
|
||||
stream.Position = header;
|
||||
using var reader = new BinaryReader(stream);
|
||||
var major = reader.ReadUInt32();
|
||||
var minor = reader.ReadUInt32();
|
||||
var count = reader.ReadInt32();
|
||||
var bundleId = reader.ReadString();
|
||||
if (major >= 2) stream.Position += 40;
|
||||
var rows = new List<object>();
|
||||
var found = new HashSet<string>();
|
||||
for (var index = 0; index < count; index++)
|
||||
{
|
||||
var offset = reader.ReadInt64();
|
||||
var size = reader.ReadInt64();
|
||||
var compressed = major == 6 ? reader.ReadInt64() : 0;
|
||||
var kind = reader.ReadByte();
|
||||
var name = reader.ReadString();
|
||||
if (!inputs.TryGetValue(name, out var input) || !found.Add(name))
|
||||
throw new InvalidDataException("Unexpected generated member: " + name);
|
||||
using var stored = new MemoryStream(bytes, checked((int)offset), checked((int)(compressed == 0 ? size : compressed)));
|
||||
using var expanded = compressed == 0 ? null : new DeflateStream(stored, CompressionMode.Decompress);
|
||||
var digest = Convert.ToHexString(SHA256.HashData((Stream)expanded ?? stored)).ToLowerInvariant();
|
||||
var expected = File.ReadAllBytes(input);
|
||||
if (expected.LongLength != size || digest != Convert.ToHexString(SHA256.HashData(expected)).ToLowerInvariant())
|
||||
throw new InvalidDataException("Generated member bytes differ: " + name);
|
||||
rows.Add(new { name, offset, size, compressed_size = compressed, file_type = kind, sha256 = digest });
|
||||
}
|
||||
if (!found.SetEquals(inputs.Keys)) throw new InvalidDataException("Generated bundle omitted an input");
|
||||
return new { source = "Microsoft.NET.HostModel + independent BinaryReader/DeflateStream", host = path, major, minor, header_offset = header, bundle_id = bundleId, sha256 = Convert.ToHexString(SHA256.HashData(bytes)).ToLowerInvariant(), files = rows };
|
||||
}
|
||||
Loaded 100 of 1369 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user