Tabela de Importação
Visualização da Tabela de Importação
No cabeçalho opcional IMAGE_OPTIONAL_HEADER, o campo DataDirectory fornece uma estrutura de diretório de dados, definida como:
typedef struct _DIRETORIO_DADOS {
DWORD EnderecoRVA; // RVA relativo ao diretório
DWORD TamanhoTotal; // Tamanho do item do diretório
} DIRETORIO_DADOS, *PDIRETORIO_DADOS;
EnderecoRVA: RVA (Endereço Virtual Rleativo) após o carregamento do PE na memória.
TamanhoTotal: Tamanho da tabela de importação.
O FOA (Offset no Arquivo) da tabela de importação pode ser determinado através da conversão de endereços conforme a estrutura do PE.
Estrutura da Tabela de Importação
A estrutura IMAGE_IMPORT_DESCRIPTOR é definida assim:
typedef struct _DESCRITOR_IMPORTACAO {
union {
DWORD Caracteristicas; // 0 para descritor nulo de encerramento
DWORD PrimeiroThunkOriginal; // RVA para IAT original não vinculada
} DUMMYUNIONNAME;
DWORD CarimboTempo; // 0 se não vinculado, -1 se vinculado com timestamp real
DWORD CadeiaEncaminhador; // -1 se não houver encaminhadores
DWORD NomeModulo; // RVA para o nome do módulo
DWORD PrimeiroThunk; // RVA para IAT (com endereços reais se vinculado)
} DESCRITOR_IMPORTACAO;
typedef DESCRITOR_IMPORTACAO UNALIGNED *PDESCRITOR_IMPORTACAO;
No assembly, a estrutura é representada como:
DESCRITOR_IMPORTACAO STRUCT
union
Caracteristicas dd ?
PrimeiroThunkOriginal dd ?
ends
CarimboTempo dd ?
CadeiaEncaminhador dd ?
NomeModulo dd ?
PrimeiroThunk dd ?
DESCRITOR_IMPORTACAO ENDS
PrimeiroThunkOriginal: Aponta para uma tabela RVA com nomes ou números de ordem das funções importadas, usando a estrutura IMAGE_THUNK_DATA.
NomeModulo: RVA para o nome do módulo importado.
PrimeiroThunk: Aponta para a RVA da IAT (Import Address Table). Antes do carregamento, contém os mesmos dados que PrimeiroThunkOriginal; após o carregamento, é preenchido com endereços reais das funções.
IMAGE_THUNK_DATA
A estrutura IMAGE_THUNK_DATA tem versões de 32 e 64 bits. A definição para 32 bits:
typedef struct _DADO_THUNK32 {
union {
DWORD EncaminhadorString; // PBYTE
DWORD Funcao; // PDWORD
DWORD Ordem; // Valor de ordem se bit mais alto for 1
DWORD EnderecoDados; // RVA para IMAGE_IMPORT_BY_NAME se bit mais alto não for 1
} u1;
} DADO_THUNK32;
typedef DADO_THUNK32 * PDADO_THUNK32;
No assembly:
DADO_THUNK32 STRUCT
union u1
EncaminhadorString dd ?
Funcao dd ?
Ordem dd ?
EnderecoDados dd ?
ends
DADO_THUNK32 ENDS
Ordem: Válido quando o bit mais alto de IMAGE_THUNK_DATA é 1, representando o número de ordem da função importada.
EnderecoDados: Aponta para IMAGE_IMPORT_BY_NAME quando o bit mais alto não é 1, indicando importação por nome.
Ordem e EnderecoDados são mutualmente exclusivos, determinados pelo bit mais alto. Se for 1, usa-se a ordem; caso contrário, usa-se o nome.
IMAGE_IMPORT_BY_NAME
A estrutura IMAGE_IMPORT_BY_NAME é definida como:
typedef struct _NOME_IMPORTACAO {
WORD Dica;
CHAR NomeFuncao[1];
} NOME_IMPORTACAO, *PNOME_IMPORTACAO;
Dica: Número de ordem da função na tabela de exportação, opcional.
NomeFuncao: String terminada em NULL com o nome da função importada. A definição com array de tamanho 1 permite acesso flexível a strings de comprimento variável.
Diferença entre OriginalFirstThunk e FirstThunk
Ambos os campos em IMAGE_IMPORT_DESCRIPTOR apontam para estruturas IMAGE_THUNK_DATA, mas diferem após o carregamento. No disco, ambos contêm RVAs para nomes ou ordens de funções. Na memória, PrimeiroThunkOriginal mantém os dados originais (tabela de nomes de importação, INT), enquanto PrimeiroThunk é preenchido pelo loader do Windows com endereços reais das funções (tabela de endereços de importação, IAT).
Análise Manual da Tabela de Importação
Para analisar manualmente, localize o diretório de dados no índice 4 e siga os RVAs para entender as estruturas de importação.
Tabela de Realocação
A tabela de realocação é encontrada no índice 5 do diretório de dados. A estrutura IMAGE_BASE_RELOCATION é:
typedef struct _REALOCACAO_BASE {
DWORD EnderecoBase;
DWORD TamanhoBloco;
// WORD DeslocamentoTipo[1];
} REALOCACAO_BASE;
typedef REALOCACAO_BASE UNALIGNED * PREALOCACAO_BASE;
No assembly:
REALOCACAO_BASE STRUCT
EnderecoBase dd ?
TamanhoBloco dd ?
REALOCACAO_BASE ENDS
A tabela é composta por múltiplas estruturas REALOCACAO_BASE.
EnderecoBase: RVA inicial dos dados de realocação.
TamanhoBloco: Tamanho total do bloco, incluindo a estrutura base e os dados de realocação. A estrutura base tem 8 bytes, e TamanhoBloco é 8 + N*WORD.
DeslocamentoTipo: Array de WORDs, onde cada elemetno tem 4 bits altos para o tipo e 12 bits baixos para o offset dentro da seção. O RVA para realocação é calculado como EnderecoBase + offset. No Win32, o tipo comum é IMAGE_REL_BASED_HIGHLOW.
Valores de DeslocamentoTipo
Os tipos de realocação são definidos em Winnt.h:
#define TIPO_REALOC_ABSOLUTO 0
#define TIPO_REALOC_ALTO 1
#define TIPO_REALOC_BAIXO 2
#define TIPO_REALOC_ALTO_BAIXO 3
#define TIPO_REALOC_AJUSTE_ALTO 4
#define TIPO_REALOC_ESPECIFICO_MAQ_5 5
#define TIPO_REALOC_RESERVADO 6
#define TIPO_REALOC_ESPECIFICO_MAQ_7 7
#define TIPO_REALOC_ESPECIFICO_MAQ_8 8
#define TIPO_REALOC_ESPECIFICO_MAQ_9 9
#define TIPO_REALOC_DIR64 10