[so2] [Tema1] [Windows] Întrebare interceptor generic

Vlad Dogaru ddvlad at herebedragons.ro
Mon Mar 18 18:59:37 EET 2013


On Fri, Mar 15, 2013 at 10:12:22PM +0200, Florin-Alexandru Stancu wrote:
> Salut,
> 
> Încerc să înţeleg cum funcţionază (sper că funcţionează) codul pentru
> interceptorul din schiţa din enunţul temei (la Windows):
> 
> > _asm mov old_stack, ebp
> > _asm add old_stack, 8
> > _asm sub esp, param_size
> > _asm mov new_stack, esp
> >
> > RtlCopyMemory(new_stack, old_stack, param_size);
> >
> 
> Aici asignăm valoarea registrului ebp în variabila old_stack... presupun că
> ne-o dă dispatcherul în registrul acela, nu?

Da, EBP e folosit pe post de frame pointer pe x86.  Arată unde e
începutul stack frame-ului curent.

> Dar de ce mai adunăm 8 bytes la adresa lui după?

Sărim peste EBP-ul precedent și peste adresa de return a funcției
noastre (EIP).  Detalii și schițe utile aici [1]

[1] http://www.unixwiz.net/techtips/win32-callconv-asm.html

> Şi, mai departe, văd că alocăm memorie pe stivă pentru o nouă stivă de
> parametrii şi îi copiem acolo. Perfect.

'parametri', cu un singur i, în cazul ăsta.  Pluralul e cu un singur i,
varianta articulată a pluralului este cu doi i.

> Presupun că facem lucrul ăsta pentru ca funcţia veche, f, să aibă imediat
> pe stivă parametrii. Asta înseamnă că ne bazăm pe compilator să ne pună
> variabila new_stack fix la marginea stivei, nu?

Exact.  De fapt, ne asigurăm noi că new_stack e la marginea stivei,
pentru că ESP e vârful stivei (convenție de ABI, la fel ca și "EBP e
frame pointer").

Scăzând param_size din esp, am rezervat spațiu pe stivă pentru
param_size octeți (remember, stiva crește spre adrese mici).  Apoi
folosim memcpy pentru a copia vechii parametri în noul stack frame.

> Şi... cine curăţă stiva după aceea? Din nou, presupunere, funcţia
> apelată?

Da, funcția apelată are grijă să facă asta, în mod normal.

> Dar asta nu înseamnă că şi funcţia noastră trebuie să cureţe stiva
> pentru parametrii primiţi? Şi nu facem asta...  Deci ce se întâmplă,
> mai exact, cu stiva la ieşire?

Noi, după codul menționat de tine, apelăm apelul de sistem inițial cu
niciun parametru, adică f().  Prin urmare, trebuie să îi punem
parametrii pe stivă înainte de apel.  Deși apelăm funcția cu 0
parametri, ea ia (param_size/sizeof (int)) parametri și trebuie să o
păcălim accordingly.  Adresa de retur și vechiul EBP sunt salvate
automat la orice apel de funcție (inclusiv cu 0 parametri), deci,
imediat după f(), avem un stack frame întreg.

De curățat, funcția curăță singură stiva de parametri, restaurând ESP
(vârful stivei) la vechiul EBP, valoare care a fost salvată la apelul
f().

Hope this helps,
Vlad


More information about the so2 mailing list