top of page

Modding APKs For Premium Access On Apps

Modding APKs For Premium Access On Apps | Black Hat HQ

Modding APK Files For Free Paid Account Access


APK modification to bypass premium/license checks is a core mobile security assessment skill. The goal is to identify how the app determines "premium" status and subvert that logic. Here's the full workflow, from decompilation to repackaging.


General Workflow


APK → Decompile → Analyze → Modify → Rebuild → Sign → Install

Step 1: Decompile The APK


apktool for smali-level modifications:


bash

apktool d target.apk -o target_source

This gives you smali/ (Dalvik bytecode), res/ (resources), and AndroidManifest.xml (decoded).

jadx for Java-level analysis (far easier to read):


bash

jadx-gui target.apk

Use jadx to understand the logic, then switch to smali for the actual patching. You can also export jadx as a Gradle project and rebuild the entire app, but that's heavier.


Step 2: Find The Premium Check Logic


This is the real skill — recognizing patterns. Here's what to search for in jadx:


Keywords in strings and method names:


  • premiumprovipgoldsubscribeunlock

  • isPremiumisProisSubscribedhasAccessisUnlocked

  • skupurchasebillinglicensetrial

  • getPurchaseStateisPurchasedentitlement


Common patterns to look for:


java

// License check via boolean return
public boolean isPremium() {
    return this.premiumStatus;
}

// Feature gate
if (UserManager.isPremium()) {
    // show premium content
} else {
    // show upgrade prompt
}

// Server-side validation (harder)
if (response.getStatus().equals("premium")) { ... }

Use grep/ripgrep across the smali:


bash

rg -i "premium|ispro|unlocked|subscribed" target_source/smali/

Step 3: Patching Strategies


Strategy A: Flip the Boolean (Most Common)


Find isPremium() or equivalent and force it to always return true.


Smali example — changing a return from false to true:


Before:


smali

.method public isPremium()Z
    .locals 1
    iget-boolean v0, p0, Lcom/example/User;->isPremium:Z
    return v0
.end method

Patched (always return true):


smali

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

The const/4 v0, 0x1 sets register v0 to 1 (true) and ignores whatever the actual field holds.


Strategy B: Invert Conditions


Find if-eqz (if equal zero / if false) or if-nez (if not zero / if true) and flip them:


  • if-eqz → if-nez

  • if-nez → if-eqz

  • if-eq → if-ne


Smali conditional before:


smali

invoke-virtual {v0}, Lcom/example/User;->isPremium()Z
move-result v0
if-eqz v0, :show_upgrade_screen    # jumps to upgrade screen if NOT premium

Patched:


smali

invoke-virtual {v0}, Lcom/example/User;->isPremium()Z
move-result v0
if-nez v0, :show_upgrade_screen    # inverted — now jumps to upgrade screen if premium (never)

Strategy C: Bypass Google Play Billing Verification


Many apps use Google Play Billing Library. The verification flow typically works like:


java

BillingClient bc = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .build();

bc.queryPurchasesAsync(SkuType.INAPP, (result, purchases) -> {
    for (Purchase p : purchases) {
        if (p.getSku().equals("premium_upgrade")) {
            setPremium(true);
        }
    }
});

You have a few options here:


  1. Patch queryPurchasesAsync to inject fake purchases — Find where the callback is invoked with results and force it to return a purchase list containing the premium SKU.

  2. Patch the SKU check — Find the string comparison against "premium_upgrade" and bypass it.

  3. Hook at runtime with Frida (see below).


Strategy D: Modify SharedPreferences / Local Storage


Some apps store premium status locally (rookie mistake):


bash

# Check for stored values
rg -i "sharedpreferences|getBoolean|getString.*premium|putBoolean" target_source/smali/

Patch the read to always return true, or inject the preference before first launch.


Step 4: Rebuild & Sign


bash

# Rebuild
apktool b target_source -o modded.apk

# Generate a keystore (once)
keytool -genkey -v -keystore debug.keystore -alias debug -keyalg RSA -keysize 2048 -validity 10000

# Sign with apksigner (modern) or jarsigner (legacy)
apksigner sign --ks debug.keystore --ks-pass pass:password modded.apk

# Or use uber-apk-signer for convenience
uber-apk-signer -a modded.apk

# Install
adb install modded.apk

When Static Patching Fails: Dynamic Instrumentation


If the app has integrity checks, obfuscation, or server-side validation, use Frida:


javascript

// Hook isPremium method — Frida script
Java.perform(function() {
    var UserManager = Java.use("com.example.app.UserManager");
    UserManager.isPremium.implementation = function() {
        console.log("[*] isPremium() called — returning true");
        return true;
    };
});

Run with:


bash

frida -U -l bypass_premium.js -f com.example.app --no-pause

For Xposed/LSPosed, the equivalent module would hook the same method with XposedHelpers.findAndHookMethod().


Common Defenses You'll Encounter


Defense

Bypass

Signature verification

Patch PackageManager.getPackageInfo() or hook it with Frida

Root/Magisk detection

MagiskHide, Shamiko, or patch checkSu() methods

Emulator detection

Patch build.prop checks, hook isEmulator() checks

ProGuard/R8 obfuscation

Trace by UX flow — click premium feature, note the UI element, trace onClick → check logic

Certificate pinning

Frida script to bypass okhttp3.CertificatePinner, or use objection's android sslpinning disable

Server-side entitlement

This is the legitimate limit — if premium is enforced server-side (API returns 403 without valid token), patching the client won't help. Document this as a finding — the app is doing it right.


Practical Demo: Full Scripted Workflow


bash

#!/bin/bash
# Quick APK mod workflow
APK=$1
NAME=$(basename "$APK" .apk)

echo "[*] Decompiling..."
apktool d -f "$APK" -o "${NAME}_src"

echo "[*] Searching for premium checks..."
rg -i "ispremium|ispro|issubscribed|premium_upgrade|unlock" "${NAME}_src/smali/" --no-heading

echo "[*] Open jadx-gui for analysis (manually apply patches)"
jadx-gui "$APK" &
echo "Press enter after patching smali..."
read

echo "[*] Rebuilding..."
apktool b "${NAME}_src" -o "${NAME}_modded.apk"

echo "[*] Signing..."
uber-apk-signer -a "${NAME}_modded.apk"

echo "[*] Done. Install with: adb install ${NAME}_modded.apk"

Please Donate | Black Hat HQ
Visit Our Elite Cyber Store | Black Hat HQ
Enroll In Our Cybersecurity & Hacking Courses Online | Black Hat HQ

Comments


bottom of page