Spørgsmål:
Hvad er PLT / GOT?
perror
2013-05-03 13:39:12 UTC
view on stackexchange narkive permalink

Fra tid til anden, når jeg adskiller x86-binære filer, snubler jeg henvisning til PLT og GOT , især når jeg kalder procedurer fra det adynamiske bibliotek.

For eksempel når du kører et program i gdb:

  (gdb) info fileSymboler fra "/home/user/hello".Local exec-fil:` / home / bruger / hej ', filtype elf64-x86-64. Indgangspunkt: 0x400400 0x0000000000400200 - 0x000000000040021c er .interp 0x000000000040021c - 0x000000000040023c er .note.ABI-tag 0x000000000040023c - 0x0000000000400260 er .00n00.60. id. hash 0x0000000000400288 - 0x00000000004002a4 er .gnu.hash 0x00000000004002a8 - 0x0000000000400308 er .dynsym 0x0000000000400308 - 0x0000000000400345 er .dynstr 0x0000000000400346 - 0x000000000040034e er .gnu.version 0x0000000000400350 - 0x0000000000400370 er .gnu.version_r 0x0000000000400370 - 0x0000000000400388 er .rela.dyn 0x0000000000400388 - 0x00000000004003b8 er .rela.plt 0x00000000004003b8 - 0x00000000004003c6 er .init = > 0x00000000004003d0 - 0x0000000000400400 er .plt 0x0000000000400400 - 0x00000000004005dc sige .text 0x00000000004005dc - 0x00000000004005e5 er .fini 0x00000000004005e8 - 0x00000000004005fa er .rodata 0x00000000004005fc - 0x0000000000400630 er .eh_frame_hdr 0x0000000000400630 - 0x00000000004006f4 er .eh_frame 0x00000000006006f8 - 0x0000000000600700 er .init_array 0x0000000000600700 - 0x0000000000600708 er .fini_array 0x0000000000600708 - 0x0000000000600710 er .jcr 0x0000000000600710 - 0x00000000006008f0 er .dynamic = > 0x00000000006008f0 - 0x00000000006008f8 er .got = > 0x00000000006008f8 - 0x0000000000600920 er .got.plt 0x0000000000600920 - 0x0000000000600930 er Data, 0x0000000000600930 - 0x0000000000600938 er .bss  

Og derefter, når du adskiller ( sætter @ plt ):

  (gdb) deaktiverer fooDump af samlekode for funktion foo:
0x000000000040050c < + 0>: skubbe% RBP 0x000000000040050d < + 1>: mov% RSP,% RBP 0x0000000000400510 < + 4>: sub $ 0x10,% RSP 0x0000000000400514 < + 8>: mov% edi, -0x4 (% RBP) 0x0000000000400517 < + 11>: mov $ 0x4005ec,% edi = > 0x000000000040051c < + 16>: callq 0x4003e0 <puts @ plt> 0x0000000000400521 < + 21>: leaveq 0x0000000000400522 < + 22>:. retqEnd af assembler dump  

Så hvad er disse FÅR / PLT?

Jeg foreslår at læse bogen Linkers and Loaders, en fremragende bog om emnet. manuskripterne er frit tilgængelige her: http://www.iecc.com/linker/
To svar:
0xea
2013-05-03 15:38:27 UTC
view on stackexchange narkive permalink

PLT står for Procedure Linkage Table, som simpelthen bruges til at kalde eksterne procedurer / funktioner, hvis adresse ikke er kendt på tidspunktet for sammenkædning, og den skal løses af den dynamiske linker ved kørselstid.

GOT står for Global Offsets Table og bruges på samme måde til at løse adresser. Både PLT og GOT og andre omplaceringsoplysninger forklares i større længde i denne artikel.

Også Ian Lance Taylor, forfatteren af ​​ GOLD, har sagt op på en artikelserie på hans blog, der er helt værd at læse ( tyve dele!): indgangssted her "Linkere del 1".

Er der nogen hurtigere måde at læse de 20 dele på? hvorfor er der ikke link i den første til den næste del?
@0x90 Faktisk nævnes PLT og GOT først i del 4 af denne vidunderlige serie. Hvis du kun har brug for denne information, er her linket: http://www.airs.com/blog/archives/41. Jeg vil dog anbefale at læse det hele, det er en rigtig god serie!
@0x90 fordi han forventer, at du selvfølgelig skriver en linker til det
Bare for at se om jeg forstod dette rigtigt: (1) GOT kræves altid for at position-uafhængig kode kan finde dens afhængigheder. (2) PLT er en valgfri mekanisme til at få doven binding til at virke. (3) Det er sikkert at kalde GOT-poster 'manuelt', selvom der er en PLT.
Et indeks over de 20 blogindlæg: http://a3f.at/lists/linkers
Du kan også bare ændre nummeret i slutningen af ​​URL'en! Https: //www.airs.com/blog/archives/39https: //www.airs.com/blog/archives/40https: //www.airs. com / blog / arkiver / 41 osv.
Ciro Santilli 郝海东冠状病六四事件法轮功
2018-12-28 00:49:43 UTC
view on stackexchange narkive permalink

Lad mig sammenfatte de links, der er givet på https://reverseengineering.stackexchange.com/a/1993/12321 uden at gå i alvorlig adskillelsesanalyse for nu.

Når Linux-kernen + dynamisk linker kører en binær med exec , dumpede den traditionelt bare ELF-sektionen til en kendt hukommelsesplacering, der er specificeret af linkeren under linktid.

Så når din kodede:

  • refererede til en global variabel inde i din kode
  • kaldte en funktion inde i din kode

compiler + linker kunne bare hardcode adressen i forsamlingen, og alt ville fungere.

Hvordan kan vi dog gøre det, når vi har at gøre med delte biblioteker, som nødvendigvis skal indlæses på potentielt forskellige adresserer hver gang for at undgå konflikter mellem to delte biblioteker?

Den naive løsning ville være at beholde flytningsmetadata på den endelige eksekverbare, ligesom den faktiske linker gør og når programmet er indlæst, skal den dynamiske linker gå over hver enkelt adgang og lappe den med den rigtige adresse.

Dette ville dog være for tidskrævende, da der kunne være mange referencer at lappe på et program, og derefter ville det tage lang tid at køre det program.

Løsningen er som sædvanlig at tilføje et andet niveau af indirektion: GOT og PLT, som er to ekstra bidder af hukommelsesopsætning af kompilationssystemet + dynamisk linker.

Efter at programmet er startet, kontrollerer den dynamiske linker adressen på delte biblioteker og hacker GOT og PLT, så den peger korrekt på det krævede delt biblioteksymboler:

  • hver gang en global variabel i et delt bibliotek tilgås af dit program, udsender compileren + linker i stedet to hukommelsesadgange:

      mov 0x200271 (% rip),% rax # 200828 <_DYNAMIC + 0x1a0>mov (% rax),% eax  

    Den første indlæser den sande adresse på variablen fra GOT, som den dynamiske linker tidligere har indstillet, i rax.

    Den anden indirekte adgang får faktisk adgang til variablen indirekte gennem adressen fra rax.

  • for kode er tingene lidt mere komplicerede.

    Når en funktion fra en delt bibliotek kaldes, linkeren får os til at hoppe til en adresse i PLT.

    Første gang funktionen kaldes, bruger PLT-koden forskydninger, der er gemt i GOT til at bestemme den faktiske endelige placering af funktionen, og derefter:

    • gemmer denne forudberegnede værdi
    • springer der

    Næste gang funktionen kaldes, har værdien allerede beregnet, så det springer bare direkte derhen.

    På grund af denne dovede opløsningsmekanisme:

    • programmer kan begynde at køre hurtigt, selvom de delte biblioteker har mange symboler
    • vi kan erstatte funktioner i farten ved at spille med LD_PRELOAD variablen

I dag er positionsuafhængige eksekverbare filer (PIE) standard på distroer som Ubuntu 18.04.

Meget ligesom delte biblioteker er disse eksekverbare kompilerede, så de kan placeres i en tilfældig position i hukommelsen, hver gang de udføres, for at gøre visse sårbarheder sværere at udnytte.

Derfor er det ikke muligt at hardcode absolut funktion og variable adresser længere i så fald. Eksekverbare filer skal enten:

  • brugerinstruktionsmarkør relativ adressering, hvis de er tilgængelige på forsamlingssproget, f.eks:
    • ARMv8:
      • B kode> laver 26-bit spring, B.cond 19-bit
      • "LDR (bogstavelig)" laver 19-bit belastninger
      • ADR beregner 21-bit relative adresser, som andre instruktioner kan bruge
  • brug GOT / PLT ellers


Denne spørgsmål og svar blev automatisk oversat fra det engelske sprog.Det originale indhold er tilgængeligt på stackexchange, som vi takker for den cc by-sa 3.0-licens, den distribueres under.
Loading...