# GOT e PLT

## Introdução

Quero te mostrar a base primeiro para depois você ver a real necessidade da GOT e PLT, seja muito bem vindo e boa leitura.

**Binário Estático:** executa por conta própria, não depende de libc nem nada, tudo que ele necessita ele mesmo tem\
**Binário Dinâmico:** necessita de algo para executar, como por exemplo da libc, vamos supor que meu binário apenas exibe uma mensagem na tela com o puts(), o puts não fui eu que escrevi, ele está presente na libc, ou seja, para o meu programa funcionar eu preciso da libc, o linker faz o processo de linkagem da puts() com o meu programa

Mas o por que disso disso? Simples, imagine, se não houvesse a libc o trabalho que seria escrever todas as funções que conhecemos, e outra, imagina se houvesse uma atualização em alguma dessas funções, TODOS os binários do mundo inteiro teriam que ser alterados, pois é, a vida sem o libc seria árdua.\
Com a libc tudo fica mais fácil, houve uma atualização/modificação? Basta alterar a libc, o linker vai continuar pegando as funções e linkando com o seu binário.

Antes de prosseguir quero te mostrar que o binário é dependente da libc (claro, se ele for dinâmico, sendo sincero nunca vi uma binário estático, mas deve existir algum):

<figure><img src="/files/byKVsA78377rQD5KmRK2" alt=""><figcaption><p>Binário dependente da libc</p></figcaption></figure>

Na segunda linha você pode notar que há uma dependência da libc, e na terceira linha temos o linker usado, acredite em mim, você não vai querer apagar a sua libc, isso resultaria em um kernel panic provavelmente irreversível, o **ls** **cd** etc, comandos do linux não funcionariam mais, digo isso porque já apaguei a minha libc e mesmo com ela em mãos colocando novamente no lugar que ela pertence atráves do windows, não consegui mais acessar meu linux, resumo, tive que formatar o computador.

Enfim, você já viu sobre binários estáticos e dinâmicos, agora vamos falar sobre o **lazy binding**, isso tem mais a ver com o linker\
**Lazy Binding:** irá resolver os endereços, linka-los, apenas quando for chamado\
Isso ajuda em diversos fatores mas o principal deles: desempenho e tempo de compilação menor, mas claro que irá atrapalhar um pouco no desempenho do programa.\
Obs: se o RELRO estiver FULL, os endereços são resolvidos antes da execução e a GOT tem sua permissão setada apenas para read-only, o que impede qualquer tipo de hook

## Agora vamos falar sobre GOT e PLT

Como fazemos para resolver os endereços, o que eu quero dizer é que antes do programa ser executados não temos o endereço da puts da libc por exemplo, isso vai ficar mais facil com exemplos.

<figure><img src="/files/fZSS2x8L2pszwrx303wC" alt=""><figcaption><p>Código simples para usar de exemplo</p></figcaption></figure>

Veja que no meu exemplo eu simplesmente printo na tela Hello World!\
Uso no meu código a puts(), função da libc, não fui eu que escrevi a puts, ela está presente na libc, eu estou apenas usando ela, como acessamos ela? Precisamos do endereço dela certo? Correto, mas como o linker faz isso em tempo de execução veremos a seguir, vou explicar primeiro na teoria e depois vou explicar com exemplos.

A PLT (procedure linkage table) tem uma instrução de jmp que pula para a GOT (global offset table), o linker irá resolver o endereço e mandará para .got.plt, resumindo:\
\=> **PLT:** é responsável por armazenar o endereço que saltará para a GOT para ser resolvido\
\=> **GOT:** aqui temos os offsets das funções presentes na libc, aqui também é usado para chamar o linker para resolver o endereço\
\=> .**got.plt:** com o endereço resolvido ele é armazenado na .got.plt

E depois? Simples, com o endereço já resolvido quando for chamar a mesma função depois bastar chamar func\@plt, a plt terá um ponteiro para .got.plt que já terá a função, tentei ser o mais clarso possível, vamos ver isso na prática em um binário de 32 bits, cujo o código é aquele mencionado lá em cima.

<figure><img src="/files/l11OKEPtP3snTjUxcSgT" alt=""><figcaption><p>Disas main()</p></figcaption></figure>

Veja na main+37 a chamada para puts\@plt, vamos confirmar o endereço da PLT com o objdump:

<figure><img src="/files/Y5nlaTl193R8YX5jXceV" alt=""><figcaption><p>Objdump puts()</p></figcaption></figure>

Ele da um call justamente no 0x1040, perfeito até aqui, lembrando que estamos vendo isso antes de resolver o endereço, vamos dar uma olhado nesse endereço:

<figure><img src="/files/fgLtGUGATNLFha4zGXMJ" alt=""><figcaption><p>Disas puts()</p></figcaption></figure>

Perceba que em ebx+0xc terá o nosso ponteiro para a função puts, ele ainda não está lá porque não executamos ainda a puts, vamos executar e ver isso

<figure><img src="/files/nfe6Ub2EguHlowL83V9k" alt=""><figcaption><p>Analisando puts()</p></figcaption></figure>

Eu coloquei um breakpoint bem depois da puts para que eu pudesse analisar, enfim, vemos que o endereço da puts\@plt já mudou, vamos ver o que tem nele

<figure><img src="/files/9NvdD6pglxOSqMVfrTzI" alt=""><figcaption><p>Analisando puts()</p></figcaption></figure>

Vamos com calma, no primeiro comando podemos ver que não mudou muita coisa, mas perceba que ebx+0xc agora foi resolvido vamos ver o endereço que tem nele já que ele é um ponteiro, ele está apontando para 0xf7e19c0, demos um x/5i que pega 5 instruções do endereço, e nele está justamente a nossa puts, se você quiser dar um disas no endereço da puts() fique a vontade mas é bem grandinho por isso peguei apenas 5 instruções.

Se mesmo assim ficou confuso olhe esse pequeno exemplo:

<figure><img src="/files/BYM1BVRi4EkUf83IHpQ7" alt=""><figcaption><p>Exemplo 1</p></figcaption></figure>

## **Bônus:**

Falamos sobre GOT, PLT e .got.plt mas o que elas são? Elas são sessões, antes de sessões temos segmentos, veja um simples mapa:

<figure><img src="/files/oEhmlNyO7kgOG8NHbCTq" alt=""><figcaption><p>Exemplo 2</p></figcaption></figure>

**Outras seções interessantes:**\
\=> **.symtab:** Essa seção guarda todos os simbolos internos e externos\
\=> **.dynsym:** Essa seção guarda todos os simbolos externos\
\*Ex: na dynsym tem o simbolo do printf \[ printf(“oi”); ]\
…: na symtab tem o simbolo da main \[ int main(){return 0} ]


---

# 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://vida03.gitbook.io/redteam/binary-exploitation/got-e-plt.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.
