Excepciones en FASM

Iniciado por Yuki, 10 Febrero 2016, 00:38 AM

0 Miembros y 3 Visitantes están viendo este tema.

Yuki

Averigue como manejar una excepción en FASM, pero no se como lo hago ¿alguien me lo podria explicar?

Mas que nada tengo la duda de las líneas 6 y 7.

Según tengo entendido, FS es como una "estructura" ¿alguien me lo podria confirmar?
Otra cosa que quiero saber es de que valor de FS ([FS+hVALOR]) puedo obtener el código de la excepción sin recurrir a una api (GetExceptionCode).

format pe gui 4.0
include 'win32ax.inc'
.code
start:
    push Excepción      ; Empujamos la dirección del control de excepción.
    push dword [FS:0]   ; ¿?
    mov  [FS:0], esp    ; ¿?
    int3                ; Generamos una excepción.
Excepción:
    invoke MessageBox,0,'Intercepte una excepción!','Excepción',48
    invoke ExitProcess, 0
    ret
.end start


Gracias de antemano.

Eternal Idol

#1
Entre la linea 5 y la 6 crea un marco de SEH:

0:000> dt ntdll!_TEB
  +0x000 NtTib            : _NT_TIB
...

dt ntdll!_NT_TIB
  +0x000 ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD
...
0:000> dt ntdll!_EXCEPTION_REGISTRATION_RECORD
  +0x000 Next             : Ptr32 _EXCEPTION_REGISTRATION_RECORD
  +0x004 Handler          : Ptr32 _EXCEPTION_DISPOSITION

Handler tiene como valor en este caso Excepción y Next toma el valor que habia en FS:[0], es decir el marco SEH anterior.

En la linea 7 le asigna a ExceptionList el marco SEH que puso en la pila en las dos lineas anteriores.

Si, _TEB es la estructura, a la que se puede acceder con un offset del registro de segmento FS: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block

GetExceptionCode es una macro pero en la pila cuando tu manejador de excepciones es llamado tenes un puntero una estructura del tipo EXCEPTION_RECORD:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082%28v=vs.85%29.aspx
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Yuki

Aunque no lo creas, me confundiste un poco más, despue de leér tu comentario muchas veces y buscar información extra en internet como es debido creo entender un poco tu respuesta.

CitarHandler tiene como valor en este caso Excepción y Next toma el valor que habia en FS:[0], es decir el marco SEH anterior.

Handler vendria a ser [FS] despues de haberle movido ESP (osae la estructura) ¿no? ese termino me mato, en todo caso si es así puedo suponer que tiene 2 "miembros".

1_ Next: Puntero a la dirección que se ejecutará al ocurrir una excepción.
2_ Handler: Puntero al marco SEH anterior.

La línea 7 de llano no te entendí, no se que es "ExceptionList" (Lista de excepciones).

¿Vos interpretas como SEH a los 2 valores en la pila y [FS:0] como la lista de excepciones?

Gracias por responder, te agradeceria si me sacaras estas dudas  :)

fary

#3
De manera más vulgar.

push Excepción      ; Empujamos la dirección del control de excepción.
push dword [FS:0]  ; Empujamos el ultimo manejador de excepciones que habia (el siguiente que se ejecutara si no controla el error)
mov  [FS:0], esp    ; ponemos el puntero de la estructura. Es decir, establecemos el controlador de excepciones que acabamos de crear.


Recuerda que si nuestro controlador no es capaz de controlar la excepción (Oséa no tenemos el filtro y le pasamos la excepción a la siguiente estructura), le pasará el control a otro controlador, en este casi entra en juego el manejador de excepciones que había, osea el valor que hemos introducido en:

+0x000 Next             : Ptr32 _EXCEPTION_REGISTRATION_RECORD

Que es el anterior controlador que se creo antes que el nuestro.

saludos!
Un byte a la izquierda.

Eternal Idol

Cita de: Yuki en 10 Febrero 2016, 02:19 AM
Handler vendria a ser [FS] despues de haberle movido ESP (osae la estructura) ¿no? ese termino me mato, en todo caso si es así puedo suponer que tiene 2 "miembros".

1_ Next: Puntero a la dirección que se ejecutará al ocurrir una excepción.
2_ Handler: Puntero al marco SEH anterior.

No, Handler es el segundo campo del marco SEH (la estructura EXCEPTION_REGISTRATION_RECORD). Es al reves 1 y 2, Next como su nombre lo indica es el siguiente marco SEH en la lista (vos añadis un marco SEH y lo haces apuntar al que estaba en cabeza de la lista), Handler es el "manejador" de la excepcion, esa es la direccion de tu funcion.

Cita de: Yuki en 10 Febrero 2016, 02:19 AMLa línea 7 de llano no te entendí, no se que es "ExceptionList" (Lista de excepciones).

FS:[0] es en definitiva ExceptionList, como dice en la Wikipedia  Current Structured Exception Handling (SEH) frame. El campo ExceptionList es el primero de la TEB ya que su primer miembro es del tipo NT_TIB:

dt ntdll!_NT_TIB
  +0x000 ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD

Cita de: Yuki en 10 Febrero 2016, 02:19 AM
¿Vos interpretas como SEH a los 2 valores en la pila y [FS:0] como la lista de excepciones?

Marco SEH (o SEH frame) son esos dos valores que componen una estructura del tipo EXCEPTION_REGISTRATION_RECORD.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Yuki

Gracias por sus respuestas, veamos si entendí

push Expresión ; Sección de código que se ejecutará al ocurrir una excepción.
push DWORD [FS:0]   ; Puntero al ultimo marco (SEH) que manejará la excepción si nuestro controlador no funcionó.
mov [FS:0],ESP ; Mueve la punta del stack a [FS:0] (Mueve la "estructura" o los "2 miembros" al marco SEH) para el controlador actual.


FS de llano es la estructura TIB (Thread Information Block).
[FS:0] es un puntero a la estructura SEH (EXCEPTION_REGISTRATION_RECORD).
Los 2 primeros push son los miembros de la estructura SEH.
Al generarse una excepción, el ultimo item de la pila es un puntero a EXCEPTION_RECORD.

Espero no haber pifiado ninguna, por favor corríjanme si me equivoque o tengo una idea erronea de algúna parte de este código.

Gracias!

Eternal Idol

Cita de: Yuki en 10 Febrero 2016, 04:35 AM
FS de llano es la estructura TIB (Thread Information Block).
[FS:0] es un puntero a la estructura SEH (EXCEPTION_REGISTRATION_RECORD).
Los 2 primeros push son los miembros de la estructura SEH.
Al generarse una excepción, el ultimo item de la pila es un puntero a EXCEPTION_RECORD.

Espero no haber pifiado ninguna, por favor corríjanme si me equivoque o tengo una idea erronea de algúna parte de este código.

Gracias!

Si, bueno es TEB, cuyo primer campo es del tipo TIB (NT_TIB).
Si, ExceptionList (seria en C Teb->NtTib.ExceptionList).
Si, Next y Handler.

Casi, siempre cuando se llama a una funcion el ultimo elemento de la pila es la direccion de retorno, en este caso y por la convencion de llamada el siguiente es un puntero a EXCEPTION_RECORD. Por cierto tal vez te confundio un poco al principio el orden de los campos del marco SEH por la forma de crecer que tiene la pila:

antes de push expresion tenes como ultimo elemento la direccion de retorno:
0:000> dd @esp
000cff84  767a7c04 7ffde000 767a7be0 2c77d213

KERNEL32!BaseThreadInitThunk+0x24:
767a7c04 50              push    eax
767a7c05 ff15b0118176    call    dword ptr [KERNEL32!_imp__RtlExitUserThread (768111b0)]
...

empujaste expresion, el ultimo elemento de la pila es ese y la direccion de la misma (ESP) decrecio 4 bytes (el tamaño de un elemento):
0:000> dd @esp
000cff80  00402037 767a7c04 7ffde000 767a7be0

empujaste lo que vendria a ser Teb->NtTib.ExceptionList->Next:
0:000> dd @esp
000cff7c  000cffcc 00402037 767a7c04 7ffde000

Siguiendo la logica anterior en ESP tenes un marco SEH perfectamente valido, primero el Next y despues el Handler (y ahi continua estando la direccion de retorno).

Con todo esto espero que ahora sea mas evidente que en la linea 7 le asigna a ExceptionList el marco SEH que puso en la pila en las dos lineas anteriores  ::)
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Yuki

#7
Gracias Eternal Idol, mas claro imposible, y tan como dijiste, tenia mis dudas sobre los push conforme al marco SEH.

Yo tenia entendido que FS era TIB gracias a Wikipedia y desconocia la estructura TEB (CSLS).

Ahora voy a estudiar como cerrar este controlador de excepciones.

¿Puedo suponer que se extraen los elementos de la pila?

Según tengo entendido, es algo como:
Citarpop dword [fs:0] ; Returnamos al ultimo controlador.
add esp,4 ; Volvemos al stack pointer inicial.

Eternal Idol

Si, para sacarlo pones el puntero que habia antes en FS:[0] y listo. El codigo es correcto, siempre que lo ejecutes desde un punto donde ESP sea justamente el marco SEH que construiste (asi al estar primero el campo Next en la pila con un POP con destino FS:[0] lo restauras, y el add esp, 4 es lo mismo que un POP sin destino).

0040200d 64892500000000  mov     dword ptr fs:[0],esp fs:0053:00000000=000cffcc
0:000> dd fs:[0]
0053:00000000  000cffcc 000d0000 000cd000 00000000
0:000> dd @esp
000cff7c  000cffcc 00402041 767a7c04 7ffde000

00402014 648f0500000000  pop     dword ptr fs:[0]     fs:0053:00000000=000cff7c
0:000> dd fs:[0]
0053:00000000  000cff7c 000d0000 000cd000 00000000

0040201b 83c404          add     esp,4
0:000> dd fs:[0]
0053:00000000  000cffcc 000d0000 000cd000 00000000

0:000> dd @esp
000cff80  00402041 767a7c04 7ffde000 767a7be0

Tras esta instruccion:

0:000> dd @esp
000cff84  767a7c04 7ffde000 767a7be0 c809f9f9
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón