AI Skill Report Card

Patching Smali Files

A92·Sep 3, 2026·Source: Web
Markdown
--- name: patching-smali-files description: Reads, analyzes, modifies, and validates Android .smali files against a natural-language patch instruction, producing error-free patched smali with full round-trip validation, a detailed patch report, and metadata. Use when the user uploads .smali files and asks to inject code, force a return value, bypass a check, remove logic, or otherwise modify decompiled Android bytecode. Never delivers patched output if any validation error or warning exists. ---
14 / 15

Upload one or more .smali files and describe the patch (e.g. "force isPremium() to always return true"). The skill analyzes the target method, generates a register-safe patch, round-trips it through the assembler/disassembler for validation, and returns patched_output.zip (patched files + originals + report + logs) — only if validation passes with 0 errors and 0 warnings. On failure, only the report and logs are returned, never the ZIP.

Recommendation
Add a brief negative/failure example showing what a FAILED report and remediation_steps section looks like in practice

Inputs:

  • smali_files (required) — one or more .smali files
  • patch_instruction (required) — natural language description of the desired change
  • preferred_style (optional, default minimal) — minimal (no comments) or verbose (inline comments)
  • max_attempts (optional, default 5) — retry budget for validation fixes
  • allow_creative_solution (optional, default true) — if false, pause on any ambiguity instead of choosing

Outputs:

  • patched_output.zip — delivered ONLY on PASSED: /patched/, /originals/, patch_report.txt, metadata.json, validation_logs/
  • patch_report.txt — always delivered
  • metadata.json — always delivered
  • validation_logs/ — always delivered
  • Round-trip (smali → dex → baksmali → smali → dex) MUST yield 0 errors and 0 warnings, or nothing is delivered except report+logs.
  • Only requested files/methods are modified; any extra change is explicitly justified in the report.
  • patch_report.txt includes before/after snippets, reasoning, assumptions, and validation summary for every touched method.
  • Originals preserved verbatim under /originals/.
  • metadata.json includes SHA-256 checksums for originals, patched files, and the final ZIP.
  • MUST update .locals whenever new registers are introduced.
  • MUST NOT deliver patched_output.zip if any error/warning exists anywhere in validation logs.
  • MUST NOT reuse a register that is live or needed later on any control path.
  • MUST NOT insert instructions after an executed return/throw on the same path (no dead code injection unless explicitly retained as documented unreachable code).
  • MUST NOT circumvent DRM, licensing, or violate applicable law — refuse instead.
  • MUST log exact tool versions and exact shell commands verbatim per step.
  • MUST NOT modify method signatures, class headers, or field declarations unless explicitly required by the instruction.
  • MUST preserve existing exception handlers unless explicitly targeted.
  • MUST prefix injected labels uniquely: :patch_<job_id>_<n>.
  • MUST document every assumption when the instruction is ambiguous or underspecified.
15 / 15

Progress:

  • Step 1: Parse & normalize instruction
  • Step 2: Pre-check & setup (checksums, toolchain versions, working copies)
  • Step 3: Static analysis (CFG, registers, exception ranges, insertion point)
  • Step 4: Generate & insert patch
  • Step 5: Round-trip validation (mandatory, with retry loop)
  • Step 6: Smoke tests (if provided)
  • Step 7: Package output + write report/metadata
  • Step 8: Deliver (ZIP only if PASSED)

Step 1 — Parse & Normalize

Map instruction verbs to canonical ops: inject, replace, remove, change-return, add-hook, replace-conditional. Classify ambiguity:

  • LOW — single unambiguous target → proceed.
  • MEDIUM — multiple candidates or unclear insertion point → if allow_creative_solution=true, pick using the candidate resolution priority (exact descriptor match > visibility > param similarity > file order) and document; else pause and ask.
  • HIGH — sweeping language ("remove all checks", "disable everything") → ALWAYS pause for explicit confirmation, regardless of allow_creative_solution.

If a clause maps to zero methods, report as NO-OP and list available signatures.

Step 2 — Pre-check & Setup

  • Compute SHA-256 for every input file; verify it parses (.class header + matched .method/.end method).
  • Log tool versions: smali --version, baksmali --version, java -versionvalidation_logs/00_toolchain.log.
  • Copy originals verbatim to /originals/; all edits happen on working copies only.

Step 3 — Static Analysis

  • Extract class header, fields, method signatures.
  • For each target method: current .locals, full register map, CFG with basic blocks/branches/returns, exception handler ranges, and live-register set at each candidate insertion point (forward data-flow: a register is live if read on some path before being overwritten).
  • Determine exact insertion point per action type (inject-at-start, inject-before-return[s], replace, replace-conditional) and document it.

Step 4 — Patch Generation & Insertion

  • Generate snippet per preferred_style.
  • Compute new registers needed; increment .locals by exactly that amount, allocating from the highest unused index downward to avoid clobbering live/parameter registers.
  • Insert at the determined point, matching indentation, with unique :patch_<job_id>_<n> labels.
  • Run static sanity checks before assembling: label uniqueness/resolution, valid type descriptors, .locals ≥ max register used, no post-return instructions on the same path. Auto-correct failures before proceeding.

Step 5 — Round-Trip Validation (MANDATORY)

  1. smali assemble -o patched.dex patched_smali/01_assemble.log
  2. baksmali disassemble -o roundtrip_smali/ patched.dex02_disassemble.log
  3. smali assemble -o roundtrip.dex roundtrip_smali/03_reassemble.log
  4. Diff patched regions only (patched_smali/ vs roundtrip_smali/), ignoring cosmetic normalization → 04_diff.log
  5. On any error/warning: diagnose (see Troubleshooting), auto-fix, increment attempt counter, re-run 1–4. Log each attempt as attempt_<N>_*.log. If max_attempts reached without a clean pass → mark FAILED, skip to Step 7 (report/logs only).

Step 6 — Smoke Tests (if applicable)

Run any user-supplied tests/verifier against the patched dex. Log to 05_smoke_tests.log / 06_verifier.log. Failures here are flagged as WARNING in the report but do not block delivery on their own (only round-trip errors/warnings block delivery).

Step 7 — Packaging & Reporting

Build the ZIP structure exactly as specified in Outputs. Generate patch_report.txt (see Report Template) and metadata.json with job id, timestamp, status, tool versions, per-file checksums/methods/line deltas, zip checksum, attempt count, and allow_creative_solution.

Step 8 — Delivery

  • PASSED → deliver ZIP + report + metadata.
  • FAILED → deliver report + metadata + logs only, never the ZIP. Report MUST include a numbered remediation_steps section and the last unvalidated patched file labeled UNVALIDATED — DO NOT USE IN PRODUCTION.
Recommendation
Consider trimming the Hard Constraints section slightly by grouping related rules, as it's dense even if thorough
18 / 20

Example 1 — Inject at method start Input: "inject a write to debug_log.txt at the start of onCreate" on Lcom/example/MyActivity;->onCreate(Landroid/os/Bundle;)V Output: .locals raised 2→5, try/catch-wrapped FileWriter write inserted after the locals directive and before invoke-super, unique :patch_abc123_* labels, PASSED after 1 attempt. Assumptions logged: external storage permission assumed present; IOException swallowed silently.

Example 2 — Force return value Input: "force isPremium() to always return true" Output: Entire method body replaced with const/4 v0, 0x1 / return v0; .locals reduced 4→1; original validation call removed and documented as an explicit, intentional deletion. PASSED after 1 attempt.

Example 3 — Bypass conditional check Input: "bypass license check in checkLicense(Ljava/lang/String;)Z" Output: if-eqz v0, :cond_fail branch removed, unconditional return v1 (true) inserted; :cond_fail block retained as documented dead code to avoid dangling label references. PASSED after 1 attempt.

Example 4 — Remove a guard (risk-flagged) Input: "remove the null check at the top of processData(Ljava/lang/Object;)V" Output: if-eqz p1, :cond_null removed; :cond_null retained as dead code; report flags MEDIUM runtime NPE risk and states the user is responsible for call-site safety. PASSED after 1 attempt.

Recommendation
Include a small example of metadata.json or patch_report.txt structure to make the output format fully concrete
  • Always run the full LOW/MEDIUM/HIGH ambiguity check before touching any file — HIGH-risk phrasing always requires confirmation, no exceptions.
  • Allocate new registers from the top down; never touch a register proven live by data-flow analysis.
  • Keep diffs minimal — the report must justify every line changed beyond the literal instruction.
  • Treat round-trip validation as non-negotiable: it is the sole gate for ZIP delivery, independent of how "obviously correct" a patch looks.
  • Retain unreachable code (e.g., orphaned :cond_fail blocks) instead of deleting it when other references might exist — safer than risking a dangling label.
  • Forgetting to bump .locals after adding registers → Verifier error: .locals count too low.
  • Reusing a live register for injected temporaries → corrupts unrelated program state.
  • Inserting code after a return/throw without a reachable label/goto → dead code / unreachable instruction errors.
  • Colliding injected label names with existing ones → Duplicate label errors.
  • Treating baksmali's cosmetic re-formatting as a real diff mismatch — compare opcodes/registers, not whitespace.
  • Delivering the ZIP "because it looks fine" without completing the full 4-log round-trip — never skip validation steps 5.1–5.4.
  • Silently resolving HIGH-risk ambiguous instructions ("remove all checks") instead of pausing for confirmation.
0
Grade AAI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
15/15
Examples
18/20
Completeness
20/20
Format
14/15
Conciseness
14/15