Home > python, Uncategorized > Calling conventions y ctypes

Calling conventions y ctypes

Comencé a leer el libro “Gray Hat Python” y ya comenzamos con escollos por el camino, como no podía ser de otra manera… el primer ejemplo que se me ocurrió probar me tiraba un error.

En estas poquitas lineas voy a dejar documentado como fue que la safe, para que a nadie le suceda de nuevo.

Tal vez el error se dio porque me apure a agarrar el interprete, antes de documentarme bien acerca de ctypes y python. Pero hay veces que leer tanto le quita la gracia, y uno quiere probar rápidamente si tal o cual cosa sirve para sus propósitos ❗

Recién comencé con el capitulo 2 y me tope con ctypes, una librería que no conocía y que provee la funcionalidad de usar .dll’s desde el mismo código de python. No hace falta decir lo valioso que puede ser para nosotros tener este poder al alcance de la mano.

En el libro tenemos el siguiente ejemplo:

from ctypes import *
msvcrt  = cdll.msvcrt
message_string = "Hello world!\n"
msvcrt.printf("Testing: %s", message_string)

ahí nomas sin dudarlo, agarre la consola interactiva y me dispuse a probar ese ejemplo.

ya esta pequeña porción de código dibujo una sonrisa en mi rostro que no tenia comparación… podía usar la API de windows enterita desde mi querido python. Pero poco duraría mi algarabía :/

La segunda prueba que tenia que intentar es sacar una ventanita con MessageBox, y procedí a crear el siguiente código:

from ctypes import *
dllcargada = cdll.user32
dllcargada.MessageBoxA(0, "hola mundo", "desde python", 0x30)

probamos en la consola interactiva:

Ahí ya tenemos un error, después de probar y probar… no podia dar con la tecla que me solucionara el drama. Tal vez alguien que ya conoce la librería se daría cuenta al toque, pero en mi caso me quede en stand-by como una hora por esto.

El problema esta en la “calling convention” segun dice, pero para sacarme la duda nos vamos a attachear al python.exe y vamos a verlo desde ahí, como a nosotros nos gusta 😉

Lo único que hice fue attachear el python.exe y poner un breakpoint en MessageBoxA para que pare cuando nosotros lo llamamos, podamos tracearlo desde allí.

Los argumentos están bien, ahora hacemos un Ctrl+F9 para llegar al RETN y comenzar a tracear la parte de la llamada, para ver donde esta el moco.

Ahí esta el problema, donde retornamos de la API, este arregla el stack como si tratara de una función de “C”. MessageBoxA es definida como stdcall asi que el stack queda para atras ;).

Para mas información acerca de las calling conventions pueden pasarse una vuelta por aca.

Tratemos de solucionar esto sin tener que recurrir a tocar nuestro script (esta mas fácil zafarlo en assembler que en python :D).

Vamos a NOPEAR ese ADD ESP, ECX para ver si la zafamos con ese parchecito sucio:

le damos F9 y en la consola interactiva tenemos lo siguiente:

Vemos que esta vez no se nos quejo, y nos devolvió 1. Ese 1 corresponde al valor de EAX al finalizar la llamada a MessageBoxA. Vamos… El valor de retorno 😉

Con esto ya podemos dar por asegurado que se nos queja porque la esta tratando como una función de “C”, dejándonos a nosotros el trabajo de reparar el stack. Veamos como tiene que ser el código cuando queremos llamar a una función que esta definida como stdcall:

from ctypes import *
dllcargada = windll.user32
dllcargada.MessageBoxA(0, "hola mundo", "desde python", 0x30)

Notemos el cambio entre cdll y windll. Lo probamos y….

Ahí esta nuestra querida ventana, pero a fines prácticos, lo que nos interesa obtener es el valor de retorno de la función y que no se nos queje, ni nos de error.

Ahora ya saben. Si ctypes se engoma, verifiquen como esta definida la función a la que están llamando para usar windll o cdll en cada caso.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: