# Ataques de Evasão (Evasion Attacks)

### 📑 **Índice**

1. Fundamentos dos Evasion Attacks
2. Arquitetura e Mecanismos
3. Tipos de Ataques
4. Técnicas de Exploração
5. Implementação em Python
6. Ataques por Domínio
7. Detecção e Mitigação
8. Ferramentas e Frameworks

***

### 🔍 **Fundamentos dos Evasion Attacks**

#### **O que são Evasion Attacks?**

**Evasion Attacks (Ataques de Evasão)** são técnicas adversariais que manipulam entradas durante a inferência para fazer um modelo de machine learning classificar incorretamente uma amostra maliciosa como benigna. Diferente do data poisoning (que ataca o treinamento), os ataques de evasão ocorrem em tempo real, após o modelo já estar em produção, e são usados para contornar sistemas de detecção como antivírus, filtros de spam, detectores de intrusão e sistemas de moderação de conteúdo.

#### **Contexto Histórico**

```yaml
Evolução dos Evasion Attacks:
  2004: Primeiros ataques de evasão em classificadores lineares
  2006: Evasão em detectores de spam
  2010: Ataques a detectores de malware (PDF, executáveis)
  2013: Descoberta de vulnerabilidades em redes neurais
  2017: Ataques físicos em sistemas de visão computacional
  2019: Evasão em modelos de linguagem natural
  2022: Ataques a sistemas multimodais e foundation models
  2024: Evasão em tempo real em sistemas autônomos

Motivação:
  ✅ Modelos são vulneráveis a pequenas perturbações
  ✅ Ataques podem ser executados em tempo real
  ✅ Alta taxa de sucesso com conhecimento limitado
  ✅ Permite contornar sistemas de segurança sem acesso ao treinamento
```

#### **Diferença entre Evasion e Poisoning**

```mermaid
graph TD
    subgraph "Data Poisoning (Treinamento)"
        A[Dados de Treino] -->|Envenenados| B[Modelo]
        B --> C[Comportamento Corrompido]
    end
    
    subgraph "Evasion Attack (Inferência)"
        D[Modelo Limpo] --> E[Inferência]
        F[Amostra Maliciosa] -->|Perturbação| G[Amostra Adversarial]
        G --> E
        E -->|Classificação Incorreta| H[Bypass]
    end
```

#### **Comparação com Outros Ataques**

| Característica              | Evasion      | Poisoning   | Extraction      | Inference  |
| --------------------------- | ------------ | ----------- | --------------- | ---------- |
| **Fase do Ataque**          | Inferência   | Treinamento | Pós-treinamento | Inferência |
| **Acesso ao Modelo**        | Baixo a Alto | Alto        | Médio           | Baixo      |
| **Conhecimento Necessário** | Médio        | Alto        | Médio           | Baixo      |
| **Tempo de Execução**       | Real-time    | Lento       | Moderado        | Rápido     |
| **Objetivo**                | Bypass       | Corromper   | Copiar          | Exfiltrar  |

***

### 🏗️ **Arquitetura e Mecanismos**

#### **Princípio de Funcionamento**

```python
#!/usr/bin/env python3
# evasion_principles.py

import numpy as np
import matplotlib.pyplot as plt

class EvasionPrinciples:
    """
    Fundamentos matemáticos dos ataques de evasão
    """
    
    @staticmethod
    def linear_classifier_evasion():
        """
        Demonstração de evasão em classificador linear
        """
        # Classificador linear: f(x) = sign(w·x + b)
        w = np.array([1.0, 1.0])
        b = -5.0
        
        # Amostra maliciosa original
        x_malicious = np.array([4.0, 4.0])
        print(f"Amostra original: {x_malicious}")
        print(f"Classificação original: {np.sign(np.dot(w, x_malicious) + b)}")
        
        # Encontrar perturbação mínima para evasão
        # Queremos w·(x + δ) + b = 0 (fronteira)
        # δ = - (w·x + b) / ||w||² * w
        
        margin = np.dot(w, x_malicious) + b
        delta = -margin / np.dot(w, w) * w
        
        x_evaded = x_malicious + delta
        print(f"\nPerturbação: {delta}")
        print(f"Amostra evadida: {x_evaded}")
        print(f"Classificação evadida: {np.sign(np.dot(w, x_evaded) + b)}")
        
        return x_malicious, x_evaded, w, b
    
    @staticmethod
    def minimal_perturbation(x, target_class, model, norm='l2'):
        """
        Encontrar perturbação mínima para evasão
        """
        # Problema de otimização: min ||δ|| s.t. f(x+δ) = target_class
        
        # Em classificadores lineares, solução analítica existe
        # Em redes neurais, usamos gradiente descendente
        
        return None
    
    @staticmethod
    def visualize_decision_boundary():
        """
        Visualizar fronteira de decisão e ataque de evasão
        """
        from sklearn.svm import SVC
        
        # Gerar dados sintéticos
        np.random.seed(42)
        X = np.random.randn(200, 2)
        y = (X[:, 0] + X[:, 1] > 0).astype(int)
        
        # Treinar SVM
        clf = SVC(kernel='linear')
        clf.fit(X, y)
        
        # Ponto a ser evadido
        x_target = np.array([-1.5, -1.5])
        original_class = clf.predict([x_target])[0]
        
        # Encontrar ponto na fronteira
        w = clf.coef_[0]
        b = clf.intercept_[0]
        margin = np.dot(w, x_target) + b
        delta = -margin / np.dot(w, w) * w
        x_evaded = x_target + delta
        
        # Plotar
        plt.figure(figsize=(10, 8))
        
        # Plotar dados
        plt.scatter(X[y==0, 0], X[y==0, 1], c='blue', alpha=0.5, label='Classe 0')
        plt.scatter(X[y==1, 0], X[y==1, 1], c='red', alpha=0.5, label='Classe 1')
        
        # Plotar fronteira
        xx = np.linspace(-3, 3, 100)
        yy = -(w[0] * xx + b) / w[1]
        plt.plot(xx, yy, 'k--', label='Fronteira de Decisão')
        
        # Plotar pontos
        plt.scatter(x_target[0], x_target[1], c='green', s=200, marker='*', 
                   label=f'Original (Classe {original_class})')
        plt.scatter(x_evaded[0], x_evaded[1], c='orange', s=200, marker='X',
                   label=f'Evadido (Classe {1-original_class})')
        plt.arrow(x_target[0], x_target[1], delta[0], delta[1], 
                 head_width=0.1, head_length=0.1, fc='gray', ec='gray')
        
        plt.legend()
        plt.title('Ataque de Evasão - Fronteira de Decisão Linear')
        plt.axis('equal')
        plt.grid(True)
        plt.show()

# Executar
EvasionPrinciples.linear_classifier_evasion()
EvasionPrinciples.visualize_decision_boundary()
```

#### **Taxonomia de Ataques de Evasão**

```yaml
Classificação por Conhecimento:
  
  Caixa Branca (White-box):
    - Atacante tem acesso total ao modelo (arquitetura, pesos, gradientes)
    - Ataques mais eficazes (FGSM, PGD, C&W)
    - Cenário: modelos open-source, engenharia reversa
  
  Caixa Preta (Black-box):
    - Atacante só pode consultar o modelo (entrada → saída)
    - Ataques baseados em transferabilidade ou otimização (Boundary, HopSkipJump)
    - Cenário: APIs de ML, modelos proprietários
  
  Caixa Cinza (Gray-box):
    - Conhecimento parcial (arquitetura, mas sem pesos)
    - Ataques de transferabilidade
    - Cenário: modelos com documentação pública

Classificação por Objetivo:
  
  Ataque Não-Alvo (Non-targeted):
    - Fazer o modelo errar (qualquer classe incorreta)
    - Ex: Antivírus não detectar malware
  
  Ataque Alvo (Targeted):
    - Forçar o modelo a prever uma classe específica
    - Ex: Fazer sistema de reconhecimento facial identificar outra pessoa
```

***

### ⚔️ **Tipos de Ataques**

#### **1. Evasão em Classificadores Lineares (SVM, Regressão Logística)**

```python
#!/usr/bin/env python3
# linear_evasion.py

import numpy as np
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression

class LinearEvasionAttack:
    """
    Ataques de evasão em classificadores lineares
    """
    
    def __init__(self, model):
        self.model = model
        self.is_svm = isinstance(model, SVC)
    
    def analytical_evasion(self, x, target_class):
        """
        Evasão analítica para classificadores lineares
        Solução de forma fechada
        """
        if self.is_svm and self.model.kernel != 'linear':
            raise ValueError("Método apenas para kernel linear")
        
        # Obter pesos e bias
        if self.is_svm:
            w = self.model.coef_[0]
            b = self.model.intercept_[0]
        else:
            w = self.model.coef_[0]
            b = self.model.intercept_[0]
        
        # Calcular margem atual
        current_margin = np.dot(w, x) + b
        
        # Determinar direção para classe alvo
        # Para classe positiva (1), queremos margin > 0
        # Para classe negativa (0), queremos margin < 0
        target_margin = 1.0 if target_class == 1 else -1.0
        
        # Perturbação mínima: δ = (target_margin - current_margin) / ||w||² * w
        delta = (target_margin - current_margin) / np.dot(w, w) * w
        
        x_evaded = x + delta
        
        return x_evaded, delta
    
    def confidence_aware_evasion(self, x, target_class, confidence=0.8):
        """
        Evasão com margem de confiança
        """
        w = self.model.coef_[0]
        b = self.model.intercept_[0]
        
        # Queremos margem com confiança específica
        # Em regressão logística, a confiança está relacionada à distância à fronteira
        
        current_margin = np.dot(w, x) + b
        
        # Calcular margem necessária para confiança desejada
        # Simplificação: assumir relação linear
        required_margin = np.log(confidence / (1 - confidence))
        
        if target_class == 1:
            delta = (required_margin - current_margin) / np.dot(w, w) * w
        else:
            delta = (-required_margin - current_margin) / np.dot(w, w) * w
        
        x_evaded = x + delta
        
        return x_evaded, delta
```

#### **2. Evasão em Redes Neurais (FGSM, PGD, C\&W)**

```python
#!/usr/bin/env python3
# neural_evasion.py

import torch
import torch.nn as nn
import numpy as np

class NeuralEvasionAttack:
    """
    Ataques de evasão em redes neurais profundas
    """
    
    def __init__(self, model, device='cuda'):
        self.model = model.to(device)
        self.device = device
    
    def fgsm_attack(self, image, label, epsilon=0.1, targeted=False):
        """
        Fast Gradient Sign Method
        """
        image = image.clone().detach().requires_grad_(True)
        
        output = self.model(image)
        loss = nn.CrossEntropyLoss()(output, label)
        
        self.model.zero_grad()
        loss.backward()
        
        # Calcular perturbação
        if targeted:
            perturbation = -epsilon * image.grad.sign()
        else:
            perturbation = epsilon * image.grad.sign()
        
        adversarial = image + perturbation
        adversarial = torch.clamp(adversarial, 0, 1)
        
        return adversarial
    
    def pgd_attack(self, image, label, epsilon=0.1, alpha=0.01, num_iter=40):
        """
        Projected Gradient Descent
        """
        adversarial = image.clone()
        
        for _ in range(num_iter):
            adversarial.requires_grad = True
            output = self.model(adversarial)
            loss = nn.CrossEntropyLoss()(output, label)
            
            self.model.zero_grad()
            loss.backward()
            
            with torch.no_grad():
                perturbation = alpha * adversarial.grad.sign()
                adversarial = adversarial + perturbation
                eta = torch.clamp(adversarial - image, -epsilon, epsilon)
                adversarial = image + eta
                adversarial = torch.clamp(adversarial, 0, 1)
        
        return adversarial
    
    def deepfool_attack(self, image, label, max_iter=50):
        """
        DeepFool - encontra perturbação mínima
        """
        adversarial = image.clone()
        num_classes = self.model(image).shape[1]
        
        for _ in range(max_iter):
            adversarial.requires_grad = True
            output = self.model(adversarial)
            
            if torch.argmax(output) != label:
                break
            
            # Calcular gradientes para todas as classes
            grads = []
            for k in range(num_classes):
                self.model.zero_grad()
                output[0, k].backward(retain_graph=True)
                grads.append(adversarial.grad.clone())
                adversarial.grad.zero_()
            
            # Encontrar classe mais próxima
            f_k = output[0].detach()
            f_0 = f_k[label].item()
            
            min_dist = float('inf')
            best_w = None
            best_f = None
            
            for k in range(num_classes):
                if k == label:
                    continue
                w = grads[k] - grads[label]
                f = f_k[k] - f_0
                dist = abs(f) / torch.norm(w)
                
                if dist < min_dist:
                    min_dist = dist
                    best_w = w
                    best_f = f
            
            perturbation = (abs(best_f) / torch.norm(best_w)**2 + 1e-8) * best_w
            adversarial = adversarial + perturbation
            adversarial = torch.clamp(adversarial, 0, 1)
        
        return adversarial
    
    def cw_attack(self, image, target_class, confidence=0, learning_rate=0.01, num_iter=1000):
        """
        Carlini & Wagner L2 Attack
        """
        # Variável no espaço tanh (garante limites [0,1])
        w = torch.arctanh(image * 2 - 1).clone().detach().requires_grad_(True)
        best_adv = image.clone()
        best_dist = float('inf')
        
        optimizer = torch.optim.Adam([w], lr=learning_rate)
        
        for i in range(num_iter):
            adv = (torch.tanh(w) + 1) / 2
            output = self.model(adv)
            
            # Perda C&W
            target_one_hot = torch.zeros_like(output)
            target_one_hot.scatter_(1, target_class.unsqueeze(1), 1)
            
            real = torch.sum(target_one_hot * output)
            other = torch.max((1 - target_one_hot) * output - target_one_hot * 10000)
            loss = torch.clamp(other - real + confidence, min=0)
            
            l2_dist = torch.norm((adv - image).view(adv.shape[0], -1), dim=1)
            total_loss = loss + l2_dist
            
            optimizer.zero_grad()
            total_loss.backward()
            optimizer.step()
            
            with torch.no_grad():
                pred = torch.argmax(self.model(adv), dim=1)
                if pred == target_class:
                    dist = l2_dist.item()
                    if dist < best_dist:
                        best_dist = dist
                        best_adv = adv.clone()
        
        return best_adv
```

#### **3. Evasão em Caixa Preta (Black-box)**

```python
#!/usr/bin/env python3
# blackbox_evasion.py

import numpy as np
from scipy.optimize import minimize

class BlackBoxEvasionAttack:
    """
    Ataques de evasão sem acesso aos gradientes
    """
    
    def __init__(self, model_predict_fn):
        """
        model_predict_fn: função que retorna a saída do modelo (probabilidades)
        """
        self.predict = model_predict_fn
    
    def boundary_attack(self, x, target_class, max_iter=1000):
        """
        Boundary Attack - busca na fronteira de decisão
        """
        # Inicializar com ruído grande
        x_adv = x.copy()
        original_class = np.argmax(self.predict(x_adv))
        
        # Adicionar ruído até mudar de classe
        while np.argmax(self.predict(x_adv)) == original_class:
            noise = np.random.randn(*x.shape) * 0.1
            x_adv = x + noise
            x_adv = np.clip(x_adv, 0, 1)
        
        # Otimizar na fronteira
        epsilon = 0.1
        for i in range(max_iter):
            # Amostrar direção aleatória
            direction = np.random.randn(*x.shape)
            direction = direction / np.linalg.norm(direction)
            
            # Tentar mover em direção à original
            candidate = x_adv - epsilon * direction
            candidate = np.clip(candidate, 0, 1)
            
            # Se ainda for adversarial, aceitar
            if np.argmax(self.predict(candidate)) != original_class:
                x_adv = candidate
                epsilon *= 0.995
        
        return x_adv
    
    def hopskipjump_attack(self, x, target_class, max_iter=100):
        """
        HopSkipJumpAttack - otimização por estimativa de gradiente
        """
        # Implementação simplificada
        # O algoritmo original usa estimativa de gradiente via consultas
        
        x_adv = x.copy()
        original_class = np.argmax(self.predict(x_adv))
        
        for i in range(max_iter):
            # Estimar gradiente via diferenças finitas
            grad_est = self.estimate_gradient(x_adv, original_class)
            
            # Mover na direção do gradiente
            x_adv = x_adv + 0.01 * grad_est
            x_adv = np.clip(x_adv, 0, 1)
        
        return x_adv
    
    def estimate_gradient(self, x, target_class, epsilon=0.001, num_samples=100):
        """
        Estimar gradiente via consultas ao modelo
        """
        grad = np.zeros_like(x)
        
        for i in range(num_samples):
            # Amostrar direção aleatória
            direction = np.random.randn(*x.shape)
            direction = direction / np.linalg.norm(direction)
            
            # Estimar derivada direcional
            f_plus = self.predict(x + epsilon * direction)[target_class]
            f_minus = self.predict(x - epsilon * direction)[target_class]
            
            grad += (f_plus - f_minus) / (2 * epsilon) * direction
        
        return grad / num_samples
    
    def transfer_attack(self, x, substitute_model, substitute_attack, epsilon=0.1):
        """
        Ataque de transferabilidade
        """
        # Gerar adversarial no modelo substituto (caixa branca)
        x_adv = substitute_attack(x, substitute_model, epsilon)
        
        # Testar no modelo alvo
        target_pred = self.predict(x_adv)
        return x_adv, target_pred
```

#### **4. Evasão Física (Adversarial Patches)**

```python
#!/usr/bin/env python3
# physical_evasion.py

import numpy as np
import cv2

class PhysicalEvasionAttack:
    """
    Ataques de evasão no mundo físico (adesivos, patches)
    """
    
    def __init__(self, target_class, patch_size=(100, 100)):
        self.target_class = target_class
        self.patch_size = patch_size
    
    def generate_adversarial_patch(self, image, model, num_iter=500):
        """
        Gerar patch adversarial para colocar em objetos
        """
        patch = np.random.rand(*self.patch_size, 3)
        
        for i in range(num_iter):
            # Aplicar patch em posições aleatórias
            x, y = np.random.randint(0, image.shape[1] - self.patch_size[1]), \
                   np.random.randint(0, image.shape[0] - self.patch_size[0])
            
            image_patched = image.copy()
            image_patched[y:y+self.patch_size[0], x:x+self.patch_size[1]] = patch
            
            # Calcular perda
            pred = model.predict(image_patched)
            loss = -np.log(pred[self.target_class] + 1e-8)
            
            # Atualizar patch (simplificado - gradiente via diferenças finitas)
            grad = self.approximate_gradient(patch, image, model, x, y, loss)
            patch -= 0.01 * grad
            patch = np.clip(patch, 0, 1)
        
        return patch
    
    def approximate_gradient(self, patch, image, model, x, y, loss, epsilon=0.01):
        """
        Aproximar gradiente do patch
        """
        grad = np.zeros_like(patch)
        
        for i in range(patch.shape[0]):
            for j in range(patch.shape[1]):
                for c in range(3):
                    patch_plus = patch.copy()
                    patch_plus[i, j, c] += epsilon
                    
                    image_patched = image.copy()
                    image_patched[y:y+self.patch_size[0], x:x+self.patch_size[1]] = patch_plus
                    
                    pred_plus = model.predict(image_patched)
                    loss_plus = -np.log(pred_plus[self.target_class] + 1e-8)
                    
                    grad[i, j, c] = (loss_plus - loss) / epsilon
        
        return grad
    
    def simulate_physical_conditions(self, image, angle=15, scale=0.9, lighting=0.8):
        """
        Simular condições físicas para tornar o patch robusto
        """
        h, w = image.shape[:2]
        
        # Rotação
        M = cv2.getRotationMatrix2D((w//2, h//2), angle, scale)
        rotated = cv2.warpAffine(image, M, (w, h))
        
        # Iluminação
        darkened = rotated * lighting
        
        return darkened
```

***

### 🎨 **Ataques por Domínio**

#### **1. Evasão em Detecção de Malware**

```python
#!/usr/bin/env python3
# malware_evasion.py

import numpy as np
from sklearn.ensemble import RandomForestClassifier

class MalwareEvasionAttack:
    """
    Evasão de detectores de malware
    """
    
    def __init__(self, detector_model, feature_names):
        self.detector = detector_model
        self.features = feature_names
    
    def gradient_based_evasion(self, malware_sample, epsilon=0.1):
        """
        Modificar características do malware para evadir detecção
        """
        # Em detectores de malware, características são binárias ou discretas
        # Aplicar perturbação em características importantes
        
        malware_copy = malware_sample.copy()
        
        # Obter importância das características
        if hasattr(self.detector, 'feature_importances_'):
            importance = self.detector.feature_importances_
            
            # Modificar características mais importantes
            important_indices = np.argsort(importance)[-10:]
            
            for idx in important_indices:
                # Mudar característica binária (0→1 ou 1→0)
                malware_copy[idx] = 1 - malware_copy[idx]
        
        return malware_copy
    
    def content_perturbation(self, binary_content, target_ratio=0.5):
        """
        Modificar conteúdo binário (adição de seções, padding)
        """
        # Adicionar bytes nulos (padding) para mudar assinatura
        padding = b'\x00' * 1024
        modified = binary_content + padding
        
        return modified
    
    def section_injection(self, pe_file, benign_section):
        """
        Injetar seção benigna em executável PE
        """
        # Adicionar seção com código benigno para enganar detector
        # Exemplo simplificado
        pass
```

#### **2. Evasão em Detecção de Spam**

```python
#!/usr/bin/env python3
# spam_evasion.py

import re
import numpy as np

class SpamEvasionAttack:
    """
    Evasão de filtros de spam
    """
    
    def __init__(self, classifier, word_list):
        self.classifier = classifier
        self.word_list = word_list
    
    def good_word_insertion(self, email_text, good_words):
        """
        Inserir palavras "boas" no e-mail
        """
        for word in good_words:
            # Inserir palavra em posição aleatória
            position = np.random.randint(0, len(email_text))
            email_text = email_text[:position] + f" {word} " + email_text[position:]
        
        return email_text
    
    def misspelling_attack(self, email_text, misspell_ratio=0.1):
        """
        Introduzir erros de digitação para evadir
        """
        words = email_text.split()
        num_misspell = int(len(words) * misspell_ratio)
        indices = np.random.choice(len(words), num_misspell, replace=False)
        
        for idx in indices:
            word = words[idx]
            if len(word) > 3:
                # Substituir caractere aleatório
                pos = np.random.randint(0, len(word))
                new_char = chr(np.random.randint(97, 122))
                words[idx] = word[:pos] + new_char + word[pos+1:]
        
        return ' '.join(words)
    
    def homoglyph_attack(self, email_text):
        """
        Substituir caracteres por homógrafos (visualmente similares)
        """
        homoglyphs = {
            'a': 'а',  # Cyrillic a
            'e': 'е',  # Cyrillic e
            'o': 'о',  # Cyrillic o
            'p': 'р',  # Cyrillic p
            'c': 'с',  # Cyrillic c
            'y': 'у'   # Cyrillic y
        }
        
        for char, homoglyph in homoglyphs.items():
            email_text = email_text.replace(char, homoglyph)
        
        return email_text
```

#### **3. Evasão em Sistemas de Reconhecimento Facial**

```python
#!/usr/bin/env python3
# facial_evasion.py

import numpy as np
import cv2

class FacialRecognitionEvasion:
    """
    Evasão de sistemas de reconhecimento facial
    """
    
    def __init__(self, face_encoder, target_identity):
        self.encoder = face_encoder
        self.target = target_identity
    
    def adversarial_glasses(self, face_image, target_embedding, num_iter=100):
        """
        Gerar óculos adversariais
        """
        # Inicializar patch de óculos
        glasses = np.zeros((50, 100, 3))
        
        for i in range(num_iter):
            # Aplicar óculos na imagem
            face_with_glasses = self.apply_glasses(face_image, glasses)
            
            # Obter embedding
            embedding = self.encoder(face_with_glasses)
            
            # Calcular perda
            loss = np.linalg.norm(embedding - target_embedding)
            
            # Atualizar patch (simplificado)
            grad = self.approximate_glasses_gradient(glasses, face_image, target_embedding)
            glasses -= 0.01 * grad
            glasses = np.clip(glasses, 0, 255)
        
        return glasses
    
    def apply_glasses(self, face_image, glasses):
        """Aplicar patch de óculos na imagem facial"""
        # Detectar posição dos olhos (simplificado)
        h, w = face_image.shape[:2]
        eye_y = h // 3
        eye_x = w // 2
        
        # Colocar óculos
        face_copy = face_image.copy()
        gh, gw = glasses.shape[:2]
        y_start = eye_y - gh//2
        x_start = eye_x - gw//2
        
        face_copy[y_start:y_start+gh, x_start:x_start+gw] = glasses
        
        return face_copy
    
    def pixel_perturbation(self, face_image, epsilon=0.05):
        """
        Perturbação de pixels imperceptível
        """
        noise = np.random.normal(0, epsilon, face_image.shape)
        adversarial = face_image + noise
        return np.clip(adversarial, 0, 255).astype(np.uint8)
    
    def adversarial_mask(self, face_image, target_embedding):
        """
        Gerar máscara adversarial (ex: COVID mask)
        """
        mask = np.zeros((100, 150, 3))
        
        # Otimização similar aos óculos
        # ...
        
        return mask
```

#### **4. Evasão em Modelos de Linguagem**

```python
#!/usr/bin/env python3
# nlp_evasion.py

import numpy as np
from transformers import AutoTokenizer, AutoModelForSequenceClassification

class NLPEvasionAttack:
    """
    Evasão de classificadores de texto
    """
    
    def __init__(self, model_name='distilbert-base-uncased-finetuned-sst-2-english'):
        self.tokenizer = AutoTokenizer.from_pretrained(model_name)
        self.model = AutoModelForSequenceClassification.from_pretrained(model_name)
    
    def synonym_substitution(self, text, target_label, num_substitutions=5):
        """
        Substituir palavras por sinônimos
        """
        import nltk
        from nltk.corpus import wordnet
        
        words = text.split()
        important_indices = self.get_important_words(text, target_label)
        
        for idx in important_indices[:num_substitutions]:
            word = words[idx]
            synonyms = wordnet.synsets(word)
            
            if synonyms:
                # Obter sinônimos
                lemmas = [lemma.name() for syn in synonyms for lemma in syn.lemmas()]
                lemmas = list(set(lemmas))
                
                if lemmas:
                    # Substituir por sinônimo
                    new_word = lemmas[0].replace('_', ' ')
                    words[idx] = new_word
        
        return ' '.join(words)
    
    def get_important_words(self, text, target_label):
        """
        Identificar palavras mais importantes para a classificação
        """
        tokens = self.tokenizer(text, return_tensors='pt')
        
        # Calcular gradientes (simplificado)
        # Em implementação real, usar gradientes do modelo
        
        return np.random.choice(len(text.split()), 5, replace=False)
    
    def character_level_perturbation(self, text, perturb_ratio=0.05):
        """
        Perturbação em nível de caractere
        """
        chars = list(text)
        num_perturb = int(len(chars) * perturb_ratio)
        indices = np.random.choice(len(chars), num_perturb, replace=False)
        
        for idx in indices:
            # Substituir por caractere similar
            if chars[idx].isalpha():
                if chars[idx].islower():
                    chars[idx] = chr((ord(chars[idx]) - ord('a') + 1) % 26 + ord('a'))
                else:
                    chars[idx] = chr((ord(chars[idx]) - ord('A') + 1) % 26 + ord('A'))
        
        return ''.join(chars)
    
    def paraphrasing_attack(self, text, target_label):
        """
        Reformular frase mantendo significado
        """
        # Usar modelo de paráfrase (ex: T5)
        # Implementação simplificada
        paraphrased = text.replace("good", "great").replace("bad", "poor")
        return paraphrased
```

***

### 🛡️ **Detecção e Mitigação**

#### **1. Detecção de Amostras Adversariais**

```python
#!/usr/bin/env python3
# evasion_detection.py

import numpy as np
from sklearn.ensemble import IsolationForest

class EvasionDetector:
    """
    Detector de amostras adversariais
    """
    
    def __init__(self, model, num_features=100):
        self.model = model
        self.detector = IsolationForest(contamination=0.1, random_state=42)
        self.num_features = num_features
    
    def extract_features(self, image):
        """
        Extrair características para detecção
        """
        # Características de ativações internas
        activations = []
        
        def hook_fn(module, input, output):
            activations.append(output.detach().flatten())
        
        # Registrar hooks
        hooks = []
        for name, module in self.model.named_modules():
            if isinstance(module, (torch.nn.ReLU, torch.nn.LeakyReLU)):
                hooks.append(module.register_forward_hook(hook_fn))
        
        # Forward pass
        with torch.no_grad():
            self.model(image)
        
        # Remover hooks
        for hook in hooks:
            hook.remove()
        
        # Concatenar ativações
        features = torch.cat(activations)[:self.num_features]
        return features.numpy()
    
    def train_detector(self, clean_images):
        """
        Treinar detector com imagens limpas
        """
        features = []
        for img in clean_images:
            feat = self.extract_features(img.unsqueeze(0))
            features.append(feat)
        
        features = np.array(features)
        self.detector.fit(features)
    
    def predict(self, image):
        """
        Classificar se imagem é adversarial
        """
        features = self.extract_features(image.unsqueeze(0))
        return self.detector.predict([features])[0] == -1
    
    def local_intrinsic_dimensionality(self, image, k=10):
        """
        Calcular dimensionalidade intrínseca local (LID)
        """
        # Amostrar vizinhos
        neighbors = []
        for _ in range(k):
            noise = np.random.normal(0, 0.01, image.shape)
            neighbor = image + noise
            neighbors.append(neighbor)
        
        # Calcular distâncias
        distances = []
        for neighbor in neighbors:
            dist = np.linalg.norm(image - neighbor)
            distances.append(dist)
        
        # Estimar LID
        lid = -k / np.sum(np.log(distances))
        return lid
```

#### **2. Defesas Adversariais**

```python
#!/usr/bin/env python3
# adversarial_defenses.py

import torch
import torch.nn as nn
import numpy as np

class AdversarialDefenses:
    """
    Técnicas de defesa contra ataques de evasão
    """
    
    @staticmethod
    def feature_squeezing(image, bits=4):
        """
        Feature squeezing - reduzir espaço de características
        """
        scale = 2 ** bits
        return np.floor(image * scale) / scale
    
    @staticmethod
    def randomized_smoothing(image, num_samples=50, noise_std=0.01):
        """
        Randomized smoothing - média de predições com ruído
        """
        predictions = []
        
        for _ in range(num_samples):
            noise = np.random.normal(0, noise_std, image.shape)
            noisy = image + noise
            predictions.append(model(noisy))
        
        avg_prediction = np.mean(predictions, axis=0)
        return np.argmax(avg_prediction)
    
    @staticmethod
    def adversarial_training(model, train_loader, attack_func, epsilon=0.1, epochs=5):
        """
        Treinamento adversarial
        """
        optimizer = torch.optim.Adam(model.parameters())
        
        for epoch in range(epochs):
            for images, labels in train_loader:
                # Gerar exemplos adversariais
                adversarials = []
                for img, lbl in zip(images, labels):
                    adv = attack_func(model, img.unsqueeze(0), lbl.unsqueeze(0), epsilon)
                    adversarials.append(adv)
                
                adversarials = torch.cat(adversarials)
                
                # Treinar com dados originais + adversariais
                combined = torch.cat([images, adversarials])
                combined_labels = torch.cat([labels, labels])
                
                outputs = model(combined)
                loss = nn.CrossEntropyLoss()(outputs, combined_labels)
                
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
    
    @staticmethod
    def input_gradient_regularization(model, images, labels, lambda_reg=0.1):
        """
        Regularização de gradiente de entrada
        """
        images.requires_grad = True
        outputs = model(images)
        loss = nn.CrossEntropyLoss()(outputs, labels)
        
        # Calcular gradiente em relação à entrada
        model.zero_grad()
        loss.backward()
        
        # Adicionar regularização
        grad_norm = torch.norm(images.grad, p=2)
        total_loss = loss + lambda_reg * grad_norm
        
        return total_loss
    
    @staticmethod
    def ensemble_defense(models, image):
        """
        Defesa por ensemble - múltiplos modelos votam
        """
        predictions = []
        for model in models:
            pred = model(image)
            predictions.append(pred)
        
        avg_pred = torch.stack(predictions).mean(dim=0)
        return torch.argmax(avg_pred)
    
    @staticmethod
    def preprocess_defense(image):
        """
        Defesa por pré-processamento
        """
        # Redução de ruído
        from scipy.ndimage import median_filter
        
        # Filtro mediana
        filtered = median_filter(image, size=3)
        
        # Quantização
        quantized = np.round(filtered * 255) / 255
        
        # Redimensionamento
        from skimage.transform import resize
        resized = resize(quantized, (256, 256))
        cropped = resized[16:240, 16:240]
        
        return cropped
```

#### **3. Certificação de Robustez**

```python
#!/usr/bin/env python3
# robustness_certification.py

import numpy as np
from scipy.stats import norm

class RobustnessCertification:
    """
    Certificação de robustez contra ataques de evasão
    """
    
    @staticmethod
    def randomized_smoothing_certify(model, image, label, num_samples=1000, alpha=0.001):
        """
        Certificar raio de robustez usando randomized smoothing
        """
        predictions = []
        
        for _ in range(num_samples):
            noise = np.random.normal(0, 0.1, image.shape)
            noisy = image + noise
            pred = model(noisy)
            predictions.append(pred)
        
        # Contar predições da classe principal
        class_counts = np.bincount(predictions)
        top_class = np.argmax(class_counts)
        count_A = class_counts[top_class]
        
        # Limite inferior binomial (Clopper-Pearson)
        p_A_lower = norm.ppf(alpha, count_A / num_samples, 
                             np.sqrt(count_A * (num_samples - count_A) / num_samples**3))
        
        # Raio certificado
        sigma = 0.1
        radius = sigma * norm.ppf(p_A_lower)
        
        return radius, top_class
    
    @staticmethod
    def cleverh_score(model, image, label, num_samples=100):
        """
        Calcular CLEVER score (Cross-Lipschitz Extreme Value for nEtwork Robustness)
        """
        # Amostrar direções aleatórias
        scores = []
        
        for _ in range(num_samples):
            direction = np.random.randn(*image.shape)
            direction = direction / np.linalg.norm(direction)
            
            # Busca linear na direção
            epsilon = 0
            step = 0.01
            
            while True:
                perturbed = image + epsilon * direction
                pred = model(perturbed)
                
                if np.argmax(pred) != label:
                    scores.append(epsilon)
                    break
                
                epsilon += step
        
        return np.min(scores)
```

***

### 🛠️ **Ferramentas e Frameworks**

#### **Ferramentas para Evasion Attacks**

| Ferramenta                               | Descrição                          | Instalação                 | Uso                        |
| ---------------------------------------- | ---------------------------------- | -------------------------- | -------------------------- |
| **CleverHans**                           | Biblioteca de ataques adversariais | `pip install cleverhans`   | Pesquisa                   |
| **Foolbox**                              | Ataques robustos em PyTorch/TF     | `pip install foolbox`      | Benchmarking               |
| **Adversarial Robustness Toolbox (ART)** | Framework IBM                      | `pip install art`          | Produção                   |
| **TorchAttacks**                         | Coleção de ataques em PyTorch      | `pip install torchattacks` | Pesquisa                   |
| **TextAttack**                           | Ataques em NLP                     | `pip install textattack`   | Processamento de linguagem |

#### **Exemplo com Foolbox**

```python
#!/usr/bin/env python3
# foolbox_evasion.py

import foolbox as fb
import torch
import torchvision.models as models

class FoolboxEvasionExample:
    """
    Exemplo de uso do Foolbox para ataques de evasão
    """
    
    def __init__(self):
        # Carregar modelo
        self.model = models.resnet18(pretrained=True)
        self.model.eval()
        
        # Criar modelo Foolbox
        self.fmodel = fb.PyTorchModel(self.model, bounds=(0, 1))
    
    def fgsm_attack(self, image, label, epsilon=0.03):
        """Ataque FGSM"""
        attack = fb.attacks.LinfFastGradientAttack()
        adversarial = attack(self.fmodel, image, label, epsilons=epsilon)
        return adversarial
    
    def pgd_attack(self, image, label, epsilon=0.03, steps=40):
        """Ataque PGD"""
        attack = fb.attacks.LinfProjectedGradientDescentAttack(steps=steps)
        adversarial = attack(self.fmodel, image, label, epsilons=epsilon)
        return adversarial
    
    def deepfool_attack(self, image, label):
        """Ataque DeepFool"""
        attack = fb.attacks.LinfDeepFoolAttack()
        adversarial = attack(self.fmodel, image, label)
        return adversarial
    
    def boundary_attack(self, image, label):
        """Ataque Boundary (caixa preta)"""
        attack = fb.attacks.BoundaryAttack()
        adversarial = attack(self.fmodel, image, label)
        return adversarial
    
    def evaluate_robustness(self, images, labels, attack_name='fgsm', epsilon=0.03):
        """
        Avaliar robustez do modelo
        """
        if attack_name == 'fgsm':
            attack = fb.attacks.LinfFastGradientAttack()
        elif attack_name == 'pgd':
            attack = fb.attacks.LinfProjectedGradientDescentAttack()
        else:
            raise ValueError("Ataque não suportado")
        
        # Aplicar ataque
        adversarials, _, success = attack(self.fmodel, images, labels, epsilons=epsilon)
        
        # Calcular métricas
        clean_acc = fb.utils.accuracy(self.fmodel, images, labels)
        robust_acc = 1 - success.float().mean().item()
        
        print(f"Acurácia limpa: {clean_acc:.4f}")
        print(f"Acurácia robusta (ε={epsilon}): {robust_acc:.4f}")
        
        return adversarials, robust_acc
```

***

### 📊 **Comparação de Métodos de Evasão**

| Método       | Força       | Velocidade   | Conhecimento | Transferabilidade | Aplicação          |
| ------------ | ----------- | ------------ | ------------ | ----------------- | ------------------ |
| **FGSM**     | Média       | Muito rápida | Caixa branca | Alta              | Ataques rápidos    |
| **PGD**      | Muito forte | Lenta        | Caixa branca | Média             | Benchmarking       |
| **C\&W**     | Fortíssimo  | Muito lenta  | Caixa branca | Baixa             | Ataques ótimos     |
| **DeepFool** | Forte       | Média        | Caixa branca | Média             | Perturbação mínima |
| **Boundary** | Forte       | Muito lenta  | Caixa preta  | N/A               | APIs               |
| **Transfer** | Média       | Rápida       | Caixa preta  | Alta              | Transferabilidade  |
| **Physical** | Média       | Lenta        | Caixa branca | Baixa             | Mundo físico       |

***

### 📚 **Referências e Leitura Recomendada**

| Paper                                                               | Autores                 | Ano  | Foco            |
| ------------------------------------------------------------------- | ----------------------- | ---- | --------------- |
| Explaining and Harnessing Adversarial Examples                      | Goodfellow et al.       | 2014 | FGSM            |
| Towards Deep Learning Models Resistant to Adversarial Attacks       | Madry et al.            | 2017 | PGD             |
| Towards Evaluating the Robustness of Neural Networks                | Carlini et al.          | 2017 | C\&W            |
| DeepFool: A Simple and Accurate Method to Fool Deep Neural Networks | Moosavi-Dezfooli et al. | 2016 | DeepFool        |
| Adversarial Examples in the Physical World                          | Kurakin et al.          | 2016 | Ataques físicos |
| Decision-Based Adversarial Attacks                                  | Brendel et al.          | 2017 | Boundary attack |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/ia-e-llm/ataques-de-evasao-evasion-attacks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
