> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/HackTricks-wiki/hacktricks/llms.txt
> Use this file to discover all available pages before exploring further.

# Android Reversing — Smali & APK Decompilers

> Guide to decompiling Android APKs, modifying Smali bytecode, recompiling and signing modified APKs, and understanding the Dalvik instruction set.

Sometimes you need to modify an application's code to access hidden information, bypass checks, or understand obfuscated logic. This page covers the complete workflow: decompile → modify → recompile → sign.

## APK Decompilers

<CardGroup cols={2}>
  <Card title="jadx" icon="code">
    The recommended choice. Decompiles DEX to readable Java.

    ```bash theme={null}
    jadx app.apk                              # CLI decompilation
    jadx app.apk -d ./output --no-res         # No resources
    jadx-gui                                  # Launch GUI
    ```
  </Card>

  <Card title="JD-Gui" icon="eye">
    Pioneering GUI Java decompiler. Open the APK directly in JD-Gui to inspect code.
  </Card>

  <Card title="Bytecode-Viewer" icon="layers">
    Analyze using multiple decompilers simultaneously for cross-verification.
  </Card>

  <Card title="GDA" icon="windows">
    Windows-only with extensive Android reverse engineering features.
  </Card>

  <Card title="CFR" icon="terminal">
    Handles modern Java features well.

    ```bash theme={null}
    java -jar ./cfr.jar "app.jar" --outputdir "output/"
    java -Xmx4G -jar ./cfr.jar "app.jar" --outputdir "output/"
    ```
  </Card>

  <Card title="frida-DEXdump" icon="cpu">
    Dumps the DEX of a running APK from memory — bypasses static obfuscation removed at runtime.
  </Card>
</CardGroup>

<Tip>
  **Fastest workflow:** Use **Visual Studio Code** with the [APKLab extension](https://github.com/APKLab/APKLab) to automatically decompile, modify, recompile, sign, and install without running any commands. Also useful: [apk.sh](https://github.com/ax/apk.sh).
</Tip>

## The Smali Workflow

### Step 1 — Decompile with apktool

```bash theme={null}
apktool d APP.apk
```

This gives you Smali code and resources. Key files to inspect:

* `res/values/strings.xml` (and all XMLs under `res/values/*`)
* `AndroidManifest.xml`
* Any `.sqlite` or `.db` files

If apktool has trouble decoding, try `apktool d APP.apk -r` (skip resource decoding).

### Step 2 — Modify Smali Code

Smali is the human-readable representation of Dalvik bytecode. Reference for opcodes: [http://pallergabor.uw.hu/androidblog/dalvik\_opcodes.html](http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html)

#### Hello World Example

Java source:

```java theme={null}
public static void printHelloWorld() {
    System.out.println("Hello World")
}
```

Equivalent Smali:

```smali theme={null}
.method public static printHelloWorld()V
    .registers 2
    sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
    const-string v1, "Hello World"
    invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    return-void
.end method
```

#### Common Light Modifications

```smali theme={null}
# Modify constant values
const v9, 0xf4240
const/4 v8, 0x1
const-string v5, "wins"

# Math operations
add-int/lit8 v0, v2, 0x1   # v2 + 1, store in v0
mul-int v0,v2,0x2           # v2 * 2, store in v0

# Move values
move v1,v2

# Conditionals
if-ge  # Greater or equals
if-le  # Less or equals
if-eq  # Equals

# Get/set object attributes
iget v0, p0, Lcom/example/GameActivity;->score:I  # this.score → v0
iput v0, p0, Lcom/example/GameActivity;->score:I  # v0 → this.score

# Jumps
:goto_6
if-ne v0, v9, :goto_6
goto :goto_6
```

#### Adding Log Output

```smali theme={null}
# Log "wins: <number>"
iget v5, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I
invoke-static {v5}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
move-result-object v1
const-string v5, "wins"
invoke-static {v5, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
```

#### Injecting `System.loadLibrary()` Early

To preload a native library in a static initializer:

```smali theme={null}
.class public Lcom/example/App;
.super Landroid/app/Application;

.method static constructor <clinit>()V
    .registers 1
    const-string v0, "sotap"
    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
    return-void
.end method
```

Alternatively in `Application.onCreate()`:

```smali theme={null}
.method public onCreate()V
    .locals 1
    const-string v0, "sotap"
    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
    invoke-super {p0}, Landroid/app/Application;->onCreate()V
    return-void
.end method
```

### Step 3 — Recompile

```bash theme={null}
# Run from the folder generated by apktool d
apktool b .
# Output appears in ./dist/
```

### Step 4 — Sign the APK

```bash theme={null}
# Generate a signing key
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 \
        -validity 10000 -alias myalias

# Sign with jarsigner
jarsigner -keystore key.jks path/to/dist/app.apk myalias

# Align with zipalign
zipalign -v 4 infile.apk outfile.apk

# Or sign with apksigner (after zipalign)
apksigner sign --ks key.jks ./dist/mycompiled.apk
```

<Warning>
  Sign **either** with `jarsigner` (before `zipalign`) **or** with `apksigner` (after `zipalign`) — not both. Using both will break the signature.
</Warning>

## Understanding Dalvik / ART

* Android apps are written in **Java or Kotlin** and compiled to **Dalvik Executable (DEX) bytecode**
* The **Android Runtime (ART)** uses Ahead-of-Time (AOT) compilation of DEX to native code
* **Smali** is the assembly language for DEX — the human-readable form
* **baksmali** disassembles DEX to Smali; **smali** assembles Smali back to DEX

## References

* [Dalvik Opcodes Reference](http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html)
* [APKLab VSCode Extension](https://github.com/APKLab/APKLab)
* [apktool Documentation](https://ibotpeaches.github.io/Apktool/)
* [SoTap — Lightweight in-app JNI behavior logger](https://github.com/RezaArbabBot/SoTap)
