Hệ thống phát hiện mã độc lai đa phương thức: kết hợp phân tích tĩnh (mã máy → ảnh xám → CNN; và đặc trưng PE-header → XGBoost) với phân tích động (chuỗi API call → BiLSTM), điều phối qua tầng ensemble multi-stage.
Mục tiêu KPI: tối ưu F1-Score, ràng buộc FPR < 0.1% (không chặn nhầm file sạch).
Ý tưởng cốt lõi: chạy tầng tĩnh nhanh trước; chỉ những ca mập mờ mới đẩy sang tầng động chậm nhưng sâu → cân bằng tốc độ và độ chính xác.
┌──────────────────────────────────────────────┐
file PE (.exe/.dll) │ FastAPI Orchestrator │
───────────────────► │ POST /scan → điều phối luồng multi-stage │
└───────────────────┬──────────────────────────┘
│
┌──────────────────────────────────▼─────────────────────────────┐
STAGE 1 (TĨNH, ~ms) │
┌─────────────────────────┐ ┌──────────────────────────────────┐ │
│ Cấu phần 1: Image/CNN │ │ Cấu phần PE-tabular: XGBoost │ │
│ binary→ảnh xám→MobileNet │ │ 77 đặc trưng PE-header │ │
│ → ĐỊNH DANH HỌ + conf │ │ → P(malicious) (có benign, đo FPR)│ │
└─────────────────────────┘ └──────────────┬───────────────────┘ │
│ │
prob ∈ [0.4, 0.6]? │ (vùng mập mờ) │
┌──────────────┴───────────────┐ │
KHÔNG│ │CÓ │
▼ ▼ │
Kết luận ngay STAGE 2 (ĐỘNG, ~giây) │
Cấu phần 2: BiLSTM │
chuỗi API call → prob │
│ │
▼ │
Cấu phần 3: Meta-classifier │
(LogReg/XGBoost) → verdict cuối │
+ ngưỡng calibrate theo FPR │
└──────────────────────────────────────────────────────────────────┘
| Cấu phần | Vai trò | Mô hình | Kết quả test |
|---|---|---|---|
| 1. Image/CNN | Định danh 25 họ mã độc | MobileNetV3-Small (timm) | acc 98.56% (không rò rỉ) |
| PE-tabular | Nhị phân malware/benign + đo FPR | XGBoost (regularized) | AUC 0.996, F1 0.994 |
| 2. Dynamic/Sequence | Phân tích hành vi tuần tự | BiLSTM | F1 0.998 (synthetic) |
| 3. Ensemble | Điều phối + quyết định cuối | Orchestrator + Meta-classifier | multi-stage |
| API | Phục vụ HTTP | FastAPI /scan /health |
— |
| Dataset | Kích thước | Mô tả | Dùng cho |
|---|---|---|---|
| MalImg | 9,339 ảnh / 25 họ | Ảnh xám của file nhị phân mã độc (Kaggle) | Cấu phần 1 (CNN) |
| PE-header CSV | 19,611 mẫu (14,599 malware / 5,012 benign) | 77 đặc trưng cấu trúc PE (dataset_malwares.csv) |
PE-tabular (XGBoost) |
| API sequences | 3,000 chuỗi (1,500 / 1,500) | Chuỗi API call giả lập có cấu trúc (synth.py) |
Cấu phần 2 (BiLSTM) |
| Benign PE | 202 PE sạch thật | Trích từ wheel Windows (.pyd/.dll) bằng extract_pe |
Mở rộng dataset nhất quán |
Chi tiết:
- Malware-as-Image (Nataraj et al.): đọc byte file → mảng
uint8(0–255) → xếp thành ma trận 2D (bề rộng suy theo kích thước file) → ảnh xám → resize 224×224. - PE-header: các trường DOS/FILE/OPTIONAL header + đặc trưng section/import dẫn xuất
(entropy, suspicious imports, data directories…).
⚠️ Dataset gốc có cột hỏngSectionMaxEntropy= 0 ở 100% dòng — đã phát hiện và khắc phục bằng bộ trích nhất quán. - API sequences (synthetic): chuỗi benign thiên về API "lành"; chuỗi malware nhúng các
motif độc hại theo thứ tự thời gian — vd code injection
OpenProcess→VirtualAllocEx→WriteProcessMemory→CreateRemoteThread, ransomwareCryptEncrypt-loop, C2InternetOpen→HttpSendRequest→WinExec— xen nhiễu để buộc mô hình học ngữ cảnh tuần tự, không tách tầm thường.
Dữ liệu thô (
data/) và model (checkpoints/) không đưa lên git (xem.gitignore). Cách lấy:bash scripts/download_data.sh(MalImg qua Kaggle); CSV PE-header tự đặt vàodata/.
- Backbone: MobileNetV3-Small (pretrained ImageNet, qua
timm) — nhẹ, chạy tốt trên CPU/Apple M1 (MPS). - 2 đầu (multi-head): đầu đa lớp (25 họ) + đầu nhị phân chia sẻ backbone.
- Ảnh xám lặp 3 kênh + chuẩn hóa ImageNet; train AdamW + cosine schedule + early-stopping.
- Lưu ý: MalImg toàn malware → đầu nhị phân suy biến; CNN dùng để định danh họ, còn quyết định malware/benign do tầng PE-tabular đảm nhiệm.
- 77 đặc trưng PE-header → XGBoost với regularization (
max_depth=4,min_child_weight=5,gamma=1,reg_lambda=2,reg_alpha=0.5) + early-stopping. - Calibrate ngưỡng theo ràng buộc FPR (chọn ngưỡng nhỏ nhất thỏa
FPR ≤ targettrên val).
- Pipeline: parse báo cáo Cuckoo/CAPE JSON (hoặc CSV chuỗi) → tokenizer (top-K API +
<pad>,<unk>) → Embedding → BiLSTM → masked mean-pooling → MLP nhị phân. - Hỗ trợ
bilstm | lstm | gru | bigru. Baseline đối chứng: TF-IDF + LogReg.
- Orchestrator multi-stage: chạy tầng tĩnh; nếu
prob ∈ [0.4, 0.6]→ đánh dấuneeds_dynamic, chạy Stage 2 (động) khi có log hành vi. - Meta-classifier (LogReg/XGBoost): gộp
[prob_tabular, prob_image, confidence, …]→ quyết định cuối, ngưỡng calibrate theo FPR. (Cần dữ liệu joint để học; mặc định dùng luật hợp nhất vì 2 tầng tĩnh train trên 2 dataset rời.)
| Mô hình | Chỉ số | Giá trị |
|---|---|---|
| CNN (đa lớp, group-split không rò rỉ) | Test accuracy | 98.56% |
| CNN (đa lớp, random-split) | Test accuracy | 99.29% (thổi phồng do rò rỉ) |
| PE-tabular XGBoost | Test AUC | 0.9964 |
| PE-tabular XGBoost @0.5 | F1 / Recall / FPR | 0.994 / 0.999 / 3.06% |
| Dynamic BiLSTM (synthetic) | Test F1 / Recall / FPR | 0.998 / 0.996 / 0% |
Mô phỏng multi-stage (2,942 file): 99.9% quyết ngay ở Stage 1, chỉ 0.1% phải escalate; độ trễ TB 0.09s/file thay vì ~30s nếu chạy động tất cả (nhanh ~330×). Stage 1 đúng 99.4% ở ca chắc chắn nhưng chỉ 75% ở ca mập mờ → escalate là hợp lý.
Tạo lại: OMP_NUM_THREADS=1 python -m scripts.visualize và ... -m scripts.simulate_pipeline.
| ROC (AUC 0.996) | Đánh đổi FPR ↔ Recall |
|---|---|
![]() |
![]() |
| Confusion matrix | Top-15 đặc trưng quan trọng |
|---|---|
![]() |
![]() |
| Accuracy theo họ | Confusion 25×25 |
|---|---|
![]() |
![]() |
| Confusion | Phân bố xác suất |
|---|---|
![]() |
![]() |
| Định tuyến (hầu hết quyết ngay) | Vì sao escalate ca mập mờ | Đánh đổi độ rộng vùng ↔ độ trễ |
|---|---|---|
![]() |
![]() |
![]() |
| Chẩn đoán overfitting (train/val/test) | Trước/Sau khi xử lý | FPR + khoảng tin cậy (CV) |
|---|---|---|
![]() |
![]() |
![]() |
- Overfitting (XGBoost): thêm regularization + early-stopping → khoảng cách train–test
FPR thu hẹp từ ~80× xuống ~2× (train FPR 0.03%→1.54%).
scripts/measure_fpr.py. - Rò rỉ dữ liệu (MalImg): trùng lặp ảnh gần-trùng tới 25.6% (Yuner.A: 800 ảnh / 1
nhóm dHash). Khắc phục: group-split theo dHash (
src/static_image/dedup.py) → accuracy trung thực 98.56% (thay vì 99.29% bị thổi phồng). - Đo FPR<0.1% tin cậy: dùng 5-fold cross-validation out-of-fold trên toàn bộ 5,012 benign + khoảng tin cậy Clopper–Pearson. Kết luận: 5,012 benign đủ để đo (≥3,000 theo quy tắc số 3); chứng nhận được FPR<0.1% (CI [0%, 0.074%]) nhưng chỉ ở recall≈0 → trần do nhóm benign "khó" (installer/PUP), đúng lý do cần multi-stage.
python3 -m venv .venv && source .venv/bin/activate
pip install torch torchvision # bản chính thức hỗ trợ MPS (Metal) trên M1
pip install -r requirements.txtCode tự chọn device: cuda > mps (Apple Silicon) > cpu.
bash scripts/download_data.sh malimg # tải MalImg (Kaggle)
OMP_NUM_THREADS=1 python -m src.static_image.train --config configs/static_groupsplit.yaml # CNN (chống rò rỉ)
OMP_NUM_THREADS=1 python -m src.static_tabular.train --config configs/static_tabular.yaml # PE-tabular
python -m src.dynamic_seq.synth --out data/processed/reports/sequences.csv # sinh dữ liệu động
OMP_NUM_THREADS=1 python -m src.dynamic_seq.train --config configs/dynamic.yaml # BiLSTM# macOS: OMP_NUM_THREADS=1 tránh deadlock OpenMP của torch ở forward CPU đầu tiên.
OMP_NUM_THREADS=1 .venv/bin/uvicorn api.main:app --host 127.0.0.1 --port 8077
curl http://127.0.0.1:8077/health
# Quét bằng đặc trưng PE-header; multi-modal: thêm -F "file=@file.exe"; log động: -F "behavior=API1 API2 ..."Đầu ra /scan: prob_malicious, verdict, family, confidence, needs_dynamic, stages_run.
PYTHONPATH=. pytest -q # 15 test (metrics, binary_to_image, orchestrator, dynamic_seq) — không cần GPUDataset gốc có cột hỏng + không nối thêm file ngoài được (mismatch định nghĩa đặc trưng). Cách đúng: dựng lại từ PE thô bằng một bộ trích nhất quán:
# 1) Benign sạch — tự động từ wheel Windows (an toàn, không chạy gì):
python -m scripts.collect_benign --packages numpy scipy pillow pandas lxml --out data/processed/benign_pe.csv
# 2) Malware — tải từ MalwareBazaar (cần Auth-Key miễn phí: https://auth.abuse.ch):
export MALWAREBAZAAR_AUTH_KEY=...
python -m scripts.download_malwarebazaar --file-types exe dll --limit 200 --out data/raw/malware_samples
# 3) Gộp → dataset nhất quán (chỉ ĐỌC header, không chạy mẫu):
python -m scripts.build_dataset --benign-csv data/processed/benign_pe.csv \
--malware-dir data/raw/malware_samples --out data/processed/pe_dataset.csv
# 4) Train:
OMP_NUM_THREADS=1 python -m src.static_tabular.train --config configs/scratch_tabular.yamlcyber_secur/
├── configs/ # YAML cấu hình từng cấu phần
├── src/
│ ├── common/ # metrics (F1/FPR/Clopper-Pearson), utils (device, seed)
│ ├── static_image/ # Cấu phần 1: binary→ảnh, dataset, model, train/infer, dedup
│ ├── static_tabular/ # PE-tabular: dataset, model, train/infer, extract_pe
│ ├── dynamic_seq/ # Cấu phần 2: synth, parser, tokenizer, model, train/infer
│ └── ensemble/ # Cấu phần 3: orchestrator, meta_classifier
├── api/ # FastAPI (/scan, /health)
├── scripts/ # download_data, collect_benign, build_dataset,
│ # download_malwarebazaar, visualize, simulate_pipeline, measure_fpr
├── tests/ # 15 unit test (không cần GPU)
└── reports/figures/ # 14 biểu đồ trực quan
- Cấu phần động đang chạy trên dữ liệu giả lập → cần log hành vi thật (Cuckoo/CAPE, CIC-AndMal2020, hoặc dataset Catak "API Call Sequences") để đánh giá khả năng tổng quát.
- Meta-classifier cần tập có nhãn joint (cùng 1 file qua nhiều cấu phần) để học gộp.
- FPR<0.1% ở recall cao chưa đạt — cần đặc trưng phân biệt installer hợp pháp tốt hơn, hoặc dựa hẳn vào tầng động cho nhóm mập mờ.
- Dữ liệu lớn hơn & đa dạng hơn (nhất là benign) để tăng độ bền.













