AI Skill Report Card

Patching Smali Files

Analyzes and modifies Android .smali bytecode files based on user instructions, validates changes through assemble/disassemble round-trips, and packages results with transparent before/after reports. Use when the user uploads .smali files for patching, requests specific bytecode modifications (e.g., injecting logs, bypassing checks, hooking methods), or needs reverse engineering support in a Termux/Android workflow.

A86·Sep 3, 2026·Source: Web
14 / 15

Given a .smali file and a patch instruction, follow this pipeline:

1. Parse file → identify class header, .locals, fields, methods
2. Locate target method/instruction based on user request
3. Apply patch with correct smali syntax
4. Adjust .locals count if new registers were introduced
5. Validate: smali assemble → baksmali disassemble → diff check
6. Backup original file
7. Package: patched .smali + original (backup) + report.txt → ZIP
8. Deliver ZIP with full before/after report

Never skip the round-trip validation step, even for trivial one-line patches.

Recommendation
Add an example showing a validation failure and how it's resolved (e.g., register collision fixed after diff mismatch)
15 / 15
Progress:
- [ ] Read full .smali file (header, fields, methods, instructions)
- [ ] Identify target method(s) matching user instruction
- [ ] Check current .locals count
- [ ] Write patch using correct smali syntax
- [ ] Recalculate/update .locals if new registers used
- [ ] Backup original file (keep unmodified copy)
- [ ] Run round-trip validation (assemble → disassemble → re-assemble)
- [ ] Compare output vs expected — fix if mismatch or error/warning found
- [ ] Generate diff (before/after snippet) per changed method
- [ ] Write transparent report (file, method, snippet, reasoning)
- [ ] Package patched file + backup + report into ZIP
- [ ] Deliver ZIP with report summary

Step Details

1. Analysis Read the entire file, not just the target method. Note:

  • Class name, superclass, implemented interfaces
  • All .field declarations
  • All .method blocks with their .locals and .registers
  • Existing annotations/try-catch blocks that might be affected

2. Patch Application

  • Match user's intent to exact instruction(s) — insert, replace, or delete.
  • Use valid smali opcodes (invoke-static, const-string, move-result, etc.) with correct register types (v0, p0, etc.).
  • If injecting a call (e.g., logging), ensure return type and register slot compatibility.

3. Register Management

  • If patch introduces new local variables, increase .locals N accordingly.
  • Never reuse a register still holding a live value needed later — trace usage forward from injection point.
  • Prefer using unused/spare registers; if none, bump .locals.

4. Round-Trip Validation

smali assemble patched.smali -o patched.dex
baksmali disassemble patched.dex -o verify/
diff original_structure.smali verify/patched.smali
  • If assemble fails → syntax error, fix and retry.
  • If diff shows unintended structural drift (e.g., register renumbering) → re-check .locals.
  • Repeat until zero errors/warnings.

5. Reporting For every changed method, report:

  • File path and method signature
  • Before snippet (original instructions)
  • After snippet (patched instructions)
  • Reason for the change (tied to user's request)
  • Register changes (if any)

6. Packaging

output.zip
├── patched/<original_path>.smali
├── backup/<original_path>.smali   (unmodified original)
└── report.txt
Recommendation
Include a brief note on tooling setup/paths for smali/baksmali in Termux environment for reproducibility
18 / 20

Example 1: Input: "Inject a log call at the start of onCreate that writes 'DEBUG_LOG' to /sdcard/debug_log.txt"

Output:

File: com/example/MainActivity.smali
Method: onCreate(Landroid/os/Bundle;)V

--- BEFORE ---
.method protected onCreate(Landroid/os/Bundle;)V
    .locals 1
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
    return-void
.end method

--- AFTER ---
.method protected onCreate(Landroid/os/Bundle;)V
    .locals 3
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

    new-instance v0, Ljava/io/File;
    const-string v1, "/sdcard/debug_log.txt"
    invoke-direct {v0, v1}, Ljava/io/File;-><init>(Ljava/lang/String;)V
    const-string v2, "DEBUG_LOG"
    invoke-static {v0, v2}, Lcom/example/LogUtil;->writeToFile(Ljava/io/File;Ljava/lang/String;)V

    return-void
.end method

Reason: User requested a debug log injection at method start.
Register change: .locals increased from 1 → 3 (v0, v1, v2 added for File/String construction).
Validation: assemble/disassemble round-trip passed, no warnings.

Result packaged as patched_output.zip with backup and report.txt.

Example 2: Input: "Bypass the license check in verifyLicense() — always return true"

Output:

File: com/example/LicenseChecker.smali
Method: verifyLicense()Z

--- BEFORE ---
.method public verifyLicense()Z
    .locals 2
    ... (validation logic) ...
    move-result v0
    return v0
.end method

--- AFTER ---
.method public verifyLicense()Z
    .locals 1
    const/4 v0, 0x1
    return v0
.end method

Reason: User requested unconditional bypass returning true.
Register change: .locals reduced 2 → 1 (unused validation registers removed).
Validation: assemble/disassemble round-trip passed.
Recommendation
Add a short troubleshooting table mapping common assembler error messages to fixes
  • Always read the whole file first — context matters for register allocation and control flow.
  • Use minimal, surgical instruction changes; avoid rewriting untouched logic.
  • Match the original code's indentation/style conventions.
  • When in doubt about a register being free, insert a nop trace or check all preceding branches — never guess.
  • Test every patch through the round-trip cycle before packaging, even simple string changes.
  • Keep the original file untouched in a backup/ folder inside the ZIP.
  • State assumptions explicitly in the report (e.g., "assumed v1 was free after line 12").
  • Skipping .locals update after adding new registers — causes verifier errors (VFY: registers out of range).
  • Register collision — overwriting a register still needed by later instructions.
  • Ignoring try-catch ranges — inserting instructions inside a try block can shift catch handler offsets; verify .catch blocks still align.
  • Not validating round-trip — a patch that "looks right" can still fail dex assembly due to subtle syntax issues (e.g., wrong type descriptor).
  • Silent overrides — never change logic beyond what the user asked; if a side-effect is unavoidable, disclose it in the report.
  • Missing backup — always preserve the original file; never ship only the patched version.
0
Grade AAI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
15/15
Examples
18/20
Completeness
19/20
Format
14/15
Conciseness
13/15