Spørgsmål:
Hvordan kan jeg kontrollere, at jeg er flyttet uden for stakken uden at udløse en beskyttelsesfejl?
ŹV -
2013-04-05 19:55:53 UTC
view on stackexchange narkive permalink

Jeg tilføjer en funktion til min Linux-debugger (jeg bruger Ptrace til at manipulere den sporede proces samt libbfd / libopcodes) for at afvikle stakken og afgøre, om der findes uoverensstemmelser mellem hvert CALLs tildelte stakplads og en statisk afledt lokal variabel størrelse, udskrivning af adresse og lokal stakstørrelse for hver ramme undervejs.

Min generelle metode er at tage adressen i basismarkøren (EBP / RBP), inkrement, som markøren skal skal indeholde den gemte rammemarkør, derferens den adresse, undersøge den med PTRACE_PEEKDATA og gentag, indtil jeg henviser en adresse, der optager et område uden for stakken.

Jeg ved hvordan man kontrollerer kode / datasegmentregistre, men ideelt som en metode til at kontrollere, om jeg stadig er inde i callstack, selvom segmenteringen er blevet ændret med W ^ X-hukommelsessider eller en ellers ikke-eksekverbar stak.

Kort sagt, hvordan kan jeg kontrollere (generelt case) når jeg er flyttet uden for stakken uden at udløse en generel beskyttelsesfejl?

(Som bortset fra det, indser jeg, at jeg opererer under den antagelse, at kontrol af en adresses sidesegment er den ideelle metode her - måske findes der en anden enklere metode til at bestemme, om en adresse er inden for den aktuelle procestaks plads)

Jeg gætter på, at du arbejder under Linux. Det er helt klart nødvendigt at specificere operativsystemet her, da det indstiller stabelbaseret adresse (med en ASLR-forskydning eller ej), før processen startes.
Tak, jeg har redigeret svaret til at specificere ovenfor - Det er faktisk linux.
Stærkt anbefalet læsning om afvikling: [del 1] (http://www.mikeash.com/pyblog/friday-qa-2012-04-27-plcrashreporter-and-unwinding-the-stack-with-dwarf.html), [del 2] (http://www.mikeash.com/pyblog/friday-qa-2012-05-04-plcrashreporter-and-unwinding-the-stack-with-dwarf-part-2.html) (OS X orienteret, men mange ting gælder stadig).
Da du kender stakanvendelsen i intel / amd-miljøer, ved du, at ebp-værdierne nødvendigvis vil stige i værdi for hver på hinanden følgende tilbageførsel (hvilket betyder at få adgang til den næste forælder). I betragtning af at du ser på et Linux-miljø, kan du (noget sikkert) antage begrænsningen på 8 MB (pr. Tråd). I betragtning af at (højst sandsynligt) 4KB-sider er i brug, kan du sikkert læse ebp-værdier, der er på en større adresse end den nuværende, indtil den når en anden (og åbenbart højere) sideindgang. På dette tidspunkt kan du bruge mmap () til at se om siden er der eller ikke ...
Du kan også registrere nogle former for 'ødelagte' EBP / RBP-værdier ved at undersøge de nederste 2 bit (32-bit) eller lavere 3 bit (64-bit), fordi ESP / RSP- og EBP / RSP-værdier er 4-byte eller 8-byte justeret henholdsvis.
En svar:
perror
2013-04-05 21:16:49 UTC
view on stackexchange narkive permalink

Så det er helt uprøvet, men her er resultatet af nogle få internetbrowsere.

Først er stablens basisadresse til stede i / proc / <pid> / maps , derefter det skal være tilgængeligt fra brugerrummet på et eller andet tidspunkt.

Jeg kiggede på koden til pstack -kommandoen, der udskriver indholdet af stakken i en kørende proces. Denne kode henter basisadressen fra en link_map struktur og gemmer den inde i feltet l_addr . Dette felt er indstillet inden for funktionen readLinkMap():

  static void readLinkMap (int pid, ElfN_Addr base, struct link_map * lm, char * name, unsigned int namelen ) {/ * basisadresse * / lm->l_addr = (ElfN_Addr) ptrace (PTRACE_PEEKDATA, pid, base + offsetof (struct link_map, l_addr), 0); / * næste element i linkkortkæde * / if (-1! = (lang) lm->l_addr ||! errno) lm->l_next = (struct link_map *) ptrace (PTRACE_PEEKDATA, pid, base + offsetof (struct link_map, l_next ), 0); hvis ((-1 == (lang) lm->l_addr || -1 == (lang) lm->l_næste) && errno) {perror ("ptrace"); afslut ("kan ikke læse mål."); } loadString (pid, base + offsetof (struct link_map, l_name), name, namelen);}  

Jeg tror det er den rigtige vej at gå. Så jeg vil råde dig til at se på koden til pstack -kommandoen (filen er ikke særlig lang) og få inspiration fra den, fordi den gør noget, der ligner meget det, du vil have (på mindst hvis jeg forstår, hvad du sagde korrekt).

Håber, at denne korte note hjælper dig lidt.

Inden for brugernes spørgsmål ser dette ud til at være tilstrækkeligt. Hvis man vil implementere backtrace-funktionalitet, skal du dog sandsynligvis bruge dværg-cfi, hvis du vil have det til at være pålideligt.
@broadway: Men dværg er ikke altid til stede på alle eksekverbare filer. Du kan få hjælp til at se på det, men efter min ydmyge mening ville det være en fejl at stole helt på det og intet andet.
ja, du skal bare acceptere bruddet i så fald. Rammerne vil ofte bare ikke være der. Du kan måske prøve at heuristisk udlede registre i nogle almindelige tilfælde.


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...