# Extração de Metadados EXIF

## 📑 **Índice**

1. [Fundamentos do EXIF](#-fundamentos-do-exif)
2. [Arquitetura e Estrutura EXIF](#-arquitetura-e-estrutura-exif)
3. [Ferramentas de Extração](#-ferramentas-de-extração)
4. [Técnicas de Extração e Análise](#-técnicas-de-extração-e-análise)
5. [Implementação em Python](#-implementação-em-python)
6. [Implementação em C/C++](#-implementação-em-cc)
7. [Implementação em PowerShell](#-implementação-em-powershell)
8. [Forense e OSINT com EXIF](#-forense-e-osint-com-exif)
9. [Detecção e Mitigação](#-detecção-e-mitigação)

***

## 🔍 **Fundamentos do EXIF**

### **O que é EXIF?**

EXIF (Exchangeable Image File Format) é um padrão que especifica os formatos de arquivo de imagem e as tags de metadados utilizados por câmeras digitais, scanners e outros dispositivos de captura de imagem. Criado pela Japan Electronic Industries Development Association (JEIDA) em 1998, o EXIF incorpora informações sobre a imagem, como data/hora, configurações da câmera, geolocalização, e muito mais.

### **Contexto Histórico**

```yaml
Evolução do EXIF:
  1995: JPEG Group propõe padrão para metadados
  1998: EXIF versão 1.0 é lançado
  2002: EXIF 2.2 (EXIF Print) adiciona informações de impressão
  2005: GPS Tags são padronizadas
  2010: EXIF 2.3 adiciona suporte para vídeos
  2019: EXIF 2.32 é a versão mais recente

Motivação:
  ✅ Armazenar informações da câmera para referência
  ✅ Facilitar organização de fotos
  ✅ Suporte a geotagging
  ⚠️ Preocupações de privacidade com dados sensíveis
```

### **Importância Forense e OSINT**

```yaml
Informações Extraíveis:
  
  Geolocalização:
    - Latitude e Longitude
    - Altitude
    - Direção da câmera
  
  Dados da Câmera:
    - Modelo e fabricante
    - Número de série
    - Configurações (ISO, abertura, velocidade)
    - Data e hora da captura
  
  Dados do Dispositivo:
    - Software de edição
    - Thumbnails (às vezes contendo informações sensíveis)
    - Comentários e descrições
  
  Dados de Rede (em algumas câmeras):
    - Endereços MAC de Wi-Fi
    - SSID de redes conectadas
```

***

## 🏗️ **Arquitetura e Estrutura EXIF**

### **Estrutura do Arquivo JPEG com EXIF**

```mermaid
graph TD
    subgraph "Arquivo JPEG"
        A[SOI - Start of Image (FF D8)]
        B[APP1 Marker (FF E1)]
        C[EXIF Data Segment]
        D[APP0 - JFIF]
        E[Image Data (SOS)]
    end
    
    subgraph "EXIF Data Structure"
        F[TIFF Header]
        G[IFD0 - Primary Image]
        H[IFD1 - Thumbnail]
        I[GPS IFD]
        J[Exif IFD]
    end
    
    B --> C
    C --> F
    F --> G
    G --> H
    G --> I
    G --> J
```

### **Estrutura de Tags EXIF**

```python
# Estrutura de uma tag EXIF
class EXIFTag:
    """
    Cada tag EXIF tem:
    - Tag ID (2 bytes)
    - Type (2 bytes)
    - Count (4 bytes)
    - Value/Offset (4 bytes)
    """
    
    TAG_TYPES = {
        1: 'BYTE',      # 8-bit unsigned integer
        2: 'ASCII',     # 8-bit byte (character)
        3: 'SHORT',     # 16-bit unsigned integer
        4: 'LONG',      # 32-bit unsigned integer
        5: 'RATIONAL',  # Two LONGs (numerator/denominator)
        7: 'UNDEFINED', # 8-bit byte
        9: 'SLONG',     # 32-bit signed integer
        10: 'SRATIONAL' # Two SLONGs
    }
```

### **Tags EXIF Mais Relevantes**

| Tag ID     | Nome            | Descrição               | Valor de Exemplo       |
| ---------- | --------------- | ----------------------- | ---------------------- |
| **0x010F** | Make            | Fabricante da câmera    | "Canon"                |
| **0x0110** | Model           | Modelo da câmera        | "Canon EOS 5D Mark IV" |
| **0x0132** | DateTime        | Data e hora original    | "2024:01:15 14:30:00"  |
| **0x8298** | Copyright       | Informação de copyright | "© John Doe"           |
| **0x8827** | ISOSpeedRatings | ISO utilizado           | 400                    |
| **0x9209** | Flash           | Status do flash         | 1 (disparou)           |
| **0x8825** | GPSInfo         | Ponteiro para GPS IFD   | -                      |
| **0x0002** | GPSLatitude     | Latitude                | "22/1, 30/1, 0/1"      |
| **0x0004** | GPSLongitude    | Longitude               | "114/1, 10/1, 0/1"     |
| **0x001B** | GPSDateStamp    | Data GPS                | "2024:01:15"           |

***

## 🛠️ **Ferramentas de Extração**

### **1. ExifTool (Perl) – A Ferramenta Mais Completa**

```bash
# Instalação
# Linux
sudo apt install exiftool

# macOS
brew install exiftool

# Windows
# Download de https://exiftool.org/

# Comandos básicos
exiftool imagem.jpg

# Extrair apenas tags GPS
exiftool -gps:all imagem.jpg

# Extrair apenas dados da câmera
exiftool -camera:all imagem.jpg

# Extrair dados em formato JSON
exiftool -json imagem.jpg

# Extrair de múltiplos arquivos
exiftool -csv -r /caminho/das/fotos/ > metadados.csv

# Remover metadados
exiftool -all= imagem.jpg

# Remover apenas GPS
exiftool -gps:all= imagem.jpg

# Visualizar dados brutos
exiftool -v imagem.jpg
```

### **2. Exiv2 (C++)**

```bash
# Instalação
sudo apt install exiv2

# Comandos
exiv2 imagem.jpg

# Extrair para arquivo
exiv2 -pe imagem.jpg > metadados.txt

# Remover metadados
exiv2 rm imagem.jpg

# Extrair thumbnails
exiv2 -et imagem.jpg
```

### **3. ImageMagick (identify)**

```bash
# Instalação
sudo apt install imagemagick

# Extrair metadados
identify -verbose imagem.jpg

# Formato JSON
identify -format "%[EXIF:*]" imagem.jpg
```

### **4. jhead (JPEG Header Tool)**

```bash
# Instalação
sudo apt install jhead

# Comandos
jhead imagem.jpg

# Remover todos os metadados
jhead -purejpg imagem.jpg

# Remover apenas GPS
jhead -nogps imagem.jpg
```

### **5. Ferramentas Online (Cuidado com Privacidade!)**

```yaml
Ferramentas Online:
  - Jeffrey's Exif Viewer (exif.regex.info)
  - Metapicz (metapicz.com)
  - ExifData (exifdata.com)
  - FotoForensics (fotoforensics.com)

⚠️ ALERTA: Ferramentas online enviam suas imagens para servidores externos.
Nunca use para imagens sensíveis ou evidências forenses!
```

***

## ⚔️ **Técnicas de Extração e Análise**

### **1. Extração com ExifTool (Linha de Comando)**

```bash
#!/bin/bash
# extract_exif.sh - Script de extração de metadados

echo "=== Extração de Metadados EXIF ==="
echo

# Extrair informações básicas
echo "[1] Informações básicas:"
exiftool -FileName -FileSize -FileType -ImageSize "$1"

echo
echo "[2] Dados da câmera:"
exiftool -Make -Model -LensModel -FocalLength -FNumber -ISO -ExposureTime "$1"

echo
echo "[3] Data e hora:"
exiftool -DateTimeOriginal -CreateDate -ModifyDate "$1"

echo
echo "[4] Geolocalização:"
exiftool -GPSLatitude -GPSLongitude -GPSAltitude -GPSPosition "$1"

echo
echo "[5] Software de edição:"
exiftool -Software -Creator -Copyright "$1"

echo
echo "[6] Thumbnail presente:"
exiftool -ThumbnailImage -b "$1" | wc -c | awk '{print "Tamanho do thumbnail: " $1 " bytes"}'

# Extrair dados completos em JSON
exiftool -j "$1" > "${1%.jpg}.json"
echo
echo "[+] Dados salvos em ${1%.jpg}.json"
```

### **2. Extração com Exiv2**

```bash
#!/bin/bash
# exiv2_extract.sh

echo "=== Extração de Metadados com Exiv2 ==="
echo

# Listar todos os metadados
exiv2 -pe "$1"

# Extrair dados GPS
exiv2 -g GPSInfo "$1"

# Extrair para arquivo
exiv2 -pe "$1" > "${1%.jpg}_metadata.txt"

# Extrair thumbnail
exiv2 -et "$1"
```

### **3. Extração com jhead**

```bash
#!/bin/bash
# jhead_extract.sh

echo "=== Extração de Metadados com jhead ==="
echo

# Informações básicas
jhead "$1"

# Dados GPS formatados
jhead -nofinfo -c "$1"

# Extrair dados em formato legível
jhead -v "$1" > "${1%.jpg}_jhead.txt"
```

***

## 🐍 **Implementação em Python**

### **1. Extração com Pillow (PIL)**

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

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
import sys

class EXIFExtractor:
    """Extrator de metadados EXIF usando Pillow"""
    
    def __init__(self, image_path):
        self.image_path = image_path
        self.exif_data = {}
        self.gps_data = {}
    
    def extract(self):
        """Extrair todos os metadados EXIF"""
        try:
            image = Image.open(self.image_path)
            exif = image._getexif()
            
            if not exif:
                print("[-] Nenhum metadado EXIF encontrado")
                return None
            
            for tag_id, value in exif.items():
                tag_name = TAGS.get(tag_id, tag_id)
                
                # Processar dados GPS
                if tag_name == 'GPSInfo':
                    self.gps_data = self._extract_gps(value)
                    self.exif_data[tag_name] = self.gps_data
                else:
                    self.exif_data[tag_name] = value
            
            return self.exif_data
            
        except Exception as e:
            print(f"[-] Erro ao extrair EXIF: {e}")
            return None
    
    def _extract_gps(self, gps_info):
        """Extrair informações GPS"""
        gps = {}
        for tag_id, value in gps_info.items():
            tag_name = GPSTAGS.get(tag_id, tag_id)
            gps[tag_name] = value
        return gps
    
    def get_coordinates(self):
        """Obter coordenadas GPS em formato decimal"""
        if not self.gps_data:
            return None
        
        try:
            lat = self._convert_to_decimal(
                self.gps_data.get('GPSLatitude'),
                self.gps_data.get('GPSLatitudeRef')
            )
            lon = self._convert_to_decimal(
                self.gps_data.get('GPSLongitude'),
                self.gps_data.get('GPSLongitudeRef')
            )
            return (lat, lon)
        except:
            return None
    
    def _convert_to_decimal(self, coord, ref):
        """Converter coordenadas GPS para decimal"""
        if not coord:
            return None
        
        degrees = coord[0]
        minutes = coord[1]
        seconds = coord[2]
        
        decimal = degrees + (minutes / 60.0) + (seconds / 3600.0)
        
        if ref in ['S', 'W']:
            decimal = -decimal
        
        return decimal
    
    def display(self):
        """Exibir metadados formatados"""
        if not self.exif_data:
            return
        
        print("\n=== Metadados EXIF ===")
        print(f"Arquivo: {self.image_path}\n")
        
        # Dados da câmera
        print("[Dados da Câmera]")
        for tag in ['Make', 'Model', 'LensModel']:
            if tag in self.exif_data:
                print(f"  {tag}: {self.exif_data[tag]}")
        
        # Configurações
        print("\n[Configurações]")
        for tag in ['FNumber', 'ExposureTime', 'ISOSpeedRatings', 'FocalLength']:
            if tag in self.exif_data:
                print(f"  {tag}: {self.exif_data[tag]}")
        
        # Data e hora
        print("\n[Data/Hora]")
        for tag in ['DateTime', 'DateTimeOriginal', 'DateTimeDigitized']:
            if tag in self.exif_data:
                print(f"  {tag}: {self.exif_data[tag]}")
        
        # GPS
        if self.gps_data:
            print("\n[Geolocalização]")
            coords = self.get_coordinates()
            if coords:
                print(f"  Coordenadas: {coords[0]:.6f}, {coords[1]:.6f}")
                print(f"  Link: https://maps.google.com/?q={coords[0]},{coords[1]}")
        
        # Outras informações
        print("\n[Outras Informações]")
        for tag in ['Software', 'Copyright', 'Artist', 'ImageDescription']:
            if tag in self.exif_data:
                print(f"  {tag}: {self.exif_data[tag]}")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Uso: python exif_pillow.py <imagem.jpg>")
        sys.exit(1)
    
    extractor = EXIFExtractor(sys.argv[1])
    extractor.extract()
    extractor.display()
```

### **2. Extração com PyExifTool**

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

import subprocess
import json
import sys

class PyExifToolExtractor:
    """Extrator usando exiftool via subprocess"""
    
    def __init__(self, exiftool_path='exiftool'):
        self.exiftool_path = exiftool_path
    
    def extract(self, image_path):
        """Extrair metadados via exiftool"""
        try:
            result = subprocess.run(
                [self.exiftool_path, '-json', image_path],
                capture_output=True,
                text=True
            )
            
            if result.returncode != 0:
                print(f"[-] Erro: {result.stderr}")
                return None
            
            data = json.loads(result.stdout)[0]
            return data
            
        except Exception as e:
            print(f"[-] Erro: {e}")
            return None
    
    def extract_gps(self, image_path):
        """Extrair apenas dados GPS"""
        try:
            result = subprocess.run(
                [self.exiftool_path, '-gps:all', '-json', image_path],
                capture_output=True,
                text=True
            )
            
            if result.returncode != 0:
                return None
            
            data = json.loads(result.stdout)[0]
            return data
            
        except Exception as e:
            return None
    
    def remove_metadata(self, image_path, output_path=None):
        """Remover metadados da imagem"""
        if not output_path:
            output_path = image_path
        
        cmd = [self.exiftool_path, '-all=', '-overwrite_original', image_path]
        subprocess.run(cmd, capture_output=True)
        print(f"[+] Metadados removidos de {image_path}")

# Exemplo de uso
if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Uso: python exif_pyexiftool.py <imagem.jpg>")
        sys.exit(1)
    
    extractor = PyExifToolExtractor()
    data = extractor.extract(sys.argv[1])
    
    if data:
        print(json.dumps(data, indent=2, ensure_ascii=False))
```

### **3. Extrator Completo com Análise Forense**

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

import os
import sys
import hashlib
import json
from datetime import datetime
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS

class EXIFForensic:
    """Ferramenta forense para análise de metadados EXIF"""
    
    def __init__(self, image_path):
        self.image_path = image_path
        self.image = None
        self.exif = None
        self.hash = None
        self.results = {}
    
    def calculate_hash(self):
        """Calcular hash SHA256 da imagem"""
        with open(self.image_path, 'rb') as f:
            self.hash = hashlib.sha256(f.read()).hexdigest()
        return self.hash
    
    def analyze_file_info(self):
        """Análise básica do arquivo"""
        stats = os.stat(self.image_path)
        
        self.results['file_info'] = {
            'filename': os.path.basename(self.image_path),
            'size': stats.st_size,
            'size_mb': stats.st_size / (1024 * 1024),
            'modified': datetime.fromtimestamp(stats.st_mtime).isoformat(),
            'created': datetime.fromtimestamp(stats.st_ctime).isoformat(),
            'sha256': self.hash
        }
    
    def analyze_exif(self):
        """Análise detalhada dos metadados EXIF"""
        try:
            self.image = Image.open(self.image_path)
            exif = self.image._getexif()
            
            if not exif:
                self.results['exif'] = {'present': False}
                return
            
            exif_data = {}
            for tag_id, value in exif.items():
                tag_name = TAGS.get(tag_id, tag_id)
                
                if tag_name == 'GPSInfo':
                    exif_data['GPSInfo'] = self._parse_gps(value)
                else:
                    # Converter bytes para string se necessário
                    if isinstance(value, bytes):
                        value = value.decode('utf-8', errors='ignore')
                    exif_data[tag_name] = value
            
            self.results['exif'] = {
                'present': True,
                'data': exif_data
            }
            
        except Exception as e:
            self.results['exif'] = {'error': str(e)}
    
    def _parse_gps(self, gps_info):
        """Parsear informações GPS"""
        gps = {}
        for tag_id, value in gps_info.items():
            tag_name = GPSTAGS.get(tag_id, tag_id)
            gps[tag_name] = value
        
        # Converter para decimal
        try:
            lat = self._to_decimal(
                gps.get('GPSLatitude'),
                gps.get('GPSLatitudeRef', 'N')
            )
            lon = self._to_decimal(
                gps.get('GPSLongitude'),
                gps.get('GPSLongitudeRef', 'E')
            )
            
            if lat and lon:
                gps['latitude_decimal'] = lat
                gps['longitude_decimal'] = lon
                gps['google_maps_link'] = f"https://maps.google.com/?q={lat},{lon}"
                gps['openstreetmap_link'] = f"https://www.openstreetmap.org/?mlat={lat}&mlon={lon}"
                
        except Exception as e:
            gps['parse_error'] = str(e)
        
        return gps
    
    def _to_decimal(self, coord, ref):
        """Converter coordenada para decimal"""
        if not coord or len(coord) < 3:
            return None
        
        degrees = float(coord[0])
        minutes = float(coord[1])
        seconds = float(coord[2])
        
        decimal = degrees + (minutes / 60.0) + (seconds / 3600.0)
        
        if ref in ['S', 'W']:
            decimal = -decimal
        
        return decimal
    
    def analyze_privacy_risks(self):
        """Analisar riscos de privacidade"""
        risks = []
        
        if self.results.get('exif', {}).get('data', {}).get('GPSInfo'):
            risks.append({
                'level': 'HIGH',
                'type': 'geolocation',
                'description': 'Coordenadas GPS estão presentes na imagem'
            })
        
        if self.results.get('exif', {}).get('data', {}).get('Artist'):
            risks.append({
                'level': 'MEDIUM',
                'type': 'author',
                'description': 'Nome do autor/criador está presente'
            })
        
        if self.results.get('exif', {}).get('data', {}).get('Software'):
            software = self.results['exif']['data']['Software']
            if 'photoshop' in software.lower() or 'lightroom' in software.lower():
                risks.append({
                    'level': 'LOW',
                    'type': 'software',
                    'description': f'Software de edição identificado: {software}'
                })
        
        if self.results.get('exif', {}).get('data', {}).get('DateTimeOriginal'):
            risks.append({
                'level': 'MEDIUM',
                'type': 'timestamp',
                'description': 'Data e hora original da captura está presente'
            })
        
        self.results['privacy_risks'] = risks
    
    def generate_report(self):
        """Gerar relatório forense completo"""
        self.calculate_hash()
        self.analyze_file_info()
        self.analyze_exif()
        self.analyze_privacy_risks()
        
        return self.results
    
    def save_report(self, output_file):
        """Salvar relatório em JSON"""
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(self.results, f, indent=2, ensure_ascii=False)
        print(f"[+] Relatório salvo em {output_file}")

# Exemplo de uso
if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Uso: python exif_forensic.py <imagem.jpg> [output.json]")
        sys.exit(1)
    
    forensic = EXIFForensic(sys.argv[1])
    report = forensic.generate_report()
    
    print("\n=== RELATÓRIO FORENSE EXIF ===\n")
    print(f"Arquivo: {report['file_info']['filename']}")
    print(f"SHA256: {report['file_info']['sha256']}")
    print(f"Tamanho: {report['file_info']['size_mb']:.2f} MB")
    
    if report['exif'].get('present'):
        print("\n[+] Metadados EXIF encontrados!")
        
        if 'GPSInfo' in report['exif']['data']:
            gps = report['exif']['data']['GPSInfo']
            print(f"\n📍 Geolocalização detectada!")
            if 'google_maps_link' in gps:
                print(f"   Link: {gps['google_maps_link']}")
        
        if 'DateTimeOriginal' in report['exif']['data']:
            print(f"\n📅 Data original: {report['exif']['data']['DateTimeOriginal']}")
        
        if 'Make' in report['exif']['data'] and 'Model' in report['exif']['data']:
            print(f"📷 Câmera: {report['exif']['data']['Make']} {report['exif']['data']['Model']}")
    
    else:
        print("\n[-] Nenhum metadado EXIF encontrado")
    
    print("\n⚠️ Riscos de Privacidade:")
    for risk in report['privacy_risks']:
        print(f"  [{risk['level']}] {risk['type']}: {risk['description']}")
    
    if len(sys.argv) > 2:
        forensic.save_report(sys.argv[2])
```

***

## 🔧 **Implementação em C/C++**

### **Leitor EXIF Básico em C**

```c
// exif_reader.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

typedef struct {
    uint16_t tag;
    uint16_t type;
    uint32_t count;
    uint32_t value;
} EXIFEntry;

// Estrutura do header TIFF
typedef struct {
    uint16_t byte_order;
    uint16_t version;
    uint32_t ifd_offset;
} TIFFHeader;

// Função para ler valor little-endian
uint16_t read_uint16_le(FILE *f) {
    uint16_t val;
    fread(&val, 2, 1, f);
    return val;
}

uint32_t read_uint32_le(FILE *f) {
    uint32_t val;
    fread(&val, 4, 1, f);
    return val;
}

// Buscar marcador APP1 (EXIF)
long find_app1_marker(FILE *f) {
    uint16_t marker;
    
    while (1) {
        marker = read_uint16_le(f);
        
        if (marker == 0xFFD8) {  // SOI
            continue;
        }
        
        if ((marker & 0xFF00) == 0xFF00) {
            uint16_t length = read_uint16_le(f);
            
            if (marker == 0xFFE1) {  // APP1
                return ftell(f);
            }
            
            fseek(f, length - 2, SEEK_CUR);
        } else {
            break;
        }
    }
    
    return -1;
}

// Verificar se é EXIF
int is_exif(FILE *f, long offset) {
    char exif_id[6];
    
    fseek(f, offset, SEEK_SET);
    fread(exif_id, 1, 6, f);
    
    return (memcmp(exif_id, "Exif\0\0", 6) == 0);
}

// Ler TIFF header
int read_tiff_header(FILE *f, TIFFHeader *header) {
    fseek(f, 6, SEEK_CUR);  // Pular "Exif\0\0"
    
    header->byte_order = read_uint16_le(f);
    
    if (header->byte_order == 0x4949) {  // "II" - Intel
        header->version = read_uint16_le(f);
        header->ifd_offset = read_uint32_le(f);
        return 1;
    }
    
    return 0;
}

// Função principal
int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Uso: %s <imagem.jpg>\n", argv[0]);
        return 1;
    }
    
    FILE *f = fopen(argv[1], "rb");
    if (!f) {
        printf("Erro ao abrir arquivo\n");
        return 1;
    }
    
    long app1_offset = find_app1_marker(f);
    if (app1_offset < 0) {
        printf("Marcador APP1 não encontrado\n");
        fclose(f);
        return 1;
    }
    
    if (!is_exif(f, app1_offset)) {
        printf("Dados EXIF não encontrados\n");
        fclose(f);
        return 1;
    }
    
    TIFFHeader tiff;
    if (!read_tiff_header(f, &tiff)) {
        printf("Erro ao ler TIFF header\n");
        fclose(f);
        return 1;
    }
    
    printf("=== Metadados EXIF ===\n");
    printf("TIFF Byte Order: %s\n", tiff.byte_order == 0x4949 ? "Little Endian" : "Big Endian");
    printf("TIFF Version: 0x%04X\n", tiff.version);
    printf("IFD Offset: %u\n\n", tiff.ifd_offset);
    
    // Aqui continuaria a leitura dos IFDs e tags...
    
    fclose(f);
    return 0;
}
```

***

## 💻 **Implementação em PowerShell**

```powershell
# exif_extractor.ps1
# Extração de metadados EXIF com PowerShell

function Get-EXIFData {
    param(
        [Parameter(Mandatory=$true)]
        [string]$ImagePath
    )
    
    # Verificar se o arquivo existe
    if (-not (Test-Path $ImagePath)) {
        Write-Error "Arquivo não encontrado: $ImagePath"
        return $null
    }
    
    # Usar .NET para acessar propriedades do shell
    Add-Type -AssemblyName System.Drawing
    
    try {
        $img = [System.Drawing.Image]::FromFile($ImagePath)
        
        $properties = @{
            "FileName" = (Get-Item $ImagePath).Name
            "FileSize" = (Get-Item $ImagePath).Length
            "Width" = $img.Width
            "Height" = $img.Height
            "PixelFormat" = $img.PixelFormat
        }
        
        # Extrair propriedades EXIF
        $exif = @{}
        foreach ($prop in $img.PropertyItems) {
            $id = "0x{0:X4}" -f $prop.Id
            $value = switch ($prop.Type) {
                1 { [System.Text.Encoding]::ASCII.GetString($prop.Value) }
                2 { [System.Text.Encoding]::ASCII.GetString($prop.Value) }
                3 { [System.BitConverter]::ToUInt16($prop.Value, 0) }
                4 { [System.BitConverter]::ToUInt32($prop.Value, 0) }
                5 { 
                    $num = [System.BitConverter]::ToUInt32($prop.Value, 0)
                    $den = [System.BitConverter]::ToUInt32($prop.Value, 4)
                    if ($den -ne 0) { $num / $den } else { $null }
                }
                default { $null }
            }
            
            $exif[$id] = $value
        }
        
        $img.Dispose()
        
        # Retornar resultados
        return @{
            Properties = $properties
            EXIF = $exif
        }
        
    } catch {
        Write-Error "Erro ao processar imagem: $_"
        return $null
    }
}

function Show-EXIFReport {
    param(
        [Parameter(Mandatory=$true)]
        [string]$ImagePath
    )
    
    $data = Get-EXIFData -ImagePath $ImagePath
    
    if ($data) {
        Write-Host "`n=== Relatório EXIF ===" -ForegroundColor Cyan
        Write-Host "`n[Arquivo]"
        Write-Host "  Nome: $($data.Properties.FileName)"
        Write-Host "  Tamanho: $($data.Properties.FileSize) bytes"
        Write-Host "  Dimensões: $($data.Properties.Width)x$($data.Properties.Height)"
        
        Write-Host "`n[Metadados EXIF]"
        
        # Tags mais comuns
        $commonTags = @{
            "0x010F" = "Fabricante"
            "0x0110" = "Modelo"
            "0x0132" = "Data/Hora"
            "0x8298" = "Copyright"
            "0x8827" = "ISO"
            "0x9209" = "Flash"
            "0x920A" = "Distância Focal"
            "0x829D" = "Abertura"
        }
        
        foreach ($tag in $commonTags.Keys) {
            if ($data.EXIF[$tag]) {
                Write-Host "  $($commonTags[$tag]): $($data.EXIF[$tag])"
            }
        }
        
        # GPS
        if ($data.EXIF["0x8825"]) {
            Write-Host "`n[Geolocalização]" -ForegroundColor Green
            Write-Host "  GPS presente na imagem"
        }
    }
}

# Função para remover metadados
function Remove-EXIFData {
    param(
        [Parameter(Mandatory=$true)]
        [string]$ImagePath
    )
    
    if (-not (Get-Command exiftool -ErrorAction SilentlyContinue)) {
        Write-Error "ExifTool não está instalado. Instale via: choco install exiftool"
        return
    }
    
    & exiftool -all= -overwrite_original $ImagePath
    Write-Host "Metadados removidos de $ImagePath" -ForegroundColor Green
}

# Exemplos de uso
# Show-EXIFReport "C:\foto.jpg"
# Remove-EXIFData "C:\foto.jpg"
```

***

## 🔍 **Forense e OSINT com EXIF**

### **Análise de Geolocalização**

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

import json
import requests
import sys
from exif_forensic import EXIFForensic

class GPSAnalyzer:
    """Analisador de geolocalização de imagens"""
    
    def __init__(self, image_path):
        self.image_path = image_path
        self.forensic = EXIFForensic(image_path)
    
    def get_location(self):
        """Extrair coordenadas GPS"""
        report = self.forensic.generate_report()
        
        if 'GPSInfo' in report.get('exif', {}).get('data', {}):
            gps = report['exif']['data']['GPSInfo']
            return {
                'lat': gps.get('latitude_decimal'),
                'lon': gps.get('longitude_decimal'),
                'altitude': gps.get('GPSAltitude')
            }
        return None
    
    def reverse_geocode(self, lat, lon):
        """Obter endereço a partir de coordenadas"""
        try:
            url = f"https://nominatim.openstreetmap.org/reverse"
            params = {
                'lat': lat,
                'lon': lon,
                'format': 'json',
                'zoom': 18
            }
            response = requests.get(url, params=params)
            data = response.json()
            
            return {
                'address': data.get('display_name'),
                'country': data.get('address', {}).get('country'),
                'city': data.get('address', {}).get('city') or data.get('address', {}).get('town'),
                'street': data.get('address', {}).get('road'),
                'postcode': data.get('address', {}).get('postcode')
            }
        except Exception as e:
            return {'error': str(e)}
    
    def get_static_map(self, lat, lon, output_file='map.png'):
        """Gerar mapa estático"""
        url = f"https://maps.googleapis.com/maps/api/staticmap"
        params = {
            'center': f"{lat},{lon}",
            'zoom': 15,
            'size': '600x400',
            'markers': f"color:red|label:IMG|{lat},{lon}",
            'key': 'YOUR_API_KEY'  # Necessário API key do Google
        }
        
        # Implementação com API key
        pass
    
    def analyze(self):
        """Análise completa de geolocalização"""
        location = self.get_location()
        
        if not location or not location['lat']:
            print("[-] Nenhuma coordenada GPS encontrada")
            return None
        
        lat, lon = location['lat'], location['lon']
        
        print(f"\n📍 Coordenadas: {lat:.6f}, {lon:.6f}")
        print(f"🔗 Google Maps: https://maps.google.com/?q={lat},{lon}")
        print(f"🔗 OpenStreetMap: https://www.openstreetmap.org/?mlat={lat}&mlon={lon}")
        
        # Reverse geocoding
        address = self.reverse_geocode(lat, lon)
        if address and 'error' not in address:
            print(f"\n🏠 Endereço aproximado:")
            print(f"   {address.get('address', 'Não disponível')}")
            if address.get('city'):
                print(f"   Cidade: {address['city']}")
            if address.get('country'):
                print(f"   País: {address['country']}")
        
        return {'coordinates': (lat, lon), 'address': address}
```

### **Script de OSINT Automatizado**

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

import os
import sys
import json
import argparse
from datetime import datetime
from PIL import Image
from PIL.ExifTags import TAGS

class EXIFOSINT:
    """Ferramenta OSINT para extração e análise de metadados EXIF"""
    
    def __init__(self, directory):
        self.directory = directory
        self.results = []
    
    def scan_directory(self):
        """Escaneia diretório em busca de imagens"""
        extensions = ('.jpg', '.jpeg', '.png', '.tiff', '.bmp')
        
        for root, dirs, files in os.walk(self.directory):
            for file in files:
                if file.lower().endswith(extensions):
                    self.process_image(os.path.join(root, file))
    
    def process_image(self, image_path):
        """Processa uma imagem individual"""
        try:
            img = Image.open(image_path)
            exif = img._getexif()
            
            if not exif:
                return
            
            data = {
                'path': image_path,
                'filename': os.path.basename(image_path),
                'size': os.path.getsize(image_path),
                'modified': datetime.fromtimestamp(os.path.getmtime(image_path)).isoformat(),
                'metadata': {}
            }
            
            for tag_id, value in exif.items():
                tag_name = TAGS.get(tag_id, tag_id)
                
                # Converter bytes para string
                if isinstance(value, bytes):
                    value = value.decode('utf-8', errors='ignore')
                
                data['metadata'][tag_name] = value
            
            self.results.append(data)
            
        except Exception as e:
            print(f"Erro ao processar {image_path}: {e}")
    
    def generate_report(self, output_file='exif_report.json'):
        """Gera relatório JSON"""
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(self.results, f, indent=2, ensure_ascii=False)
        
        print(f"[+] Relatório salvo em {output_file}")
        self.print_summary()
    
    def print_summary(self):
        """Exibe resumo do scan"""
        print(f"\n=== RESUMO DO SCAN ===")
        print(f"Total de imagens analisadas: {len(self.results)}")
        
        images_with_gps = sum(1 for r in self.results if 'GPSInfo' in r.get('metadata', {}))
        images_with_author = sum(1 for r in self.results if 'Artist' in r.get('metadata', {}))
        
        print(f"Imagens com GPS: {images_with_gps}")
        print(f"Imagens com autor: {images_with_author}")
        
        # Listar coordenadas
        print("\n📍 Coordenadas encontradas:")
        for r in self.results:
            if 'GPSInfo' in r.get('metadata', {}):
                print(f"  {r['filename']}: GPS presente")
    
    def export_csv(self, output_file='exif_data.csv'):
        """Exporta dados para CSV"""
        import csv
        
        with open(output_file, 'w', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow(['Arquivo', 'Tamanho', 'Data', 'Câmera', 'GPS', 'Autor'])
            
            for r in self.results:
                writer.writerow([
                    r['filename'],
                    r['size'],
                    r['metadata'].get('DateTime', ''),
                    f"{r['metadata'].get('Make', '')} {r['metadata'].get('Model', '')}",
                    'Sim' if 'GPSInfo' in r['metadata'] else 'Não',
                    r['metadata'].get('Artist', '')
                ])
        
        print(f"[+] CSV exportado para {output_file}")

# Exemplo de uso
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Ferramenta OSINT para EXIF')
    parser.add_argument('directory', help='Diretório a ser escaneado')
    parser.add_argument('-o', '--output', default='exif_report.json', help='Arquivo de saída')
    parser.add_argument('--csv', action='store_true', help='Exportar como CSV')
    
    args = parser.parse_args()
    
    osint = EXIFOSINT(args.directory)
    osint.scan_directory()
    osint.generate_report(args.output)
    
    if args.csv:
        osint.export_csv()
```

***

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

### **Remoção de Metadados**

```bash
# ExifTool - remover todos os metadados
exiftool -all= imagem.jpg

# ExifTool - remover apenas GPS
exiftool -gps:all= imagem.jpg

# jhead - remover todos os metadados
jhead -purejpg imagem.jpg

# ImageMagick - remover metadados
convert imagem.jpg -strip imagem_clean.jpg

# Python Pillow
python -c "from PIL import Image; Image.open('img.jpg').save('clean.jpg', 'JPEG', quality=95)"

# Exiv2 - remover metadados
exiv2 rm imagem.jpg
```

### **Script de Sanitização em Massa**

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

import os
import sys
from PIL import Image
import argparse

class EXIFSanitizer:
    """Remove metadados EXIF de imagens"""
    
    def __init__(self, directory, output_dir=None, recursive=False):
        self.directory = directory
        self.output_dir = output_dir or directory
        self.recursive = recursive
        self.processed = 0
    
    def sanitize_image(self, input_path, output_path):
        """Remove metadados de uma imagem"""
        try:
            img = Image.open(input_path)
            
            # Salvar sem metadados
            img.save(output_path, 'JPEG', quality=95)
            print(f"[+] Processado: {input_path} -> {output_path}")
            self.processed += 1
            
        except Exception as e:
            print(f"[-] Erro ao processar {input_path}: {e}")
    
    def process_directory(self):
        """Processa diretório recursivamente"""
        extensions = ('.jpg', '.jpeg', '.png', '.tiff')
        
        for root, dirs, files in os.walk(self.directory):
            for file in files:
                if file.lower().endswith(extensions):
                    input_path = os.path.join(root, file)
                    
                    # Calcular caminho de saída
                    rel_path = os.path.relpath(input_path, self.directory)
                    output_path = os.path.join(self.output_dir, rel_path)
                    
                    # Criar diretório de saída
                    os.makedirs(os.path.dirname(output_path), exist_ok=True)
                    
                    self.sanitize_image(input_path, output_path)
            
            if not self.recursive:
                break
    
    def run(self):
        """Executa o processo de sanitização"""
        print(f"[*] Sanitizando imagens em {self.directory}")
        
        if not os.path.exists(self.output_dir):
            os.makedirs(self.output_dir)
        
        self.process_directory()
        print(f"\n[+] Total de imagens processadas: {self.processed}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Remove metadados EXIF de imagens')
    parser.add_argument('directory', help='Diretório de entrada')
    parser.add_argument('-o', '--output', help='Diretório de saída')
    parser.add_argument('-r', '--recursive', action='store_true', help='Processar recursivamente')
    
    args = parser.parse_args()
    
    sanitizer = EXIFSanitizer(args.directory, args.output, args.recursive)
    sanitizer.run()
```

***

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

### **Resumo Técnico**

```yaml
EXIF Metadata:
  ✅ Fonte rica de informações forenses
  ✅ Útil para OSINT e investigações
  ✅ Pode conter dados sensíveis (GPS, horários, dispositivos)

Riscos de Privacidade:
  ❌ Geolocalização expõe localização exata
  ❌ Timestamps revelam horários de atividades
  ❌ Dados de dispositivo podem identificar o usuário

Boas Práticas:
  🔐 Remover metadados antes de compartilhar imagens
  🔐 Configurar dispositivos para não registrar GPS
  🔐 Usar ferramentas de sanitização automática
```

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

1. **Para Usuários**
   * Desativar geotagging em câmeras e smartphones
   * Remover metadados antes de compartilhar fotos online
   * Usar ferramentas como ExifTool para sanitização
2. **Para Investigadores**
   * Preservar imagens originais (hash, cadeia de custódia)
   * Extrair metadados antes de qualquer processamento
   * Documentar todas as alterações realizadas
3. **Para Desenvolvedores**
   * Implementar sanitização automática em aplicações
   * Alertar usuários sobre metadados antes do upload
   * Usar bibliotecas seguras para processamento de imagens


---

# 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/rede-and-infraestrutura/extracao-de-metadados-exif.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.
