Stack Pivoting - EBP2Ret - EBP chaining
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ця техніка використовує можливість маніпулювати Base Pointer (EBP) для з'єднання виконання кількох функцій через обережне використання регістра EBP та інструкцій leave; ret
.
Нагадаємо, що leave
в основному означає:
And as the EBP is in the stack before the EIP it's possible to control it controlling the stack.
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.
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 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) followed by the shellcode to execute.
Some ROP 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.
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.
Usually it's modified the byte 0x00t o jump as far as possible.
Also, it's common to use a RET sled in the stack and put the real ROP chain at the end to make it more probably that the new ESP points inside the RET SLED and the final ROP chain is executed.
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, but more complex with no apparent benefit but could be interesting in some edge-cases.
Moreover, here you have an example of a challenge that uses this technique with a stack leak to call a winning function. This is the final payload from the page:
Як пояснено в цьому пості, якщо бінарний файл скомпільований з деякими оптимізаціями, EBP ніколи не контролює ESP, отже, будь-який експлойт, що працює шляхом контролю EBP, в основному зазнає невдачі, оскільки не має жодного реального ефекту. Це пов'язано з тим, що пролог і епілог змінюються, якщо бінарний файл оптимізований.
Не оптимізовано:
Оптимізовано:
pop rsp
гаджетНа цій сторінці ви можете знайти приклад використання цієї техніки. Для цього завдання потрібно було викликати функцію з 2 специфічними аргументами, і був pop rsp
гаджет та є leak з стеку:
Перевірте техніку ret2esp тут:
Ret2esp / Ret2reg64 біти, експлуатація off by one з ланцюгом rop, що починається з ret sled
64 біти, без relro, canary, nx та pie. Програма надає leak для стеку або pie та WWW для qword. Спочатку отримайте leak стеку та використайте WWW, щоб повернутися і отримати leak pie. Потім використайте WWW, щоб створити вічний цикл, зловживаючи записами .fini_array
+ викликом __libc_csu_fini
(більше інформації тут). Зловживаючи цим "вічним" записом, записується ланцюг ROP у .bss і в кінці викликається, підіймаючись з RBP.
В ARM64, пролог та епілоги функцій не зберігають і не відновлюють реєстр SP у стеку. Більше того, інструкція RET
не повертає за адресою, на яку вказує SP, а за адресою всередині x30
.
Отже, за замовчуванням, просто зловживаючи епілогом, ви не зможете контролювати реєстр SP, переписуючи деякі дані всередині стеку. І навіть якщо вам вдасться контролювати SP, вам все ще знадобиться спосіб контролювати реєстр x30
.
пролог
епілог
Спосіб виконати щось подібне до стекового підіймання в ARM64 полягатиме в тому, щоб мати можливість контролювати SP
(контролюючи якийсь реєстр, значення якого передається до SP
, або тому, що з якоїсь причини SP
бере свою адресу зі стеку, і у нас є переповнення) і потім зловживати епілогом, щоб завантажити реєстр x30
з контрольованого SP
і RET
до нього.
Також на наступній сторінці ви можете побачити еквівалент Ret2esp в ARM64:
Ret2esp / Ret2regВчіться та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Вчіться та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)