Čtení: 40 minHodnotí se: úlohy 1 a 2, zkouška

1 Zásobník, ABI a rozbor funkce

Po přečtení umíš
  • popsat volací konvence a poznat je v assembleru
  • přečíst prolog, epilog a rámec zásobníku
  • odvodit typ proměnné z instrukcí
  • vysvětlit princip SEH

Ke zkoušce se počítá šest otevřených otázek hlavně na teorii, ale stejné znalosti potřebuješ i na úlohách. Na distanční zkoušce jde o dva okruhy, u kterých musíš mluvit bez přípravy.

1.1 Ukázka: co čteme

Funkce začíná téměř vždy stejně:

push ebp          ; ulož rámec volajícího
mov  ebp, esp     ; nový rámec
sub  esp, 8       ; místo pro lokální proměnné
...
mov  esp, ebp     ; epilog: zruš lokální proměnné
pop  ebp
ret

Z sub esp, 8 víme, že lokální proměnné zabírají 8 bajtů. Z [ebp+8] je první parametr a z [ebp-4] první lokální proměnná.

argument 1návratová adresauložený EBPlokální proměnnálokální proměnnáEBP+8EBP+4EBPEBP-4EBP-8 (ESP)zásobník roste dolů, k nižším adresám
Rámec funkce v 32bitovém kódu po prologu.

CALL uloží návratovou adresu a skočí. RET ji vyzvedne.

1.2 Volací konvence

Konvence Parametry Kdo uklízí zásobník
__cdecl zásobník zprava volající, add esp, n po volání
__stdcall zásobník zprava volaný, ret n
__fastcall první v ECX, EDX volaný
__thiscall this v ECX volaný
Windows x64 RCX, RDX, R8, R9 volající
Linux x64 RDI, RSI, RDX, RCX, R8, R9 volající

Jak ji poznat: add esp, 8 za call znamená __cdecl se dvěma parametry. Funkce končící ret 8 je __stdcall.

1.3 Typ proměnné z instrukcí

Vidíš Znamená
MOVSX hodnota se znaménkem
MOVZX hodnota bez znaménka
JG, JL, JGE porovnání se znaménkem
JA, JB, JNB porovnání bez znaménka
[REG], [REG+4], [REG+8] ukazatel na strukturu
[EBP+8] předané do API typ z dokumentace API

Typy z API jsou nejlevnější informace: jakmile víš, že je argument CreateFileA, znáš jeho význam i typ.

1.4 Strukturovaná obsluha výjimek

32bitový kód registruje obsluhu na zásobníku a ukazatel na ni je ve FS:[0]. Struktura _EXCEPTION_REGISTRATION obsahuje předchozí záznam a handler, MSVC přidává scopetable a trylevel. Výjimky proto tvoří spojový seznam.

Při analýze si všimni, že except a catch bloky nejsou v normálním toku, a přitom v nich může být důležitý kód. Obfuskace toho využívají.

1.5 Dekorace jmen

C++ kóduje do symbolu typy parametrů, kvůli přetěžování. _foo@8 je __stdcall se 8 bajty argumentů. Není-li symbol, je to první vodítko k typu.

1.6 Kvíz

Kvíz

1. Po call f je add esp, 12. Co z toho plyne?
2. Kde je v 32bitové funkci s rámcem první parametr?
3. Co prozradí MOVZX?
4. Co platí pro Windows x64? Může být správně více možností, ale také žádná.
5. Jak vzniká a zaniká rámec zásobníku?
Ukázat řešeníProlog uloží EBP, nastaví EBP na ESP a odečte místo pro proměnné. Epilog vrátí ESP z EBP, obnoví EBP a RET vyzvedne návratovou adresu.

1.7 Tahák

Tahák
  • [ebp+8] parametr, [ebp-4] lokální proměnná, [ebp+4] návratová adresa.
  • add esp, n za voláním: cdecl. ret n: stdcall. this v ECX: thiscall.
  • x64 Windows: RCX, RDX, R8, R9, uklízí volající.
  • MOVSX a JG se znaménkem, MOVZX a JA bez.
  • SEH: spojový seznam, hlava ve FS:[0].

Zdroje

  • rev01cz: reverzní inženýrství strany 4–15, zarovnání 17–21, dekorace jmen 22–25, volací konvence 26–28, prolog 31–37, SEH 38–51, epilog 52–53, rámec 54–63, znaménka 64–65, API 66–69
  • NI-REV cvičení 1 a 2