# Import Table

Foi visto que no diretório de dados *Import Table* há um ponteiro para a IDT (*Import Directory Table*), apontado pelo valor do campo *VirtualAddress*. Vamos conhecer essa IDT de uma vez.

## Import Directory Table

A IDT é um *array* de estruturas do tipo IMAGE\_IMPORT\_DESCRIPTOR definidas a seguir:

```c
typedef struct {
    uint32_t RvaImportLookupTable; // Antigo OriginalFistThink
    uint32_t TimeDateStamp;
    uint32_t ForwarderChain;
    uint32_t Name;
    uint32_t RvaImportAddressTable; // Antigo FirstThunk (ou Thunk Table)
} IMAGE_IMPORT_DESCRIPTOR;
```

> Não se deve confundir esta IDT (*Import Descriptor Table*) com outra IDT (*Interrupt Descriptor Table*). Esta última é uma estrutura que mapeia interrupções para seus devidos *handlers*, assunto que foge do escopo deste livro.

O número de elementos do *array* de estruturas IMAGE\_IMPORT\_DESCRIPTOR é igual ao número de bibliotecas que o executável PE depende, ou seja, o número de diferentes DLLs das quais o executável importa funções. Há ainda um elemento final, completamente zerado (preenchido com *null bytes*) para indicar o fim do *array*.

### RvaImportLookupTable

O campo *RvaImportLookupTable* (antigamente conhecido por *OriginalFirstThunk* que era unido com *Characteristics*) aponta para uma tabela chamada de *Import Lookup Table (ILT)*

#### Import Lookup Table (ILT)

Essa tabela é um *array* de números de 64-bits (ou 32-bits para PE32). Para cada um desses números, seu *bit* mais significativo *(MSB - Most Significant Bit)*, se ligado, define que a função será importada por número. Se desligado, a função é importada por nome. Os *bits* remanescentes guardam um endereço para uma estrutura que finalmente contém o nome da função. Essa estrutura é chamada de *Hint/Name Table*.

**Hint/Name Table**

Os elementos desta tabela obedecem a seguinte estrutura:

```c
typedef struct {
	uint16_t Hint;
	uint8_t Name[1];
} IMAGE_IMPORT_BY_NAME;
```

Onde *Name* possui tamanho variável pois contém o nome da função a ser importada.

Note que o número de entradas na ILT (número de elementos deste *array*) é igual ao número de funções importadas por uma DLL em particular definida na IDT.

### Name

Este campo contém o endereço de uma *string* que é o nome da DLL importada. Por exemplo: *SHELL32.dll*. A *string* é terminada em *null*.

### RvaImportAddressTable

Este campo aponta finalmente para o que chamamos de *IAT (Import Address Table)*, muito conhecida por quem faz engenharia reversa. Essa tabela é em princípio idêntica à *Import Lookup Table*, mas no processo de carregamento do executável (*load time*, que estudaremos mais à frente no livro), ela é preenchida com os endereços reais das funções importadas. Isto porque um executável dinamicamente *linkado* não sabe, antes de ser carregado em memória, qual o endereço de cada função de cada DLL que ele precisa chamar.

É importante lembrar o conceito de biblioteca compartilhada aqui. A ideia é ter apenas uma cópia dela carregada em memória e todos os programas que a utilizam podem chamar suas funções. Esta é a razão para o longo esquema de preenchimento da IAT pelo *loader*.

## Exercícios

Para fixar este conteúdo, é importante validar o que foi aprendido. Abra o executável da calculadora no **DIE**, marque a caixa **Advanced** se já não estiver marcada e clique no botão **PE** como a imagem a seguir mostra:

![Obtendo informações avançadas sobre o PE no DIE](/files/b3WugLAlvMOzj8bPZDGQ)

No menu da esquerda, vá em **IMAGE\_NT\_HEADERS -> IMAGE\_OPTIONAL\_HEADER -> IMAGE\_DIRECTORY\_ENTRIES** e copie o endereço (coluna **Address**) do segundo diretório, que é justamente o endereço da IDT, como a imagem a seguir ilustra:

![Visualizando o diretório de Imports (Import Table) no DIE](/files/RclyO5pb5AXRz5mHMSNm)

> Perceba que o DIE chama o campo *VirtualAddress* dos diretórios apenas de *Address*. Inconsistências assim podem ocorrer em várias ferramentas e literaturas, mas se você souber do que se trata, vai sempre se dar bem, mesmo que nomes diferentes sejam usados para se referir à mesma coisa.

Agora no **HxD**, abra o mesmo binário e vá até este *offset* da IDT com o Ctrl+G. No binário que usei aqui o endereço é 0x38f8.

Lá, os primeiros quatros *bytes* são o valor do campo *RvaImportLookupTable* do primeiro elemento do *array*. Se você seguir este *offset*, vai chegar na ILT. O primeiro elemento da ILT é um número de 64-bits, ou seja, de 8 *bytes* que aponta para a *Hint/Name Table*. Nesta tabela, o nome da função começa no terceiro *byte* conforme definição, logo após o campo *Hint*.

![Olhando a IDT, ILT e Hint/Name Table no HxD](/files/5DdeEABLURpMGujnLsVe)

Como desafio adicional, descubra à qual DLL a função pertence apenas olhando para a imagem anterior. Dica: busque pelo campo *Name* da IDT e siga o valor que ele contém neste binário.


---

# 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://mentebinaria.gitbook.io/engenharia-reversa/05-o-formato-pe/import-table.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.
