# Backdrops APK Premium Feature Reverse Engineering
## CTF Challenge - Dynamic Analysis Guide

### 📋 Overview
This repository contains Frida scripts and analysis for reverse engineering the Backdrops wallpaper app's premium feature implementation.

---

## 🔍 Key Findings

### Premium Check Flow
The app uses a layered approach to verify premium purchases:

1. **DatabaseObserver.java** - High-level premium check methods:
   - `isPremiumPackUnlocked(String sku)` - Main method for checking premium pack access
   - `isPro()` - Checks if user has Pro subscription
   - `isPackTrinity()`, `isPackAmoled()`, `isPackAcid()`, etc. - Individual pack checks

2. **DatabaseHandlerIAB.java** - Local SQLite database for purchases:
   - Stores purchased items in table: `Premium(id, item, token)`
   - `getPurchased(String sku)` - Synchronous check
   - `existPurchase(String sku)` - RxJava Observable-based check
   - `AddtoPurchased(ItemPurchased)` - Adds purchase after successful billing

3. **ThemeApp.java** - Application class:
   - `g()` - Returns singleton `DatabaseHandlerIAB` instance
   - Central access point for purchase database

### Premium SKU Constants (in j1.E / PlayBillingActivity)
```
f21381A = SKU_PACK_TRINITY
f21382B = SKU_PACK_AMOLED  
f21383C = SKU_PRO
f21384D = SKU_PACK_ACID
f21385E = SKU_PACK_OPTIC
f21386F = SKU_PACK_VOID
f21387G = SKU_PACK_SYNTH
```

---

## 🛠️ Frida Scripts

### Script 1: `frida_backdrops_analysis.js` (Analysis Only)
**Purpose**: Monitor and log all premium check calls without modification.

**Features**:
- Hooks all `DatabaseObserver` premium check methods
- Logs SKU parameters and return values
- Tracks purchase database queries
- Monitors Google Play Billing API calls
- Shows stack traces for premium checks

**Usage**:
```bash
# Connect to USB device
frida -U -f com.backdrops.wallpapers -l frida_backdrops_analysis.js

# Or attach to running app
frida -U com.backdrops.wallpapers -l frida_backdrops_analysis.js
```

**What to look for**:
- Watch console when clicking on premium collections
- Note which SKUs are being checked
- Observe the flow: `isPremiumPackUnlocked()` → `existPurchase()` → SQLite query
- Check if any purchases exist in the database

---

### Script 2: `frida_backdrops_bypass.js` (Bypass + Analysis)
**Purpose**: Bypass all premium checks to unlock wallpapers.

**Features**:
- **AUTO-BYPASS**: All premium checks return TRUE
- Hooks `isPremiumPackUnlocked()`, `isPro()`, and all pack-specific checks
- Overrides `getPurchased()` to always return TRUE
- Modifies RxJava `existPurchase()` to emit TRUE
- Provides fake purchase tokens when needed
- RPC interface for manual control

**Usage**:
```bash
# Start app with bypass
frida -U -f com.backdrops.wallpapers -l frida_backdrops_bypass.js

# Or attach to running app  
frida -U com.backdrops.wallpapers -l frida_backdrops_bypass.js
```

**Result**: All premium wallpaper collections should be unlocked! 🎉

---

## 🎮 Interactive RPC Functions

The bypass script exports functions you can call from Python:

```python
import frida
import sys

device = frida.get_usb_device()
session = device.attach("com.backdrops.wallpapers")

# Load script
with open("frida_backdrops_bypass.js") as f:
    script = session.create_script(f.read())
script.load()

# Call RPC functions
api = script.exports

# List current purchase status
api.list_purchases()

# Inject fake purchase for specific SKU
api.inject_purchase("premium.pack.trinity")

# Toggle bypass on/off
api.toggle_bypass(False)  # Disable bypass
api.toggle_bypass(True)   # Re-enable bypass
```

Or use frida-tools REPL:
```bash
frida -U com.backdrops.wallpapers -l frida_backdrops_bypass.js

# In REPL:
%load frida_backdrops_bypass.js
rpc.exports.listPurchases()
rpc.exports.injectPurchase("premium.pack.trinity")
```

---

## 📊 Testing Workflow

### Phase 1: Reconnaissance (Analysis Script)
1. Install the Backdrops APK on your device
2. Start Frida server on device
3. Run the **analysis script**
4. Open the app and navigate through menus
5. Try to access premium collections
6. Observe console output:
   - Which methods are called?
   - What SKUs are checked?
   - What does the database contain?

### Phase 2: Exploitation (Bypass Script)
1. Close the app completely
2. Run the **bypass script**
3. Launch the app
4. Navigate to premium collections
5. Observe console showing bypasses in action
6. All premium wallpapers should now be accessible! 🎨

### Phase 3: Verification
1. Try downloading premium wallpapers
2. Check if they apply as wallpaper
3. Verify no payment prompts appear
4. Test different premium packs (Trinity, Amoled, Acid, etc.)

---

## 🔐 Attack Surface Analysis

### Vulnerability: Client-Side Premium Verification
**Issue**: The app relies entirely on local SQLite database for premium status checks.

**Attack Vector**:
```
User opens premium content 
  → App calls DatabaseObserver.isPremiumPackUnlocked(sku)
    → Queries ThemeApp.g().existPurchase(sku)  
      → Reads SQLite database "premium" table
        → Returns Boolean TRUE/FALSE
          → App shows/hides content based on result
```

**Exploitation Methods**:

1. **Runtime Hooking** (Our approach):
   - Hook Java methods with Frida
   - Force return values to TRUE
   - ✅ No app modification needed
   - ✅ Easy to test and toggle

2. **Database Manipulation**:
   ```bash
   # Find the database
   adb shell "find /data/data/com.backdrops.wallpapers -name 'premium'"
   
   # Pull database
   adb pull /data/data/com.backdrops.wallpapers/databases/premium premium.db
   
   # Inject fake purchases (SQLite)
   sqlite3 premium.db
   INSERT INTO Premium (id, item, token) VALUES (1, 'premium.pack.trinity', 'fake_token');
   
   # Push back
   adb push premium.db /data/data/com.backdrops.wallpapers/databases/premium
   ```

3. **APK Patching** (Static):
   - Decompile APK with apktool
   - Modify `DatabaseObserver.smali` to always return true
   - Recompile and sign APK
   - ❌ More complex, signature issues

---

## 🎯 CTF Flag Hunting

If this is a CTF, the flag might be:

1. **In premium wallpaper metadata**: Download and check EXIF data
   ```bash
   exiftool premium_wallpaper.jpg | grep -i flag
   ```

2. **In the database after bypass**: 
   ```bash
   adb shell "sqlite3 /data/data/com.backdrops.wallpapers/databases/premium 'SELECT * FROM Premium'"
   ```

3. **In network traffic**: Use Burp Suite or mitmproxy
   ```bash
   mitmproxy --mode transparent --showhost
   ```

4. **Hidden in resources**: Check strings in premium collections
   ```bash
   strings com.backdrops.wallpapers.apkm | grep -i flag
   ```

5. **Logged when accessing specific pack**: Watch Frida console output carefully!

---

## 📱 Device Setup

### Requirements
- Android device (rooted or non-rooted with frida-gadget)
- Frida installed on host machine
- Frida server running on Android device
- USB debugging enabled

### Frida Installation
```bash
# On host machine (PC)
pip install frida-tools

# On Android device
# Download frida-server for your architecture
# https://github.com/frida/frida/releases

adb push frida-server-16.x.x-android-arm64 /data/local/tmp/frida-server
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"
```

### Verify Frida
```bash
frida-ps -U
# Should list running Android processes
```

---

## 🐛 Troubleshooting

### "Failed to spawn: unable to find process"
```bash
# List installed packages
adb shell pm list packages | grep backdrop

# Verify package name
frida-ps -Uai | grep -i backdrop
```

### "Failed to attach: process not found"
```bash
# Make sure app is running
adb shell am start com.backdrops.wallpapers/.activities.MainActivity

# Try spawn mode instead
frida -U -f com.backdrops.wallpapers -l script.js
```

### "Script runtime error: Java is not available"
- Device must be rooted OR use frida-gadget
- Ensure frida-server is running as root
- Check frida-server version matches frida-tools

### Bypass doesn't work
1. Check that hooks are installed (look for "[+] Hooked:" messages)
2. Verify BYPASS_ENABLED is true
3. Try restart app after attaching script
4. Check logcat for app crashes: `adb logcat | grep -i backdrop`

---

## 🧪 Advanced Techniques

### Dump entire purchase database
```javascript
Java.perform(function() {
    var ThemeApp = Java.use("com.backdrops.wallpapers.ThemeApp");
    var dbHandler = ThemeApp.g();
    var db = dbHandler.getReadableDatabase();
    
    var cursor = db.rawQuery("SELECT * FROM Premium", null);
    console.log("Database contents:");
    while(cursor.moveToNext()) {
        var id = cursor.getInt(0);
        var item = cursor.getString(1);
        var token = cursor.getString(2);
        console.log("  " + id + " | " + item + " | " + token);
    }
    cursor.close();
});
```

### Trace all method calls in a class
```javascript
Java.perform(function() {
    var targetClass = Java.use("com.backdrops.wallpapers.data.DatabaseObserver");
    var methods = targetClass.class.getDeclaredMethods();
    
    methods.forEach(function(method) {
        var methodName = method.getName();
        targetClass[methodName].implementation = function() {
            console.log("[TRACE] " + methodName + "()");
            return this[methodName].apply(this, arguments);
        };
    });
});
```

### Monitor network requests for premium content
```javascript
Java.perform(function() {
    var RestClient = Java.use("com.backdrops.wallpapers.data.remote.RestClient");
    // Hook network methods to see API endpoints for premium wallpapers
});
```

---

## 📚 Code References

### Key Classes to Study:
- `com.backdrops.wallpapers.data.DatabaseObserver` - Premium verification logic
- `com.backdrops.wallpapers.data.local.DatabaseHandlerIAB` - Purchase database
- `j1.E` (PlayBillingActivity) - Google Play Billing integration
- `com.backdrops.wallpapers.ThemeApp` - App singleton with DB access
- `com.backdrops.wallpapers.fragment.PremiumWallFrag` - Premium UI

### Database Schema:
```sql
CREATE TABLE Premium(
    id INTEGER PRIMARY KEY,
    item TEXT,      -- SKU identifier
    token TEXT      -- Purchase token from Google Play
)
```

---

## ⚖️ Legal Disclaimer

This material is for **educational purposes only** as part of a CTF challenge. 

- Do not use these techniques to pirate paid applications
- Respect software licenses and intellectual property
- Only test on apps you own or have permission to analyze
- Understand local laws regarding reverse engineering

---

## 🏆 Success Criteria

You've successfully completed the challenge when:
- [x] You can hook premium check methods
- [x] You can monitor premium verification flow  
- [x] You understand the database structure
- [x] You can bypass premium checks
- [x] You can access all premium wallpapers
- [ ] You found the flag! (if applicable)

---

## 📝 Notes

- The app uses RxJava for async operations - watch for `Single<Boolean>` returns
- Google Play Billing is integrated but local checks happen first
- Premium status is cached - may need to restart app after DB injection
- Some wallpapers may still require network connectivity to download

---

## 🤝 Contributing

Found a better technique? Discovered additional flags? Open an issue or PR!

---

**Happy Hacking! 🔓🎨**
