Introduction to x64
Увод у x64
x64, познат и као x86-64, је 64-битна архитектура процесора која се превасно користи у десктоп и серверском рачунарству. Потиче из x86 архитектуре коју је произвео Intel, а касније је усвојила AMD под именом AMD64, и данас је преовлађујућа архитектура у личним рачунарима и серверима.
Регистри
x64 се проширује на x86 архитектуру, имајући 16 регистара опште намене обележених rax
, rbx
, rcx
, rdx
, rbp
, rsp
, rsi
, rdi
, и r8
до r15
. Сваки од ових може да чува 64-битну (8-бајтну) вредност. Ови регистри такође имају 32-битне, 16-битне и 8-битне подрегистре за компатибилност и специфичне задатке.
rax
- Традиционално се користи за вредности повратка из функција.rbx
- Често се користи као базни регистар за операције са меморијом.rcx
- Обично се користи за бројаче петљи.rdx
- Користи се у разним улогама укључујући проширене аритметичке операције.rbp
- Базни показивач за стек фрејм.rsp
- Показивач стека, прати врх стека.rsi
иrdi
- Користе се за изворне и одредишне индексе у операцијама са низовима/меморијом.r8
доr15
- Додатни регистри опште намене уведени у x64.
Конвенција позива
Конвенција позива x64 варира између оперативних система. На пример:
Windows: Прва четири параметра се преносе у регистре
rcx
,rdx
,r8
, иr9
. Додатни параметри се стављају на стек. Вредност повратка је уrax
.System V (обично коришћен у UNIX-подобним системима): Првих шест целих или показивачких параметара се преносе у регистре
rdi
,rsi
,rdx
,rcx
,r8
, иr9
. Вредност повратка је такође уrax
.
Ако функција има више од шест улаза, остали ће бити пренесени на стек. RSP, показивач стека, мора бити поредио на 16 бајтова, што значи да адреса на коју указује мора бити делива са 16 пре него што се било који позив деси. То значи да обично морамо осигурати да је RSP правилно поређен у нашем shellcode-у пре него што направимо позив функције. Међутим, у пракси, системски позиви функционишу много пута иако овај захтев није испуњен.
Конвенција позива у Swift
Swift има своју конвенцију позива која се може наћи на https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#x86-64
Уобичајене инструкције
x64 инструкције имају богат сет, одржавајући компатибилност са ранијим x86 инструкцијама и уводећи нове.
mov
: Премести вредност из једног регистра или меморијске локације у други.Пример:
mov rax, rbx
— Премешта вредност изrbx
уrax
.push
иpop
: Постави или уклони вредности на/са стека.Пример:
push rax
— Поставља вредност уrax
на стек.Пример:
pop rax
— Уклоњава врх вредности из стека уrax
.add
иsub
: Операције сабирања и одузимања.Пример:
add rax, rcx
— Сабира вредности уrax
иrcx
, чувајући резултат уrax
.mul
иdiv
: Операције мултипликације и делења. Напомена: ове имају специфична понашања у вези са коришћењем операнда.call
иret
: Користе се за позивање и враћање из функција.int
: Користи се за активирање софтверског прекида. На пример,int 0x80
се користио за системске позиве у 32-битном x86 Линуксу.cmp
: Упоређује две вредности и поставља флагове ЦПУ-а на основу резултата.Пример:
cmp rax, rdx
— Упоређујеrax
саrdx
.je
,jne
,jl
,jge
, ...: Условне скок инструкције које мењају ток контроле на основу резултата претходнеcmp
или теста.Пример: Након инструкције
cmp rax, rdx
,je label
— Скаче наlabel
ако јеrax
једнакrdx
.syscall
: Користи се за системске позиве у неким x64 системима (као што је модерни Unix).sysenter
: Оптимизована инструкција системског позива на неким платформама.
Функционални пролог
Постави стари базни показивач:
push rbp
(чува базни показивач позиваоца)Премести тренутни показивач стека у базни показивач:
mov rbp, rsp
(поставља нови базни показивач за текућу функцију)Алокирај простор на стеку за локалне променљиве:
sub rsp, <size>
(где је<size>
број бајтова који су потребни)
Функционални епилог
Премести тренутни базни показивач у показивач стека:
mov rsp, rbp
(ослобађа локалне променљиве)Уклоните стари базни показивач са стека:
pop rbp
(враћа базни показивач позиваоца)Врати:
ret
(враћа контролу позиваоцу)
macOS
системски позиви
Постоје различите класе системских позива, можете наћи их овде:
Zatim, možete pronaći svaki syscall broj na ovoj adresi:
Dakle, da biste pozvali open
syscall (5) iz Unix/BSD klase, potrebno je da mu dodate: 0x2000000
Dakle, broj syscall-a za pozivanje open bi bio 0x2000005
Shellcodes
Da biste kompajlirali:
Da biste izdvojili bajtove:
Last updated