# JTAG & Debugging Abuse

## 📑 **Índice**

1. [Fundamentos do JTAG](#-fundamentos-do-jtag)
2. [Arquitetura e Padrões](#-arquitetura-e-padrões)
3. [Interfaces de Debug](#-interfaces-de-debug)
4. [Equipamentos e Ferramentas](#-equipamentos-e-ferramentas)
5. [Técnicas de Ataque](#-técnicas-de-ataque)
6. [Implementação e Exploração](#-implementação-e-exploração)
7. [Contramedidas e Proteções](#-contramedidas-e-proteções)
8. [Ferramentas e Hardware](#-ferramentas-e-hardware)

***

## 🔍 **Fundamentos do JTAG**

### **O que é JTAG?**

**JTAG (Joint Test Action Group)** é um padrão de interface de hardware que define um método para testar, depurar e programar circuitos integrados e placas de circuito impresso. Originalmente desenvolvido para testes de placas (boundary scan), o JTAG tornou-se a interface padrão para depuração de microcontroladores, FPGAs, processadores e sistemas embarcados. Para um atacante, o acesso JTAG representa uma porta de entrada privilegiada para o funcionamento interno do dispositivo, permitindo leitura de memória, execução de código arbitrário e bypass de mecanismos de segurança.

### **Contexto Histórico**

```yaml
Evolução do JTAG:
  1985: IEEE 1149.1 - Padrão JTAG original (teste de placas)
  1990: Primeiros processadores com suporte JTAG
  1995: JTAG adotado para depuração de software embarcado
  2000: Extensão para programação de memória flash
  2005: JTAG utilizado para ataques a sistemas embarcados
  2010: Ferramentas de debug abertas (OpenOCD, UrJTAG)
  2015: JTAG em dispositivos móveis e IoT
  2020: Ataques de segurança baseados em JTAG documentados
  2024: Contramedidas avançadas (JTAG locking, secure debug)

Motivação:
  ✅ Controle total do dispositivo (leitura/escrita de memória)
  ✅ Execução de código arbitrário
  ✅ Bypass de bootloaders seguros
  ✅ Extração de firmware e chaves criptográficas
  ✅ Debugging de sistemas "bloqueados"
```

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

```mermaid
graph TD
    subgraph "Interface JTAG"
        A[TDI - Test Data In]
        B[TDO - Test Data Out]
        C[TCK - Test Clock]
        D[TMS - Test Mode Select]
        E[TRST - Test Reset (opcional)]
    end
    
    subgraph "Dispositivo Alvo"
        F[TAP Controller]
        G[Boundary Scan Register]
        H[Instruction Register]
        I[Data Registers]
    end
    
    A --> F
    B <--> F
    C --> F
    D --> F
    
    F --> G
    F --> H
    F --> I
```

### **Comparação com Outras Interfaces de Debug**

| Interface | Pinos | Velocidade | Uso Típico           | Acesso          |
| --------- | ----- | ---------- | -------------------- | --------------- |
| **JTAG**  | 4-5   | 10-100 MHz | Processadores, FPGAs | Leitura/Escrita |
| **SWD**   | 2     | 1-50 MHz   | ARM Cortex           | Leitura/Escrita |
| **BDM**   | 6     | 10-50 MHz  | Motorola/Freescale   | Leitura/Escrita |
| **cJTAG** | 2     | 1-50 MHz   | Microcontroladores   | Leitura/Escrita |
| **ISP**   | 3-4   | 1-10 MHz   | Programação de flash | Escrita apenas  |
| **UART**  | 2-3   | 115200-3M  | Debug console        | Leitura/Escrita |

***

## 🏗️ **Arquitetura e Padrões**

### **Padrões JTAG**

```yaml
IEEE 1149.1 (JTAG Clássico):
  - Pinos: TDI, TDO, TCK, TMS, (TRST)
  - Estados: 16 estados no TAP controller
  - Registradores obrigatórios: Bypass, Boundary Scan, Device ID
  - Velocidade: Até 100 MHz (depende do dispositivo)

IEEE 1149.7 (cJTAG - Compact JTAG):
  - Pinos: 2 (TMS e TCK compartilhados)
  - Compatível com JTAG clássico
  - Menor footprint para dispositivos móveis
  - Consumo reduzido

IEEE 1532 (In-System Configuration):
  - Extensão para programação de CPLDs/FPGAs
  - Baseado no JTAG clássico

ARM SWD (Serial Wire Debug):
  - Pinos: 2 (SWDIO, SWCLK)
  - Alternativa ao JTAG para ARM Cortex
  - Menos pinos, mesma funcionalidade
  - Velocidade similar ao JTAG
```

### **TAP Controller (Test Access Port)**

```mermaid
stateDiagram-v2
    [*] --> Test-Logic-Reset
    
    Test-Logic-Reset --> Run-Test-Idle: 1
    Run-Test-Idle --> Select-DR-Scan: 1
    Select-DR-Scan --> Select-IR-Scan: 1
    Select-DR-Scan --> Capture-DR: 0
    
    Select-IR-Scan --> Capture-IR: 0
    Select-IR-Scan --> Test-Logic-Reset: 1
    
    Capture-IR --> Shift-IR: 0
    Shift-IR --> Exit1-IR: 1
    Exit1-IR --> Update-IR: 1
    Exit1-IR --> Pause-IR: 0
    
    Update-IR --> Run-Test-Idle: 1
    Update-IR --> Select-DR-Scan: 0
    
    Capture-DR --> Shift-DR: 0
    Shift-DR --> Exit1-DR: 1
    Exit1-DR --> Update-DR: 1
    Exit1-DR --> Pause-DR: 0
    
    Update-DR --> Run-Test-Idle: 1
    Update-DR --> Select-DR-Scan: 0
```

### **Registradores JTAG**

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

class JTAGRegisters:
    """
    Registradores padrão JTAG
    """
    
    # Instruções comuns
    INSTRUCTION_BYPASS = 0b111111
    INSTRUCTION_IDCODE = 0b000001
    INSTRUCTION_SAMPLE_PRELOAD = 0b000010
    INSTRUCTION_EXTEST = 0b000100
    INSTRUCTION_HIGHZ = 0b001000
    INSTRUCTION_CLAMP = 0b010000
    
    # Instruções específicas de fabricantes (exemplo ARM)
    ARM_INSTRUCTIONS = {
        0x01: "DPACC (Debug Port Access)",
        0x02: "APACC (Access Port Access)",
        0x03: "IDCODE",
        0x08: "ABORT",
        0x0A: "CTRL_STAT",
        0x0B: "SELECT",
        0x0C: "RDW (Read Watchpoint)",
        0x0D: "RDB (Read Breakpoint)",
    }
    
    class TAPState:
        """Estados do TAP Controller"""
        STATES = {
            0x0: "Test-Logic-Reset",
            0x1: "Run-Test-Idle",
            0x2: "Select-DR-Scan",
            0x3: "Capture-DR",
            0x4: "Shift-DR",
            0x5: "Exit1-DR",
            0x6: "Pause-DR",
            0x7: "Exit2-DR",
            0x8: "Update-DR",
            0x9: "Select-IR-Scan",
            0xA: "Capture-IR",
            0xB: "Shift-IR",
            0xC: "Exit1-IR",
            0xD: "Pause-IR",
            0xE: "Exit2-IR",
            0xF: "Update-IR"
        }
    
    @classmethod
    def parse_instruction(cls, instruction_code, manufacturer="unknown"):
        """
        Parsear instrução JTAG
        """
        if manufacturer == "arm":
            return cls.ARM_INSTRUCTIONS.get(instruction_code, f"Unknown ARM instruction: {hex(instruction_code)}")
        elif instruction_code == cls.INSTRUCTION_BYPASS:
            return "BYPASS"
        elif instruction_code == cls.INSTRUCTION_IDCODE:
            return "IDCODE"
        elif instruction_code == cls.INSTRUCTION_SAMPLE_PRELOAD:
            return "SAMPLE/PRELOAD"
        elif instruction_code == cls.INSTRUCTION_EXTEST:
            return "EXTEST"
        else:
            return f"Unknown instruction: {hex(instruction_code)}"

# Exemplo
reg = JTAGRegisters()
print(f"BYPASS: {reg.parse_instruction(0b111111)}")
print(f"ARM DPACC: {reg.parse_instruction(0x01, 'arm')}")
```

***

## 🔌 **Interfaces de Debug**

### **JTAG Pinout Comum**

```yaml
Conectores JTAG Padrão:
  
  Header 20 pinos (ARM padrão):
    - 1: VTref (VCC alvo)
    - 2: NC
    - 3: nTRST
    - 4: GND
    - 5: TDI
    - 6: GND
    - 7: TMS
    - 8: GND
    - 9: TCK
    - 10: GND
    - 11: RTCK
    - 12: GND
    - 13: TDO
    - 14: GND
    - 15: nSRST
    - 16: GND
    - 17: DBGRQ
    - 18: GND
    - 19: 5V
    - 20: GND

  Header 10 pinos (ARM Cortex):
    - 1: VTref
    - 2: TMS/SWDIO
    - 3: GND
    - 4: TCK/SWCLK
    - 5: GND
    - 6: TDO/SWO
    - 7: KEY
    - 8: TDI
    - 9: GND
    - 10: nSRST

  Header 5 pinos (JTAG/SWD):
    - 1: VCC
    - 2: SWDIO/TMS
    - 3: SWCLK/TCK
    - 4: GND
    - 5: SWO (opcional)
```

### **Identificação de Pontos JTAG**

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

import itertools
import time

class JTAGPinFinder:
    """
    Identificação de pinos JTAG em placas desconhecidas
    """
    
    def __init__(self, gpio_pins):
        self.pins = gpio_pins
        self.results = {}
    
    def test_tck(self, pin):
        """
        Identificar pino TCK (Test Clock)
        TCK geralmente tem clock constante (1-50 MHz)
        """
        # Em hardware real, medir frequência
        # Se o pino tem clock constante, é provavelmente TCK
        print(f"[*] Testando pino {pin} para TCK...")
        return False
    
    def test_tms(self, pin):
        """
        Identificar pino TMS (Test Mode Select)
        TMS muda de estado durante operações
        """
        print(f"[*] Testando pino {pin} para TMS...")
        return False
    
    def test_tdi(self, pin):
        """
        Identificar pino TDI (Test Data In)
        TDI recebe dados do debugger
        """
        print(f"[*] Testando pino {pin} para TDI...")
        return False
    
    def test_tdo(self, pin):
        """
        Identificar pino TDO (Test Data Out)
        TDO envia dados para o debugger
        """
        print(f"[*] Testando pino {pin} para TDO...")
        return False
    
    def scan_pins(self):
        """
        Escanear todos os pinos em busca de JTAG
        """
        for pin in self.pins:
            # Testar cada função
            if self.test_tck(pin):
                self.results['TCK'] = pin
            elif self.test_tms(pin):
                self.results['TMS'] = pin
            elif self.test_tdi(pin):
                self.results['TDI'] = pin
            elif self.test_tdo(pin):
                self.results['TDO'] = pin
        
        return self.results

# Exemplo
# finder = JTAGPinFinder([1,2,3,4,5,6,7,8,9,10])
# result = finder.scan_pins()
```

***

## 🛠️ **Equipamentos e Ferramentas**

### **Hardware de Debug**

| Equipamento            | Função               | Preço Médio (R$) | Onde Encontrar     |
| ---------------------- | -------------------- | ---------------- | ------------------ |
| **J-Link (SEGGER)**    | Debugger universal   | \~R$ 800-2000    | Mouser, DigiKey    |
| **ST-Link/V2**         | Debugger STM32       | \~R$ 50-100      | AliExpress, Shopee |
| **FTDI FT2232H**       | JTAG adaptador USB   | \~R$ 80-150      | AliExpress, Mouser |
| **Bus Pirate**         | Multi-ferramenta     | \~R$ 150-250     | AliExpress         |
| **OpenOCD compatible** | Debugger open source | \~R$ 30-80       | DIY (RPi Pico)     |
| **Raspberry Pi Pico**  | JTAG/SWD via GPIO    | \~R$ 35-50       | Shopee, AliExpress |
| **ESP-Prog**           | Debugger ESP32       | \~R$ 60-100      | AliExpress         |

### **Raspberry Pi Pico como Debugger (SWD)**

```python
# pico_swd_debugger.py - Para Raspberry Pi Pico

import machine
import time
import array

class SWDDebugger:
    """
    Debugger SWD simples usando Raspberry Pi Pico
    """
    
    # Comandos SWD
    SWD_CMD_ID_DP = 0
    SWD_CMD_ID_AP = 1
    
    # Registradores DP
    DP_IDCODE = 0x00
    DP_CTRL_STAT = 0x04
    DP_SELECT = 0x08
    DP_RDBUFF = 0x0C
    
    def __init__(self, swdio_pin=2, swclk_pin=3):
        """
        Inicializar debugger SWD
        """
        self.swdio = machine.Pin(swdio_pin, machine.Pin.OUT)
        self.swclk = machine.Pin(swclk_pin, machine.Pin.OUT)
        
        # Configurar pinos
        self.swdio.value(0)
        self.swclk.value(0)
        
        self.init_swd()
    
    def clock_cycle(self):
        """
        Gerar um ciclo de clock
        """
        self.swclk.value(1)
        time.sleep_us(1)
        self.swclk.value(0)
        time.sleep_us(1)
    
    def write_bit(self, bit):
        """
        Escrever um bit no SWDIO
        """
        self.swdio.value(bit)
        self.clock_cycle()
    
    def read_bit(self):
        """
        Ler um bit do SWDIO
        """
        # Mudar direção para entrada
        self.swdio = machine.Pin(2, machine.Pin.IN)
        self.clock_cycle()
        bit = self.swdio.value()
        # Voltar para saída
        self.swdio = machine.Pin(2, machine.Pin.OUT)
        return bit
    
    def init_swd(self):
        """
        Inicializar comunicação SWD
        """
        # Sequência de 8 bits para ativar SWD
        # 0b10011110 (0x9E) - SW-DP activation
        activation_seq = 0x9E
        
        for i in range(8):
            bit = (activation_seq >> i) & 1
            self.write_bit(bit)
        
        # Aguardar resposta
        time.sleep_us(10)
        
        # Ler ACK
        ack = 0
        for i in range(3):
            ack |= self.read_bit() << i
        
        if ack == 0b001:  # OK
            print("[+] SWD inicializado com sucesso")
            return True
        else:
            print(f"[-] Falha na inicialização SWD (ACK: {ack:03b})")
            return False
    
    def read_dp_register(self, address):
        """
        Ler registrador DP
        """
        # Comando de leitura
        cmd = (0 << 1) | (1 << 2) | (self.SWD_CMD_ID_DP << 4)
        
        # Enviar comando
        for i in range(8):
            self.write_bit((cmd >> i) & 1)
        
        # Ler ACK
        ack = 0
        for i in range(3):
            ack |= self.read_bit() << i
        
        if ack != 0b001:
            return None
        
        # Ler dados (32 bits)
        data = 0
        for i in range(32):
            data |= self.read_bit() << i
        
        # Paridade
        parity = self.read_bit()
        
        return data
    
    def read_idcode(self):
        """
        Ler IDCODE do dispositivo
        """
        return self.read_dp_register(self.DP_IDCODE)

# Exemplo
# debugger = SWDDebugger()
# idcode = debugger.read_idcode()
# print(f"IDCODE: {hex(idcode)}")
```

### **Ferramentas de Software**

```bash
# OpenOCD - Open On-Chip Debugger
sudo apt install openocd
openocd -f interface/jlink.cfg -f target/stm32f4x.cfg

# UrJTAG - Universal JTAG
sudo apt install urjtag
jtag> cable ft2232
jtag> detect

# pyOCD - Python CMSIS-DAP
pip install pyocd
pyocd list
pyocd flash --target stm32f429zi firmware.bin

# J-Link Commander
JLinkExe -device STM32F429ZI -if SWD -speed 4000

# GDB with JTAG
arm-none-eabi-gdb
(gdb) target remote localhost:3333
(gdb) monitor reset
(gdb) load firmware.elf
```

***

## ⚔️ **Técnicas de Ataque**

### **1. Leitura de Memória via JTAG**

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

import pylink
import time

class JTAGMemoryReader:
    """
    Leitura de memória via JTAG/SWD
    """
    
    def __init__(self, jlink_serial=None):
        """
        Inicializar J-Link
        """
        self.jlink = pylink.JLink()
        
        if jlink_serial:
            self.jlink.open(jlink_serial)
        else:
            # Abrir primeiro J-Link encontrado
            self.jlink.open()
        
        print(f"[+] J-Link conectado: {self.jlink.product_name}")
    
    def connect_to_target(self, device, interface='SWD', speed=4000):
        """
        Conectar ao dispositivo alvo
        """
        self.jlink.connect(device, interface=interface, speed=speed)
        print(f"[+] Conectado a: {device}")
        
        # Reset e halt
        self.jlink.reset()
        self.jlink.halt()
        print("[+] Target halted")
    
    def read_memory(self, address, size_bytes):
        """
        Ler memória do dispositivo
        """
        try:
            data = self.jlink.memory_read8(address, size_bytes)
            return bytes(data)
        except Exception as e:
            print(f"[-] Erro na leitura: {e}")
            return None
    
    def read_flash(self, start_address, size_bytes):
        """
        Ler flash do dispositivo
        """
        print(f"[*] Lendo flash: 0x{start_address:08X} - {size_bytes} bytes")
        data = self.read_memory(start_address, size_bytes)
        
        if data:
            # Salvar em arquivo
            with open('flash_dump.bin', 'wb') as f:
                f.write(data)
            print(f"[+] Flash salvo em flash_dump.bin")
        
        return data
    
    def read_ram(self, start_address, size_bytes):
        """
        Ler RAM do dispositivo
        """
        print(f"[*] Lendo RAM: 0x{start_address:08X} - {size_bytes} bytes")
        return self.read_memory(start_address, size_bytes)
    
    def search_for_strings(self, data, min_length=4):
        """
        Buscar strings na memória lida
        """
        strings = []
        current = []
        
        for byte in data:
            if 32 <= byte <= 126:  # ASCII imprimível
                current.append(chr(byte))
            else:
                if len(current) >= min_length:
                    strings.append(''.join(current))
                current = []
        
        if len(current) >= min_length:
            strings.append(''.join(current))
        
        return strings

# Exemplo de uso
# reader = JTAGMemoryReader()
# reader.connect_to_target('STM32F429ZI')
# flash = reader.read_flash(0x08000000, 1024*1024)
# strings = reader.search_for_strings(flash)
# print(f"Strings encontradas: {strings[:10]}")
```

### **2. Escrita de Memória (Firmware Injection)**

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

import pylink
import time

class JTAGFirmwareInjector:
    """
    Injeção de firmware via JTAG
    """
    
    def __init__(self, jlink):
        self.jlink = jlink
    
    def write_memory(self, address, data):
        """
        Escrever dados na memória
        """
        try:
            self.jlink.memory_write8(address, list(data))
            print(f"[+] Dados escritos em 0x{address:08X}")
            return True
        except Exception as e:
            print(f"[-] Erro na escrita: {e}")
            return False
    
    def write_flash(self, start_address, firmware_path):
        """
        Programar firmware na flash
        """
        with open(firmware_path, 'rb') as f:
            firmware = f.read()
        
        print(f"[*] Programando firmware: {len(firmware)} bytes")
        
        # Desbloquear flash para escrita
        self.unlock_flash()
        
        # Escrever em blocos
        block_size = 1024
        for offset in range(0, len(firmware), block_size):
            block = firmware[offset:offset+block_size]
            address = start_address + offset
            self.write_memory(address, block)
            print(f"  Progresso: {offset}/{len(firmware)} bytes")
        
        # Verificar
        self.verify_flash(start_address, firmware)
        
        return True
    
    def unlock_flash(self):
        """
        Desbloquear flash para escrita
        """
        # Específico para cada dispositivo
        # Exemplo: STM32
        self.write_memory(0x40023C00, [0x45670123])  # Flash Key Register
        self.write_memory(0x40023C04, [0xCDEF89AB])  # Flash Key Register
        print("[+] Flash desbloqueada")
    
    def verify_flash(self, start_address, expected_data):
        """
        Verificar integridade da flash
        """
        read_data = self.read_memory(start_address, len(expected_data))
        
        if read_data == expected_data:
            print("[+] Verificação OK")
            return True
        else:
            print("[-] Verificação falhou")
            return False
    
    def execute_code(self, entry_point):
        """
        Executar código injetado
        """
        # Set PC (Program Counter)
        self.jlink.write_reg('PC', entry_point)
        
        # Run
        self.jlink.go()
        print(f"[+] Executando código em 0x{entry_point:08X}")

# Exemplo
# injector = JTAGFirmwareInjector(jlink)
# injector.write_flash(0x08000000, 'malicious_firmware.bin')
```

### **3. Bypass de Bootloader Seguro**

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

class SecureBootBypass:
    """
    Técnicas para bypass de secure boot via JTAG
    """
    
    @staticmethod
    def halt_at_boot():
        """
        Parar execução durante bootloader
        """
        print("[*] Conectando durante boot...")
        print("[*] Target halted")
        print("[!] Bootloader bypassado - execução interrompida")
        
        # Agora pode-se ler/modificar memória antes da verificação
        return True
    
    @staticmethod
    def modify_signature_check():
        """
        Modificar instrução de verificação de assinatura
        """
        # Identificar endereço da verificação
        signature_check_addr = 0x08001234  # Exemplo
        
        # Patch para sempre retornar sucesso
        # ARM: MOV R0, #0 ; BX LR
        patch = [0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1]
        
        print(f"[*] Patch em 0x{signature_check_addr:08X}: {patch}")
        print("[+] Verificação de assinatura bypassada")
        
        return True
    
    @staticmethod
    def dump_bootloader():
        """
        Extrair bootloader para análise
        """
        print("[*] Extraindo bootloader via JTAG...")
        # Ler região de bootloader
        bootloader_start = 0x08000000
        bootloader_size = 0x8000
        
        # bootloader_data = jlink.read_memory(bootloader_start, bootloader_size)
        # with open('bootloader.bin', 'wb') as f:
        #     f.write(bootloader_data)
        
        print("[+] Bootloader extraído")
        return True
```

### **4. Ataque a Sistemas de Pagamento (Exemplo)**

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

class POSTerminalAttack:
    """
    Ataque a terminais de pagamento via JTAG
    """
    
    def __init__(self):
        self.debugger = None
        self.has_jtag = False
    
    def locate_jtag_points(self):
        """
        Localizar pontos JTAG no terminal
        """
        print("[*] Procurando pontos JTAG...")
        print("  - Verificando conectores internos")
        print("  - Buscando pads de teste")
        print("  - Identificando pinos via multímetro")
        
        # Simular descoberta
        jtag_pins = {
            'TMS': 5,
            'TCK': 7,
            'TDI': 9,
            'TDO': 13,
            'TRST': 3
        }
        
        print(f"[+] Pontos JTAG encontrados: {jtag_pins}")
        self.has_jtag = True
        
        return jtag_pins
    
    def extract_keys(self):
        """
        Extrair chaves criptográficas
        """
        print("[*] Extraindo chaves criptográficas...")
        
        # Regiões de memória comuns para chaves
        key_locations = [
            0x08001000,  # Flash
            0x20000000,  # SRAM
            0x1FFF0000,  # System memory
        ]
        
        keys = []
        for loc in key_locations:
            # data = debugger.read_memory(loc, 256)
            # keys.append(data)
            pass
        
        print(f"[+] {len(keys)} chaves extraídas")
        return keys
    
    def bypass_pin_verification(self):
        """
        Bypass de verificação de PIN
        """
        print("[*] Localizando verificação de PIN...")
        
        # Patch da instrução de comparação
        # CMP R0, #0 -> CMP R0, #0 (modificar para sempre igual)
        print("[+] Verificação de PIN bypassada")
        
        return True
    
    def dump_transaction_logs(self):
        """
        Extrair logs de transações
        """
        print("[*] Extraindo logs de transações...")
        
        # Localizar região de logs
        logs_start = 0x08020000
        logs_size = 0x10000
        
        # logs = debugger.read_memory(logs_start, logs_size)
        print(f"[+] {logs_size} bytes de logs extraídos")
        
        return True

# Exemplo
# pos = POSTerminalAttack()
# pos.locate_jtag_points()
# pos.extract_keys()
# pos.bypass_pin_verification()
```

***

## 🛡️ **Contramedidas e Proteções**

### **Proteções de Hardware**

```yaml
Proteções Contra JTAG Abuse:
  
  JTAG Locking (Secured Mode):
    - Desabilita JTAG após programação
    - Requer autenticação para reativar
    - Implementado na maioria dos microcontroladores
  
  Fuse Bits:
    - Queima de fusíveis que desabilitam JTAG
    - Irreversível
    - Comum em AVR, PIC
  
  Read-Out Protection (RDP):
    - Protege leitura de flash via JTAG
    - Níveis: 0 (desprotegido), 1 (protegido), 2 (irreversível)
  
  Secure Debug Authentication:
    - Autenticação antes de permitir acesso JTAG
    - Uso de chaves criptográficas
    - Challenge-response
  
  Physical Tamper Detection:
    - Sensores que detectam tentativas de acesso JTAG
    - Apagamento de memória ao detectar violação
  
  Ocultação de Pontos JTAG:
    - Remoção de conectores JTAG em produção
    - Uso de pads ocultos sob componentes
    - Camadas extras de PCB
```

### **Configuração de Proteção (STM32)**

```c
// stm32_jtag_lock.c
#include "stm32f4xx.h"

void enable_jtag_lock(void) {
    // Configurar Option Bytes
    FLASH_OBProgramInitTypeDef OBInit;
    
    OBInit.OptionType = OPTIONBYTE_RDP;
    OBInit.RDPLevel = OB_RDP_LEVEL_2;  // Nível máximo de proteção
    
    HAL_FLASH_OB_Unlock();
    HAL_FLASH_OB_Program(&OBInit);
    HAL_FLASH_OB_Lock();
    
    // JTAG desabilitado permanentemente
    // Somente reset geral reativa (com perda de dados)
}

void enable_read_out_protection(void) {
    // RDP Level 1: Flash não pode ser lida via JTAG
    FLASH_OBProgramInitTypeDef OBInit;
    OBInit.OptionType = OPTIONBYTE_RDP;
    OBInit.RDPLevel = OB_RDP_LEVEL_1;
    
    HAL_FLASH_OB_Unlock();
    HAL_FLASH_OB_Program(&OBInit);
    HAL_FLASH_OB_Lock();
}
```

### **Detecção de Acesso JTAG**

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

import time
import machine

class JTAGDetection:
    """
    Detecção de tentativas de acesso JTAG
    """
    
    def __init__(self):
        self.tamper_pin = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)
        self.jtag_detected = False
    
    def check_jtag_voltage(self):
        """
        Verificar tensão em pinos JTAG
        """
        # Em hardware real, ler tensão dos pinos JTAG
        # Níveis anormais podem indicar tentativa de acesso
        return False
    
    def check_clock_activity(self):
        """
        Verificar atividade de clock nos pinos JTAG
        """
        # Monitorar TCK para atividade não autorizada
        return False
    
    def on_tamper_detect(self):
        """
        Callback quando tamper detectado
        """
        print("[!] TENTATIVA DE ACESSO JTAG DETECTADA!")
        self.jtag_detected = True
        
        # Apagar memória sensível
        self.erase_sensitive_data()
        
        # Registrar evento
        self.log_incident()
        
        return True
    
    def erase_sensitive_data(self):
        """
        Apagar dados sensíveis
        """
        print("[*] Apagando chaves criptográficas...")
        print("[*] Apagando logs...")
        print("[+] Dados sensíveis apagados")
    
    def log_incident(self):
        """
        Registrar incidente
        """
        with open("/secure/logs/tamper.log", "a") as f:
            f.write(f"JTAG tamper detected at {time.time()}\n")
```

***

## 🔧 **Ferramentas e Hardware DIY**

### **OpenOCD Configuration**

```tcl
# openocd.cfg
# Interface
source [find interface/jlink.cfg]
transport select swd
adapter speed 4000

# Target
source [find target/stm32f4x.cfg]

# Commands
init
reset halt
flash write_image erase firmware.bin 0x08000000
reset
exit
```

### **Raspberry Pi Pico como JTAG**

```python
# pico_jtag.py - JTAG via PIO (Programmable I/O)

import rp2
import machine
import array

@rp2.asm_pio(
    out_init=rp2.PIO.OUT_LOW,
    out_shiftdir=rp2.PIO.SHIFT_LEFT,
    sideset_init=rp2.PIO.OUT_LOW,
    autopull=True,
    pull_thresh=32
)
def jtag_program():
    # Programa PIO para JTAG
    # Implementação simplificada
    wrap_target()
    # Enviar dados TDI
    out(pins, 1) .side(0)
    # Clock TCK
    set(pins, 1) .side(1)
    set(pins, 0) .side(0)
    wrap()

class PicoJTAG:
    """
    JTAG via Raspberry Pi Pico PIO
    """
    
    def __init__(self):
        # Configurar PIO
        self.sm = rp2.StateMachine(0, jtag_program, freq=50_000_000,
                                    set_base=machine.Pin(0),
                                    out_base=machine.Pin(1),
                                    sideset_base=machine.Pin(2))
        self.sm.active(1)
    
    def shift_data(self, tdi_data, bits=32):
        """
        Deslocar dados JTAG
        """
        self.sm.put(tdi_data, 8)
        tdo_data = self.sm.get()
        return tdo_data
    
    def read_idcode(self):
        """
        Ler IDCODE via JTAG
        """
        # Selecionar IR
        # Instrução IDCODE
        # Ler dados
        pass

# Exemplo
# jtag = PicoJTAG()
# idcode = jtag.read_idcode()
# print(f"IDCODE: {hex(idcode)}")
```

### **Custos Estimados (BRL)**

| Equipamento                  | Preço Médio (R$) | Onde Encontrar     |
| ---------------------------- | ---------------- | ------------------ |
| **J-Link EDU Mini**          | \~R$ 300-400     | Mouser, DigiKey    |
| **ST-Link/V2 clone**         | \~R$ 30-50       | AliExpress, Shopee |
| **FT2232H Module**           | \~R$ 80-120      | AliExpress         |
| **Raspberry Pi Pico**        | \~R$ 35-50       | Shopee, AliExpress |
| **Bus Pirate**               | \~R$ 150-200     | AliExpress         |
| **Logic Analyzer**           | \~R$ 50-100      | AliExpress         |
| **Total Setup Básico**       | \~R$ 100-150     | -                  |
| **Total Setup Profissional** | \~R$ 500-800     | -                  |

***

## 📊 **Conclusão e Boas Práticas**

### **Resumo Técnico**

```yaml
JTAG & Debugging Abuse:
  ✅ Acesso privilegiado ao dispositivo
  ✅ Leitura/escrita de memória
  ✅ Execução de código arbitrário
  ✅ Bypass de mecanismos de segurança

Defesas:
  ❌ JTAG locking (quando implementado)
  ✓ Read-Out Protection (RDP)
  ✓ Fusíveis permanentes
  ✓ Remoção física de pontos JTAG
  ✓ Detecção de tamper
```

### **Recomendações Finais**

1. **Para Desenvolvedores**
   * Habilitar JTAG locking em produção
   * Usar RDP Level 2 quando possível
   * Remover pads de teste em produção
   * Implementar detecção de tamper
2. **Para Pesquisadores/Pentesters**
   * Identificar pontos JTAG em placas
   * Usar ferramentas como Bus Pirate ou J-Link
   * Estudar datasheets para pinout
   * Documentar configurações de segurança
3. **Para Profissionais de Segurança**
   * Verificar proteções JTAG em produtos
   * Testar resistência a ataques físicos
   * Implementar secure boot
   * Considerar módulos de segurança dedicados


---

# 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/hardware/jtag-and-debugging-abuse.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.
