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 належним чином вирівняний у нашому шелл-коді перед викликом функції. Однак на практиці системні виклики працюють багато разів навіть якщо це вимога не виконується.
Конвенція виклику в 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 Linux.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, <розмір>
(де<розмір>
- кількість байтів, необхідних)
Епілог Функції
Перемістити поточний вказівник бази в вказівник стеку:
mov rsp, rbp
(звільнити локальні змінні)Вилучити старий вказівник бази зі стеку:
pop rbp
(відновлює вказівник бази викликача)Повернення:
ret
(повертає управління викликачу)
macOS
системні виклики
Існують різні класи системних викликів, ви можете знайти їх тут:
Потім ви можете знайти кожен номер системного виклику за цим посиланням:
Таким чином, для виклику системного виклику open
(5) з класу Unix/BSD потрібно додати: 0x2000000
Отже, номер системного виклику для виклику open буде 0x2000005
Шелл-коди
Для компіляції:
Для вилучення байтів:
Last updated