Introduction to x64
Wprowadzenie do x64
x64, znany również jako x86-64, to architektura procesora 64-bitowa powszechnie używana w komputerach stacjonarnych i serwerach. Wywodząca się z architektury x86 opracowanej przez Intel, a później przyjęta przez AMD pod nazwą AMD64, jest dominującą architekturą w komputerach osobistych i serwerach obecnie.
Rejestry
x64 rozwija architekturę x86, oferując 16 rejestrów ogólnego przeznaczenia oznaczonych jako rax
, rbx
, rcx
, rdx
, rbp
, rsp
, rsi
, rdi
oraz r8
do r15
. Każdy z nich może przechowywać wartość 64-bitową (8 bajtów). Rejestry te posiadają również podrejestry 32-bitowe, 16-bitowe i 8-bitowe dla kompatybilności i określonych zadań.
rax
- Tradycyjnie używany do wartości zwracanych z funkcji.rbx
- Często używany jako rejestr bazowy do operacji na pamięci.rcx
- Zwykle używany jako licznik pętli.rdx
- Używany w różnych rolach, w tym w operacjach arytmetycznych.rbp
- Wskaźnik bazowy dla ramki stosu.rsp
- Wskaźnik stosu, śledzący górę stosu.rsi
irdi
- Używane jako indeksy źródła i celu w operacjach na łańcuchach/pamięci.r8
dor15
- Dodatkowe rejestry ogólnego przeznaczenia wprowadzone w x64.
Konwencja wywoływania
Konwencja wywoływania x64 różni się między systemami operacyjnymi. Na przykład:
Windows: Pierwsze cztery parametry są przekazywane w rejestrach
rcx
,rdx
,r8
ir9
. Kolejne parametry są umieszczane na stosie. Wartość zwracana znajduje się wrax
.System V (często używany w systemach przypominających UNIX): Pierwsze sześć parametrów całkowitoliczbowych lub wskaźnikowych jest przekazywanych w rejestrach
rdi
,rsi
,rdx
,rcx
,r8
ir9
. Wartość zwracana również znajduje się wrax
.
Jeśli funkcja ma więcej niż sześć wejść, reszta zostanie przekazana na stos. RSP, wskaźnik stosu, musi być wyrównany do 16 bajtów, co oznacza, że adres, do którego wskazuje, musi być podzielny przez 16 przed jakimkolwiek wywołaniem. Oznacza to, że zazwyczaj musielibyśmy upewnić się, że RSP jest odpowiednio wyrównany w naszym kodzie shellcode przed wykonaniem wywołania funkcji. Jednak w praktyce wywołania systemowe działają wiele razy nawet jeśli to wymaganie nie jest spełnione.
Konwencja wywoływania w Swift
Swift ma swoją własną konwencję wywoływania, którą można znaleźć pod adresem https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#x86-64
Powszechne instrukcje
Instrukcje x64 posiadają bogaty zestaw, zachowując kompatybilność z wcześniejszymi instrukcjami x86 i wprowadzając nowe.
mov
: Przenosi wartość z jednego rejestru lub lokalizacji pamięci do drugiego.Przykład:
mov rax, rbx
— Przenosi wartość zrbx
dorax
.push
ipop
: Wstawia lub pobiera wartości z/do stosu.Przykład:
push rax
— Wstawia wartość zrax
na stos.Przykład:
pop rax
— Pobiera najwyższą wartość ze stosu dorax
.add
isub
: Operacje dodawania i odejmowania.Przykład:
add rax, rcx
— Dodaje wartości wrax
ircx
, przechowując wynik wrax
.mul
idiv
: Operacje mnożenia i dzielenia. Uwaga: mają one określone zachowania dotyczące używania operandów.call
iret
: Używane do wywoływania i powrotu z funkcji.int
: Używane do wywołania oprogramowania przerwania. Na przykładint 0x80
było używane do wywołań systemowych w 32-bitowym x86 Linuxie.cmp
: Porównuje dwie wartości i ustawia flagi CPU na podstawie wyniku.Przykład:
cmp rax, rdx
— Porównujerax
zrdx
.je
,jne
,jl
,jge
, ...: Instrukcje skoku warunkowego, które zmieniają przepływ sterowania na podstawie wyników poprzedniegocmp
lub testu.Przykład: Po instrukcji
cmp rax, rdx
,je label
— Skacze dolabel
, jeślirax
jest równyrdx
.syscall
: Używane do wywołań systemowych w niektórych systemach x64 (np. nowoczesne Unixy).sysenter
: Zoptymalizowana instrukcja wywołania systemowego na niektórych platformach.
Prolog Funkcji
Wstaw stary wskaźnik bazowy:
push rbp
(zapisuje wskaźnik bazowy wywołującego)Przenieś bieżący wskaźnik stosu do wskaźnika bazowego:
mov rbp, rsp
(ustawia nowy wskaźnik bazowy dla bieżącej funkcji)Zaalokuj miejsce na stosie dla zmiennych lokalnych:
sub rsp, <rozmiar>
(gdzie<rozmiar>
to liczba potrzebnych bajtów)
Epilog Funkcji
Przenieś bieżący wskaźnik bazowy do wskaźnika stosu:
mov rsp, rbp
(dezalokuje zmienne lokalne)Wyjmij stary wskaźnik bazowy ze stosu:
pop rbp
(przywraca wskaźnik bazowy wywołującego)Powrót:
ret
(zwraca kontrolę do wywołującego)
macOS
wywołania systemowe
Istnieją różne klasy wywołań systemowych, możesz je znaleźć tutaj:
Następnie, możesz znaleźć numer każdego syscalla pod tym adresem:
Więc aby wywołać syscall open
(5) z klasy Unix/BSD, musisz dodać: 0x2000000
Więc numer syscalla do wywołania open to 0x2000005
Shellkody
Aby skompilować:
Aby wyodrębnić bajty:
Last updated