| name | adversarial-ml-evasion |
| description | Craft adversarial examples that cause trained ML classifiers to misclassify at inference time — image recognition, malware detectors, IDS, spam filters. |
| allowed-tools | Bash Read Write |
| metadata | {"subdomain":"ai-security","when_to_use":"adversarial example evasion classifier bypass ml model fool misclassify image recognition malware detector IDS antivirus neural network perturbation FGSM PGD","tags":"adversarial-ml, evasion, classifier-bypass, computer-vision, malware-evasion, ids-evasion","mitre_attack":"T1562.001, T1036, T1027"} |
Adversarial ML Evasion
Adversarial examples are inputs modified with small, deliberate perturbations that reliably
cause a trained classifier to produce incorrect predictions. The perturbation is typically
imperceptible to humans or functionally irrelevant, while the model's decision boundary is
crossed. This is distinct from LLM jailbreaks: the target is a trained discriminative model
(CNN, gradient-boosted tree, SVM, LSTM) served via an API or embedded in a product.
Authorized use only. All testing must be conducted against systems you own or have
explicit written permission to assess. Generating adversarial inputs against production
ML APIs without authorization may violate the CFAA and equivalent statutes.
ATT&CK Mapping
| Technique | Use |
|---|
| T1562.001 — Impair Defenses: Disable or Modify Tools | Evade ML-based AV/EDR/IDS |
| T1036 — Masquerading | Make malicious content look benign to a classifier |
| T1027 — Obfuscated Files or Information | Perturb a file/image to fool static ML analysis |
1. Reconnaissance — understand the target model
Before crafting perturbations, determine the attack surface:
curl -s -X POST "$TARGET/predict" \
-H "Content-Type: application/json" \
-d '{"data": [[0.0]*784]}' | jq .
2. White-box evasion (full model access)
Use when you have the model weights (pentest scope, internal system, open-source model).
2a. FGSM — Fast Gradient Sign Method (single step)
import torch, torchvision.transforms as T
from PIL import Image
import requests, json
def fgsm(model, x, y_true, epsilon=0.03):
"""Single-step gradient attack. Fast, low distortion for strong models."""
x.requires_grad_(True)
loss = torch.nn.CrossEntropyLoss()(model(x), y_true)
loss.backward()
return (x + epsilon * x.grad.sign()).clamp(0, 1).detach()
2b. PGD — Projected Gradient Descent (iterative, stronger)
def pgd(model, x, y_true, epsilon=0.03, alpha=0.007, steps=40):
"""Madry's PGD — iterative FGSM with projection back into epsilon-ball."""
x_adv = x.clone().detach().requires_grad_(True)
for _ in range(steps):
loss = torch.nn.CrossEntropyLoss()(model(x_adv), y_true)
loss.backward()
with torch.no_grad():
x_adv = x_adv + alpha * x_adv.grad.sign()
delta = torch.clamp(x_adv - x, -epsilon, epsilon)
x_adv = torch.clamp(x + delta, 0, 1).detach().requires_grad_(True)
return x_adv
2c. C&W — Carlini & Wagner (optimization-based, minimal distortion)
pip install adversarial-robustness-toolbox
python - <<'EOF'
from art.attacks.evasion import CarliniL2Method
from art.estimators.classification import PyTorchClassifier
attack = CarliniL2Method(classifier=clf, confidence=0.5, max_iter=100)
x_adv = attack.generate(x=x_test[:10])
EOF
3. Black-box evasion (API access only)
3a. Score-based: NES / ZOO (gradient-free estimation)
When confidence scores are returned, estimate gradient via finite differences:
import numpy as np
def nes_gradient_estimate(query_fn, x, sigma=0.01, n=50):
"""Natural Evolution Strategy gradient estimate from prediction scores."""
grads = np.zeros_like(x)
for _ in range(n):
noise = np.random.randn(*x.shape)
pos = query_fn(x + sigma * noise)
neg = query_fn(x - sigma * noise)
grads += (pos - neg) * noise
return grads / (2 * n * sigma)
3b. Transfer attack (surrogate model)
The reference approach from 13o-bbr-bbq/machine_learning_security's CNN_test:
pip install cleverhans
python - <<'EOF'
import tensorflow as tf
from cleverhans.tf2.attacks.fast_gradient_method import fast_gradient_method
x_adv = fast_gradient_method(surrogate_model, x_test, eps=0.03, norm=np.inf)
EOF
3c. Hard-label: HopSkipJump
When only the predicted label is returned (no scores):
python - <<'EOF'
from art.attacks.evasion import HopSkipJump
from art.estimators.classification import BlackBoxClassifier
def predict_fn(x):
...
clf = BlackBoxClassifier(predict_fn, input_shape=(32,32,3), nb_classes=10)
attack = HopSkipJump(classifier=clf, max_iter=50, max_eval=1000)
x_adv = attack.generate(x=x_test[:5])
EOF
4. Physical-world / domain-specific attacks
4a. Adversarial patches (object detection, face recognition)
Craft a printable patch that fools YOLO/RetinaNet regardless of placement:
pip install adversarial-robustness-toolbox
python - <<'EOF'
from art.attacks.evasion import AdversarialPatch
attack = AdversarialPatch(classifier=clf, rotation_max=22.5, scale_min=0.1, scale_max=1.0)
patch, mask = attack.generate(x=x_train[:100])
EOF
4b. Malware binary perturbation (AV/EDR evasion)
For ML-based static AV/EDR (MalConv, EMBER model):
python - <<'EOF'
import lief, numpy as np
binary = lief.parse("sample.exe")
binary.dos_stub = bytes(np.random.randint(0, 256, 64))
builder = lief.PE.Builder(binary)
builder.build()
builder.write("sample_adv.exe")
EOF
4c. Network traffic / IDS evasion
For ML-based IDS (random-forest or neural-net on flow features):
scapy - <<'EOF'
from scapy.all import *
EOF
5. Tooling reference
| Tool | Attack type | Notes |
|---|
IBM ART (adversarial-robustness-toolbox) | White+black-box, patches, physical | Best all-round; PyTorch/TF/Sklearn |
| CleverHans | White-box FGSM/PGD | TF2 native |
| Foolbox | White+black-box | NumPy-first, easy API |
| AutoZOOM | Black-box score-based | Autoencoder-based gradient compression |
| deep-pwning | Legacy Metasploit-style | Largely unmaintained |
pip install adversarial-robustness-toolbox foolbox cleverhans
6. Validation checklist
7. Detection signals (defender perspective)
- Input pixel distribution deviates from natural image statistics (high-frequency noise)
- Feature-squeeze defence: score changes drastically when input is median-filtered
- Input preprocessing (JPEG re-encode, resize+crop) breaks gradient-based perturbations
- Ensemble disagreement: 3 models with different architectures disagree on the adversarial input
- Activation distribution of adversarial inputs differs from clean examples (mahalanobis-distance detector)