Introduction to x64
Introduzione a x64
x64, noto anche come x86-64, è un'architettura del processore a 64 bit utilizzata principalmente nel calcolo desktop e server. Originaria dell'architettura x86 prodotta da Intel e successivamente adottata da AMD con il nome AMD64, è l'architettura predominante nei computer personali e nei server odierni.
Registri
x64 amplia l'architettura x86, presentando 16 registri ad uso generale denominati rax
, rbx
, rcx
, rdx
, rbp
, rsp
, rsi
, rdi
e r8
fino a r15
. Ciascuno di essi può memorizzare un valore 64-bit (8 byte). Questi registri dispongono anche di sotto-registri a 32 bit, 16 bit e 8 bit per la compatibilità e per compiti specifici.
rax
- Tradizionalmente utilizzato per i valori di ritorno dalle funzioni.rbx
- Spesso utilizzato come registro base per le operazioni di memoria.rcx
- Comunemente utilizzato per i contatori di ciclo.rdx
- Utilizzato in vari ruoli, inclusa l'aritmetica estesa.rbp
- Puntatore base per il frame dello stack.rsp
- Puntatore stack, che tiene traccia della cima dello stack.rsi
erdi
- Utilizzati come indici sorgente e destinazione nelle operazioni di stringa/memoria.r8
ar15
- Registri ad uso generale aggiuntivi introdotti in x64.
Convenzione di Chiamata
La convenzione di chiamata x64 varia tra i sistemi operativi. Ad esempio:
Windows: I primi quattro parametri vengono passati nei registri
rcx
,rdx
,r8
er9
. Ulteriori parametri vengono spinti nello stack. Il valore di ritorno è inrax
.System V (comunemente usato nei sistemi simili a UNIX): I primi sei parametri interi o puntatori vengono passati nei registri
rdi
,rsi
,rdx
,rcx
,r8
er9
. Anche il valore di ritorno è inrax
.
Se la funzione ha più di sei input, il resto verrà passato nello stack. RSP, il puntatore stack, deve essere allineato a 16 byte, il che significa che l'indirizzo a cui punta deve essere divisibile per 16 prima di qualsiasi chiamata. Questo significa che normalmente dovremmo assicurarci che RSP sia correttamente allineato nel nostro shellcode prima di effettuare una chiamata di funzione. Tuttavia, nella pratica, le chiamate di sistema funzionano molte volte anche se questo requisito non è soddisfatto.
Convenzione di Chiamata in Swift
Swift ha la sua propria convenzione di chiamata che può essere trovata in https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#x86-64
Istruzioni Comuni
Le istruzioni x64 dispongono di un ricco set, mantenendo la compatibilità con le istruzioni x86 precedenti e introducendone di nuove.
mov
: Sposta un valore da un registro o da una posizione di memoria a un'altra.Esempio:
mov rax, rbx
— Sposta il valore darbx
arax
.push
epop
: Push o pop dei valori nello/ dallo stack.Esempio:
push rax
— Inserisce il valore inrax
nello stack.Esempio:
pop rax
— Estrae il valore in cima allo stack inrax
.add
esub
: Operazioni di addizione e sottrazione.Esempio:
add rax, rcx
— Aggiunge i valori inrax
ercx
memorizzando il risultato inrax
.mul
ediv
: Operazioni di moltiplicazione e divisione. Nota: queste hanno comportamenti specifici relativi all'uso degli operandi.call
eret
: Usati per chiamare e ritornare dalle funzioni.int
: Usato per generare un interruzione software. Ad esempio,int 0x80
veniva utilizzato per le chiamate di sistema in Linux x86 a 32 bit.cmp
: Confronta due valori e imposta i flag della CPU in base al risultato.Esempio:
cmp rax, rdx
— Confrontarax
conrdx
.je
,jne
,jl
,jge
, ...: Istruzioni di salto condizionale che modificano il flusso di controllo in base ai risultati di un precedentecmp
o test.Esempio: Dopo un'istruzione
cmp rax, rdx
,je label
— Salta alabel
serax
è uguale ardx
.syscall
: Usato per le chiamate di sistema in alcuni sistemi x64 (come Unix moderni).sysenter
: Un'istruzione di chiamata di sistema ottimizzata su alcune piattaforme.
Prologo della Funzione
Push del vecchio puntatore base:
push rbp
(salva il puntatore base del chiamante)Sposta il puntatore stack corrente al puntatore base:
mov rbp, rsp
(imposta il nuovo puntatore base per la funzione corrente)Assegna spazio nello stack per le variabili locali:
sub rsp, <size>
(dove<size>
è il numero di byte necessario)
Epilogo della Funzione
Sposta il puntatore base corrente al puntatore stack:
mov rsp, rbp
(dealloca le variabili locali)Estrai il vecchio puntatore base dallo stack:
pop rbp
(ripristina il puntatore base del chiamante)Ritorna:
ret
(restituisce il controllo al chiamante)
macOS
chiamate di sistema
Ci sono diverse classi di chiamate di sistema, puoi trovarle qui:
Quindi, puoi trovare il numero di ogni chiamata di sistema in questo URL:
Quindi, per chiamare la chiamata di sistema open
(5) dalla classe Unix/BSD è necessario aggiungere: 0x2000000
Quindi, il numero di chiamata di sistema per chiamare open sarebbe 0x2000005
Shellcodes
Per compilare:
Per estrarre i byte:
Last updated