Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# APK files
*.apk
*.xapk

# Decompiled output
tools/apk/decompiled/

# Traffic captures
tools/traffic/*.flow
tools/traffic/*.jsonl

# Signature output
*.signature.json

# Python
__pycache__/
*.pyc
.venv/
venv/

# OS
.DS_Store
Thumbs.db

# mitmproxy
~/.mitmproxy/
62 changes: 62 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# AGENTS.md

## Cursor Cloud specific instructions

This repository (`tik-api`) provides tools for analyzing TikTok's Android APK and API communications.

### Installed Tools

| Tool | Version | Path | Purpose |
|------|---------|------|---------|
| Android SDK CLI | latest | `/opt/android-sdk/` | APK management, `adb`, `apksigner`, `aapt` |
| apktool | 2.7.0 | system | APK decompilation (smali + resources) |
| jadx | 1.5.1 | `/opt/jadx/bin/jadx` | APK decompilation (Java source) |
| mitmproxy | 12.2.1 | `~/.local/bin/mitmdump` | HTTPS traffic interception |
| frida | 17.8.2 | `~/.local/bin/frida` | Runtime instrumentation / SSL pinning bypass |
| keytool | JDK 21 | system | Certificate extraction |

### Environment Variables

These are set in `~/.bashrc`:
```
ANDROID_HOME=/opt/android-sdk
PATH includes: $ANDROID_HOME/cmdline-tools/latest/bin, $ANDROID_HOME/platform-tools, $ANDROID_HOME/build-tools/35.0.0, /opt/jadx/bin, ~/.local/bin
```

### Key Scripts

- `scripts/extract_signature.sh <apk>` — Extract APK signing certificate (shell)
- `scripts/extract_tiktok_signature.py <apk>` — Full signature analysis with JSON output (Python)
- `scripts/decompile_apk.sh <apk>` — Decompile APK to smali + Java source
- `scripts/capture_traffic.sh [port]` — Start mitmproxy for traffic capture
- `scripts/tiktok_proxy_addon.py` — mitmproxy addon that filters/logs TikTok API traffic
- `scripts/ssl_bypass_frida.js` — Frida script to bypass SSL pinning on TikTok
- `scripts/analyze_traffic.py <flow>` — Analyze captured mitmproxy flow files

### Caveats

- **No KVM/hardware virtualization** in cloud VM — Android emulator cannot run with HW accel. Use a physical device or local emulator connected via `adb connect`.
- **TikTok APK not bundled** — download manually and place in `tools/apk/`. The APK cannot be auto-downloaded from CDNs.
- **SSL pinning** — TikTok uses certificate pinning. Use `scripts/ssl_bypass_frida.js` with Frida or patch `network_security_config.xml` via apktool.
- **mitmproxy CA** — for Android 7+, system CA certs require root or APK patching. Install CA from `http://mitm.it` on the device.

### Workflow: Extract TikTok Signature

```bash
# Place TikTok APK in tools/apk/
python3 scripts/extract_tiktok_signature.py tools/apk/tiktok.apk
```

### Workflow: Capture API Traffic

```bash
# 1. Start proxy with TikTok filter addon
mitmdump -p 8080 -s scripts/tiktok_proxy_addon.py

# 2. On device/emulator: set proxy to <VM_IP>:8080, install CA from http://mitm.it
# 3. Run Frida SSL bypass:
frida -U -f com.zhiliaoapp.musically -l scripts/ssl_bypass_frida.js --no-pause

# 4. Analyze captured traffic:
python3 scripts/analyze_traffic.py tools/traffic/tiktok_api_log.jsonl
```
99 changes: 98 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,98 @@
# tik-api
# tik-api

TikTok Android APK analysis and API traffic interception toolkit.

## Tools

| Tool | Purpose |
|------|---------|
| `apksigner` | APK signature verification & certificate extraction |
| `apktool` | APK decompilation (smali + resources) |
| `jadx` | APK decompilation (Java source code) |
| `mitmproxy` | HTTPS traffic interception proxy |
| `frida` | Runtime instrumentation & SSL pinning bypass |
| `adb` | Android Debug Bridge |
| `aapt` | Android Asset Packaging Tool |

## Quick Start

### 1. Extract APK Signature

```bash
# Using shell script
bash scripts/extract_signature.sh path/to/tiktok.apk

# Using Python (full analysis + JSON output)
python3 scripts/extract_tiktok_signature.py path/to/tiktok.apk
```

### 2. Decompile APK

```bash
bash scripts/decompile_apk.sh path/to/tiktok.apk [output-dir]
```

### 3. Capture API Traffic

```bash
# Start proxy with TikTok API filter
mitmdump -p 8080 -s scripts/tiktok_proxy_addon.py

# On Android device: set Wi-Fi proxy to <your-ip>:8080
# Install CA certificate: http://mitm.it

# Bypass SSL pinning with Frida
frida -U -f com.zhiliaoapp.musically -l scripts/ssl_bypass_frida.js --no-pause
```

### 4. Analyze Captured Traffic

```bash
python3 scripts/analyze_traffic.py tools/traffic/capture.flow
```

## Directory Structure

```
tik-api/
├── scripts/
│ ├── extract_signature.sh # APK signature extraction (shell)
│ ├── extract_tiktok_signature.py # APK signature extraction (Python)
│ ├── decompile_apk.sh # APK decompilation
│ ├── capture_traffic.sh # Traffic capture launcher
│ ├── tiktok_proxy_addon.py # mitmproxy TikTok filter addon
│ ├── ssl_bypass_frida.js # Frida SSL pinning bypass
│ └── analyze_traffic.py # Traffic analysis tool
├── tools/
│ └── apk/ # Place APK files here
├── config/ # Configuration files
├── requirements.txt # Python dependencies
└── AGENTS.md # Cloud agent instructions
```

## Requirements

- Java 11+ (OpenJDK 21 recommended)
- Python 3.10+
- Android SDK (platform-tools, build-tools)

### Install Python Dependencies

```bash
pip3 install -r requirements.txt
```

## TikTok API Signature Headers

Key headers captured by the traffic analysis tools:

| Header | Description |
|--------|-------------|
| `X-Gorgon` | Request signature (device-generated) |
| `X-Khronos` | Timestamp component of signature |
| `X-Argus` | Enhanced request signature |
| `X-Ladon` | Additional signature parameter |
| `X-SS-STUB` | MD5 hash of POST body |
| `X-SS-REQ-TICKET` | Request timestamp ticket |
| `X-TT-Token` | Session token |
| `X-BD-Client-Key` | Client encryption key |
Empty file added config/.gitkeep
Empty file.
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mitmproxy>=12.0.0
frida-tools>=14.0.0
requests>=2.31.0
126 changes: 126 additions & 0 deletions scripts/analyze_traffic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""
Analyze captured mitmproxy traffic flows for TikTok API endpoints.
Usage: python3 scripts/analyze_traffic.py <flow-file>

Extracts:
- API endpoints and methods
- Request/response headers
- Request parameters and body
- Device signature parameters (X-Gorgon, X-Khronos, X-SS-STUB, etc.)
"""

import sys
import json
from pathlib import Path

try:
from mitmproxy.io import FlowReader
from mitmproxy.http import HTTPFlow
except ImportError:
print("Error: mitmproxy not installed. Run: pip3 install mitmproxy")
sys.exit(1)


TIKTOK_DOMAINS = [
"api.tiktokv.com",
"api16-normal-c-useast1a.tiktokv.com",
"api16-normal-c-useast2a.tiktokv.com",
"api22-normal-c-useast1a.tiktokv.com",
"api22-normal-c-useast2a.tiktokv.com",
"log.tiktokv.com",
"mon.tiktokv.com",
"ib.tiktokv.com",
"webcast.tiktok.com",
"mssdk.tiktokv.com",
]

SIGNATURE_HEADERS = [
"x-gorgon",
"x-khronos",
"x-ss-stub",
"x-ss-req-ticket",
"x-tt-token",
"x-bd-client-key",
"x-bd-kmsv",
"x-argus",
"x-ladon",
"x-helios",
"x-tyhon",
"x-tt-dm-status",
"passport-sdk-version",
]


def analyze_flow(flow_file: str):
flows = []
with open(flow_file, "rb") as f:
reader = FlowReader(f)
for flow in reader.stream():
if isinstance(flow, HTTPFlow) and flow.response:
flows.append(flow)

print(f"\nTotal flows captured: {len(flows)}")

tiktok_flows = []
for flow in flows:
host = flow.request.host
if any(domain in host for domain in TIKTOK_DOMAINS) or "tiktok" in host:
tiktok_flows.append(flow)

print(f"TikTok API flows: {len(tiktok_flows)}\n")

for i, flow in enumerate(tiktok_flows, 1):
req = flow.request
resp = flow.response
print(f"{'='*60}")
print(f"[{i}] {req.method} {req.url[:120]}")
print(f" Status: {resp.status_code}")
print(f" Host: {req.host}")
print(f" Path: {req.path.split('?')[0]}")

sig_headers = {}
for h in SIGNATURE_HEADERS:
val = req.headers.get(h)
if val:
sig_headers[h] = val

if sig_headers:
print(f" Signature Headers:")
for k, v in sig_headers.items():
print(f" {k}: {v[:80]}{'...' if len(v) > 80 else ''}")

if req.query:
print(f" Query params: {len(req.query)} params")
for k, v in list(req.query.items())[:10]:
print(f" {k}={v[:60]}{'...' if len(str(v)) > 60 else ''}")

content_type = resp.headers.get("content-type", "")
if "json" in content_type and resp.content:
try:
body = json.loads(resp.content)
print(f" Response (JSON): {json.dumps(body, ensure_ascii=False)[:200]}...")
except json.JSONDecodeError:
print(f" Response: {len(resp.content)} bytes")
else:
print(f" Response: {len(resp.content)} bytes ({content_type})")

print()


def main():
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <flow-file>")
print(f" Example: {sys.argv[0]} tools/traffic/capture_20260317.flow")
sys.exit(1)

flow_file = sys.argv[1]
if not Path(flow_file).exists():
print(f"Error: File not found: {flow_file}")
sys.exit(1)

analyze_flow(flow_file)


if __name__ == "__main__":
main()
36 changes: 36 additions & 0 deletions scripts/capture_traffic.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash
# Start mitmproxy to capture TikTok API traffic
# Usage: ./scripts/capture_traffic.sh [port] [output-file]
#
# For Android device/emulator:
# 1. Set proxy on device: <host-ip>:<port>
# 2. Install mitmproxy CA: http://mitm.it
# 3. For Android 7+, you need to patch the APK's network_security_config.xml
# or use Frida to bypass SSL pinning

set -e

PORT="${1:-8080}"
OUTPUT="${2:-/workspace/tools/traffic/capture_$(date +%Y%m%d_%H%M%S).flow}"

mkdir -p "$(dirname "$OUTPUT")"

echo "============================================"
echo " mitmproxy Traffic Capture"
echo "============================================"
echo ""
echo "Listening on port: $PORT"
echo "Output file: $OUTPUT"
echo ""
echo "Configure your device/emulator proxy:"
echo " Host: $(hostname -I | awk '{print $1}')"
echo " Port: $PORT"
echo ""
echo "Install CA certificate on device: http://mitm.it"
echo ""
echo "Press Ctrl+C to stop capture."
echo ""

mitmdump -p "$PORT" -w "$OUTPUT" \
--set flow_detail=2 \
--set console_eventlog_verbosity=info
34 changes: 34 additions & 0 deletions scripts/decompile_apk.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash
# Decompile APK using apktool (smali) and jadx (Java source)
# Usage: ./scripts/decompile_apk.sh <path-to-apk> [output-dir]

set -e

APK_PATH="${1:?Usage: $0 <path-to-apk> [output-dir]}"
OUTPUT_DIR="${2:-/workspace/tools/apk/decompiled}"

if [ ! -f "$APK_PATH" ]; then
echo "Error: APK file not found: $APK_PATH"
exit 1
fi

APK_NAME=$(basename "$APK_PATH" .apk)
SMALI_DIR="$OUTPUT_DIR/${APK_NAME}_smali"
JAVA_DIR="$OUTPUT_DIR/${APK_NAME}_java"

echo "============================================"
echo " Decompiling: $(basename "$APK_PATH")"
echo "============================================"

echo ""
echo "[1/2] apktool (smali + resources) -> $SMALI_DIR"
apktool d "$APK_PATH" -o "$SMALI_DIR" -f 2>&1 | tail -3
echo ""

echo "[2/2] jadx (Java source) -> $JAVA_DIR"
jadx -d "$JAVA_DIR" "$APK_PATH" --no-res 2>&1 | tail -5
echo ""

echo "Done. Output directories:"
echo " Smali: $SMALI_DIR"
echo " Java: $JAVA_DIR"
Loading