Análise Estática Avançada: Níveis de Abstração
Consiste em levar o binário para um disassembler (IDA Pro ou Ghidra) para analisar o código Assembly.
- Binário: Código em formato que o computador executa.
- Assembly: Linguagem de baixo nível (x86, x64, ARM, etc).
- Nível de Abstração:
- Linguagem de Alto Nível (C/C++) → Compilador → Código de Máquina (CPU).
- Código de Máquina (Binário) → Disassembler → Linguagem de Baixo Nível (Assembly).
Arquitetura x86 (Von Neumann)
A maioria dos computadores modernos segue esta arquitetura:
- CPU: Executa o código.
- RAM (Main Memory): Armazena dados e códigos.
- I/O System: Liga dispositivos (teclado, monitor, HD).
Layout da Memória RAM para um Programa:
- Stack (Pilha): Variáveis locais, parâmetros de funções e controle de fluxo.
- Heap: Memória dinâmica alocada durante a execução (
malloc,free). - Code: Instruções executadas pela CPU.
- Data: Variáveis globais e valores inicializados.
Assembly x86: Instruções e Opcodes
Formato da Instrução:
Mnemonic | Destination Operand | Source Operand
mov | ecx | 0x42
- Opcode: Valor numérico que diz à CPU qual operação realizar (ex:
B9para mov em certos contextos). - Operands (Operandos):
- Immediate: Valores fixos (ex:
0x42). - Register: Registradores (ex:
ecx). - Memory address: Endereço de memória, denotado por colchetes (ex:
[eax]).
- Immediate: Valores fixos (ex:
Registradores (Registers)
Espaços de dados na CPU de acesso ultra rápido.
- General Registers: EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI.
- Exemplo EAX: Pode ser dividido em AX (16 bits), AH (8 bits high) e AL (8 bits low).
- Status Register (EFLAGS): Cada bit é uma flag (0 ou 1) indicando resultados de operações.
- ZF (Zero Flag): Definida se o resultado for zero.
- CF (Carry Flag): Definida se o resultado for muito grande/pequeno para o operando.
- SF (Sign Flag): Definida se o resultado for negativo.
- TF (Trap Flag): Usada para debugging (executa uma instrução por vez).
- Instruction Pointer (EIP): Mantém o endereço da próxima instrução a ser executada.
Instruções Comuns
Movimentação e Aritmética
mov eax, ebx: Copia EBX para EAX.add eax, ebx: EAX = EAX + EBX.sub eax, 0x10: EAX = EAX - 0x10.inc edx: Incrementa EDX em 1.dec ecx: Decrementa ECX em 1.mul 0x50: Multiplica EAX por 0x50 (resultado em EDX:EAX).div 0x75: Divide EDX:EAX por 0x75.
Lógica
xor eax, eax: Limpa o registrador EAX (zera o valor).or eax, 0x7575: Operação lógica OR.shl/shr: Deslocamento de bits (Shift Left / Shift Right).
Stack (Pilha - LIFO)
push: Coloca valor no topo da pilha.pop: Retira o valor do topo.- ESP (Stack Pointer): Aponta para o topo da pilha.
- EBP (Base Pointer): Referência fixa para acessar parâmetros e variáveis locais.
Condicionais e Branching (Desvios)
Comparações:
test eax, eax: Faz umandlógico. Se EAX for 0, defineZF=1. Comumente usado para checar valores NULL.cmp dst, src: Faz umsub(subtração), mas não altera os operandos, apenas as flags.- Se
dst = src,ZF=1. - Se
dst < src,CF=1.
- Se
Saltos (Jumps):
jmp: Salto incondicional.jz/je: Pula seZF=1(resultado zero ou igual).jnz/jne: Pula seZF=0(não zero ou diferente).jg: Pula se maior (signed).jl: Pula se menor (signed).ja/jb: Pula se maior/menor (unsigned).