MobileAudit APK Analysis Process: From File Upload to Security Findings Generation
MobileAudit executes a 15-step static analysis pipeline that hashes, decompiles, and pattern-matches uploaded APKs to generate security findings, orchestrated via Django views and Celery workers.
The APK analysis process in MobileAudit (mpast/mobileaudit) converts Android application packages into detailed security assessments through systematic reverse engineering and static code analysis. This Django-based framework coordinates asynchronous tasks to unpack manifests, decompile bytecode with JADX, and identify vulnerabilities via regex pattern matching. Each stage persists data to PostgreSQL through Django ORM models, creating a permanent audit trail of permissions, components, and security findings.
Step 1: Upload and Asynchronous Task Orchestration
The pipeline initiates when a user submits the ScanForm through the web interface.
Handling the Upload in Django
In app/views.py, the create_scan function processes the multipart form submission, instantiates a Scan database record with status "In Progress", and immediately delegates processing to a Celery worker to prevent HTTP timeouts.
# app/views.py lines 73-86
def create_scan(request):
form = ScanForm(request.POST, request.FILES)
if form.is_valid():
scan = form.save(commit=False)
scan.status = Status.IN_PROGRESS
scan.save()
task_create_scan.delay(scan.id)
return redirect('scan', scan_id=scan.id)
Celery Worker Initialization
The task_create_scan function in app/worker/tasks.py receives the scan ID, updates the Celery task state for progress tracking, and invokes the core analysis engine.
# app/worker/tasks.py lines 10-15
@shared_task(bind=True)
def task_create_scan(self, scan_id):
scan = Scan.objects.get(id=scan_id)
self.update_state(state='PROGRESS', meta={'progress': 10})
analysis.analyze_apk(self, scan)
Step 2: Metadata Extraction and APK Validation
Before decompilation, analysis.analyze_apk computes cryptographic fingerprints and extracts manifest declarations using AndroGuard.
Cryptographic Hash Calculation
The set_hash_app function (lines 20-41 in app/analysis.py) streams the uploaded APK to compute MD5, SHA-1, and SHA-256 hashes, storing them on the Scan model for integrity verification and correlation with threat intelligence.
# Conceptual implementation from app/analysis.py
def set_hash_app(apk_path):
hashes = {}
for algo in ['md5', 'sha1', 'sha256']:
hasher = hashlib.new(algo)
with open(apk_path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
hasher.update(chunk)
hashes[algo] = hasher.hexdigest()
return hashes
Manifest Parsing and Component Enumeration
The get_info_apk function (lines 35-57 in app/analysis.py) uses androguard.APK to extract the package name, version, minimum SDK version, and declared permissions. It creates Permission objects for every entry in the AndroidManifest.xml.
The get_intent_filter function (lines 76-95 in app/analysis.py) catalogs activities, services, receivers, and providers, creating Component and IntentFilter relationships. Activities flagged as MAIN and LAUNCHER are specifically marked as the main entry point, mapping the application's attack surface.
Certificate and Signing Information
If the APK contains signing certificates, get_info_certificate (lines 97-119 in app/analysis.py) extracts every certificate's version, SHA-1/SHA-256 fingerprints, issuer, subject, and validity period, persisting them as Certificate objects linked to the scan.
VirusTotal Integration (Optional)
When VIRUSTOTAL_ENABLED is configured, the system queries VirusTotal for existing reports via get_report_virus_total. If no report exists and VIRUSTOTAL_UPLOAD is true, the file uploads automatically via upload_virus_total or upload_virus_total_v3 functions in app/integration.py, storing detection ratios as VirusTotalScan and Antivirus records (referenced in lines 73-85 of app/analysis.py).
Step 3: Decompilation and Asset Extraction
JADX Decompilation
The decompile_jadx function (lines 18-22 in app/analysis.py) executes the external JADX binary via os.system, generating a full Java source tree under DECOMPILE_PATH. This human-readable code enables regex-based pattern matching in subsequent stages.
# app/analysis.py lines 18-22
def decompile_jadx(apk_path, output_dir):
cmd = f'jadx -d {output_dir} {apk_path}'
os.system(cmd)
Icon Extraction
The update_icon function (lines 24-31 in app/analysis.py) extracts the application icon from the APK resources, Base64-encodes the PNG/JPG data, and attaches it to the scan record for visual identification in the web interface.
Step 4: Deep Code Analysis and Findings Generation
With decompiled sources available, the system traverses the directory tree to identify sensitive patterns and database files.
Directory Tree Traversal
The get_tree_dir function (lines 22-45 in app/analysis.py) walks DECOMPILE_PATH, categorizing files by extension:
- Database files (
.db,.sqlite3,.sql) → processed byget_info_database - Source files (
.java,.kt,.xml) → fed to the pattern matching engine - Other assets → cataloged via
get_info_file
Pattern Matching Engine
The find_patterns function (lines 73-108 in app/analysis.py) loads active Pattern records (regular expressions) from the database and executes them against every line of source code. Each match creates a Finding record with severity classification, plus related String, Domain, and optional helper objects for IP addresses, URLs, and Base64 strings.
# Conceptual implementation from app/analysis.py
def find_patterns(file_path, scan):
patterns = Pattern.objects.filter(active=True)
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
for line_num, line in enumerate(f, 1):
for pattern in patterns:
if re.search(pattern.regex, line):
Finding.objects.create(
scan=scan,
pattern=pattern,
line_number=line_num,
path=file_path,
match=line.strip()
)
File Cataloging
Regardless of pattern matches, get_info_file (lines 86-104 in app/analysis.py) records every encountered file with its type classification (image, media, xml, html, other), building a comprehensive inventory of application assets.
Step 5: Scan Finalization and Findings Presentation
Upon completion, analysis.analyze_apk sets the Scan status to Finished, updates the finished_on timestamp, and sets progress to 100% (lines 99-108 in app/analysis.py). The Celery task state updates to reflect completion.
The scan view in app/views.py (lines 31-70) retrieves all related objects—Finding, Permission, Component, Certificate, and File—rendering them in app/templates/scan.html with syntax highlighting and severity filtering.
Programmatic Interaction with the APK Analysis Process
Triggering Scans via HTTP API
You can initiate the APK analysis process programmatically using multipart POST requests to the Django application:
import requests
url = "http://localhost:8000/create_scan/"
files = {"apk": open("target.apk", "rb")}
data = {"description": "Automated security scan", "app": 1}
response = requests.post(
url,
files=files,
data=data,
cookies={"sessionid": "your-session-cookie"}
)
print(f"Scan created: {response.url}")
Monitoring Scan Progress
Query the database directly to track analysis status:
from app.models import Scan
scan = Scan.objects.get(id=42)
print(f"Status: {scan.status}, Progress: {scan.progress}%")
print(f"Findings count: {scan.findings.count()}")
print(f"Completed: {scan.finished_on}")
Retrieving Security Findings
Extract all critical findings after completion, excluding informational severity:
from app.models import Finding, Severity
findings = Finding.objects.filter(
scan_id=42
).exclude(severity=Severity.NO)
for finding in findings:
print(f"[{finding.severity}] {finding.pattern.name}")
print(f"Location: {finding.path}:{finding.line_number}")
print(f"Match: {finding.match}\n")
Summary
- Upload Handling: The
create_scanview inapp/views.pyaccepts APK uploads and delegates processing to Celery viatask_create_scanto avoid blocking the web server. - Metadata Extraction:
set_hash_app,get_info_apk, andget_info_certificatecompute hashes, parse the AndroidManifest.xml, and extract signing certificate details using AndroGuard. - Decompilation:
decompile_jadxinvokes the JADX binary to convert Dalvik bytecode to Java source, enabling static analysis of implementation details. - Pattern Matching:
find_patternsexecutes configurable regular expressions against decompiled sources, creatingFindingrecords for security issues like hardcoded passwords or insecure URLs. - Asynchronous Architecture: The entire APK analysis process runs outside the request-response cycle, with progress persisted to the database and rendered via the
scanview upon completion.
Frequently Asked Questions
How does MobileAudit handle the APK upload process?
MobileAudit receives uploads through the Django view create_scan in app/views.py, which validates the ScanForm, creates a database record with "In Progress" status, and immediately fires task_create_scan.delay(scan.id) to process the file asynchronously via Celery, preventing HTTP timeouts during large file transfers.
What decompiler does MobileAudit use for APK analysis?
The framework utilizes JADX (via decompile_jadx in app/analysis.py lines 18-22) to decompile APK files into readable Java source code. The function executes jadx -d {output_dir} {apk_path} as a system command, creating a directory tree that the pattern matching engine subsequently scans for security vulnerabilities.
How are security findings generated from the source code?
Findings emerge through the find_patterns function (lines 73-108 in app/analysis.py), which loads active regex Pattern objects from the database and applies them to every line of decompiled Java, Kotlin, and XML files. Each match instantiates a Finding record with severity, file path, line number, and matched content, creating associated String and Domain objects for context.
Can the APK analysis process be automated via API?
Yes. The Django web interface exposes standard HTTP endpoints that accept programmatic interaction. Clients can POST multipart forms to /create_scan/ with the APK file and metadata, then poll the Scan model's status and progress fields or query the finished_on timestamp to determine when Finding records are available for retrieval via the ORM or REST interface.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →