Ir al contenido principal

WinDbg Breakpoint on key pressed

Imaginad por un momento que os surge la necesidad de detener la ejecución de un programa cuando se pulsa una determinada tecla o combinación de estas, en fin, algo normal que a cualquier persona se le puede pasar por la imaginación, ¿o no?. Bromas aparte, para conseguirlo podemos utilizar infinidad de técnicas y en esta ocasión voy a comentaros la última que he empleado yo en uno de los trabajos que estoy realizando actualmente.

Esta técnica consiste en colocar un punto de ruptura en la llamada a la API TranslateAccelerator. Ahora bien, debemos tener en cuenta que si colocamos un breakpoint de ejecución sin más, el debugger estará constantemente saltando y no podremos conseguir nuestro objetivo o, cuando menos, será muy desesperante.

Para evitar tal situación, lo que tenemos que hacer es utilizar un breakpoint condicional para indicarle al debugger que se detenga solamente cuando se cumple una determinada condición o condiciones y por consiguiente que continúe con la ejecución normal del programa en el resto de los casos.

A modo de ejemplo y haciendo uso de uno de los depuradores que más me gusta (sí el depurador de Microsoft), vamos a detener la ejecución del programa cuando se pulse la tecla INTRO. Para esto, es preciso conocer tanto el prototipo de la API TranslateAccelerator que podéis ver a continuación:

int WINAPI TranslateAccelerator(
  _In_  HWND hWnd,
  _In_  HACCEL hAccTable,
  _In_  LPMSG lpMsg
);


como las estructuras de datos involucradas, ya que, si os fijáis el tercer parámetro de la API es un puntero a la estructura MSG. En este caso la principal estructura que debemos conocer es MSG, ya que necesitaremos hacer buen uso de algunos de sus miembros:

typedef struct tagMSG {
  HWND   hwnd;
  UINT   message;
  WPARAM wParam;
  LPARAM lParam;
  DWORD  time;
  POINT  pt;
} MSG, *PMSG, *LPMSG;


Llegados a este punto, ya conocemos bien a nuestro objetivo y cómo podemos "jugar" con él. Ahora tan solo falta saber cómo le decimos al depurador que utilice toda esta información. Aunque puede hacerse de varias formas, la técnica que expongo aquí es mediante el uso del evaluador de expresiones al estilo C++ que incorpora el debugger.

Si observamos la estructura MSG, enseguida nos damos cuenta de que hay varias cosas muy útiles para conseguir nuestro objetivo. Dado que queremos detener la ejecución del programa al pulsar una tecla, será preciso acceder al miembro 'message' de MSG.

En concreto el mensaje que vamos a capturar será WM_KEYDOWN cuyo valor constante equivalente en hexadecimal es el 0x0100. Además, como no queremos que se detenga la ejecución al pulsar cualquier tecla, sino solamente la tecla ENTER, también tendremos que utilizar el miembro 'wParam' que nos indicará cual es la tecla (VK_KEY) que se ha pulsado. En este caso para la tecla ENTER el valor que deberá contener 'wParam' será 0x0D (ya sabéis el número de la suerte).

Bueno, pues ahora sí que tenemos a nuestro alcance todo lo que necesitamos, así que, manos a la obra. Vamos a indicarle al debugger cual será nuestro maravilloso breakpoint:

bp 003814ac "j @@c++((((ole32!MSG *)@eax)->message == 0x0100) && (((ole32!MSG *)@eax)->wParam == 0x0D)) ''; 'gc'"

Como digo, hay muchas maneras de conseguir esto mismo, pero para mi caso concreto, esta era la más efectiva. La expresión habla más o menos por si sola, no obstante si tenéis alguna duda, sentiros libres de comentarlo.

¡Suerte y feliz debugging!

Comentarios

  1. 003814ac es el offset del textbox/objeto, el handler de la ventana el entry point de la aplicación, o...? Gracias.

    ResponderEliminar
  2. Este comentario ha sido eliminado por el autor.

    ResponderEliminar

Publicar un comentario

Entradas populares de este blog

Como usar el TL431 (muy facil)

En este artículo, no vamos a entrar en el funcionamiento interno de este IC, ni tampoco en sus características técnicas, puesto que para esos fines ya existe su hoja de datos correspondiente. Más bien, lo que pretendo aquí es dejar constancia de como podemos utilizar este IC desde un punto de vista práctico, útil y sobre todo de una manera sencilla, con el objetivo de que cualquiera pueda utilizarlo. Si has llegado hasta aquí, probablemente ya sabes que por internet hay mucha información sobre este IC, pero también bastante confusa o excesivamente técnica, sin mostrar tan siquiera un ejemplo de funcionamiento, o como calcular sus pasivos. Pues se acabó, a partir de hoy y después de leer este post, ya te quedará claro como utilizar el TL431 para obtener una tensión de referencia estable y precisa. Vamos al grano y que mejor que empezar aclarando que el TL431 NO ES EXACTAMENTE UN ZENER como se empeñan en decir en muchos sitios, es verdad que se le conoce como el Zener Progra

Expresión Regular para números en Notación Científica (1.5e-10)

No cabe duda que las expresiones regulares tienen un potencial de mucho valor a la hora de analizar textos, ya sea para marcado, búsqueda de patrones, o incluso la programación de un compilador, un analizador de frases, de expresiones matemáticas, etc.   En esta ocasión he tenido que echar mano de ellas para el análisis de textos matemáticos en los cuales aparecen números en Notación Científica (con exponentes del tipo 1.5E-10). Pues bien, una expresión regular que me está funcionando bastante bien es la siguiente:   [-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?    Esta expresión regular se puede descomponer en los siguientes bloques, para poder interpretarla con mayor facilidad:  El primer bloque [-+]? está indicando que el número podría estar precedido opcionalmente de un signo - o un signo + El segundo bloque [0-9]* indica que podría aparecer un número de 0 o más dígitos del 0 al 9  El tercer bloque indica que también de manera opcional podría aparecer un pun

Ingeniería Inversa de Firmware en un PIC 16Fxxx de Microchip

Como parece que no tengo mejores cosas que hacer, no se me ocurre otra forma mejor de pasar una tarde de Sábado que hacer un poco de Ingeniería Inversa a un microcontrolador PIC de la casa Microchip.   En esta ocasión se trata de un microcontrolador de la familia 16Fxxx (tipo 16F876, 16F84, etc.) cuyos opcodes tienen un tamaño de 14 bits. El mismo sistema será válido para otros microcontroladores de otras familias o incluso fabricantes, incluso aún cambiando la arquitectura del microcontrolador, la base esencial del análisis será similar en multitud de casos.   Siempre que se me plantea una situación similar, me gusta entender los entresijos de lo que tengo entre manos y, en la medida de lo posible intento empezar "a mano" o "a pelo" en el proceso de obtención de los Nemotécnicos ó, en definitiva las instrucciones en lenguaje ensamblador.   A continuación os muestro un pequeño pedacito de un firmware que he estado analizando, se trata del comienzo del m