# How MobileAudit's Pattern Engine Detects Vulnerabilities and Malicious Code in Decompiled APKs

> Discover how MobileAudit's pattern engine effectively detects vulnerabilities and malicious code in decompiled APKs by applying custom regex to source code. Improve your security analysis.

- Repository: [Mónica Pastor/mobileaudit](https://github.com/mpast/mobileaudit)
- Tags: deep-dive
- Published: 2026-03-07

---

**MobileAudit's pattern engine detects vulnerabilities by decompiling APKs with jadx, traversing the resulting source tree, and applying user-defined regular expressions to identify hardcoded secrets, malicious URLs, IPs, and other security indicators.**

MobileAudit is an open-source mobile application security scanner that automates the detection of vulnerabilities and malicious code in Android APKs. At the heart of the `mpast/mobileaudit` repository lies a regex-based pattern engine that systematically analyzes decompiled source code to surface security findings. This article examines the architectural flow, core implementation details, and practical usage of MobileAudit's detection engine.

## Architectural Overview of the Detection Pipeline

The pattern engine operates as a sequential pipeline that transforms raw APK binaries into structured security findings. The process begins when a user uploads an APK through the web interface or API, triggering an asynchronous Celery task. The system then decompiles the application, walks the resulting directory tree, and executes regex patterns against every relevant source file. Each match generates a `Finding` object enriched with contextual metadata such as line numbers, code snippets, and malware associations.

## Step-by-Step Detection Process

### APK Decompilation with JADX

The analysis begins in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py) where the `analyze_apk` function (lines 44-96) orchestrates the scan. First, it invokes `decompile_jadx` (lines 18-22) to execute the `jadx` command-line tool:

```bash
jadx -d <DECOMPILE_PATH> <APK_FILE>

```

This command decompiles the Dalvik bytecode into human-readable Java and Kotlin source files, alongside XML resource files, creating a navigable source tree for pattern matching.

### File Tree Traversal

Once decompilation completes, `get_tree_dir` (lines 22-38 in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py)) walks the directory structure using `os.walk`. The function filters for files with extensions `.java`, `.kt`, or `.xml`, reads each file's complete content into memory, and passes the data to the pattern matching engine:

```python
for dirpath, dirs, files in os.walk(dir):
    for filename in files:
        fname = os.path.join(dirpath, filename)
        extension = os.path.splitext(fname)[1]
        if extension in ('.java', '.kt', '.xml'):
            f = open(fname, mode="r", encoding="utf-8")
            content = f.read()
            f.close()
            find_patterns(1, '', content, fname, dir, scan)

```

### Pattern Loading and Compilation

The `find_patterns` function queries the database for active detection rules via `Pattern.objects.filter(active=True)`. Each `Pattern` object (defined in [`app/models.py`](https://github.com/mpast/mobileaudit/blob/main/app/models.py), lines 100-113) contains a regular expression string, default severity, CWE mapping, and human-readable metadata:

```python
class Pattern(models.Model):
    id = models.AutoField(primary_key=True)
    default_cwe = models.ForeignKey(Cwe, on_delete=models.CASCADE)
    default_risk = models.ForeignKey(Risk, on_delete=models.CASCADE, null=True)
    default_name = models.TextField()
    default_description = models.TextField(blank=True)
    default_severity = models.CharField(max_length=10, choices=Severity.choices)
    default_mitigation = models.TextField(blank=True)
    pattern = models.TextField()           # ← the regex string

    active = models.BooleanField(default=True)

```

### Regex Matching and Context Extraction

For each active pattern, the engine compiles the regex with `re.MULTILINE` support and iterates through all matches in the file content (lines 73-80 in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py)):

```python
for p in patterns:
    pattern = re.compile(p.pattern, re.MULTILINE)
    for match in pattern.finditer(line):
        # Process match...

```

The system calculates precise line numbers and extracts code snippets using `get_position` (lines 71-77) and `get_match_lines` (lines 53-71), ensuring findings include actionable context for developers.

### Type Classification and Malware Lookup

MobileAudit's engine applies special handling based on pattern IDs to enrich findings with security intelligence (lines 82-88 and 90-103):

- **Pattern ID 8**: IP addresses
- **Pattern ID 9**: URLs (checked against the `Malware` database table)
- **Pattern ID 10**: Email addresses
- **Pattern ID 21**: Hexadecimal strings
- **Pattern ID 22**: Base64 encoded data

For URL patterns, the engine parses the domain and queries the `Malware` model to identify known malicious infrastructure:

```python
if p.id == 9:                     # URL pattern

    type = 'URL'
    url = urllib.parse.urlsplit(match.group())
    try:
        m = Malware.objects.get(url__icontains=url.netloc)
    except Malware.DoesNotExist:
        m = None

```

### Finding Persistence

Each match creates a `Finding` record (lines 24-41) storing metadata including severity, CWE classification, risk level, and the matched line content. The system also creates associated `String` objects to store extracted values and `Domain` objects for URL findings linked to malware entries (lines 44-53):

```python
finding = Finding(
    scan=scan,
    path=name.replace(dir, ""),
    line_number=position,
    line=match.group(),
    snippet=snippet,
    status=Status.TD,
    type=p,
    name=p.default_name,
    description=p.default_description,
    severity=p.default_severity,
    cwe=p.default_cwe,
    risk=p.default_risk,
    user=scan.user,
)
finding.save()
String.objects.create(type=type, value=match.group(), scan=scan, finding=finding)

```

## Adding Custom Detection Patterns

Security teams can extend MobileAudit's detection capabilities by creating new `Pattern` objects via the Django admin interface or programmatically. The following example demonstrates adding a regex to detect hardcoded AWS secret access keys:

```python
from app.models import Pattern, Cwe, Risk, Severity

# Retrieve or create supporting metadata

cwe = Cwe.objects.get_or_create(cwe=326)[0]          # CWE-326: Inadequate Encryption Strength

risk = Risk.objects.get_or_create(risk=3)[0]        # Risk rating scale

# Create the detection pattern

Pattern.objects.create(
    default_cwe=cwe,
    default_risk=risk,
    default_name="AWS Secret Access Key",
    default_description="Hard-coded AWS secret access key found in source code.",
    default_severity=Severity.HI,
    pattern=r'AKIA[0-9A-Z]{16}',
    active=True,
)

```

Once persisted to the database, the pattern engine automatically includes this regex in subsequent scans without requiring application restarts.

## Key Source Files and Their Roles

| File | Role |
|------|------|
| **[`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py)** | Core engine implementing decompilation (`decompile_jadx`), directory traversal (`get_tree_dir`), pattern matching (`find_patterns`), and finding persistence. |
| **[`app/models.py`](https://github.com/mpast/mobileaudit/blob/main/app/models.py)** | Database schema defining `Pattern` (regex rules), `Finding` (scan results), `String` (extracted values), `Domain` (URL metadata), and `Malware` (threat intelligence). |
| **[`app/worker/tasks.py`](https://github.com/mpast/mobileaudit/blob/main/app/worker/tasks.py)** | Celery task definitions that orchestrate asynchronous scan execution via `scan_task`. |
| **[`app/views.py`](https://github.com/mpast/mobileaudit/blob/main/app/views.py)** | Web interface endpoints for pattern management and finding visualization. |

## Summary

- MobileAudit's pattern engine leverages **jadx** to decompile APKs into readable Java, Kotlin, and XML source code.
- The engine traverses the decompiled tree and applies **user-defined regular expressions** loaded dynamically from the database via the `Pattern` model.
- Special pattern IDs trigger contextual analysis, including **malware database lookups** for URLs and classification of IPs, emails, base64, and hex strings.
- Each match generates a `Finding` record with precise line numbers, code snippets, severity ratings, and CWE mappings for actionable remediation.
- Security teams can extend detection capabilities by adding new regex patterns without modifying core engine code.

## Frequently Asked Questions

### How does MobileAudit decompile APK files for analysis?

MobileAudit utilizes the **jadx** decompiler to convert Android APK bytecode into human-readable source code. When a scan initiates, the `decompile_jadx` function in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py) (lines 18-22) executes the command `jadx -d <DECOMPILE_PATH> <APK_FILE>`, producing Java, Kotlin, and XML files that the pattern engine subsequently analyzes.

### What types of security patterns can the engine detect?

The engine detects vulnerabilities through customizable regular expressions stored in the `Pattern` model. Built-in pattern types include hardcoded **IP addresses** (ID 8), **URLs** (ID 9) with malware intelligence integration, **email addresses** (ID 10), **hexadecimal strings** (ID 21), and **base64 encoded data** (ID 22). Users can add patterns for secrets, cryptographic keys, or proprietary business logic exposure.

### How does MobileAudit handle URL detection and malware verification?

When the pattern engine identifies a URL using pattern ID 9, it parses the domain using `urllib.parse.urlsplit` and queries the `Malware` database table to check for known malicious infrastructure. If a match exists, the engine creates a `Domain` object linking the finding to the malware record, enriching the security report with threat intelligence context. This implementation appears in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py) lines 82-88 and 90-103.

### Can security teams add custom vulnerability patterns without modifying source code?

Yes, security teams can extend detection capabilities by creating new `Pattern` objects through the Django admin interface or programmatically via the ORM. Each pattern requires a regular expression string, severity rating, CWE mapping, and metadata description. Once saved to the database with `active=True`, the engine automatically includes the new pattern in subsequent scans without requiring application restarts or code modifications, as demonstrated in the `find_patterns` function in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py).