An open API service indexing awesome lists of open source software.

https://github.com/vicnesterenko/mac-malware-analysis

App for static macOS malware analysis
https://github.com/vicnesterenko/mac-malware-analysis

fastapi malware-analysis

Last synced: 1 day ago
JSON representation

App for static macOS malware analysis

Awesome Lists containing this project

README

          

# Mac Malware Analysis

A lightweight FastAPI web application for safe, static analysis of suspicious macOS-related files.
Upload a file through the browser or REST API and receive a structured analysis report — no execution, no shell commands, no dynamic behavior.

---

## Why this project exists

macOS malware triage usually requires a mix of CLI tools, proprietary sandboxes, and manual pattern matching.
This project provides a focused, portable, self-hosted triage tool that covers the most common static signals:
hashes, string extraction, persistence indicators, YARA scanning, and an explainable risk score.
It is designed as a learning and portfolio project for junior malware analysts and security engineers.

---

## Main features

| Feature | Details |
|---------|---------|
| File upload | Drag-and-drop web UI or REST API |
| Hashing | MD5, SHA-1, SHA-256 |
| File-type detection | libmagic + header fallback |
| String extraction | Printable ASCII and UTF-16LE |
| Indicator extraction | URLs, domains, IPs, emails, macOS paths |
| Suspicious commands | curl, wget, osascript, security, base64, chmod +x, shell -c |
| Persistence detection | LaunchAgent, LaunchDaemon, launchctl, cron, shell profiles |
| YARA scanning | Three built-in educational rules; gracefully skipped if yara-python is missing |
| Risk scoring | Transparent, reason-per-factor, 0–100 heuristic scale |
| JSON report | Downloadable, stored in `reports/` |
| HTML result page | Colour-coded by risk level |

---

## Safety guarantees

- Uploaded files are **never executed**, imported, or unpacked.
- No `subprocess` calls on uploaded content.
- Filenames are sanitized; a random UUID is used for temporary storage.
- Temporary files are deleted in a `finally` block immediately after analysis.
- Only the generated JSON report is stored.
- Report downloads are protected against path-traversal attacks.
- File contents are never logged.

---

## Architecture

```
app/
main.py FastAPI application, middleware, exception handlers
config.py Settings loaded from environment / .env
models.py Pydantic response models
helpers.py Logging configuration
routes/
web.py HTML routes: GET /, POST /analyze
analysis.py API routes: POST /api/analyze, GET /api/reports/{id}
services/
analyzer.py Orchestrates all analysis steps
file_validation.py Size and filename validation
hashing.py MD5 / SHA-1 / SHA-256
file_type.py libmagic + header detection
string_extractor.py ASCII and UTF-16LE extraction
indicators.py URL, IP, email, path, command patterns
persistence.py LaunchAgent / LaunchDaemon / cron patterns
yara_scanner.py YARA scanning with graceful fallback
risk_engine.py Heuristic scoring with per-reason breakdown
report_service.py JSON report save / load
templates/ Jinja2 HTML templates
static/ CSS stylesheet
rules/ YARA rules (three educational rules)
safe_samples/ Harmless demonstration files
reports/ Generated JSON reports (gitignored except .gitkeep)
tests/ pytest test suite
```

---

## Local installation on macOS

```bash
# 1. Install libmagic
brew install libmagic

# 2. Clone the repository
git clone https://github.com/your-username/mac-malware-analysis.git
cd mac-malware-analysis

# 3. Create virtual environment
python3 -m venv .venv
source .venv/bin/activate

# 4. Install dependencies
pip install -r requirements.txt

# 5. Run the server
uvicorn app.main:app --reload
```

Open http://localhost:8000 in your browser.

---

## Local installation on Linux

```bash
# Install system dependencies
sudo apt-get install -y libmagic1

# Then follow the macOS steps from step 2 above
```

---

## Running with Docker

```bash
# Build and start
docker compose up --build

# Stop
docker compose down
```

The application will be available at http://localhost:8000.
Reports are stored in `./reports/` on your host machine via a volume mount.

---

## Web usage

1. Open http://localhost:8000
2. Drag and drop a file or click to browse.
3. Click **Analyze File**.
4. Review the colour-coded result page.
5. Click **Download JSON Report** to save the full report.

---

## API usage

### Analyze a file

```bash
curl -X POST \
-F "file=@safe_samples/suspicious_demo.sh" \
http://localhost:8000/api/analyze
```

### Download a report

```bash
curl http://localhost:8000/api/reports/ \
-o report.json
```

### Health check

```bash
curl http://localhost:8000/healthcheck
```

Interactive API docs: http://localhost:8000/docs

---

## Example JSON response

```json
{
"report_id": "a3b4c5d6e7f8...",
"filename": "suspicious_demo.sh",
"size_bytes": 321,
"file_type": {
"description": "POSIX shell script, ASCII text executable",
"mime_type": "text/x-shellscript"
},
"hashes": {
"md5": "...",
"sha1": "...",
"sha256": "..."
},
"indicators": {
"urls": ["https://update.example.invalid/payload"],
"domains": ["update.example.invalid"],
"ipv4_addresses": [],
"emails": [],
"file_paths": ["/Library/LaunchAgents/com.example.demo.plist"],
"suspicious_commands": ["chmod_executable", "curl", "security_password_access", "shell_execute"]
},
"persistence": {
"detected": true,
"findings": [
{
"technique": "user_launch_agent",
"evidence": ["$HOME/Library/LaunchAgents/"],
"confidence": "medium"
}
]
},
"yara": {
"enabled": true,
"available": true,
"matches": [
{
"rule": "MacOS_Persistence_References",
"meta": { "severity": "high", "description": "..." },
"tags": []
}
],
"errors": []
},
"risk": {
"score": 100,
"level": "high",
"reasons": [
{ "code": "yara:MacOS_Persistence_References", "points": 30, "description": "High-severity YARA rule matched." },
{ "code": "macos_persistence", "points": 20, "description": "Reference to a LaunchAgent or LaunchDaemon path." },
{ "code": "credential_access", "points": 20, "description": "macOS Keychain access command detected." },
{ "code": "download_execute", "points": 20, "description": "Download and execution commands appear together." },
{ "code": "network_indicators", "points": 2, "description": "Suspicious URLs extracted from the file." }
],
"disclaimer": "This heuristic score does not prove that a file is malicious."
}
}
```

---

## Running tests

```bash
# Activate virtual environment first
source .venv/bin/activate

# Run all tests
pytest -v

# Run with coverage
pytest --cov=app --cov-report=term-missing
```

---

## YARA installation notes

`yara-python` requires the YARA C library.

**macOS:**
```bash
brew install yara
pip install yara-python
```

**Linux:**
```bash
sudo apt-get install -y libyara-dev
pip install yara-python
```

**Docker:** The Dockerfile installs `libmagic1` but not the YARA C library, because `yara-python`'s binary wheel often bundles it.
If YARA scanning is unavailable, the analysis still completes and `yara.available` will be `false` in the response.

---

## Known limitations

- Static analysis only: runtime behavior is not observed.
- Mach-O parsing is limited to header-based type detection (no `otool` or `nm` wrapping).
- YARA rules are educational and not a comprehensive signature set.
- ZIP, DMG, PKG, and application bundles are not unpacked.
- No authentication: suitable for local or internal network use only.
- Maximum upload size is 20 MB.

---

## False-positive considerations

Static indicators frequently match legitimate software:

- Developer tools reference `LaunchAgents` paths.
- Updater scripts use `curl` and `chmod +x`.
- Backup software accesses the Keychain.
- High entropy appears in compiled binaries and compressed assets.

Always interpret the risk score alongside context. It is a triage signal, not a verdict.

---

## Ethical-use notice

This tool is designed for defensive security research, malware triage, and education.

- Do not upload files belonging to others without authorization.
- Do not use this tool to analyze files obtained illegally.
- The author accepts no liability for misuse.

---

## Running from any directory

Template, static, report, temporary upload, and YARA paths are resolved from the
project location rather than the shell's current working directory.

The recommended command is:

```bash
cd mac-malware-analysis
uvicorn app.main:app --reload
```

Running `python app/main.py` is also supported.