Autor
|
Tema: posible problema con integridad de la pila (Leído 7,187 veces)
|
black_flowers
Desconectado
Mensajes: 65
|
no tengo muy claro que es lo que falla con este codigo. Es un programa en asebler que lanza la calcularora, y está pensado para ser convertido en una shellcode. Está basado en el típico ejemplo que se usa para hacer una shellcode, y en general su estructura es esta: funcion que busca dirección de getprocaddress buscar direccion de winexec ejecutar winexec calc.exe buscar direccion de exitprocess ejecutar exitprocess Funciona correctamente hasta llegar a buscar la dirección de exitprocess. Al llegar ahí, algún fallo hay al meter la cadena en la pila y no reconoce tal cadena, y getprocaddress no encuentra su dirección. Podría ser que se pierde la integridad de la pila, la verdad el tema de la integridad de la pila no lo he logrado entender. Así que pongo el código a ver si podeis confirmarme algo. .386 .model flat, stdcall ;32 bit memory model option casemap :none ;case sensitive assume fs:nothing .code dirFuncion proc ; ****************************************** ; Buscamos la dirección base de kernel32.dll ; ****************************************** xor ebx, ebx ;utilizamos ebx en lugar de eax porque con eax salen caracteres nulos. Al final movemos ebx -> eax para tenerloigual que antes. mov ebx, fs:[ebx+30h] mov ebx, [ebx+0Ch] mov ebx, [ebx+1Ch] mov ebx, [ebx] mov ebx, [ebx] mov ebx, [ebx+08h] mov eax, ebx push eax ; guardamos en la pila la direccion base de kernel32.dll ; *********************************************************************** ; Buscamos la direccion de GetProcAddress dada la direccion base de kernel32.dll ; *********************************************************************** busca_funcion: mov esi, [esp] ; puntero a la direccion base add esi, [esi+03Ch] ; puntero a PE signature mov edx, [esi+078h] ; puntero a la Export table add edx, [esp] ; sumamos la direccion base mov ecx, edx ; esto evita meter el 20h (un espacio) que nos corta la shellcode add ecx, 1fh inc ecx mov ebx, [ecx] ; puntero al array AddressOfNames add ebx, [esp] xor eax, eax ; indice de AddressOfNames bucle_funcion: ; buscamos la funcion a partir de la direccion base mov edi, [ebx] add edi, [esp] ; como ya no usamos el segmento .data, comparamos directamente el nombre de ; la libreria y para ello la introducimos al reves. Ademas, al ser 7 bytes, ; tenemos que separar en un dword, un word y un byte, para que no nos coja ; ningun caracter nulo cmp dword ptr [edi], 50746547h jnz funcion_no_encontrada cmp dword ptr [edi + 4], 41636f72h jnz funcion_no_encontrada cmp dword ptr [edi + 8], 65726464h jnz funcion_no_encontrada cmp word ptr [edi + 12], 7373h je funcion_encontrada funcion_no_encontrada: nop ; ponemos un NOP aqui porque tras depurar con el Olly ; vi que usaba \x09 (tabulador) y me rompia la shellcode ; de esta forma amplio el salto en un byte y en lugar de ; 09 pondra 0A add ebx, 4 inc eax cmp eax, dword ptr [edx+18h] jnz bucle_funcion funcion_encontrada: mov esi, dword ptr [edx + 24h] ; puntero a la tabla de ordinales add esi, [esp] ; añadimos la direccion base xor ecx, ecx mov cx, word ptr [esi + 2 * eax] ; cx = numero de la funcion que se ha encontrado mov edi, dword ptr [edx + 1ch] ; puntero a la tabla de direcciones add edi, [esp] ; añadimos la direccion base mov eax, dword ptr [edi + 4 * ecx] ; puntero a la función encontrada add eax, [esp] ; añadimos la direccion base y tenemos la direccion de getprocadress en eax pop esi ;con esto quitamos el valor base del kernel32 que de lo contrario seria la proxima instruccion a ejecutar, y lo metemos en esi para no perderlo ;leave ;esta instruccion es para dejar la pila como estaba, en este ejemplo se he echo manualmente enla instruccion anterior ret dirFuncion endp start: ; ********************************** ; programa principal ; ********************************** call dirFuncion ;mov esi, [esp] ;push ebp ;mov ebp, esp xor dl, dl sub esp, 0fh ; dejamos espacio en la pila para meter nuestra cadena mov byte ptr [ebp-0ah], 57h ; 'W' mov byte ptr [ebp-09h], 69h ; 'i' mov byte ptr [ebp-08h], 6eh ; 'n' mov byte ptr [ebp-07h], 45h ; 'E' mov byte ptr [ebp-06h], 78h ; 'x' mov byte ptr [ebp-05h], 65h ; 'e' mov byte ptr [ebp-04h], 63h ; 'c' mov byte ptr [ebp-03h], dl ; 0x00 lea ecx, [ebp-0ah] ; cargamos la direccion que apunta a nuestra cadena push ecx push esi ;dirección base de kernel32 call eax ; llamamos a getprocadress ;push ebp ;mov ebp, esp sub esp, 11h ; dejamos espacio en la pila para meter nuestra cadena mov byte ptr [ebp-11h], 63h ; 'c' mov byte ptr [ebp-10h], 61h ; 'a' mov byte ptr [ebp-0fh], 6Ch ; 'l' mov byte ptr [ebp-0eh], 63h ; 'c' mov byte ptr [ebp-0dh], 2Eh ; '.' mov byte ptr [ebp-0ch], 65h ; 'e' mov byte ptr [ebp-0bh], 78h ; 'x' mov byte ptr [ebp-0ah], 65h ; 'e' mov byte ptr [ebp-09h], dl ; 0x00 push 5 ;parametro de winexec (show) lea ecx, [ebp-11h] ; cargamos la direccion que apunta a nuestra cadena push ecx call eax ;llamamos a winexec call dirFuncion ;llamamos a la funcion para obtener el geptrocaddress ;push ebp ;mov ebp, esp sub esp, 20h ; dejamos espacio en la pila para meter nuestra cadena mov byte ptr [ebp-12h], 45h ; 'E' mov byte ptr [ebp-11h], 78h ; 'x' mov byte ptr [ebp-10h], 69h ; 'i' mov byte ptr [ebp-0fh], 74h ; 't' mov byte ptr [ebp-0eh], 50h ; 'P' mov byte ptr [ebp-0dh], 72h ; 'r' mov byte ptr [ebp-0ch], 6fh ; 'o' mov byte ptr [ebp-0bh], 63h ; 'c' mov byte ptr [ebp-0ah], 65h ; 'e' mov byte ptr [ebp-09h], 73h ; 's' mov byte ptr [ebp-08h], 73h ; 's' mov byte ptr [ebp-07h], dl ; '0' lea ecx, [ebp-12h] ; cargamos la direccion que apunta a nuestra cadena push ecx push esi ;dirección base de kernel32 call eax ; llamamos a getprocadress ;obtenemos direccion de exitprocess xor ecx, ecx push ecx call eax ;llamamos a exitprocess end start ;ml -c -coff -Cp e:\masm_archivos\shellcode_getprocaddress_exitprocess2\shellcode_getprocaddress_exitprocess2.asm ;link /SUBSYSTEM:WINDOWS shellcode_getprocaddress_exitprocess2.obj
|
|
« Última modificación: 21 Marzo 2011, 20:57 pm por [Zero] »
|
En línea
|
|
|
|
black_flowers
Desconectado
Mensajes: 65
|
bueno como la pregunta es así muy general voy a intentar preguntar alo más concreto a ver si poco a poco lo voy entendiendo. En primer lugar: como podeis ver lo que hago es meter las cadenas "manualmente" en la pila para luego utilizarlas como parametro al llamar a las funciones correspondientes. Por qué es necesario entonces (si es que realmente lo es) hacer estas dos instrucciones antes de meter las cadenas? push ebp mov ebp, esp
Me muestro dudoso de que sea necesario pues he comprobado que no siempre es necesario y que el programa funciona igual lo haga o no. bien esa es la primera duda, espero me podais ayudar puesto que no puedo encontrar informacion sobre esto en ningún otro sitio. El Hacker es mi última esperanza. Un saludo.
|
|
« Última modificación: 21 Marzo 2011, 20:57 pm por [Zero] »
|
En línea
|
|
|
|
[Zero]
Wiki
Desconectado
Mensajes: 1.082
CALL DWORD PTR DS:[0]
|
bueno como la pregunta es así muy general voy a intentar preguntar alo más concreto a ver si poco a poco lo voy entendiendo. En primer lugar: como podeis ver lo que hago es meter las cadenas "manualmente" en la pila para luego utilizarlas como parametro al llamar a las funciones correspondientes. Por qué es necesario entonces (si es que realmente lo es) hacer estas dos instrucciones antes de meter las cadenas? push ebp mov ebp, esp
Me muestro dudoso de que sea necesario pues he comprobado que no siempre es necesario y que el programa funciona igual lo haga o no. bien esa es la primera duda, espero me podais ayudar puesto que no puedo encontrar informacion sobre esto en ningún otro sitio. El Hacker es mi última esperanza. Un saludo. Eso es para guardar el puntero de pila en la pila. Si por ejemplo llamas a una función desde tu main, y tienes que reservar espacio para más cadenas o lo que sea, puedes perder el ebp del main, entonces lo guardas en la pila, y mueves esp (dir por encima de donde metiste ebp) a ebp, así puedes trabajar con ebp como lo hacías en el main. Luego, antes de retornar, recuperas ebp y retornas. Ahora no puedo probar el código de arriba, mañana lo hago, pero te recomiendo mientras intentar buscar el error con un depurador como OllyDbg, ahí vas a poder ver qué es lo que hay en la pila y como avanza, y por qué se produce el error. Saludos
|
|
|
En línea
|
“El Hombre, en su orgullo, creó a Dios a su imagen y semejanza. Nietzsche
|
|
|
black_flowers
Desconectado
Mensajes: 65
|
¡gracias! por tu ayuda. Por lo menos ya se algo más. Además y a raíz de eso se me ocurre que puede haber un pequeño fallo en el mantenimiento de la integridad de lapila (quelo hay seguro y seguro que más de uno pero a saber donde están...). Y consiste en que aunque se guarde el ebp y mover el esp (para meter la cadena en la pila) luego de meter la cadena no se recupera por ningún sitio.
con respecto a depurar el programa con olly te diré que ya lo he hecho y visto lo que pasa en la pila sólo que no entiendo que es loque pasa. Sólo te puedo decir que el paso que falla es al llamar a EndProcess ya que aunque la cadena se introduce en lapila (veo los codigos ascii ahi metidos) no se reconoce como tal y falla al llamar a getprocadress (devuelve el error número 2:file not found), pues nohay una cadena correcta en los parámetros pasados.
|
|
« Última modificación: 21 Marzo 2011, 23:05 pm por black_flowers »
|
En línea
|
|
|
|
[Zero]
Wiki
Desconectado
Mensajes: 1.082
CALL DWORD PTR DS:[0]
|
Bueno, no puedo compilar hoy (mañana te lo miro), pero vi esta línea que utilizas en todo el programa: mov byte ptr [ebp-07h], dl ; '0'
Asegúrate de que edx vale 0, el valor de edx (y de muchos otros regitros) puede cambiar con cada llamada a API's. Fíjate que esté el caracter nulo en la pila, y que luego del "lea" ecx apunte a la cadena. Saludos
|
|
|
En línea
|
“El Hombre, en su orgullo, creó a Dios a su imagen y semejanza. Nietzsche
|
|
|
black_flowers
Desconectado
Mensajes: 65
|
oh, mein god. Era el dl tal y como tú decías. Para ser sincero no sabia que era un registro y que debía de ser una especie de variable definida antes. Vale ahí estaba el fallo. de todas formas sigo sin entender lo de antes y me gustaría aclararlo ahora que ya esta el temainiciado y que estoy tan próximo a resolverlo. Me refiero a si es necesario almacenar el ebp en la pila para luego elevarlo. Recordemos que no se tratade una función sino de meter manualmente una cadena en lapila, Y en caso de que se hiciese... ¿no habría que recuperarlo (el ebp me refiero) al final una vez introducida la cadena? Desde ya muchas gracias pues te confirmo que era ese el problema, gracias!
|
|
|
En línea
|
|
|
|
[Zero]
Wiki
Desconectado
Mensajes: 1.082
CALL DWORD PTR DS:[0]
|
oh, mein god. Era el dl tal y como tú decías. Para ser sincero no sabia que era un registro y que debía de ser una especie de variable definida antes. Vale ahí estaba el fallo. de todas formas sigo sin entender lo de antes y me gustaría aclararlo ahora que ya esta el temainiciado y que estoy tan próximo a resolverlo. Me refiero a si es necesario almacenar el ebp en la pila para luego elevarlo. Recordemos que no se tratade una función sino de meter manualmente una cadena en lapila, Y en caso de que se hiciese... ¿no habría que recuperarlo (el ebp me refiero) al final una vez introducida la cadena? Desde ya muchas gracias pues te confirmo que era ese el problema, gracias! No es necesario recuperar el ebp original si no lo necesitas, depende de lo que quieras hacer. Y para funciones, no sé como ensambla masm, pero fasm ya se encarga de que no haya problemas en esas cosas con las macros de funciones. Lo mejor es que pruebes a hacer cosas, funciones, meter cadenas, y juegues con ebp y esp para que lo pilles. Puedes analizar otras shellcodes también, para ver como juega con ellos, no sé. Saludos
|
|
|
En línea
|
“El Hombre, en su orgullo, creó a Dios a su imagen y semejanza. Nietzsche
|
|
|
|
black_flowers
Desconectado
Mensajes: 65
|
sí, yo tambien lo he comprobado, sí lo hace. Por cierto tambien he comprobado que no tiene sentido guardar el valor de ebp en la pila si luego no se va a recuperar. De todas formas ya que estoy lanzado apreguntar... todavía me queda una última duda. Si os fijais el espacio que se resta al esp no es el mismo que eltamaño de la cadena. Por ejemplo "calc.exe" tiene 8 caracteres + 1 caracter nulo = 9 caracteres. Pero he comprobado de forma empírica, que si no resto 11h a la pila no funciona el programa. No funciona porque aunque la cadena parece ser que la reconoce (pues aparece "calc.exe" en la pila..., al llamar a winexec devuelve file not found. Es decir que se ha de restar un número mayor o igual a 11h, con 10h o menor ya no funciona. Lo mismo pasa con las otras dos cadenas, con "winexec" y con "ExitProcess" en los cuales hay que reservar más espacio en la pila del en realidad necesitan. no así, es necesario colocar la cadena desde el principio, ya que puedo posicionar los caracteres, en lugar de desde la posición ebp-11h, hacerlo desde la ebp-09h. Vuelvo a poner el código que tengo ahora ya que he modificado algunas cosas. .386 .model flat, stdcall ;32 bit memory model option casemap :none ;case sensitive assume fs:nothing
.code
dirFuncion proc ; ****************************************** ; Buscamos la dirección base de kernel32.dll ; ****************************************** xor ebx, ebx ;utilizamos ebx en lugar de eax porque con eax salen caracteres nulos. Al final movemos ebx -> eax para tenerloigual que antes. mov ebx, fs:[ebx+30h] mov ebx, [ebx+0Ch] mov ebx, [ebx+1Ch] mov ebx, [ebx] mov ebx, [ebx] mov ebx, [ebx+08h] mov eax, ebx push eax ; guardamos en la pila la direccion base de kernel32.dll
; *********************************************************************** ; Buscamos la direccion de GetProcAddress dada la direccion base de kernel32.dll ; *********************************************************************** busca_funcion: mov esi, [esp] ; puntero a la direccion base add esi, [esi+03Ch] ; puntero a PE signature mov edx, [esi+078h] ; puntero a la Export table add edx, [esp] ; sumamos la direccion base
mov ecx, edx ; esto evita meter el 20h (un espacio) que nos corta la shellcode add ecx, 1fh inc ecx mov ebx, [ecx] ; puntero al array AddressOfNames add ebx, [esp] xor eax, eax ; indice de AddressOfNames
bucle_funcion: ; buscamos la funcion a partir de la direccion base mov edi, [ebx] add edi, [esp]
; como ya no usamos el segmento .data, comparamos directamente el nombre de ; la libreria y para ello la introducimos al reves. Ademas, al ser 7 bytes, ; tenemos que separar en un dword, un word y un byte, para que no nos coja ; ningun caracter nulo cmp dword ptr [edi], 50746547h jnz funcion_no_encontrada cmp dword ptr [edi + 4], 41636f72h jnz funcion_no_encontrada cmp dword ptr [edi + 8], 65726464h jnz funcion_no_encontrada cmp word ptr [edi + 12], 7373h je funcion_encontrada funcion_no_encontrada: nop ; ponemos un NOP aqui porque tras depurar con el Olly ; vi que usaba \x09 (tabulador) y me rompia la shellcode ; de esta forma amplio el salto en un byte y en lugar de ; 09 pondra 0A add ebx, 4 inc eax cmp eax, dword ptr [edx+18h] jnz bucle_funcion
funcion_encontrada: mov esi, dword ptr [edx + 24h] ; puntero a la tabla de ordinales add esi, [esp] ; añadimos la direccion base xor ecx, ecx mov cx, word ptr [esi + 2 * eax] ; cx = numero de la funcion que se ha encontrado mov edi, dword ptr [edx + 1ch] ; puntero a la tabla de direcciones add edi, [esp] ; añadimos la direccion base mov eax, dword ptr [edi + 4 * ecx] ; puntero a la función encontrada add eax, [esp] ; añadimos la direccion base y tenemos la direccion de getprocadress en eax pop esi ;con esto quitamos el valor base del kernel32 que de lo contrario seria la proxima instruccion a ejecutar, y lo metemos en esi para no perderlo ;leave ;esta instruccion es para dejar la pila como estaba, en este ejemplo se he echo manualmente enla instruccion anterior ret dirFuncion endp
start:
; ********************************** ; programa principal ; **********************************
call dirFuncion ;mov esi, [esp] ;push ebp ;mov ebp, esp xor dl, dl sub esp, 0bh ; dejamos espacio en la pila para meter nuestra cadena mov byte ptr [ebp-08h], 57h ; 'W' mov byte ptr [ebp-07h], 69h ; 'i' mov byte ptr [ebp-06h], 6eh ; 'n' mov byte ptr [ebp-05h], 45h ; 'E' mov byte ptr [ebp-04h], 78h ; 'x' mov byte ptr [ebp-03h], 65h ; 'e' mov byte ptr [ebp-02h], 63h ; 'c' mov byte ptr [ebp-01h], dl ; 0x00 lea ecx, [ebp-08h] ; cargamos la direccion que apunta a nuestra cadena push ecx push esi ;dirección base de kernel32 call eax ; llamamos a getprocadress ;mov esp,ebp ;pop ebp ;push ebp ;mov ebp, esp xor dl, dl sub esp, 11h ; dejamos espacio en la pila para meter nuestra cadena mov byte ptr [ebp-09h], 63h ; 'c' mov byte ptr [ebp-08h], 61h ; 'a' mov byte ptr [ebp-07h], 6Ch ; 'l' mov byte ptr [ebp-06h], 63h ; 'c' mov byte ptr [ebp-05h], 2Eh ; '.' mov byte ptr [ebp-04h], 65h ; 'e' mov byte ptr [ebp-03h], 78h ; 'x' mov byte ptr [ebp-02h], 65h ; 'e' mov byte ptr [ebp-01h], dl ; 0x00 lea ecx, [ebp-09h] ; cargamos la direccion que apunta a nuestra cadena push 5 ;parametro de winexec (show) push ecx call eax ;llamamos a winexec ;mov esp,ebp ;pop ebp call dirFuncion ;llamamos a la funcion para obtener el geptrocaddress ;push ebp ;mov ebp, esp xor dl, dl sub esp, 20h ; dejamos espacio en la pila para meter nuestra cadena mov byte ptr [ebp-12h], 45h ; 'E' mov byte ptr [ebp-11h], 78h ; 'x' mov byte ptr [ebp-10h], 69h ; 'i' mov byte ptr [ebp-0fh], 74h ; 't' mov byte ptr [ebp-0eh], 50h ; 'P' mov byte ptr [ebp-0dh], 72h ; 'r' mov byte ptr [ebp-0ch], 6fh ; 'o' mov byte ptr [ebp-0bh], 63h ; 'c' mov byte ptr [ebp-0ah], 65h ; 'e' mov byte ptr [ebp-09h], 73h ; 's' mov byte ptr [ebp-08h], 73h ; 's' mov byte ptr [ebp-07h], dl ; '0' lea ecx, [ebp-12h] ; cargamos la direccion que apunta a nuestra cadena push ecx push esi ;dirección base de kernel32 call eax ; llamamos a getprocadress ;obtenemos direccion de exitprocess xor ecx, ecx push ecx call eax ;llamamos a exitprocess end start
|
|
|
En línea
|
|
|
|
Иōҳ
Desconectado
Mensajes: 563
|
;00402044 4C 6F 61 64 4C 69 62 72 LoadLibr ;0040204C 61 72 79 41 00 aryA. mov ebp,esp; ebp puntero al stack sub esp, 0Dh; reservamos espacio xor ecx,ecx mov byte ptr [ebp - 0Dh], 4Ch mov byte ptr [ebp - 0Ch], 6Fh mov byte ptr [ebp - 0Bh], 61h mov byte ptr [ebp - 0Ah], 64h mov byte ptr [ebp - 09h], 4Ch mov byte ptr [ebp - 08h], 69h mov byte ptr [ebp - 07h], 62h mov byte ptr [ebp - 06h], 72h mov byte ptr [ebp - 05h], 61h mov byte ptr [ebp - 04h], 72h mov byte ptr [ebp - 03h], 79h mov byte ptr [ebp - 02h], 41h mov byte ptr [ebp - 01h], cl lea ecx, dword ptr [ebp - 0Dh] push ecx push edx; BaseKernel call ebx; GPA add esp, 0Dh; Balanceamos la pila
pues aqui te dejo un ejemplo que he usado y comprabado, mas que explicarte ahi tienes la respuesta Salu2!
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
problema pila cmos pc
Electrónica
|
smokg
|
9
|
9,687
|
26 Febrero 2009, 01:12 am
por smokg
|
|
|
Problema con la pila
ASM
|
B14573R
|
4
|
3,999
|
12 Diciembre 2009, 10:32 am
por Eternal Idol
|
|
|
problema con integridad referencial en access (urge) [resuelto]
Bases de Datos
|
xexio
|
2
|
5,321
|
14 Junio 2010, 19:49 pm
por xexio
|
|
|
problema con pila del bios
« 1 2 »
Hardware
|
Aeros
|
10
|
9,719
|
11 Julio 2010, 16:46 pm
por simorg
|
|
|
Pila en C++ ¡Problema! Solucionado
Programación C/C++
|
¡Micronet!
|
2
|
8,447
|
27 Octubre 2010, 04:46 am
por ¡Micronet!
|
|