Skip to main content
Glama
1111laaaddaaa

StaticApkAuditor MCP

README.md
# StaticApkAuditor MCP

A Model Context Protocol (MCP) server that exposes [Apktool](https://ibotpeaches.github.io/Apktool/)-based decompilation plus a suite of custom static-analysis heuristics for Android APK security assessment, through natural-language commands in Claude Code / Claude Desktop.

## What this is for

You point it at an APK. It decompiles it, then gives an AI assistant a set of tools to analyze the result — attack surface, permissions, hardcoded secrets, crypto usage, native libraries, business logic candidates — and cross-checks findings from other tools like MobSF. Every call is logged to disk as a markdown report, so you end up with an audit trail, not just a chat transcript.

**This is a static-analysis aid, not a complete pentest.** Several tools produce *candidates for manual/dynamic verification*, not confirmed vulnerabilities — this is called out explicitly in tool descriptions and in the built-in prompts. Runtime behavior (race conditions, workflow bypasses, actual data exfiltration) needs dynamic testing (Frida, Burp/mitmproxy, a real device) to confirm.

## Quick Start

Assumes Java, Apktool, and Python 3.10+ are already installed (see [Prerequisites](#prerequisites) below if not).

```bash
# 1. Set up the project folder
mkdir static-apk-auditor && cd static-apk-auditor

# 2. Create a venv and install the one dependency
python3 -m venv venv
source venv/bin/activate          # Windows: venv\Scripts\activate
pip install -r requirements.txt

# 3. Sanity check — should hang waiting for stdio input, Ctrl+C to stop
python3 server.py

# 4. Register with Claude Code (adjust paths to your actual location)
claude mcp add static-apk-auditor \
  --env APKTOOL_WORK_DIR=$(pwd)/data \
  -- $(pwd)/venv/bin/python3 $(pwd)/server.py

# 5. Verify it connected
claude mcp list
```

Then, inside a `claude` session, in the same folder you ran `claude mcp add` from (registration defaults to that folder's scope):

```
/mcp__static-apk-auditor__security_audit
/absolute/path/to/some.apk
```

or just ask in plain language — the model will call `decode_apk` and the rest of the tools on its own:

```
Decompile /absolute/path/to/some.apk and give me a quick security triage.
```

See [Prompts](#prompts-guided-workflows) and [Tools](#tools) below for everything available, or run `/mcp` in a Claude Code session to browse them interactively.

## Project structure

```
static-apk-auditor/                  # your folder can be named anything — this is just an example
├── server.py                    # the MCP server — single file, FastMCP-based
├── requirements.txt              # just "mcp"
├── README.md                     # this file
├── prompts/
│   ├── security_audit.md         # 16-point checklist, OWASP Mobile Top 10 mapping
│   └── mobsf_review.md           # MobSF finding validation workflow
├── venv/                         # created locally, not part of the repo
└── data/                         # created automatically on first decode_apk call
                                   # (this is APKTOOL_WORK_DIR — see Configuration below)
```

### Runtime data layout (created automatically)

Every APK you analyze gets its own self-contained folder under `APKTOOL_WORK_DIR`:

```
$APKTOOL_WORK_DIR/<apk_filename_without_extension>/
├── source/
│   └── <original>.apk           # copy of the APK you pointed the tool at
├── decoded/
│   ├── AndroidManifest.xml
│   ├── smali/, smali_classes2/, ...
│   ├── res/, assets/, lib/
│   └── ...                      # apktool's decompiled output
├── reports/
│   ├── 20260706_175359_809_decode_apk.md
│   ├── 20260706_175412_112_analyze_manifest.md
│   ├── 20260706_175430_501_check_root_detection.md
│   └── ...                      # one markdown file per tool call, ever
└── final_reports/
    ├── 20260706_223500_123_security_audit.md
    └── 20260706_224100_456_mobsf_review.md
                                   # the finished, synthesized reports
                                   # (Summary + Detailed Findings + Risk Table),
                                   # saved explicitly via save_final_report
```

Every tool call — regardless of which tool, regardless of success or failure — writes a timestamped markdown file to that APK's `reports/` folder. This isn't optional per-call logging; it's a decorator (`@logged_tool`) applied to every registered tool, so nothing calling into this server goes unrecorded. Each report contains the tool name, the parameters it was called with, and its full output.

`reports/` and `final_reports/` serve different purposes: `reports/` is the raw call log (every individual tool invocation, useful for auditing exactly what was checked and when), while `final_reports/` holds only the polished, human-readable write-ups — the actual deliverable you'd hand to a developer or client. The `security_audit` and `mobsf_review` prompts both end with a mandatory call to `save_final_report`, which is what populates `final_reports/`; without that call, the synthesized report only exists in the chat response and isn't persisted anywhere on disk.

## Prerequisites

**1. Java JDK 8+** (required by Apktool)
```bash
# Ubuntu/Debian
sudo apt update && sudo apt install default-jdk

# macOS
brew install openjdk
java -version
```

**2. Apktool**
```bash
# Ubuntu/Debian
sudo apt install apktool

# macOS
brew install apktool
apktool --version
```

**3. Python 3.10+**
```bash
python3 --version
```

**4. (Optional) aapt** — for full `get_apk_info` metadata without needing to decode first
```bash
brew install aapt   # or: brew install --cask android-commandlinetools
```
If `aapt` isn't installed, `get_apk_info` falls back to parsing the already-decoded `AndroidManifest.xml` instead of failing silently.

## Installation

```bash
git clone <your-repo-or-just-copy-the-files> static-apk-auditor
cd static-apk-auditor
python3 -m venv venv
source venv/bin/activate      # Windows: venv\Scripts\activate
pip install -r requirements.txt
```

Sanity check:
```bash
python3 server.py
# Should hang waiting for stdio input (that's normal) — Ctrl+C to stop.
```

## Connecting to Claude Code

```bash
claude mcp add apktool-pro \
  --env APKTOOL_WORK_DIR=/absolute/path/to/static-apk-auditor/data \
  -- /absolute/path/to/static-apk-auditor/venv/bin/python3 /absolute/path/to/static-apk-auditor/server.py
```

Verify:
```bash
claude mcp list
claude mcp get apktool-pro   # should show "✔ Connected"
```

Note: `claude mcp add` registers the server scoped to the **current directory** by default (`local` scope). If you want it available from any project, add `--scope user`.

### Connecting to Claude Desktop (alternative)

Edit your config file (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
  "mcpServers": {
    "apktool-pro": {
      "command": "/absolute/path/to/static-apk-auditor/venv/bin/python3",
      "args": ["/absolute/path/to/static-apk-auditor/server.py"],
      "env": {
        "APKTOOL_WORK_DIR": "/absolute/path/to/static-apk-auditor/data"
      }
    }
  }
}
```
Restart Claude Desktop after saving.

## Configuration (environment variables)

| Variable | Default | Purpose |
|---|---|---|
| `APKTOOL_PATH` | `apktool` | Path to the apktool executable, if not on PATH |
| `AAPT_PATH` | `aapt` | Path to aapt, if not on PATH |
| `APKTOOL_WORK_DIR` | `~/.static-apk-auditor` | Root folder for all per-APK source/decoded/reports data |

## Tools

### Core (decompilation & manifest)

| Tool | Parameters | Description |
|---|---|---|
| `decode_apk` | `apk_path`, `force=False` | Decompiles an APK with apktool. Output persists under `APKTOOL_WORK_DIR/<slug>/decoded/` (not a tempdir), and a copy of the source APK is kept in `.../source/`. |
| `get_apk_info` | `apk_path` | Basic metadata: package, version, SDK levels, file size. Uses aapt if available, otherwise falls back to parsing the decoded manifest. |
| `build_apk` | `decoded_dir`, `output_apk=None` | Rebuilds an APK from a (possibly modified) decoded directory. Output is unsigned — sign separately with `apksigner`. |
| `install_framework` | `framework_apk` | Installs a system framework APK so apktool can decode system/OEM apps that reference it. |
| `analyze_manifest` | `decoded_dir` | Parses `AndroidManifest.xml` directly via `xml.etree`: package/version/SDK, exported components (Activity/Service/Receiver/Provider), intent-filters/deep links, `debuggable`/`allowBackup`/`taskAffinity`. |
| `list_permissions` | `decoded_dir` | Lists all requested permissions, flags which are classified "dangerous" by the Android permission model. |
| `extract_strings` | `decoded_dir`, `locale="en"` | Extracts string resources for a given locale. |
| `find_smali_references` | `decoded_dir`, `pattern`, `max_matches=200` | Regex search across all decompiled `.smali` files, with file + line for each match. |

### Security heuristics

| Tool | Parameters | Description |
|---|---|---|
| `list_native_libraries` | `decoded_dir` | Lists `.so` libraries and CPU architectures shipped in the APK — flags code that smali search can't see into. |
| `check_ssl_pinning` | `decoded_dir` | Scans for custom `TrustManager`/`HostnameVerifier` implementations that could defeat certificate validation, plus `CertificatePinner` usage and `network_security_config.xml` contents. |
| `check_pending_intents` | `decoded_dir` | Finds `PendingIntent.getActivity/getBroadcast/getService` calls and flags ones without `FLAG_IMMUTABLE` nearby. |
| `extract_js_bundle_strings` | `decoded_dir`, `pattern=<url regex>` | For React Native / Expo apps: searches `assets/*.bundle` and `assets/*.js` for a pattern (defaults to extracting URLs — usually where real backend endpoints leak). |
| `check_root_detection` | `decoded_dir` | Scans for root/emulator detection and anti-tampering signatures: su-binary paths, RootBeer/RootTools, SafetyNet, Play Integrity, `test-keys` build tag, generic `isRooted`-style method names. Presence tells you what you'll need to bypass for dynamic testing; absence is itself a finding for sensitive apps. |

### Business logic reconnaissance

| Tool | Parameters | Description |
|---|---|---|
| `map_sensitive_flows` | `decoded_dir`, `extra_keywords=None` | Locates methods/classes whose names suggest sensitive operations (payments, entitlements, roles, discounts, quotas) and shows nearby `invoke-*` calls as lightweight call context. A candidate map for manual/dynamic review — **not** a confirmed vulnerability list. |
| `find_client_side_only_checks` | `decoded_dir` | Heuristic: flags sensitive-keyword hits where a local comparison (`if-*`/`cmp-*`) appears without an adjacent network call — suggests the decision may be made client-side and potentially bypassable by patching + rebuilding. |

### MobSF report validation

| Tool | Parameters | Description |
|---|---|---|
| `load_mobsf_report` | `report_path` | Loads and normalizes a MobSF static-analysis JSON report (`code_analysis`, `manifest_analysis`, `permissions`, `urls`/`emails`/`firebase_urls`, `network_security`, `certificate_analysis`). Does not judge validity by itself. |
| `cross_validate_mobsf_finding` | `decoded_dir`, `finding_pattern`, `mobsf_file_hint=None` | Cross-checks one MobSF finding against your own decompiled output (smali + string resources) to catch false positives. Returns evidence for the model to classify — Confirmed / False Positive / Needs Manual Review — it does not classify on its own. |

## Prompts (guided workflows)

Prompts are invoked explicitly as slash commands in Claude Code (`/apktool-pro:<name>`), unlike tools, which the model calls on its own as needed.

| Prompt | Arguments | What it does |
|---|---|---|
| `security_audit` | `apk_path` | Runs the full 16-point checklist (attack surface, permissions, secrets, crypto, WebView, storage, SSL pinning, task hijacking, root detection, exported receivers/providers, JS bundle, native libs, logging, dependency versions, PendingIntent mutability, business logic) and outputs: Summary → Detailed Findings (with Confidence rating + adb PoC steps) → Risk Table mapped to OWASP Mobile Top 10 (M1–M10). |
| `mobsf_review` | `apk_path`, `mobsf_report_path` | Loads a MobSF JSON report, cross-validates every finding against the actual decompiled code, classifies each as Confirmed/False Positive/Needs Manual Review, re-assesses severity independently of MobSF's own rating, and produces a Prioritized Action List of Confirmed findings only. |
| `quick_triage` | `apk_path` | Fast pass: exported components + dangerous permissions + obvious hardcoded secrets. For when you don't need the full audit. |

## Usage examples

```
Use decode_apk to decompile /path/to/app.apk
```

```
/apktool-pro:security_audit apk_path="/path/to/app.apk"
```

```
Use check_root_detection on the decompiled output
```

```
/apktool-pro:mobsf_review apk_path="/path/to/app.apk" mobsf_report_path="/path/to/mobsf_report.json"
```

To see all available tools and their exact parameters at any time, run `/mcp` in a Claude Code session and select `apktool-pro`.

## Getting a MobSF report

If you're running MobSF locally:
```bash
# upload the APK, get back a hash
curl -F 'file=@/path/to/app.apk' http://localhost:8000/api/v1/upload \
  -H "Authorization: <MOBSF_API_KEY>"

# fetch the JSON report using that hash
curl -X POST http://localhost:8000/api/v1/report_json \
  -H "Authorization: <MOBSF_API_KEY>" \
  --data "hash=<hash_from_upload>" -o mobsf_report.json
```

## Known limitations

- **Static analysis only.** Nothing here executes the app or intercepts real traffic. Business-logic findings and some "confirmed" static findings still need dynamic verification before you treat them as proven.
- **`build_apk` output is unsigned.** Sign with `apksigner` before installing on a device.
- **Regex-based heuristics** (`check_ssl_pinning`, `check_root_detection`, `map_sensitive_flows`, etc.) can miss obfuscated/renamed code and can false-positive on unrelated matches — treat their output as a shortlist to review, not a verdict.
- **`install_framework`** is only needed for decoding system/OEM APKs that reference `framework-res.apk`; most third-party app analysis won't need it.

## Design notes

- `APKTOOL_WORK_DIR` is always respected — every APK gets a persistent, self-contained folder (`source/`, `decoded/`, `reports/`, `final_reports/`); nothing writes to a throwaway tempdir.
- `get_apk_info` falls back to parsing the decoded manifest if `aapt` isn't installed, rather than returning nothing useful.
- Every tool call is auto-logged (`reports/`); finished, synthesized reports are saved separately via `save_final_report` (`final_reports/`).
- Built on `FastMCP` for straightforward tool/prompt registration.

## Legal / responsible use

Only analyze APKs you own or have explicit written permission to test. Decompiled APKs may contain sensitive user data — handle output accordingly and clean up `APKTOOL_WORK_DIR` after an engagement if it contains client data. This tool does not perform any network exfiltration or active exploitation on its own; PoC commands in `security_audit` output (e.g. `adb shell am start ...`) are meant to be run manually against a device/emulator you control.