# How MobileAudit Checks for Malware Domains Using MalwareDB and Maltrail Databases

> Learn how MobileAudit identifies malware domains by checking APK extracted URLs against MalwareDB and Maltrail databases for enhanced security.

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

---

**MobileAudit detects malicious URLs during APK analysis by cross-referencing extracted domains against a locally stored `Malware` table populated from MalwareDB and Maltrail feeds.**

MobileAudit is an open-source Android security analysis platform maintained in the `mpast/mobileaudit` repository. When scanning APK files, the tool automatically extracts URLs embedded in code and checks them against known malicious domain databases. This malware domain verification operates entirely offline after initial data import, ensuring fast analysis without external API latency.

## How the Malware Domain Detection Works

The malware domain check follows a four-stage pipeline: **feature flag validation**, **URL pattern extraction**, **substring database lookup**, and **finding correlation**. This architecture enables MobileAudit to flag suspicious domains discovered during static analysis without requiring internet connectivity during the scan itself.

The process relies on Django ORM queries against a pre-populated `Malware` model, using case-insensitive substring matching to identify domains listed in the Malware Domain List and Maltrail threat feeds.

## Step-by-Step Domain Verification Process

### Enabling the Feature Flag

Malware domain checking is controlled by the `MALWARE_ENABLED` setting in [`app/config/settings.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/settings.py). By default, this feature is active:

```python

# app/config/settings.py

MALWARE_ENABLED = env('MALWARE_ENABLED', True)   # toggle via env var

```

When this setting is `False`, MobileAudit skips all malware database queries during analysis, improving performance for scans where domain reputation checks are unnecessary.

### URL Extraction from APKs

During static analysis in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py), MobileAudit identifies URL patterns using pattern ID `9`. When the scanner encounters a match, it parses the string using Python's `urllib.parse` module to isolate the domain:

```python

# app/analysis.py – find_patterns()

if p.id == 9:                     # URL pattern

    type = 'URL'
    url = urllib.parse.urlsplit(match_str)

```

The `urlsplit` operation returns a `SplitResult` object where `url.netloc` contains the extracted domain (e.g., `example.com`).

### Database Lookup Logic

If malware checking is enabled, MobileAudit queries the local `Malware` table using a case-insensitive substring search against the domain:

```python

# app/analysis.py (excerpt)

if settings.MALWARE_ENABLED:
    # look for a Malware record whose URL field contains the domain part of the match

    m = Malware.objects.get(url__icontains=url.netloc)

```

The `url__icontains` lookup performs a case-insensitive SQL `LIKE` query, matching if the domain appears anywhere within the stored malware URL entries. This catches both exact matches and subdomains listed in the threat feeds.

### Storing Results with Domain Associations

After lookup, MobileAudit creates a `Domain` object linked to the current scan. If malware was detected, the code attaches the matching `Malware` record via foreign key:

```python

# app/analysis.py – after creating a Finding

if type == 'URL':
    if m:   # malicious domain was found

        u = Domain(scan=scan, domain=url.netloc,
                   finding=finding, malware=m)
    else:
        u = Domain(scan=scan, domain=url.netloc,
                   finding=finding)
    u.save()

```

The `Domain` model includes a `malware` foreign key that references the specific threat intelligence entry, allowing the UI to display detailed context about why the domain was flagged.

## Data Sources and Feed Configuration

The `Malware` table is populated from two public threat intelligence feeds defined in [`app/config/settings.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/settings.py):

- **MalwareDB**: `https://www.malwaredomainlist.com/mdlcsv.php` (CSV format containing known malicious domains)
- **Maltrail**: `https://raw.githubusercontent.com/stamparm/aux/master/maltrail-malware-domains.txt` (plain-text list of suspicious domains)

A separate import routine (external to the analysis flow) downloads these files periodically and creates `Malware` objects storing the URL, description, IP address, and discovery date. Once imported, the analysis engine performs fast local lookups without hitting remote services for every APK scan.

## Code Implementation Details

### Malware Model Structure

The `Malware` model in [`app/models.py`](https://github.com/mpast/mobileaudit/blob/main/app/models.py) stores entries from both feeds with the following schema:

```python

# app/models.py

class Malware(models.Model):
    date = models.CharField(max_length=255, null=True)
    url = models.TextField(blank=True, null=True)
    ip = models.TextField(blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    # … other metadata fields …

```

### Malware Database Browser

The `/malware/` endpoint in [`app/views.py`](https://github.com/mpast/mobileaudit/blob/main/app/views.py) renders all stored malware entries, allowing users to browse the threat intelligence database that powers the domain checks:

```python

# app/views.py

def malware(request):
    malwares = Malware.objects.all()
    return render(request, 'malware.html', {'malwares': malwares})

```

## Summary

- **Feature toggle**: Malware domain checking is controlled by `settings.MALWARE_ENABLED` and defaults to `True`.
- **Pattern matching**: URLs are identified using pattern ID `9` and parsed with `urllib.parse.urlsplit()` to extract domains.
- **Database query**: Domains are checked against the `Malware` table using `url__icontains` for case-insensitive substring matching.
- **Data sources**: The local database is populated from MalwareDB and Maltrail URLs defined in [`app/config/settings.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/settings.py).
- **Result storage**: Detected domains are saved as `Domain` objects with optional foreign key links to matching `Malware` records.
- **Offline operation**: After initial import, all malware checks run locally in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py) without external API calls.

## Frequently Asked Questions

### How does MobileAudit determine if a URL is malicious?

MobileAudit extracts the domain from URLs found in APK code using `urllib.parse.urlsplit()`, then queries the local `Malware` database with a case-insensitive substring search (`url__icontains`). If the domain appears in the pre-loaded MalwareDB or Maltrail feeds, the URL is flagged as malicious.

### What databases does MobileAudit use for malware domain detection?

MobileAudit leverages two public threat intelligence feeds: the Malware Domain List (MalwareDB) and the Maltrail project. These are configured via `MALWAREDB_URL` and `MALTRAILDB_URL` in [`app/config/settings.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/settings.py), and their data is imported into the local Django database for offline querying.

### Can I disable malware domain checking in MobileAudit?

Yes. Set the environment variable `MALWARE_ENABLED=False` or modify [`app/config/settings.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/settings.py) to disable the feature. When disabled, MobileAudit skips the `Malware.objects.get()` query in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py), improving scan performance while omitting domain reputation checks.

### Where does MobileAudit store the malware domain data?

The malware data is stored in the `Malware` Django model defined in [`app/models.py`](https://github.com/mpast/mobileaudit/blob/main/app/models.py), which includes fields for URL, IP address, description, and discovery date. This table is queried during analysis in [`app/analysis.py`](https://github.com/mpast/mobileaudit/blob/main/app/analysis.py) and browsable via the `/malware/` view in [`app/views.py`](https://github.com/mpast/mobileaudit/blob/main/app/views.py).