# 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](https://2831222458-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L8zFFHkPxQb-_1XSGR9%2Fuploads%2Fgit-blob-deef7c8ec112bcc845e74af3b3133131cf77ab0c%2Fdie_calc_pe_advanced.png?alt=media)

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](https://2831222458-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L8zFFHkPxQb-_1XSGR9%2Fuploads%2Fgit-blob-f50fdf0d23101da2e973767ad5516ed465719664%2Fdie_calc_it.png?alt=media)

> 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](https://2831222458-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L8zFFHkPxQb-_1XSGR9%2Fuploads%2Fgit-blob-03d0b09221466ba2ccc055b5b2ce8f10833a4695%2Fdie_calc_ilt.png?alt=media)

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.
