mirror of
https://github.com/morluto/rea
synced 2026-10-27 14:42:18 -04:00
96fd98cce0
* feat(apktool): decode Android resource tables through a caller-supplied launcher Add an Apktool family with two operations over the caller's apktool launcher (REA_APKTOOL_COMMAND, absolute, or apktool on PATH): - inspect_apktool_client: resolved launcher, selection source, and version; decodes nothing. - decode_android_resources: apktool d --no-src in a provider-owned workspace that is removed before the result returns. Projects the decoded AndroidManifest.xml (bounded at 512 KiB), apktool.yml version and SDK facts exactly as printed, string resources verbatim (default or one locale, bounded at 2000 entries, nested-markup entries counted as unparsed), available string locales, and the decoded file count with a hard cap. The target APK is digested with SHA-256 before decoding so Evidence binds the observation to the exact input. Smali production is skipped by design: Java-source recovery belongs to the JADX family. Workspace cleanup happens before results return; an unremovable workspace is named in the limitations instead of abandoned. Verified against apktool 2.7.0-dirty (Debian packaging) on Linux with OpenJDK 25 against a signed aapt2-built probe APK with two resource locales: launcher version, on-disk digest agreement, metadata projection, manifest package agreement, and both string tables (default and de). Parser goldens come from the same decode. READMEs carry the new 'Android resources' row in every supported language. * fix(apktool): own snapshots and bound decoded resource reads * docs(apktool): describe owned resources and bounded projection --------- Co-authored-by: REA Contributor <contributor@rea.tools> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
87 lines
4.1 KiB
Markdown
87 lines
4.1 KiB
Markdown
# Apktool resource decoding
|
||
|
||
REA decodes Android resource tables and the binary manifest through the
|
||
caller's Apktool launcher. This completes the static triad for Android
|
||
targets: Java/Kotlin sources through the JADX family, engine-grade
|
||
decompilation through JEB, and resources through this family. REA never
|
||
installs Apktool or a Java runtime.
|
||
|
||
## Supply tools
|
||
|
||
Use Apktool 2.7.0 or newer (verified with 2.7.0) and a Java runtime the
|
||
launcher can find. Select the launcher through the environment:
|
||
|
||
```sh
|
||
# Optional: absolute path to the apktool launcher (upstream wrapper or a
|
||
# java -jar script); without it, apktool resolves from PATH.
|
||
export REA_APKTOOL_COMMAND=/absolute/path/apktool
|
||
```
|
||
|
||
Readiness is `rea inspect-apktool-client`: it runs `apktool --version` and
|
||
reports the resolved launcher, its selection source, and its version. A
|
||
missing launcher reports `capability_unavailable` with the
|
||
`REA_APKTOOL_COMMAND` remediation rather than attempting an installation.
|
||
|
||
## Answer an analyst question
|
||
|
||
```sh
|
||
rea inspect-apktool-client
|
||
rea decode-android-resources /targets/Example.apk
|
||
rea decode-android-resources /targets/Example.apk --locale de
|
||
rea decode-android-resources /targets/Example.apk --no-strings
|
||
```
|
||
|
||
Equivalent MCP methods are `inspect_apktool_client` and
|
||
`decode_android_resources`. The decode request takes `path`, an optional
|
||
`locale` (project `res/values-<locale>/strings.xml` instead of the default
|
||
table), and `include_strings` (default true). Regional locales such as `pt-BR`
|
||
select Android's `values-pt-rBR`; Android qualifiers such as `pt-rBR` and
|
||
`b+zh+Hans+CN` may also be supplied directly.
|
||
|
||
## Interpret the result
|
||
|
||
- **An owned APK snapshot is digested and decoded.** `target.sha256` and
|
||
`target.bytes` bind the observation to the exact APK that was decoded.
|
||
- **Metadata comes from apktool.yml as apktool printed it.** Version codes
|
||
keep their own spelling (`'7'` versus `7`); `package_name` is read from
|
||
the decoded manifest, not inferred.
|
||
- **The manifest is the decoded text**, bounded at 512 KiB and reported as
|
||
truncated when larger.
|
||
- **Strings are projected verbatim.** Escaped entities stay escaped, and
|
||
entries containing nested markup (`<b>`, `<xliff:g>`) are counted as
|
||
unparsed rather than flattened — the limitation names the count. The
|
||
default table is bounded to 2000 entries with partial coverage when more
|
||
exist; `locales` lists every `values-<locale>` that has a strings table.
|
||
- **Smali is skipped by design** (`apktool d --no-src`): Java-source
|
||
recovery belongs to the JADX family. Resource smali edits and rebuild are
|
||
a follow-up lane with mutation authority.
|
||
- **Workspaces are owned and short-lived.** Decoding happens in a
|
||
provider-owned temporary directory that is removed before the result is
|
||
returned. The APK snapshot and framework cache both live inside this directory.
|
||
If removal fails, the result names the residual path and the provider retains
|
||
ownership for a cleanup retry on close, including failed decodes.
|
||
|
||
## Resource and lifecycle limits
|
||
|
||
- The decode runs with a 600 s deadline and a 4 MiB output capture budget;
|
||
a stopped decode reports `provider_timeout` and exceeded budgets report
|
||
`resource_constraint`.
|
||
- Manifest reads are bounded to 512 KiB before decoding UTF-8. Strings XML
|
||
reads are bounded to 8 MiB; larger documents are skipped with partial
|
||
coverage and an explicit limit, rather than reported as missing.
|
||
- `decoded_file_count` is capped at 100,000 files; the cap is reported in
|
||
the limitations when hit.
|
||
- Apktool's own decode failures (`AndrolibException`, directory traversal
|
||
refusals) surface as `unsupported_target` with apktool's reason preserved
|
||
verbatim.
|
||
|
||
## Real verification
|
||
|
||
`npm run verify:apktool -- --apk PATH` exercises both operations against a
|
||
real launcher. Record: apktool 2.7.0-dirty (Debian packaging) on Linux with
|
||
OpenJDK 25 against a signed aapt2-built probe APK carrying two resource
|
||
locales — launcher version, on-disk digest agreement, apktool.yml metadata
|
||
(1.2.3, SDK 24–34), manifest package agreement, default and `de` string
|
||
tables projected. Parser goldens in the test suite come from the same
|
||
decode. See `docs/testing.md` for the lane summary.
|