# 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="https://418865174-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFu6uaU65JuQBpnFAUDk8%2Fuploads%2Fq2B5bWnPFinYTAYdV2gr%2Fdependencia_da_libc.png?alt=media&#x26;token=b88c36ad-721f-464d-b789-e29971132daa" 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="https://418865174-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFu6uaU65JuQBpnFAUDk8%2Fuploads%2F5WcoRFKDdzArJf0eugY8%2Fexample_simple.png?alt=media&#x26;token=d45134ab-4b73-45b1-8ba9-768ae7960973" 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="https://418865174-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFu6uaU65JuQBpnFAUDk8%2Fuploads%2FpDy70OD2JMd3oKftYuVn%2Fdisas_main.png?alt=media&#x26;token=94b07b50-605a-4c9e-a9d5-bc2ab0dc5ece" 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="https://418865174-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFu6uaU65JuQBpnFAUDk8%2Fuploads%2Fv5sqOtC1WzDZQCutpu9p%2Fobjdump_puts.png?alt=media&#x26;token=6c024f8f-6b7c-4a05-a4fc-d29e92a3bac6" 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="https://418865174-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFu6uaU65JuQBpnFAUDk8%2Fuploads%2FZ3rB8Xjbd14zxMeZ0tdq%2Fdisas_puts.png?alt=media&#x26;token=37b9ade5-d775-4de5-b9a7-ad4814284cb9" 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="https://418865174-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFu6uaU65JuQBpnFAUDk8%2Fuploads%2FmAXowyEAPTYlS3zUcohk%2Fanalisando_puts_execucao.png?alt=media&#x26;token=6e4f3c12-384a-4880-8e42-9bd74f18bbd8" 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="https://418865174-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFu6uaU65JuQBpnFAUDk8%2Fuploads%2F7TWtsho0Fxx1nhMPSLGq%2Ffinal-1.png?alt=media&#x26;token=93a74527-3497-43ec-8b6e-1b048d94208f" 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="https://418865174-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFu6uaU65JuQBpnFAUDk8%2Fuploads%2FXcFpmPKPL8cDCEYwhnuA%2Fplt_after.png?alt=media&#x26;token=12a12b8e-774c-40b9-bfd6-2321e143000c" 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="https://418865174-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFu6uaU65JuQBpnFAUDk8%2Fuploads%2Fgm9VX0bnsHkD23d8c2KK%2Fsections.png?alt=media&#x26;token=8dec6d79-3883-482c-aceb-e76a4c9bb7cf" 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} ]
