Introduction to x64
Uvod u x64
x64, poznat i kao x86-64, je arhitektura procesora od 64 bita koja se uglavnom koristi u desktop i serverskom računarstvu. Potiče od x86 arhitekture proizvedene od strane Intela, a kasnije je usvojena od strane AMD-a pod imenom AMD64, i danas je dominantna arhitektura u ličnim računarima i serverima.
Registri
x64 proširuje x86 arhitekturu, uključujući 16 registara opšte namene označenih kao rax
, rbx
, rcx
, rdx
, rbp
, rsp
, rsi
, rdi
, i r8
do r15
. Svaki od njih može čuvati vrednost od 64 bita (8 bajtova). Ovi registri takođe imaju 32-bitne, 16-bitne i 8-bitne pod-registre radi kompatibilnosti i specifičnih zadataka.
rax
- Tradicionalno se koristi za vrednosti povratka iz funkcija.rbx
- Često se koristi kao bazni registar za operacije sa memorijom.rcx
- Obično se koristi za brojače petlji.rdx
- Koristi se u različitim ulogama uključujući proširene aritmetičke operacije.rbp
- Bazni pokazivač za okvir steka.rsp
- Pokazivač steka, prati vrh steka.rsi
irdi
- Koriste se za izvore i odredišta indeksa u string/memorijskim operacijama.r8
dor15
- Dodatni registri opšte namene uvedeni u x64.
Konvencija pozivanja
Konvencija pozivanja u x64 varira između operativnih sistema. Na primer:
Windows: Prva četiri parametra se prosleđuju u registrima
rcx
,rdx
,r8
, ir9
. Dodatni parametri se guraju na stek. Vrednost povratka je urax
.System V (često korišćen u UNIX-sličnim sistemima): Prva šest celobrojnih ili pokazivačkih parametara se prosleđuju u registrima
rdi
,rsi
,rdx
,rcx
,r8
, ir9
. Vrednost povratka je takođe urax
.
Ako funkcija ima više od šest ulaza, ostali će biti prosleđeni na stek. RSP, pokazivač steka, mora biti poravnan na 16 bajtova, što znači da adresa na koju pokazuje mora biti deljiva sa 16 pre bilo kog poziva. To znači da obično moramo da se pobrinemo da je RSP pravilno poravnan u našem shell kodu pre nego što pozovemo funkciju. Međutim, u praksi, sistemski pozivi često funkcionišu čak i ako ovaj zahtev nije ispunjen.
Konvencija pozivanja u Swift-u
Swift ima svoju konvenciju pozivanja koja se može pronaći na https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#x86-64
Uobičajene instrukcije
x64 instrukcije imaju bogat set, održavajući kompatibilnost sa ranijim x86 instrukcijama i uvodeći nove.
mov
: Premeštanje vrednosti iz jednog registra ili lokacije u memoriji u drugi.Primer:
mov rax, rbx
— Premešta vrednost izrbx
urax
.push
ipop
: Guranje ili izvlačenje vrednosti sa/na stek.Primer:
push rax
— Gura vrednost izrax
na stek.Primer:
pop rax
— Izvlači vrh steka urax
.add
isub
: Operacije sabiranja i oduzimanja.Primer:
add rax, rcx
— Sabira vrednosti urax
ircx
čuvajući rezultat urax
.mul
idiv
: Operacije množenja i deljenja. Napomena: ove imaju specifična ponašanja u vezi sa korišćenjem operanada.call
iret
: Koriste se za pozivanje i vraćanje iz funkcija.int
: Koristi se za pokretanje softverskog prekida. Na primer,int 0x80
se koristio za sistemski poziv u 32-bitnom x86 Linux-u.cmp
: Upoređuje dve vrednosti i postavlja zastave CPU-a na osnovu rezultata.Primer:
cmp rax, rdx
— Upoređujerax
sardx
.je
,jne
,jl
,jge
, ...: Uslovne skok instrukcije koje menjaju tok kontrole na osnovu rezultata prethodnogcmp
ili testa.Primer: Nakon
cmp rax, rdx
instrukcije,je label
— Skoči nalabel
ako jerax
jednakrdx
.syscall
: Koristi se za sistemski poziv u nekim x64 sistemima (kao što su moderni Unix sistemi).sysenter
: Optimizovana instrukcija za sistemski poziv na nekim platformama.
Prolog funkcije
Guranje starog baznog pokazivača:
push rbp
(čuva bazni pokazivač pozivaoca)Premeštanje trenutnog pokazivača steka u bazni pokazivač:
mov rbp, rsp
(postavlja novi bazni pokazivač za trenutnu funkciju)Alokacija prostora na steku za lokalne promenljive:
sub rsp, <veličina>
(gde je<veličina>
broj bajtova potrebnih)
Epilog funkcije
Premeštanje trenutnog baznog pokazivača u pokazivač steka:
mov rsp, rbp
(dealocira lokalne promenljive)Izvlačenje starog baznog pokazivača sa steka:
pop rbp
(vraća bazni pokazivač pozivaoca)Povratak:
ret
(vraća kontrolu pozivaocu)
macOS
syscalls
Postoje različite klase syscalls, možete ih pronaći ovde: ovde:
Zatim, možete pronaći broj svakog sistemskog poziva na ovom linku:
Dakle, da biste pozvali open
sistemski poziv (5) iz Unix/BSD klase, morate dodati: 0x2000000
Dakle, broj sistemskog poziva za pozivanje open bio bi 0x2000005
Shellkodovi
Za kompajliranje:
Za izdvajanje bajtova:
Last updated