120 Commits
Author SHA1 Message Date
pancake 0ee5e01498 Give duplicate Dart method names unique r2 flags and function names
r2 flag names are unique, so flagging a second function with a repeated
Dart name (e.g. Native._anon_closure) moved the flag away from the first
one, and current r2's af then named it after the Mach-O sym.func.* flag.
Suffix repeats with their address, use the same names for afs, and rename
analyzed functions after the af pass.

Also skip var recovery, call-following and jump tables in the signature
af pass (AuthPass -AAA 47s -> 29s) and raise R2R_TIMEOUT to 60s.
2026-11-06 13:54:07 +01:00
pancake 441d614937 Scan complete instruction ranges for standalone xrefs 2026-10-21 12:47:42 +02:00
pancake 25a5b3f026 Decode Record fields in snapshot value graphs 2026-10-21 12:46:56 +02:00
pancake 3bfdd5601a Resolve direct ObjectPool Code targets 2026-10-21 12:20:58 +02:00
pancake 84a25ea38c Resolve ObjectPool Field names and owners 2026-10-21 12:12:31 +02:00
pancake 2bf613618f Propagate ObjectPool collection strings into analysis 2026-10-21 10:52:18 +02:00
pancake a2fd82106e Include ObjectPool instance strings in -z output 2026-10-21 10:39:11 +02:00
pancake bd6f596279 Fix ObjectPool string xrefs through instance fields 2026-10-21 09:32:21 +02:00
pancake 3cef0ce07a Fix signed 64-bit varint decoding
cs_read_tagged64 biased the final byte by -64 instead of -192, adding
128 << shift to every Mint/Smi value, which inflated field offsets and
decoded constants.
2026-10-09 16:05:25 +02:00
pancake 7d019ea748 Resolve class method entry points
Map each Function's code index (a raw InstructionTable slot, including
discarded-Code slots) to its entry address. Class-derived names only
replace placeholder names when merged into the function list, so
InstructionTable names stay authoritative for deduplicated code.
2026-10-09 16:05:23 +02:00
pancake f7c6cc5b3d Extract class metadata from Dart 2.14-3.3 snapshots
modern_can_extract_classes only accepted OBJECT_HEADER (3.4+) snapshots,
so CID_SHIFT1 apps such as Dart 2.19 fell back to the string heuristic
after the legacy parser failed. Gate on modern_supported instead.
2026-10-09 16:05:20 +02:00
pancake 24e3502737 Complete code xrefs for Dart 2.19 2026-10-06 17:50:40 +02:00
pancake 78719df43e Fix Dart 2.19 ObjectPool xrefs after Type fill parsing 2026-10-06 17:30:45 +02:00
pancake a9efd1d262 doc: record x86-64 Dart AOT scan support 2026-10-02 12:33:45 +02:00
pancake 05c0616b37 Add r2flutter.str options to configure string parsing limits 2026-10-01 17:41:24 +02:00
pancake b7f425ca97 Apply dart pool refs to actual data strings with -AAA 2026-10-01 16:34:11 +02:00
pancake db30ebcb55 Annotate NULL_REG (x22) null/true/false idioms in -AAA
x22 caches Object::null() program-wide; the VM places null/true/false as
adjacent heap objects, so the compiler materialises booleans with add off
NULL_REG (true = null+0x20, false = null+0x30 on arm64, constant across Dart
versions and pointer compression). The scan now comments add x22,#0x20/#0x30
as true/false, mov from x22 as null, and compares against x22 as null checks -
the primitive the certificate-pinning bypass keys on. Verified on iOS
(cws=8) and Android (cws=4).
2026-10-01 14:30:49 +02:00
pancake 5651efc492 Expose the ObjectPool as anal.gp in r2flutter-A
x27/PP is the only Dart reserved register with a static address (the pool is
in the snapshot). r2flutter -A now seeds anal.gp with the pool base,
anal.gpseed=x27, anal.roregs=x27,gp,zero and an 'f PP' flag, so plain-r2
analysis/ESIL resolves [x27, off] pool loads - matching what -p -r already
set up. Resolution runs on a shallow DartCtx copy so the per-command read
cache (ctx->rmem) is not shared into the analysis DartApp and double-freed.
2026-10-01 14:30:46 +02:00
pancake a6fc7e4829 Fix PP mis-identification: a loaded pool value is not a PP pointer
The tracker marked the destination of a pool load as a PP pointer, so a later
[dst, field] deref was read as another slot: ldr x30,[x27,0x18] (a Code
object) then ldur x30,[x30,7] (entry-point) produced a bogus PP slot +0x1f,
and the blr reported 'indirect call via PP+0x1f'. Now:
- pp_load tags the dest with has_pp_slot/pp_slot (the slot it came from),
  never has_pp_off;
- flutter_process_pp_slot_deref carries that taint across the entry-point
  deref so the blr names the real slot and can xref it;
- a hard guard rejects any pp_off & 7, since valid slots are always
  word-aligned ((index+2)*8), killing every misaligned +0x..7 bogus comment.
2026-10-01 12:23:36 +02:00
pancake d0467e4e41 Resolve PP-slot comments to kind/name and add xrefs
After -AAA, non-string PP slots were left as bare 'dart: PP slot +0x..'
comments even though -O resolves them by hand. Resolve every slot up front
with modern_collect_direct_pool_refs and, in the analysis:
- inline the resolved name for function/class slots,
- add a navigable xref to the entrypoint for code/function slots (CALL for
  blr, DATA otherwise), mapping code_index through the instruction table,
- label every remaining slot by its kind, so none stays a bare offset.
2026-10-01 12:23:31 +02:00
fatalSecandClaude Opus 5 67935055e5 Speed up -AAA on large snapshots without changing its results
On a 37,863-function Dart 3.13 iOS app `r2flutter -AAA` took 19 minutes
(1,136s). Three costs grew with snapshot size:

- read_mem cached a single 1 MB window. modern_load_rodata_strings
  alternates between a cluster alloc stream and the RO data image
  megabytes away, so each string refilled the window twice (a 1 MB read
  plus the 0xff fill r_io_bank_read_at does first). Keep four windows
  with LRU eviction. Move the cache behind a pointer so DartCtx copies
  (flutter_model_load, dart_recovery_model_load) share buffers together
  with their addresses instead of leaving the original with stale ones,
  and drop a window whose refill failed since the failed read already
  overwrote it. `-f` 12.4s -> 0.5s; -c/-i/-T/-S ~6s -> <0.25s.

- afs stores prototypes through r_anal_save_parsed_type, which calls
  r_anal_remove_parsed_type for each declared type. For an existing name
  that sorts and scans the whole type database although r_type_del has
  already removed every key of a function type. Names repeat often:
  anonymous closures, and names the C parser cuts at ':' (dyn:call is
  stored as `call`). Parse the prototype with r_anal_cparse and
  r_type_del those names first so afs takes its early return. The
  signature pass went from 1,127s to 27s.

- With anal.trycatch (the radare2 6.2.2 default) every af walks all flags
  twice for try.<addr>.catch|filter. After -AAA creates its flags that is
  O(flags) per function. Disable it around r2flutter's af loops when no
  try.* flag exists, which cannot change the result.

-AAA now takes 36s on that app (35s -> 6s on a smaller 3.13 build). A
dump of afl, afs @@F, f, CC and ax after -AAA is byte-identical to the
previous build on both apps (796,194 and 138,032 lines), and so is stderr.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01KmxPHTVwSkr2HTHJHQsord
2026-09-19 00:17:15 +08:00
FatalSec 5c4a51d5fb Fix Dart 3.13 ObjectPool decode: parse early base-object clusters
- Support Dart 3.13 combined VM snapshots
- Add CID kinds and layouts for LocalVarDescriptors, ApiError, and UnwindError
- Fix stream desync causing "PP not resolved" in `r2flutter -p`
- Skip zero-length ObjectPools when resolving PP slots
2026-09-16 07:48:42 +08:00
pancake 5d86dff9fa Update all tests to use commands instead of !! oneliners 2026-09-03 18:09:11 +02:00
pancake 14c1847177 Probe Snapshot Layouts for Unknown Hashes 2026-09-01 16:18:24 +02:00
pancake edd90ba5c7 Retain Snapshot Object Value Graph 2026-09-01 15:36:07 +02:00
pancake a7317c7705 Retain Serialized Class Layout Metadata 2026-09-01 15:20:54 +02:00
pancake 3fe9dff0cc Support Dart 3.13 Single Snapshots 2026-09-01 15:16:12 +02:00
pancake 2e85b70bda Parse Versioned Code Cluster Layouts 2026-09-01 14:58:59 +02:00
pancake b45d487fd3 Handle Versioned ObjectPool Entry Bits 2026-09-01 14:54:37 +02:00
pancake b1994cd98e Add Versioned Snapshot Reference Decoding 2026-09-01 14:51:16 +02:00
pancake 3b9d12efea Parse Version-Specific Snapshot Headers 2026-09-01 14:46:26 +02:00
pancake 54c7aed1ba Performance improvement 1.6x for -x 2026-08-14 20:39:18 +02:00
pancake bea45d8348 Better api names 2026-08-12 15:19:50 +02:00
pancake 2db2a74bc7 Fix pp string references on iOS, better perf and more testing 2026-08-12 13:41:45 +02:00
pancake 02efb309a2 Fix ppstring recovery in disasm and add tests 2026-08-12 12:55:44 +02:00
pancake 08001fe45b Tutorial to bypass ssl pinning on iOS/flutter 2026-08-12 12:30:46 +02:00
pancake b6ea0b8923 Synthetic legacy tags 2026-08-12 00:09:05 +02:00
pancake 540efcf5e1 Fix remaining iOS symbol recovery blockers 2026-08-11 21:07:03 +02:00
pancake 6a7e01b0c9 Fix tags reads on iOS 2026-08-11 19:30:45 +02:00
pancake 897a98d24d Unify the tag from cid getter for the 3 possible formats 2026-08-11 14:17:36 +02:00
pancake d387c0b15b Harden unknown-hash handling and report version provenance
- Replaces the hardcoded 'v3.9.2 defaults' fallback
- Fix load_layout_from_json to use that profile on the -f/-A decode path for
  unknown hashes, instead of a degenerate zeroed layout (cws=0/alignment=0);
- Adds a version_source field to -H, guessed layout is never exact match now
2026-08-11 11:29:32 +02:00
pancake 33588f29a7 Make -p (and cluster-stream walkers) fast: cache reads, skip RBin strings
* Make -p (and cluster-stream walkers) fast: cache reads, skip RBin strings

r2flutter -p burned ~100% CPU for several seconds on large libapp.so/App
images. Two bottlenecks were responsible:

1. read_mem() went through the full radare2 IO stack (banks, caches,
   interval trees, mmap seek/lseek) once per byte, because the cluster
   stream decoders read one byte at a time while walking the whole
   modern_parse_cluster_meta stream twice. read_mem() now serves reads from
   a forward-sliding 1 MiB window cached in DartCtx, collapsing millions of
   IO calls into a handful. The cache is scoped to a single command and
   freed in dart_obf_fini. A request is only served when fully contained in
   the window; a failed windowed refill falls back to an exact read, so
   semantics are unchanged.

2. The standalone tool let r_core_bin_load run RBin's whole-file string
   scan (the single largest profile entry) even though r2flutter never uses
   RBin's string list. The CLI now sets bin.strings=false before loading.
   The core plugin path is untouched.

On test/bins/android/mafia/libapp.so (14 MB), -p drops from ~2.6s to
~0.05s (~50x) with byte-identical output across all actions; the shared
read cache also speeds up the heavier -x/-z walkers. Full custom
testsuite (35/35) still passes.
2026-07-07 19:27:31 +02:00
pancake 48736a2a89 Properly set anal.roregs for x27 2026-07-07 16:15:27 +02:00
pancake 07b0ca1e4e Resolve serialized ObjectPool string xrefs and entrypoint CLI alias 2026-07-07 16:09:23 +02:00
pancake 7f6449b82a Resolve ObjectPool string xrefs from serialized PP data 2026-07-07 15:39:25 +02:00
pancake 4886597928 Add -E for entrypoint and instruction-image codemeta 2026-07-06 20:00:31 +02:00
pancake bfaf13a013 Use the script to sync with the missing 21 versions of Dart 2026-07-05 20:48:49 +02:00
pancake 5cf313c681 Refactor version metadata: single offsets.json, remove CID fields from DartVerLayout
- Consolidate all version metadata into offsets.json as the single source
  of truth (hashes, version profiles, offset arrays)
- Remove CID fields (cid_class, cid_function, cid_code, cid_string, ...)
  from DartVerLayout struct — all CID lookups now go through dart_cid.c's
  cid_tables[] via dart_cid_get()
- Remove CID fast-path switch from dart_cid_get(); always use cid_tables[]
- Replace l->cid_* references in dart_pool_parse.c and dart_pool_names.c
  with dart_cid_get(l, DART_CID_*) calls
- Remove CID fallback assignments from dart_pick_layout_by_hash()
- Delete obsolete scripts/derive_offsets.py and scripts/gen_offsets.sh
- Add `make gen` target to regenerate C files from offsets.json
- Update doc/learn.md, doc/support.md, INFO.md, and test expectations
2026-07-03 20:33:44 +02:00
Abhi 78013b15e1 Add support for Dart 3.11.x and 3.12.x snapshot profiles
- Update snapshot hash mapping for Dart 3.11.5, 3.12.0, and 3.12.1.
- Add CID and layout profiles for the new versions.
- Document that snapshot hashes are shared across patch-release groups.
- Update documentation and test expectations.
2026-06-29 19:13:54 +05:30
pancake 91c3e94630 Allow to override the DartVersion from cli (-D)
* Useful for hacked binaries and fuzzy analysis for unknown/unsupported builds
2026-06-25 02:04:25 +02:00