Skip to content

Instantly share code, notes, and snippets.

@theSoberSobber
Created May 26, 2025 19:55
Show Gist options
  • Save theSoberSobber/75e04603bc56cb3a1e8565a18e572de9 to your computer and use it in GitHub Desktop.
Save theSoberSobber/75e04603bc56cb3a1e8565a18e572de9 to your computer and use it in GitHub Desktop.
My Guide to Decompiling and Recompiling modern apks with splits for cert pinning/check bypass and or any other modifications (smali).

APK Modification & Installation Guide

Quick reference for decompiling, patching, and reinstalling Android APKs with split configurations.

Prerequisites

  • Android SDK Build Tools installed
  • Java JDK installed
  • apktool installed
  • ADB connected to device

Step-by-Step Process

1. Extract APKs from Device

# List installed packages
adb shell pm list packages | grep <package_name>

# Pull base APK
adb pull /data/app/~~<hash>~~/<package_name>-<hash>==/base.apk

# Pull split APK (if exists)
adb pull /data/app/~~<hash>~~/<package_name>-<hash>==/split_config.arm64_v8a.apk

2. Decompile Base APK

apktool d base.apk -o base

3. Make Your Modifications

Edit files in the base/ directory (smali files, resources, etc.)

Common Modifications:

A. Enable Network Security Config (for HTTPS interception)

  1. Create network security config file:
# Create the xml directory if it doesn't exist
New-Item -ItemType Directory -Force -Path "base/res/xml"

# Create network_security_config.xml
@"
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">localhost</domain>
        <domain includeSubdomains="true">10.0.2.2</domain>
    </domain-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system"/>
            <certificates src="user"/>
        </trust-anchors>
    </base-config>
</network-security-config>
"@ | Out-File -FilePath "base/res/xml/network_security_config.xml" -Encoding UTF8
  1. Modify AndroidManifest.xml:
<!-- Add these attributes to the <application> tag -->
<application
    android:networkSecurityConfig="@xml/network_security_config"
    android:debuggable="true"
    ... >

B. Enable Debugging In base/AndroidManifest.xml, add android:debuggable="true" to the <application> tag.

4. Rebuild APK

apktool b base -o base-patched.apk

5. Align APK (Required for Android 11+)

& "D:\Android\android-sdk\build-tools\34.0.0\zipalign.bat" -v 4 "base-patched.apk" "base-patched-aligned.apk"

6. Create Debug Keystore (One-time setup)

& "C:\Program Files\Java\jdk-17\bin\keytool.exe" -genkey -v -keystore "debug.keystore" -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 -storepass android -keypass android -dname "CN=Android Debug,O=Android,C=US"

7. Sign APKs

# Sign the patched base APK
& "D:\Android\android-sdk\build-tools\34.0.0\apksigner.bat" sign --ks "debug.keystore" --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android "base-patched-aligned.apk"

# Sign the split APK
& "D:\Android\android-sdk\build-tools\34.0.0\apksigner.bat" sign --ks "debug.keystore" --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android "split_config.arm64_v8a.apk"

8. Uninstall Original App

adb uninstall <package_name>

9. Install Modified APKs

adb install-multiple "base-patched-aligned.apk" "split_config.arm64_v8a.apk"

Common Modifications Examples

Network Security Config

Create base/res/xml/network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">localhost</domain>
        <domain includeSubdomains="true">10.0.2.2</domain>
    </domain-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system"/>
            <certificates src="user"/>
        </trust-anchors>
    </base-config>
</network-security-config>

AndroidManifest.xml Modifications

Add to <application> tag in base/AndroidManifest.xml:

<application
    android:networkSecurityConfig="@xml/network_security_config"
    android:debuggable="true"
    android:allowBackup="true"
    android:usesCleartextTraffic="true"
    ... >

Common Issues & Solutions

APK Alignment Error (Android 11+)

Error: Targeting R+ (version 30 and above) requires the resources.arsc... Solution: Use zipalign before signing (Step 5)

Signature Verification Failed

Error: INSTALL_PARSE_FAILED_NO_CERTIFICATES Solution: Use apksigner instead of jarsigner for modern APKs

Native Library Extraction Error

Error: Failed to extract native libraries Solution: Ensure split APK is properly signed and uninstall original app first

File Structure After Process

project-folder/
├── base.apk                    # Original base APK
├── split_config.arm64_v8a.apk  # Original split APK
├── base/                       # Decompiled source
├── base-patched.apk           # Rebuilt APK
├── base-patched-aligned.apk   # Aligned & signed APK (final)
└── debug.keystore             # Debug signing key

Quick Commands Summary

# Full workflow
apktool d base.apk -o base
# [make modifications]
apktool b base -o base-patched.apk
zipalign -v 4 base-patched.apk base-patched-aligned.apk
apksigner sign --ks debug.keystore --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android base-patched-aligned.apk
apksigner sign --ks debug.keystore --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android split_config.arm64_v8a.apk
adb uninstall <package_name>
adb install-multiple base-patched-aligned.apk split_config.arm64_v8a.apk
@theSoberSobber
Copy link
Author

Automatic Script to do it on windows, check config and paths though before running

# APK Modification Automation Script
# Usage: .\apk-modifier.ps1 -PackageName "com.application.zomato"

param(
    [Parameter(Mandatory=$true)]
    [string]$PackageName,
    
    [string]$WorkDir = "D:\reverse-engineering-$($PackageName.Split('.')[-1])",
    [string]$AndroidSdk = "D:\Android\android-sdk\build-tools\34.0.0",
    [string]$JavaPath = "C:\Program Files\Java\jdk-17\bin"
)

# Color functions for better output
function Write-Success { param($Message) Write-Host "$Message" -ForegroundColor Green }
function Write-Info { param($Message) Write-Host "ℹ️  $Message" -ForegroundColor Cyan }
function Write-Warning { param($Message) Write-Host "⚠️  $Message" -ForegroundColor Yellow }
function Write-Error { param($Message) Write-Host "$Message" -ForegroundColor Red }
function Write-Step { param($Step, $Message) Write-Host "[$Step] $Message" -ForegroundColor Magenta }

# Check if required tools exist
function Test-Prerequisites {
    Write-Step "0" "Checking prerequisites..."
    
    $tools = @(
        @{ Path = "$AndroidSdk\apksigner.bat"; Name = "apksigner" },
        @{ Path = "$AndroidSdk\zipalign.bat"; Name = "zipalign" },
        @{ Path = "$JavaPath\keytool.exe"; Name = "keytool" }
    )
    
    foreach ($tool in $tools) {
        if (-not (Test-Path $tool.Path)) {
            Write-Error "$($tool.Name) not found at $($tool.Path)"
            exit 1
        }
    }
    
    try {
        $null = Get-Command "adb" -ErrorAction Stop
        $null = Get-Command "apktool" -ErrorAction Stop
    } catch {
        Write-Error "ADB or apktool not found in PATH"
        exit 1
    }
    
    Write-Success "All prerequisites found"
}

# Create working directory
function Initialize-WorkDirectory {
    Write-Step "1" "Initializing work directory: $WorkDir"
    
    if (Test-Path $WorkDir) {
        Write-Warning "Work directory exists. Cleaning up..."
        Remove-Item -Path "$WorkDir\*" -Recurse -Force -ErrorAction SilentlyContinue
    } else {
        New-Item -ItemType Directory -Force -Path $WorkDir | Out-Null
    }
    
    Set-Location $WorkDir
    Write-Success "Work directory ready"
}

# Find and pull APK from device
function Get-ApkFromDevice {
    Write-Step "2" "Finding and pulling APK from device..."
    
    # Find package path
    $packageInfo = adb shell pm list packages -f | Select-String $PackageName
    if (-not $packageInfo) {
        Write-Error "Package $PackageName not found on device"
        exit 1
    }
    
    # Extract path (format: package:/data/app/...)
    $packagePath = ($packageInfo -split "=")[0] -replace "package:", ""
    $packageDir = Split-Path $packagePath -Parent
    
    Write-Info "Found package at: $packageDir"
    
    # Pull base APK
    Write-Info "Pulling base.apk..."
    adb pull "$packageDir/base.apk" "base.apk"
    if (-not $?) {
        Write-Error "Failed to pull base.apk"
        exit 1
    }
    
    # Try to pull split APK
    Write-Info "Looking for split APKs..."
    $splitApks = adb shell ls "$packageDir/" | Select-String "split_config"
    
    foreach ($splitApk in $splitApks) {
        $splitName = $splitApk.ToString().Trim()
        Write-Info "Pulling $splitName..."
        adb pull "$packageDir/$splitName" "$splitName"
    }
    
    Write-Success "APK files pulled successfully"
}

# Decompile APK
function Invoke-ApkDecompile {
    Write-Step "3" "Decompiling base.apk..."
    
    apktool d base.apk -o base
    if (-not $?) {
        Write-Error "Failed to decompile APK"
        exit 1
    }
    
    Write-Success "APK decompiled to 'base' directory"
}

# Wait for user modifications
function Wait-ForModifications {
    Write-Step "4" "Ready for modifications"
    Write-Info "The APK has been decompiled to the 'base' directory."
    Write-Info "You can now:"
    Write-Info "  - Edit smali files"
    Write-Info "  - Modify resources"
    Write-Info "  - Add network security config"
    Write-Info "  - Enable debugging in AndroidManifest.xml"
    Write-Warning "Press ENTER when you're done with your modifications..."
    
    # Open the base directory in Explorer for convenience
    Start-Process explorer.exe -ArgumentList $PWD\base
    
    Read-Host
    Write-Success "Proceeding with recompilation..."
}

# Add common modifications
function Add-CommonModifications {
    Write-Step "4.5" "Adding common modifications..."
    
    # Create network security config
    $xmlDir = "$WorkDir\base\res\xml"
    if (-not (Test-Path $xmlDir)) {
        New-Item -ItemType Directory -Force -Path $xmlDir | Out-Null
    }
    
    $networkConfig = @"
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">localhost</domain>
        <domain includeSubdomains="true">10.0.2.2</domain>
    </domain-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system"/>
            <certificates src="user"/>
        </trust-anchors>
    </base-config>
</network-security-config>
"@
    
    $networkConfig | Out-File -FilePath "$xmlDir\network_security_config.xml" -Encoding UTF8
    Write-Success "Created network_security_config.xml"
    
    # Modify AndroidManifest.xml
    $manifestPath = "$WorkDir\base\AndroidManifest.xml"
    if (Test-Path $manifestPath) {
        $manifest = Get-Content $manifestPath -Raw
        
        # Add debuggable and network security config if not present
        if ($manifest -notmatch 'android:debuggable="true"') {
            $manifest = $manifest -replace '(<application[^>]*)', '$1 android:debuggable="true"'
        }
        
        if ($manifest -notmatch 'android:networkSecurityConfig') {
            $manifest = $manifest -replace '(<application[^>]*)', '$1 android:networkSecurityConfig="@xml/network_security_config"'
        }
        
        if ($manifest -notmatch 'android:usesCleartextTraffic') {
            $manifest = $manifest -replace '(<application[^>]*)', '$1 android:usesCleartextTraffic="true"'
        }
        
        $manifest | Out-File -FilePath $manifestPath -Encoding UTF8
        Write-Success "Modified AndroidManifest.xml"
    }
}

# Recompile APK
function Invoke-ApkRecompile {
    Write-Step "5" "Recompiling APK..."
    
    apktool b base -o base-patched.apk
    if (-not $?) {
        Write-Error "Failed to recompile APK"
        exit 1
    }
    
    Write-Success "APK recompiled as base-patched.apk"
}

# Align APK
function Invoke-ApkAlign {
    Write-Step "6" "Aligning APK for Android 11+..."
    
    & "$AndroidSdk\zipalign.bat" -v 4 "base-patched.apk" "base-patched-aligned.apk"
    if (-not $?) {
        Write-Error "Failed to align APK"
        exit 1
    }
    
    Write-Success "APK aligned successfully"
}

# Create debug keystore if not exists
function New-DebugKeystore {
    Write-Step "7" "Setting up debug keystore..."
    
    if (-not (Test-Path "debug.keystore")) {
        Write-Info "Creating debug keystore..."
        & "$JavaPath\keytool.exe" -genkey -v -keystore "debug.keystore" -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 -storepass android -keypass android -dname "CN=Android Debug,O=Android,C=US"
        if (-not $?) {
            Write-Error "Failed to create keystore"
            exit 1
        }
    }
    
    Write-Success "Debug keystore ready"
}

# Sign APKs
function Invoke-ApkSigning {
    Write-Step "8" "Signing APKs..."
    
    # Sign base APK
    Write-Info "Signing base APK..."
    & "$AndroidSdk\apksigner.bat" sign --ks "debug.keystore" --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android "base-patched-aligned.apk"
    if (-not $?) {
        Write-Error "Failed to sign base APK"
        exit 1
    }
    
    # Sign split APKs
    $splitApks = Get-ChildItem -Filter "split_config*.apk"
    foreach ($splitApk in $splitApks) {
        Write-Info "Signing $($splitApk.Name)..."
        & "$AndroidSdk\apksigner.bat" sign --ks "debug.keystore" --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android $splitApk.FullName
        if (-not $?) {
            Write-Error "Failed to sign $($splitApk.Name)"
            exit 1
        }
    }
    
    Write-Success "All APKs signed successfully"
}

# Uninstall original app
function Remove-OriginalApp {
    Write-Step "9" "Uninstalling original app..."
    
    adb uninstall $PackageName
    if ($LASTEXITCODE -eq 0) {
        Write-Success "Original app uninstalled"
    } else {
        Write-Warning "App might not be installed or uninstall failed (continuing anyway)"
    }
}

# Install modified APKs
function Install-ModifiedApp {
    Write-Step "10" "Installing modified APKs..."
    
    $apksToInstall = @("base-patched-aligned.apk")
    $splitApks = Get-ChildItem -Filter "split_config*.apk"
    $apksToInstall += $splitApks.FullName
    
    Write-Info "Installing: $($apksToInstall -join ', ')"
    
    adb install-multiple $apksToInstall
    if (-not $?) {
        Write-Error "Failed to install APKs"
        Write-Info "APK files are ready at: $WorkDir"
        Write-Info "You can try manual installation or troubleshoot the issue"
        exit 1
    }
    
    Write-Success "Modified app installed successfully!"
}

# Main execution
function Main {
    try {
        Write-Info "🚀 Starting APK Modification Process for: $PackageName"
        Write-Info "Working directory: $WorkDir"
        
        Test-Prerequisites
        Initialize-WorkDirectory
        Get-ApkFromDevice
        Invoke-ApkDecompile
        Wait-ForModifications
        Add-CommonModifications
        Invoke-ApkRecompile
        Invoke-ApkAlign
        New-DebugKeystore
        Invoke-ApkSigning
        Remove-OriginalApp
        Install-ModifiedApp
        
        Write-Success "🎉 APK modification and installation completed successfully!"
        Write-Info "Modified files are available at: $WorkDir"
        
    } catch {
        Write-Error "Script failed: $($_.Exception.Message)"
        Write-Info "Check the error above and try again"
        exit 1
    }
}

# Run the script
Main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment