void processarDados()
{
int valores[10] = { 10, 20, 30, 40, 50, 60, 70, 80 };
valores[0] = 110;
valores[1] = 120;
valores[2] = 130;
valores[3] = 140;
valores[4] = 150;
valores[5] = 160;
valores[6] = 170;
valores[7] = 180;
return;
}
5: int valores[10] = { 10, 20, 30, 40, 50, 60, 70, 80 };
0012F590 mov dword ptr [ebp-28h],0Ah
0012F597 mov dword ptr [ebp-24h],14h
0012F59E mov dword ptr [ebp-20h],1Eh
0012F5A5 mov dword ptr [ebp-1Ch],28h
0012F5AC mov dword ptr [ebp-18h],32h
0012F5B3 mov dword ptr [ebp-14h],3Ch
0012F5BA mov dword ptr [ebp-10h],46h
0012F5C1 mov dword ptr [ebp-0Ch],50h
0012F5C8 xor eax,eax
0012F5CA mov dword ptr [ebp-8],eax
0012F5CD mov dword ptr [ebp-4],eax
6: valores[0] = 110;
0012F5D0 mov eax,4
0012F5D5 imul ecx,eax,0
0012F5D8 mov dword ptr [ebp+ecx-28h],6Eh
7: valores[1] = 120;
0012F5E0 mov eax,4
0012F5E5 shl eax,0
0012F5E8 mov dword ptr [ebp+eax-28h],78h
8: valores[2] = 130;
0012F5F0 mov eax,4
0012F5F5 shl eax,1
0012F5F7 mov dword ptr [ebp+eax-28h],82h
9: valores[3] = 140;
0012F5FF mov eax,4
0012F604 imul ecx,eax,3
0012F607 mov dword ptr [ebp+ecx-28h],8Ch
10: valores[4] = 150;
0012F60F mov eax,4
0012F614 shl eax,2
0012F617 mov dword ptr [ebp+eax-28h],96h
11: valores[5] = 160;
0012F61F mov eax,4
0012F624 imul ecx,eax,5
0012F627 mov dword ptr [ebp+ecx-28h],0A0h
12: valores[6] = 170;
0012F62F mov eax,4
0012F634 imul ecx,eax,6
0012F637 mov dword ptr [ebp+ecx-28h],0AAh
13: valores[7] = 180;
0012F63F mov eax,4
0012F644 imul ecx,eax,7
0012F647 mov dword ptr [ebp+ecx-28h],0B4h
Identificação de Arrays em Engenharia Reversa
Este é um array local de inteiros
int valores[10]na pilha
Na desmontagem, suas características são:
- Um bloco contínuo de espaço na pilha
- Base fixa (
ebp-28h) - Espaçamento fixo de 4 bytes entre elementos
- Padrão de acesso consistente:
[ebp + índice*4 - 28h] - Índice × tamanho do elemento = deslocamento
Ao encontrar esse padrão em engenharia reversa, é altamente provável que seja um array.
Estrutura da Stack Frame e Array (Importante)
1️⃣ Tamanho da Stack Frame
0012F5B3 sub esp,0F4h
Isso indica:
- A função alocou 0xF4 = 244 bytes na pilha
- Inclui: array, variáveis temporárias, preenchimneto de depuração, cookie, etc.
2️⃣ Endereço de início do array
mov dword ptr [ebp-28h],0Ah
mov dword ptr [ebp-24h],14h
mov dword ptr [ebp-20h],1Eh
...
mov dword ptr [ebp-0Ch],50h
Esta é a evidência mais direta de um array:
| Elemento | Endereço |
|---|---|
| valores[0] | ebp-28h |
| valores[1] | ebp-24h |
| valores[2] | ebp-20h |
| valores[3] | ebp-1Ch |
| valores[4] | ebp-18h |
| valores[5] | ebp-14h |
| valores[6] | ebp-10h |
| valores[7] | ebp-0Ch |
Incremento de +4 bytes entre cada elemento → Array de int
3️⃣ Por que é int valores[10]?
mov dword ptr [ebp-8],eax
mov dword ptr [ebp-4],eax
- De
-28ha-4hcobre 40 bytes - 40 ÷ 4 = 10 inteiros
- Apesar de só 8 elementos serem inicializados, o tamanho do array é 10
Em engenharia reversa: Não se deixe enganar pela quantidade de inicializações, observe o tamanho do espaço alocado
Características da Inicialização de Arrays em Reversa
Código fonte:
int valores[10] = {10, 20, 30, 40, 50, 60, 70, 80};
Correspondente em assembly:
mov dword ptr [ebp-28h],0Ah
mov dword ptr [ebp-24h],14h
mov dword ptr [ebp-20h],1Eh
mov dword ptr [ebp-1Ch],28h
...
mov dword ptr [ebp-0Ch],50h
Técnicas de Identificação em Reversa
- Escritas contínuas
- Passo fixo
- Execução incondicional
️ Isso representa a inicialização de array expandida em tempo de compilação
Características Principais do Acesso por Índice (Foco)
1️⃣ valores[0] = 110;
mov eax,4
imul ecx,eax,0
mov dword ptr [ebp+ecx-28h],6Eh
Redução:
ecx = 4 * 0
[ebp - 28h + ecx] = 110
️ Fórmula padrão:
valores[i] = *(base + i * sizeof(int))
2️⃣ valores[1] = 120;
mov eax,4
shl eax,0
mov dword ptr [ebp+eax-28h],78h
shl 0⇒1 * 4- Deslocmaento =
4
️ Acessando valores[1]
3️⃣ valores[2] / valores[4] (usando shl)
shl eax,1 ; 2 * 4
shl eax,2 ; 4 * 4
O compilador usa deslocamento (shift) em vez de multiplicação (mais rápido)
4️⃣ valores[3] / valores[5~7] (usando imul)
imul ecx,eax,3
imul ecx,eax,5
imul ecx,eax,7
Quando o índice não é potência de 2 → usa imul
Resumo em Reversa: "Fórmula Ouro" de Acesso a Arrays
[ebp + índice * tamanho_do_elemento + deslocamento_base]
Neste caso específico:
[ebp + índice*4 - 28h]
Por que os Acessos não são Uniformes? (shl / imul misturados)
Esta é uma estratégia de otimização do compilador, não diferença no código fonte:
| Índice | Método gerado |
|---|---|
| 1, 2, 4 | shl |
| 3, 5, 6, 7 | imul |
Em engenharia reversa:
Qualquer padrão com índice × constante + base fixa = array
Não se preocupe com a instrução específica.
Lista de Verificação para Identificação de Arrays em Reversa (Aplicação Prática)
Ao encontrar as seguintes características, pode marcar diretamente como array:
Endereços contínuos na pilha ✔ Deslocamento inicial fixo (ebp-28h) ✔ Espaçamento entre elementos = tamanho do tipo ✔ Índice envolvido em multipilcação/deslocamento ✔ Vários acessos à mesma base
Reconstrução Final em Reversa (Completa)
void processarDados()
{
int valores[10];
valores[0] = 110;
valores[1] = 120;
valores[2] = 130;
valores[3] = 140;
valores[4] = 150;
valores[5] = 160;
valores[6] = 170;
valores[7] = 180;
}
Resumo em Uma Frase (Mnemônico de Reversa)
"Contínuo + base fixa + índice × tamanho = array"