Programación en Lenguaje Ensamblador

-El Verdadero Lenguaje de las Máquinas-

¡Quiero Ver Mas Allá de lo Evidente!

–Crackeando tutorial de Iczelion con OllyDbg–

En esta nota procesaremos el primero de los tutoriales de Iczelion, aunque en realidad vamos a comenzar por el segundo porque la primera parte de lo único que habla es de como funciona el MASM. Y como hay mas gente que habla inglés de la que sabe ensamblador, mejor pasamos a los códigos.

Para esta parte, la mayoría de ustedes ya leyeron la parte teórica, asi que no voy a volver a explicar cosas como para que sirve el .386 (no es la entrada al Modo Protegido) ni lo del modelo flat y stdcall ni los includes ni lo de optioncasemap. Además de que nada de esto nos va a servir. La parte de la sección de datos que tiene 2 cadenas ascii no es la gran cosa y si han seguido este blog desde el principio ya han de saber lo que es una cadena ASCII-Z. Lo único que nos interesa son estas 2 lineas:

invoke MessageBox, NULL,addr MsgBoxText, addr MsgCaption, MB_OK

invoke ExitProcess,NULL

¿Parece sencillo? ¡No lo es! Lo mismo dijeron muchos que intentaron descifrar los tutoriales de Iczelion y ahora viven de hacer querys de SQL. Ese invoke no es una operación de CPU sino una horrible macro, y el primer renglón en realidad se “desenrolla” en 5 instrucciones que en su totalidad miden 18 bytes. Sin contar que a su vez tiene dos llamadas a otra macro anidada llamada ‘addr’ Esta última puede convertirse en 3 o 4 instrucciones mas cada vez que aparece dependiendo de la complejidad de los operandos.

El segundo invoke se desenrolla en solo 2 instrucciones que en total miden solo 7 bytes.

Bueno, los 2 invokes es lo último que ven muchos programadores antes de frustrarse e irse de DBA’s. Pero nosotros tenemos el depurador OllyDbg y al comando de:

OllyDbg, ¡Quiero ver mas allá de lo Evidente!

Obtenemos esta vista del demo de Iczelion en lenguaje máquina:


debug

	00401000 >/$ 6A 00          PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
	00401002  |. 68 00304000    PUSH msgbox.00403000                     ; |Title = "Iczelion's tutorial no.2"
	00401007  |. 68 19304000    PUSH msgbox.00403019                     ; |Text = "Win32 Assembly is Great!"
	0040100C  |. 6A 00          PUSH 0                                   ; |hOwner = NULL
	0040100E  |. E8 0D000000    CALL            ; \MessageBoxA
	00401013  |. 6A 00          PUSH 0                                   ; /ExitCode = 0
	00401015  \. E8 00000000    CALL          ; \ExitProcess
	0040101A   .-FF25 00204000  JMP DWORD PTR DS:[<&KERNEL32.ExitProcess>;  kernel32.ExitProcess
	00401020   $-FF25 08204000  JMP DWORD PTR DS:[<&USER32.MessageBoxA>] ;  USER32.MessageBoxA

Como pueden ver, y si no pueden mas abajo lo reescribí en texto para que sea mas sencillo de lamear, las macros se desenrollaron y se convirtieron en instrucciones de ensamblador, las constantes se convirtieron en simples números y además podemos ver las posiciones de memoria del programa.

Para los que ven por primera vez algo como esto, la primera columna indica las posiciones dentro de la memoria virtual, la segunda son los OpCodes en Lenguaje Máquina y la columna que parece código es en realidad código desensamblado. Hasta donde puede, OllyDbg intenta averiguar lo que el programa está haciendo y escribe comentarios en el extremo derecho del código. En este caso, supo que estábamos llamando a MessageBox y Exit Process e incluso identificó plenamente los parámetros. Ahora veamos paso por paso lo que el programa está haciendo:

6A 00 PUSH 0

Aquí están empujando un cero de 32 bits al stack. Esta es la constante MB_OK que le dice a MessageBox el estilo de caja.

68 00304000 PUSH msgbox.00403000

En esta linea están empujando al stack la posición de memoria de la cadena ASCII-Z que dice “Iczelion’s tutorial no.2”. Esta posición es 403000. Pero en el source se usa la etiqueta MsgCaption. La macro addr en este caso no hizo nada porque 403000 es una posición de memoria absoluta. Cuando se usan direcciones relativas como esp + 123h o ebx + edi, addr convierte estas posiciones relativas en absolutas con el uso de la instrucción LEA (esta será motivo de otra entrada)


debug

En esta captura de pantalla se ve el segmento de memoria en ascii y hexadecimal. Si conocen de memoria el código ASCII pueden leer las cadenas directamente. Noten el cero binario con el que terminan y la posición de memoria a la que hacen referencia las funciones que usan texto.

00401007 |. 68 19304000 PUSH msgbox.00403019

Esta linea hace lo mismo que la anterior pero manda al stack la posición de la cadena ascii que dice: «Win32 Assembly is Great!»

0040100C |. 6A 00 PUSH 0 ; |hOwner = NULL

En esta linea se empuja otro cero al stack que le dice a MessageBox que la ventana no tiene padres, pues hOwner indica el handler del Pwner Owner o dueño de la ventana. Este cero indica que aparece en el centro del escritorio. Pero eso ya es cosa de la API de Windows


0040100E |. E8 0D000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA

Aquí se llama a MessageBoxA. Nótese la A mayúscula que va al final. Para Windows hay diferencias entre funciones ascii y unicode. En este caso llamamos a MessageBox versión ASCII. Otra de las cosas importantes que nos ocultan las macros.

00401013 |. 6A 00 PUSH 0 ; /ExitCode = 0

Esta ya es parte del segundo Invoke, aquí se empuja un cero al stack que es el único parámetro de la función ExitProcess que termina el programa. La constante NULL se transforma en cero, parece que NULL es mas sencillo de leer en un código que el propio cero.

0040101A .-FF25 00204000 JMP DWORD PTR DS:[<&KERNEL32.ExitProcess>; kernel32.ExitProcess

Finalmente se llama a la función API de windows ExitProcess y se termina el programa. La linea que sigue pertenece un sistema de llamado de funciones conocido como JUMP TABLE o trampolín. Que permite que un programa pueda llamar funciones externas y cambiantes sin necesidad de reprogramación. En esta tabla se colocan los verdaderos llamados a función y cuando hacemos un CALL para ejecutar una función API lo que en realidad hacemos es saltar a esta tabla. Este es un mecanismo interesante pero no hay urgencia de verlo porque FASM no lo usa. De hecho, este programa hace exactamente lo mismo que el PEDEMO.ASM que viene en los ejemplos del fasm y en este mismo blog en la nota llamada “¡Al fin un código!”

Hasta ahora, apenas hemos entendido lo que realmente ocurre tras esos inocentes invokes, y ya tienen una idea de lo peligrosas que pueden ser las macros para los principiantes, es mejor que las guarden para cuando tengan artritis y no puedan teclear sus programas los suficientemente rápido. O por lo menos hasta que realmente sepan lo que están haciendo y lo confirmen con el depurador de códigos en la primera oportunidad.

Para recapitular, hoy aprendimos todo esto:

1.- Se necesita un depurador para entender los tutoriales de Iczelion.

2.- Una macro puede desenrollarse en muchísimas instrucciones de Ensamblador

3.- Los argumentos de una función se introducen por el STACK en orden inverso a como quedan dentro del stack frame.

4.- Las constantes como MB_OK, hOwner, etc. Se convierten en simples números enteros casi siempre de 32 bits

5.- La macro ADDR convierte una referencia a memoria de tipo relativa a una posición de memoria absoluta usando la instrucción LEA.

6.- En este caso se usa una JUMP TABLE para hacer las llamadas a la API de Windows, pero FASM no trabaja asi.

Por ahora me regreso a donde estaba, estoy desarrollando una trampa para lamers muy divertida, aunque va a estar lista para la siguiente temporada de caza y esta es hasta el final del otoño. Por ahora traten de leer y analizar los tutoriales de Iczelion ustedes solos a ver que mas se encuentran, recuerden que hay un link a la web de Iczelion a la derecha de este blog.

junio 9, 2009 - Posted by | Uncategorized | , , , , ,

15 comentarios »

  1. Jajajjajaja… Leon-o y su Espada del Augurio… xD

    Comentarios por Carlos Ruiz | junio 9, 2009 | Responder

    • y yo que creia que las nuevas generaciones no captarian ese chiste…

      Comentarios por asm86 | junio 9, 2009 | Responder

      • Holap:

        Es que… esteee… no pertenezco precisamente a las nuevas generaciones… xDDD

        Saludooos :P

        Comentarios por carlosruizortega | junio 10, 2009

  2. estuve investigando sobre tu lenguaje ensamblador
    y me parece muy tedioso y aburrido, ademas de que aqui en mexico no hay trabajo para esas perdidas de tiempo,
    creo que lo mejor sera olvidarse de esas cosas y ponerse a hacer algo en serio, por ejemplo un sistema con una conexion a base de datos en Visual Basic 6.0, eso para que veas si es laborioso, pero hay paga por el trabajo hecho ok.

    Asi que piensale,
    o comida o niñerias.

    Comentarios por manuel garza | junio 15, 2009 | Responder

    • Tambien se de mucha gente que te paga si «les haces un trabajo bien hecho» y no tienes que esforzarte mas de una o dos horas…

      Desde luego me refiero a adelantos como el .NET y similares. Asi puede que no te mates tanto. Solo recuerda que hay prestigiosas empresas de desarrollo de software TIC donde solo tienes una oportunidad para que tus querys corran. Y si fallas te echan a la calle. Pero aun ahi podras ganarte la vida si «les haces un trabajo bien hecho» a los clientes de otras empresas

      Comentarios por asm86 | junio 15, 2009 | Responder

    • Lastima que tu ejemplo no sea algo «serio» y cualquier mono con secundaria terminada pueda hacerlo.

      P.D: Tu ejemplo laborioso acabo de hacerlo en 5 minutos, ¿Dónde está mi dinero?

      Comentarios por Zyklon | junio 16, 2009 | Responder

      • Si te refieres a la nota de «Al fin otro codigo y esta vez mas dificil» ese era un sencillo ejemplo para principiantes, o como decia un cuento infantil: — Para los que quieren aprender a leer y se sienten valientes–.
        La unica vez que se hablo de dinero por hacer algo fue en un comentario donde se hablaba de una vieja apuesta sobre hacer un Raytracer en Ensamblador. Si te refieres al ejemplo laborioso a ese raytracer ve y reclama tu premio al que escribio eso en los comentarios.

        Comentarios por asm86 | junio 16, 2009

    • Que onda Mario, creo que Zyklon se refiere al comentario que hizo manuelamer garza:
      [por ejemplo un sistema con una conexion a base de datos en Visual Basic 6.0, eso para que veas si es laborioso]

      Comentarios por blackpig | junio 16, 2009 | Responder

      • Menos mal, pense que tendria que rendir cuentas a Gobernacion. Ahora que si se refiere a eso, supongo que no se programa en Ensamblador simplemente porque nadie podria pagarlo. Como le esta pasando a unos conocidos alla en el DF. Creo que es bueno que alguien vaya a darle un susto.

        Comentarios por asm86 | junio 16, 2009

  3. Ademas de que no hay paga,
    es algo innecesario
    eso es para gente sin quehacer
    la gente de aqui no necesita esas perdidas de tiempo
    se parten el alma como para que les exijas mas
    por favor
    es un esfuerzo muy grande el que aprendan a programar en visual basic 6.0, tu quieres enseñar aleman a un niño mexicano
    que acaba de aprender a decir mama, por favor
    despierta, estas en mexico, aqui o jalas o jalas, no hay de otra
    eso dejalo para gente rica y sin que hacer como los de eua.

    saludos

    Manuel Garza

    Comentarios por Manuel Garza | junio 17, 2009 | Responder

    • Esta vez estoy totalmente de acuerdo con Manuelamer Garza. Sobre todo en la parte donde dice:

      «

      tu quieres enseñar aleman a un niño mexicano
      que acaba de aprender a decir mama

      »

      Esos son los chiquitines que llegan lejos en Mexico. Ahora que si hubieras dicho mamá con acento en la A otra cosa sería. Por lo de ponerse a «jalar» pues eso ya es de cada quien

      Comentarios por asm86 | junio 17, 2009 | Responder

    • [se parten el alma como para que les exijas mas]

      Que raro, yo he visto todo lo contrario a que se «partan el alma», mas aun en México y me atrevería a decir que en gran parte de Latinoamerica.

      [es un esfuerzo muy grande el que aprendan a programar en visual basic 6.0]

      El esfuerzo no es que aprendan a «programar en visual basic 6.0» el esfuerzo está en que quieran aprender a programar (individualmente del lenguaje) y la gran mayoría cuando ven que no es fácil se desaniman (y empiezan a flojear) y en vez de poner mas de su parte pasan una de dos cosas: se buscan otro oficio «mas facilito» o buscan a quien echarle la culpa porque «no aprendieron» (esque el profe!!, esque trabajo!!)

      [eso dejalo para gente rica y sin que hacer como los de eua.]

      Que lastima que te auto-limites de esa forma.

      Comentarios por Zyklon | junio 18, 2009 | Responder

  4. E hola muy buenos los articulos…..a pesar de que son muy basicos todavia…espero que sigas publicando mas articulos….aa otra cosa creo que es mejor centrarse en asm que en los lamers que es una perdida de tiempo ver esos articulos….nada saludos..

    El conocimiento es poder.

    Saludos.

    Comentarios por Adel86_ | junio 21, 2009 | Responder

  5. ¿Hacer una conexión a BD en VB 6.0, es laborioso o dificil? hahahahaha, Cualquiera se conecta a una base de datos,no se necesita mucha habilidad, ya sea MySql,Oracle,Access,etc… yo lo he hecho por varios años. No creo que este sea el lugar para las personas que piensan en bases de datos o querys, para eso pueden ir y ver los miles de sitios,blogs,etc que google despliega, dedicados a VB,C#,etc…

    Saludos

    Comentarios por El Julio | junio 23, 2009 | Responder

  6. creo que deberian leer el cuento
    EL PRINCIPE FELIZ de Oscar Wilde ( como me encanta este cuento )
    ya que programar en asm es un placer ademas hay muchas formas de ganar dinero y si tienen mucha razon » No creo que este sea el lugar para las personas que piensan en bases de datos o querys, para eso pueden ir y ver los miles de sitios,blogs,etc que google despliega, dedicados a VB,C#,etc»

    Comentarios por raul = sirmonodemar | julio 18, 2009 | Responder


Deja un comentario