05 agosto 2004

Resaca

Bueno, hoy ha sido un día interesante en el trabajo. Por un lado, y a pesar de estar todavía de resaca por los excesos mencionados en el anterior post, he descubierto algo interesante y he usado algo que hasta ahora no había tenido oportunidad de hacer. Os explico.

El programa para el cliente PDAs requiere que ciertas funcionalidades se realicen después de girar el escritorio: al ser una aplicación móvil, a alguien más inteligente que yo se le ocurrió durante el diseño el poder girar el escritorio para poder ver las aplicaciones en formato horizontal o vertical. Hacer esto con un monitor es complicado, pero con la PDA es un simple giro de muñeca. El caso es que el fabricante de las PDAs que estamos utilizando (Gotive) nos ha proporcionado (no es para menos, teniendo en cuenta el precio de cada uno de los cacharritos y la cantidad que hemos comprado) amablemente el SDK, en forma de un sólo archivo DLL, que han desarrollado para sus clientes.

Echándole un vistazo a la ayuda de ese SDK, me doy cuenta de que es poco más que un wrapper para las funciones de la API de Windows CE. Un wrapper bastante completo, la verdad, porque incluye funciones para manejar la orientación de pantalla, la retroiluminación de la misma, la lectura de códigos de barras mediante el lector integrado, etc. De todas esas funciones, yo sólo quería usar la que cambia la orientación de pantalla y la que obtiene la orientación de pantalla actual. ¿Cómo podría yo llamar sólo a esas funciones y obviar el resto del wrapper? La respuesta: ILDASM.

El ILDASM es una herramienta de Microsoft, incluida en VS .NET 2003 (aunque creo que también estaba incluida en .NET 2002) que nos permite descompilar un fichero .EXE, .DLL, .OBJ o .LIB creado con .NET. Ojo, todos quietos. No os va a proporcionar el código fuente de nada. Lo que hace es extraer de un archivo compilado el lenguaje intermedio de Microsoft, o MSIL, y mostrarlo en pantalla o en un archivo.

Pongamos un ejemplo: éste es un código vergonzantemente simple, para escribir en la pantalla "Hola, Mundo!" 5 veces:



namespace Prueba
{
class HolaPesao
{
[STAThread]
static void Main(string[] args)
{
for(int i=0; i<5; i++)
{
Console.Write("Hola, mundo!!\n");
}
Console.Write("Pulse cualquier tecla para terminar\n");
Console.ReadLine();
}
}
}


Generamos la solución para obtener un fichero .EXE, en este caso, y luego abrimos la consola de .NET. Nos dirigimos al directorio donde tengamos el exe y escribimos ildasm <nombre_archivo> donde nombre_archivo será el nombre de nuestro compilado. Obtenemos la siguiente ventana:







En ella podemos apreciar cómo a partir de un prueba.exe, tenemos un espacio de nombres llamado Prueba, que a su vez contiene una clase llamada HolaPesao, con un método Main() que es el que nos interesa. Si hacemos doble clic en el método Main() obtenemos una ventana con el siguiente chorro de código:



.method private hidebysig static void Main(string[] args)
cil managed
{
.entrypoint
.custom instance void
[mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 39 (0x27)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0012
IL_0004: ldstr "Hola, mundo!!\n"
IL_0009: call void [mscorlib]System.Console::Write(string)
IL_000e: ldloc.0
IL_000f: ldc.i4.1
IL_0010: add
IL_0011: stloc.0
IL_0012: ldloc.0
IL_0013: ldc.i4.5
IL_0014: blt.s IL_0004
IL_0016: ldstr "Pulse cualquier tecla para terminar\n"
IL_001b: call void [mscorlib]System.Console::Write(string)
IL_0020: call string [mscorlib]System.Console::ReadLine()
IL_0025: pop
IL_0026: ret
} // end of method HolaPesao::Main

Como veréis no es que sea un código muy claro pero algo se puede averiguar.

Bueno, teniendo en cuenta esta breve disgresión sobre el des-ensamblador de Microsoft, vuelvo a lo mío. Abrí el fichero DLL que contiene el SDK de nuestra PDA (os acordáis, ¿verdad?) y hago doble-clic sobre el método SetRotation pues mi intuición ;-) me dice que ese método puede tener algo que ver con lo que quiero hacer, que es rotar la pantalla. Y me encuentro con que el código MSIL hace una obvia llamada P/Invoke a una función API contenida en la DLL lcdapi.dll. API que, por cierto, no sale en Google; pero por suerte su firma es bastante sencilla, y el P/Invoke viene a ser algo como sigue:



[DllImport("lcdapi.dll")]
static extern bool GLCDSetRotation(int Degrees);

Muy sencilla. Y voilá, gracias a esto me he ahorrado 52 Kbs de fichero DLL superfluo, extrayendo la función que necesito mediante el des-ensamblado de una DLL de fabricante que es un wrapper y nada más. La función me ha dado algún problema muy curioso (¿y qué funcion no da problemas en .NET CF?), pero de eso os hablaré mañana, cuando lo haya solucionado.

Nota importante: este artículo, y los venideros que tengan código fuente, ha quedado así de bonito gracias a Jean-Claude Manoli y su estupenda herramienta on-line para formato de código fuente en C#, el c# code format. Al César lo que es del César.

1 Comments:

  • Saludos,

    Me llamos bastante la atencion tu publicacion!

    Fijate de esto, yo actualmente tengo un problema relacionado al tuyo con respecto a .DLL

    Si te soy sincero el problema trata que en mi compañia perdimos el password de una maquina que usamos con alta frecuencia y para acabar de remate la empresa que lo fabrica no existe!!!

    Ahora yo alli medio se sobre programacion en ensamblador, y gracias a dios tenemos el PROGRAMA BASE del toda la maquina.

    Buscando y buscando entre tantos tipos de archivos y codigos encriptados y bla bla bla vi un .DLL que se denomina "PASSWORD.DLL" y bueno deseo firmemente ver que demonio hay alli adentro pues!

    Fijate, no se en que lenguaje esta realizado este programa, realmente no reconozco el lenguaje, simplemente soy ing. electronico y de programacion se lo fundamental.

    Ahora existira una manera de conseguir el password? si no es mucha molestia me podras facilitar tu correo para enviarte mas informacion para que puedas ver los codigos y estas cosas! a ver si de repente podamos obtener el codigo!


    Muchas Gracias

    By Blogger Romulo Marquez, at 11:11 p. m.  

Publicar un comentario

<< Home