Files
rea/src/cli.ts
T
Quentin Limo 96fd98cce0 feat(apktool): decode Android resource tables through a caller-supplied launcher (#1556)
* 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>
2026-10-10 23:04:12 +08:00

103 lines
5.2 KiB
TypeScript

import { snapshotEnvironment } from "./process/snapshotEnvironment.js";
import { createDirectAnalysis } from "./composition/directAnalysis.js";
import { registerEvmCommands } from "./cli/evmCommands.js";
import { registerAnalysisViewCommands } from "./cli/analysisViewCommands.js";
import { registerBinaryDiagnosticsCommands } from "./cli/binaryDiagnosticsCommands.js";
import { Cli } from "incur";
import { createLogger, parseLogLevel } from "./logger.js";
import { PRODUCT_IDENTITY } from "./identity.js";
import { npxRegistrationCommand } from "./application/ClientRegistrationIdentity.js";
import { registerSetupCommands } from "./cli/setupCommands.js";
import { registerCoreAnalysisCommands } from "./cli/coreAnalysisCommands.js";
import { registerUtilityCommands } from "./cli/utilityCommands.js";
import { registerArtifactCommands } from "./cli/artifactCommands.js";
import { registerManagedCommands } from "./cli/managedCommands.js";
import { registerFirmwareCommands } from "./cli/firmwareCommands.js";
import { registerAndroidCommands } from "./cli/androidCommands.js";
import { registerApktoolCommands } from "./cli/apktoolCommands.js";
import { registerJebCommands } from "./cli/jebCommands.js";
import { registerAdbCommands } from "./cli/adbCommands.js";
import { registerEvidenceCommands } from "./cliEvidenceCommands.js";
import { registerProcessCommands } from "./cli/processCommands.js";
import { registerBrowserCommands } from "./cli/browserCommands.js";
import { registerWebScriptCommands } from "./cli/webScriptCommands.js";
import { registerWebModuleCommands } from "./cli/webModuleCommands.js";
import { registerWebSourceLocationCommands } from "./cli/webSourceLocationCommands.js";
import { registerWebRuntimeCommands } from "./cli/webRuntimeCommands.js";
import { registerWebNetworkCaptureCommands } from "./cli/webNetworkCaptureCommands.js";
import { registerJavaScriptRecoveryCommands } from "./cli/javascriptRecoveryCommands.js";
import { registerAdvancedBrowserCommands } from "./cli/browserAdvancedCommands.js";
import { registerBrowserScenarioCommands } from "./cliBrowserScenarioCommands.js";
import { registerElectronCommands } from "./cli/electronCommands.js";
import { registerJavaScriptRuntimeObservationCommands } from "./cliJavaScriptRuntimeCommands.js";
import { registerApplicationCommands } from "./cli/applicationCommands.js";
import { presentOmittableDefaults } from "./cli/omittableDefaults.js";
import type { CliInstance } from "./cli/types.js";
import {
streamCliCommandResults,
type CliResultOutput,
} from "./cli/streamedJsonOutput.js";
/**
* Build the one-shot Incur CLI without starting Hopper at import time.
* Analysis commands acquire and close their own sessions; bare `mcp` and
* `--mcp` are intercepted by the executable dispatcher before this module loads.
*/
export const createCli = (
selectedEnvironment: Readonly<
Record<string, string | undefined>
> = process.env,
resultOutput?: CliResultOutput,
): CliInstance => {
const environment = snapshotEnvironment(selectedEnvironment);
const analysis = createDirectAnalysis(environment);
const logger = createLogger(
"cli",
environment.REA_LOG_LEVEL === undefined
? "silent"
: parseLogLevel(environment.REA_LOG_LEVEL),
);
const cli = Cli.create(PRODUCT_IDENTITY.cliBinary, {
version: PRODUCT_IDENTITY.packageVersion,
description: "Reverse engineer anything from your terminal or agent.",
mcp: {
command: npxRegistrationCommand().join(" "),
instructions:
"Ask what software, artifact, protocol, or behavior the user wants to understand, then choose the available investigation capabilities that can produce evidence.",
},
sync: false,
});
registerSetupCommands(cli, logger, environment);
registerCoreAnalysisCommands(cli, logger, analysis.runDirectAnalysis);
registerUtilityCommands(cli, logger, environment, analysis);
registerEvmCommands(cli, logger, environment);
registerArtifactCommands(cli, logger, analysis.runProviderAnalysis);
registerManagedCommands(cli, logger, analysis.runProviderAnalysis);
registerAndroidCommands(cli, logger, environment);
registerApktoolCommands(cli, logger, environment);
registerJebCommands(cli, logger, environment);
registerAdbCommands(cli, logger, environment);
registerFirmwareCommands(cli, logger, environment);
registerBinaryDiagnosticsCommands(cli, logger, environment);
registerAnalysisViewCommands(cli, logger);
registerEvidenceCommands(cli, logger);
registerProcessCommands(cli, logger, environment);
registerBrowserCommands(cli, logger);
registerWebScriptCommands(cli, logger);
registerWebModuleCommands(cli, logger, environment);
registerWebSourceLocationCommands(cli, logger, environment);
registerWebRuntimeCommands(cli, logger);
registerWebNetworkCaptureCommands(cli, logger, environment);
registerJavaScriptRecoveryCommands(cli, logger, environment);
registerAdvancedBrowserCommands(cli, logger);
registerBrowserScenarioCommands(cli, logger, environment);
registerElectronCommands(cli, logger, environment);
registerJavaScriptRuntimeObservationCommands(cli, logger);
registerApplicationCommands(cli, logger);
presentOmittableDefaults(cli);
if (resultOutput !== undefined) streamCliCommandResults(cli, resultOutput);
return cli;
};