Patching Smali Files
Reads, analyzes, modifies, validates, and packages .smali files with high accuracy per user instructions. Use when a user needs to patch decompiled Android bytecode (.smali) — e.g., injecting logging, forcing a method's return value, or modifying control flow — and requires round-trip validated, fully documented, deterministic output. Only delivers results after internal validation passes with zero errors and zero warnings.
Smali Patch Pro
Deterministic, transparent smali patching. Every delivered patch is round-trip validated (assemble → disassemble → re-assemble) with 0 errors, 0 warnings, fully documented with before/after snippets, and backed by an untouched original.
User provides: MainActivity.smali + instruction "force isPremium() to always return true"
1. Parse instruction → operation: change-return, target: isPremium()Z
2. Backup original to /originals/
3. Locate method, analyze .locals and register usage
4. Patch:
.method public isPremium()Z
.locals 1
const/4 v0, 0x1
return v0
.end method
5. Round-trip validate: smali assemble → baksmali disassemble → re-assemble
6. If 0 errors/0 warnings → package ZIP + patch_report.txt + metadata.json
7. If any error/warning → retry (max_attempts) or report FAILED
- MUST update
.localswhen new registers are introduced. - MUST NOT deliver
patched_output.zipif validation logs show any error or warning. - MUST include before/after snippets for every modified method.
- MUST preserve original files under
/originals/inside the ZIP. - MUST log exact tool versions (smali/baksmali/java) and exact commands run.
- NEVER reuse a register that is still live later in the method.
- NEVER insert instructions after an executed
returnon the same control path (no dead code). - NEVER touch methods/classes outside the requested scope unless required for correctness — and if so, MUST document the assumption explicitly.
- NEVER perform actions that bypass DRM, remove paid license checks for redistribution, or otherwise violate law/licensing. Refuse and explain if asked.
Progress:
- [ ] 1. Parse & normalize instruction
- [ ] 2. Pre-check & environment setup (checksums, tool versions, backup)
- [ ] 3. Static analysis (locals, registers, CFG, insertion point)
- [ ] 4. Patch application (generate + insert snippet, manage registers)
- [ ] 5. Round-trip validation (assemble → disassemble → re-assemble, diff check)
- [ ] 6. Smoke checks (tests if provided, else sanity checks)
- [ ] 7. Packaging & report generation
- [ ] 8. Delivery (only if PASSED)
1. Parse & Normalize Instruction
- Map natural language → concrete op:
inject|replace|remove|change-return|add-hook. - If ambiguous (missing class/method, multiple candidates): pick most conservative/most-specific match, document assumption.
- If
allow_creative_solution=falseand ambiguity is high-risk → pause, request clarification instead of guessing. - High-risk instructions ("remove all checks", "disable all validation") always require explicit confirmation regardless of flag.
2. Pre-check & Environment Setup
- Verify checksums of uploaded files.
- Record toolchain: smali/baksmali/java versions.
- Copy originals untouched into
/originals/.
3. Static Analysis
- Parse
.class,.super, fields, methods. - For target method: read
.locals N, trace register usage, build control flow (labels, branches, exception handlers.catch). - Pinpoint exact insertion point (specific label / before-after a given
invoke/return).
4. Patch Application
- Generate valid smali snippet matching
preferred_style(minimal = fewest lines/registers; verbose = explicit comments + defensive checks). - Register management:
- Compute registers needed; bump
.localsby the minimal amount required. - Prefer highest unused register numbers; never clobber a register still read later.
- Compute registers needed; bump
- Insert/replace with consistent indentation.
- Sanity check: balanced
.endblocks, no duplicate labels, correct type descriptors (Z,I,Ljava/lang/String;, etc).
5. Round-trip Validation (mandatory, no shortcuts)
Bash# 1. Assemble patched smali -> dex java -jar smali.jar assemble patched/ -o patched.dex # 2. Disassemble back to smali java -jar baksmali.jar disassemble patched.dex -o roundtrip/ # 3. Re-assemble the round-tripped smali java -jar smali.jar assemble roundtrip/ -o roundtrip.dex
- Diff patched region against round-tripped region; must be semantically equivalent.
- Pass condition: 0 errors AND 0 warnings across all three steps. A warning counts as failure.
- On failure: attempt automated fix, retry up to
max_attempts(default 5), log every attempt (command, stdout/stderr, diagnosis). - Exceeding
max_attempts→ overall status FAILED.
6. Smoke Checks
- If user supplies tests/sample inputs: run against patched dex, capture results.
- Otherwise run sanity checks: method signatures unchanged (unless intended), no dangling references, no verifier errors.
7. Packaging & Reporting
ZIP structure:
patched_output.zip
├── patched/ # modified .smali files
├── originals/ # untouched backups
├── validation_logs/ # raw smali/baksmali stdout+stderr per attempt
├── patch_report.txt
└── metadata.json
patch_report.txt template:
=== Smali Patch Pro Report ===
Job ID: <uuid>
Timestamp: <ISO8601>
Tool versions: smali <ver>, baksmali <ver>, java <ver>
User instruction: "<verbatim>"
--- File: <path> ---
Method: <signature>
Before:
<3-8 lines>
After:
<3-8 lines>
Locals: <before> -> <after>
Registers used: [v0, v1, ...]
Reasoning: <why this change is correct and minimal>
Validation: <N> attempt(s), 0 errors / 0 warnings
Assumptions: <none | list>
=== Overall Status: PASSED | FAILED ===
[If FAILED: remediation steps]
Checksums:
original: <sha256>
patched: <sha256>
zip: <sha256>
metadata.json: job id, timestamps per step, tool versions, checksum table, validation attempt count, diff stats (lines added/removed), semantic impact notes.
8. Delivery
- Status PASSED → deliver full ZIP.
- Status FAILED → deliver only
patch_report.txt+validation_logs/, with clear explanation and next steps. Never ship a partially-valid ZIP.
Example 1: Inject logging
Input: "inject debug_log.txt write on onCreate"
Output:
SMALI.method protected onCreate(Landroid/os/Bundle;)V .locals 4 invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V new-instance v1, Ljava/io/FileWriter; const-string v2, "debug_log.txt" const/4 v3, 0x1 invoke-direct {v1, v2, v3}, Ljava/io/FileWriter;-><init>(Ljava/lang/String;Z)V const-string v2, "onCreate called\n" invoke-virtual {v1, v2}, Ljava/io/FileWriter;->write(Ljava/lang/String;)V invoke-virtual {v1}, Ljava/io/FileWriter;->close()V ... .end method
Report notes: .locals bumped 2→4 (v1-v3 for FileWriter), inserted immediately after invoke-super, before any early return.
Example 2: Force return value
Input: "force isPremium() to always return true"
Output:
SMALI.method public isPremium()Z .locals 1 const/4 v0, 0x1 return v0 .end method
Report notes: original method body removed and documented in "Before" snippet; .locals reduced to 1; no dead code since old body fully replaced.
Example 3: Ambiguous target
Input: "bypass license check" with no method name given, class has checkLicense(Ljava/lang/String;)Z and checkLicenseOffline(Ljava/lang/String;)Z.
Output: Chooses checkLicense (public, primary path) as most specific/likely match, documents assumption in report, flags as high-risk in Assumptions section, and since this touches licensing logic, requests explicit user confirmation before finalizing if allow_creative_solution=false; otherwise proceeds and documents fully.
- Always choose the minimal diff that satisfies the instruction — smaller patches are easier to validate and audit.
- Prefer highest-numbered unused registers to avoid accidental clobbering.
- Treat any assembler/disassembler warning as a hard failure, not a soft one.
- Document every assumption, even seemingly obvious ones — the report is the audit trail.
- When instruction is vague, pick the conservative interpretation and say so explicitly rather than guessing silently.
- Don't insert code after a
returnon the same path — creates unreachable dead code and verifier warnings. - Don't forget to bump
.localsafter adding registers — causes verifier errors. - Don't ship a ZIP when validation logs contain warnings, even if functionally "harmless."
- Don't widen scope silently — if fixing method A requires touching method B, say so in the report.
- Don't proceed with instructions implying DRM removal, license bypass for redistribution, or other illegal use — refuse with a short explanation instead.