Tema destacado: Nueva página de elhacker.net en Google+ 
Autor
|
Tema: Problemas con ESP (Leído 3,793 veces)
|
c1c4tr1z
Desconectado
Mensajes: 27
|
Estaba leyendo un poco últimamente sobre el mundo de la pila y un problema grande que tengo es que me cuesta encontrar la dirección de ESP para sobreescribir el RET. Quizás porque hace poco me undo en este tema. Vi un pequeño pedazo de código echo por Anon que me intereso mucho: unsigned long get_esp(void) { __asm__("movl %esp,%eax"); }
Así que que me hice un pequeño script para realizar la misma función, simplemente para probar: #include <stdio.h> char *ASM="__asm__(\"movl %esp,%eax\")"; int main(int argc, char *argv[]){ printf("\n0x%X\n\n",(unsigned long int *)ASM-atoi(argv[1])); return 0; }
Lo que no tengo bien en claro seria si no es mejor hacer algo como esto (ejemplo): c1c4tr1z@c1c4tr1z:~$ gdb ret GNU gdb 6.8-debian Copyright (C) 2008 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"... (gdb) run 0 Starting program: /home/c1c4tr1z/Escritorio/ret 0
0x80A1588
Program exited normally. (gdb) break main Breakpoint 1 at 0x8048202: file ret.c, line 4. (gdb) run 0 Starting program: /home/c1c4tr1z/Escritorio/ret 0
Breakpoint 1, main (argc=2, argv=0xbfac1074) at ret.c:4 4 printf("\n0x%X\n\n",(unsigned long int *)ASM-atoi(argv[1])); (gdb) x/bx $eip 0x8048202 <main+18>: 0xa1 (gdb) i registers eax 0xbfac1074 -1079242636 ecx 0xbfac0e30 -1079243216 edx 0xbfac100c -1079242740 ebx 0x0 0 esp 0xbfac0e00 0xbfac0e00 ebp 0xbfac0e18 0xbfac0e18 esi 0x20618 132632 edi 0x3 3 eip 0x8048202 0x8048202 <main+18> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb) quit
Aunque el programa no tenga ningún tipo de overflow, en el caso de haberlo ¿Esta bien echa la forma de conseguir la direccion de ESP? Si alguien puede iluminarme el camino, porfavor hable! Saludos y muchas gracias!
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Bueno recordaremos que la memoria es un lugar dinamico y mas a un la pila, la direccion que obtengamos es aproximado de lo que seria el ESP. Ahora veo tu codigo: ASM-atoi(argv[1]) wtf? tu hiciste una funcion ASM-atoi? Al parecer tu lo que estas obteniendo es la direccion en memoria de la cadena o algo :S char *ASM="__asm__(\"movl %esp,%eax\")"; y eso no es la direccion del ESP, es la direccion de la cadena. Lo interesante para quitarnos de dudas seria imprimir el contenido de 0x80A1588printf "%s\n", 0x80A1588 o x/24 0x80A1588 Saludos!!
|
|
|
|
|
En línea
|
|
|
|
c1c4tr1z
Desconectado
Mensajes: 27
|
Si, un error mio por tratar de simplificar las cosas :S Aunque gracias a esto comprendo algunas cosas.. Bueno, a lo que voy es que me cuesta trabajo entender y encontrar la forma de conseguir el "return address" para que al sobrepasar el buffer (en un overflow común) se pueda volver a ESP con el shellcode. Algo como: char buffer[1024] AAAA..x1028 + RET + SHELLCODE + \x00 (Quizas no sepa explicarme bien  )
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Si si comprendo, solo que necesitas tener la direccion exacta y recuerda que puede variar un poco. por eso algunos usan los NOP para tener un terreno para resbalar hacia el shellcode, recuerda que tambien puedes usar variables de entorno las cuales casi no cambian de direccion.
Saludos.
|
|
|
|
|
En línea
|
|
|
|
sirdarckcat
Troll Buena Onda y
CoAdmin
 
Desconectado
Mensajes: 6.947
Lavando Platos
|
ASM-atoi no puede ser el nombre de una funcion, mas bien seria, a la variable ASM le restas atoi(argv[1])
|
|
|
|
|
En línea
|
|
|
|
c1c4tr1z
Desconectado
Mensajes: 27
|
@sirdarckcat: Si, exactamente, mi problema apareció cuando guarde el ASM en una variable y trate de ejecutarlo con (void *). Pero igualmente ya estoy captando como es el tema  .
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
A deberás no se como no lo vi, lo bueno que ya esta quedando aclarado.
Saludos y exelentes fiestas de año.
|
|
|
|
|
En línea
|
|
|
|
achernar_
Desconectado
Mensajes: 114
|
Yo no entendí mucho para que querés obtener la direccion del ESP, pero como vi que decias algo sobre shellcodes puede que esto te sea útil. Cuando querés ejecutar una shellcode, necesitás hacer un jmp esp, se suele utilzar una direccion de una dll conocida (p/ej kernel32 y user32) donde esté este salto. Para encontrar esto se usa una herramienta que se llama findjmp.exe. No estoy seguro de que sea lo que necesités pero espero que te sea útil. http://foro.elhacker.net/bugs_y_exploits/pedazo_de_herramienta_busca_offsets_en_dlls_findjmpexe-t101215.0.html;msg456090
|
|
|
|
|
En línea
|
Tengo una habilidad sorprendente para hacer cosas que no sorprenden.
|
|
|
c1c4tr1z
Desconectado
Mensajes: 27
|
Gracias por la herramienta, pero yo estoy trabajando en GNU/Linux. Necesitaba la dirección de ESP para poder volver al comienzo del stack e inyectar el shellcode.
|
|
|
|
|
En línea
|
|
|
|
dark_hat
Desconectado
Mensajes: 183
|
En linux puedes buscar los opcodes de jmp esp o call esp en el ELF en cuestión o en las librerías que use o bien poner una dirección a ojo aproximada de esp y q la shellcode tenga varios NOP al principio.
|
|
|
|
|
En línea
|
Eso que huele es un poco de incienso, eso marrón una tableta de turrón...
|
|
|
Arkangel_0x7C5
Desconectado
Mensajes: 298
|
la direccion del ret suele estar en EBP
|
|
|
|
|
En línea
|
|
|
|
c1c4tr1z
Desconectado
Mensajes: 27
|
En linux puedes buscar los opcodes de jmp esp o call esp en el ELF en cuestión o en las librerías que use o bien poner una dirección a ojo aproximada de esp y q la shellcode tenga varios NOP al principio. En realidad eso es un poco mas difícil con patchs para protección o el patch para VA. la direccion del ret suele estar en EBP La direccion de retorno suele estar en EIP, a menos que me este perdiendo de algo. Igualmente encontré una manera interesante que estuve probando. Se trata de usar ptrace() para conseguir los registros, dándome un valor aproximado de ESP.
|
|
|
|
|
En línea
|
|
|
|
Arkangel_0x7C5
Desconectado
Mensajes: 298
|
La direccion de retorno suele estar en EIP, a menos que me este perdiendo de algo.
eip siempre apunta a la proxima intrucion a ejecutar y yo me referia a que cuando haces un cal a una funcion, siempre empieza asi: call funcion ;funcion: push ebp mov ebp,esp ........ ........ ....... leave ret por lo que la direccion que tomara ret siempre esta en [ebp+4] y los parametros a la funcion a partir de [ebp+8] y da igual el lenguaje y compilador que uses. comprovadlo con algun debunguer si quereis.
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Yep, Totalmente cierto la dirección de retorno suele estar cerca de donde a punta EBP, lo que dice c1c4tr1z es que la Dirección de retorno esta en EIP, pero esto solo es cuando ya esta por saltar al shellcode, esto es cuando ya lograste sobrescribir dicho registro.
Saludos.
|
|
|
|
|
En línea
|
|
|
|
c1c4tr1z
Desconectado
Mensajes: 27
|
Si, ya entendi a lo que se referia juan113. Bueno, de paso dejo el codigo al que me referia con ptrace(): #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/ptrace.h> #include <linux/user.h> void usage(){ printf("++-- Usage: ./esp_ptrace <pid>\n++-- C1c4Tr1Z <research@voodoo-labs.org>\n"); exit(0); } int main(int argc, char *argv[]){ pid_t pid; struct user_regs_struct registers; long esp; int stat=0; if(argc<2) usage(); pid=atoi(argv[1]); if(ptrace(PTRACE_ATTACH, pid, NULL, NULL)){ perror("++-- ptrace()"); return 0; } wait(&stat); printf("++-- PID: %d\n",pid); printf("++-- PPID: %d\n",getpid()); if((ptrace(PTRACE_GETREGS, pid, ®isters, ®isters))<0){ perror("++-- ptrace()"); ptrace(PTRACE_DETACH, pid, NULL, NULL); return 0; } esp=registers.esp+0x3CC;//getting original %esp printf("++-- ESP: %c[%dm0x%lx%c[%dm\n",0x1b,31, esp,0x1b,0); ptrace(PTRACE_DETACH, pid, NULL, NULL); return 0; } Es un codigo simple para conseguir un address valido de ESP. $ ./daemon 0xbf94ac58:11115 [...] $ ./esp_ptrace 11115 ++-- PID: 11115 ++-- PPID: 11184 ++-- ESP: 0xbf94ac58 $ Claro que lo podrian cambiar para que se ajuste a sus necesidades 
|
|
|
|
« Última modificación: 28 Enero 2009, 21:10 por c1c4tr1z »
|
En línea
|
|
|
|
|
|