1.1 Ejemplos en Ventana de desensamblado - OllyDBG: Vamos a manejarnos un poco con lo más básico en esta ventana.
Voy a abrir un programa cualquiera con el OllyDBG y pongo una imagen de la ventana de desensamblado:
Estamos parados en el
OEP (Punto de Entrada Original) del programa. Si se observa un poco vemos en la imagen un salto a la librería MSVBVM60, por lo tanto podemos ya imaginarnos que se trata de un programa compilado con Visual Basic.
Vamos a hacer unos pequeños ejercícios:
1.- Ir a la dirección 418E80.
-Como expliqué en el párrafo anterior podemos o bien pulsar el botón número 10 de la siguiente imagen:
o bien, podemos pulsar
Ctrl+G o
botón derecho --> Goto --> Expresion.
De estas 3 formas se nos abrirá una ventana y ahí podremos poner la dirección a la que queremos ir: 418E80:
pulsamos Ok y nos llevará directamente a esa dirección.
2.- Poner un Breakpoint (BP - lugar donde parará el debugger) en 418E80Lo primero vamos a la dirección 418E80, explicado en el punto anterior.
Una vez ahí, pulsamos simplemente
F2, o
botón derecho --> Breakpoint --> Toggle o simplemente
2 clicks en la columna "Hex dump" y veremos cómo se pone la dirección en rojo. Ya tenemos puesto el punto de ruptura.
En este punto, voy a añadir que OllyDBG nos permite poner varios tipos de BP. Hemos visto el más común y típico, pero también podría ser necesario que parase en 418E80 solamente cuando por ej. el registro EAX sea igual a 2 (
botón derecho --> Breakpoint --> Condicional) y ahí pondríamos la condición, que no se va a explicar aquí.
Otro tipo de BP son los Hardware Breakpoints. Sólo podemos poner 4. Si pulsamos
botón derecho --> Breakpoints, veremos que en la ventana de desensamblado podemos poner un Hardware on execution. Para ver los HBP que tenemos podemos ir al menú:
Debug --> Hardware Breakpoints y ahí veremos los que tenemos puestos. Si intentamos poner más de 4,
OllyDBG nos avisará que debemos borrar uno.
3.- Modificar una instrucciónImaginemos que tenemos lo siguiente:
402E40 DEC EAXDespués de analizar el código detenidamente, sabemos que ese DEC EAX (en mi programa) lo que hace es disminuir una vida. Como yo no quiero que me quite una vida, pues voy a modificar ese código.
Puedo hacerlo de varias formas:
-NOPEAR TODO: Nos ponemos sobre esa linea y pulsamos
botón derecho --> binary --> Fill with NOPs y así rápidamente ya tenemos todo lleno de NOPs.
-DEC EAX se compone de un sólo byte. En la columna dissasembly podemos clickear dos veces y nos saldrá una ventana donde podremos modificar el código. Por ej. podríamos poner: NOP y tendremos lo mismo que antes, o simplemente INC EAX y nos incrementará EAX u otra cosa que se nos ocurra.
-Modificar el byte. En la columna Hex dump, podemos pulsar botón derecho --> Binary --> Edit y podemos modificar el byte.
4.- Ir a MessageBoxALos más Newbies desconocen esta opción. Lo primero que tenemos que asegurarnos es que se haya cargado la librería correspondiente.
Me explico. Por ejemplo la función MessageBoxA se encuentra en user32.dll. Si nuestro programa no ha cargado user32.dll esto que vamos a hacer no funcionará.
Simplemente hacemos como antes cuando quisimos ir a una dirección:
pulsar el botón número 10 de la siguiente imagen:
o bien, podemos pulsar
Ctrl+G o
botón derecho --> Goto --> ExpresionY ahí escribimos: MessageBoxA, y OllyDBG nos llevará ahí.
5.- Poner un comentarioEs posible que algún código ya sepamos exactamente lo que hace. Para ver todo mucho más sencillo podemos poner nuestro propio lenguaje. Por ej.
401200 DEC EAX <-- Quita un día
...
402000 Call 4032EC <-- Call que pone un botón activado
etc...
De este modo, cuando lleguemos a este código ya sabemos qué hace exactamente todo y no tenemos que volver a analizar.
Para poner comentarios, como ya se ha explicado, podemos por ej. pulsar dos veces en la columna "Comment" y se abrirá una ventana y ahí podremos poner lo que queramos.
Esto aunque parezca una tontería, es realmente muy útil, sobre todo a la hora de trabajar con programas con mucho código. También nos ayuda a encontrar las zonas que nos interesan, ya que podemos buscar nuestros propios comentarios.
Para buscar nuestros comentarios pulsamos botón derecho --> Search for --> user-defined comment y podremos seleccionar lo que queramos. Muy útil.
6.- Me he movido por el código y ahora no sé volver donde estaba antes.Estamos parados en un determinado código. Ahora vamos a una dirección y después a otra. Podemos volver a las dos anteriores simplemente pulsando la tecla "-" (menos). Si queremos ir ahora para adelante podemos pulsar la tecla "+" e iremos de nuevo a la última dirección que estuvimos.
Es posible también que lo que se quiera sea ir al lugar donde estaba detenido el debugger. Esto es muy fácil, ya que sabemos que el debugger está parado en el valor del registro EIP, por lo tanto podemos cliquear dos veces en este registro e iremos donde está parado nuestro debugger. Podemos también pulsar la tecla "C" de la barra de herramientas.
7.- Acabo de entrar en una CALL de una librería. Quiero volver al código de donde fue llamada.Una opción manual sería ir a cada RET pulsando Ctrl+F9 y después F7 para pasar el RET y haciendo esto llegaríamos a nuestro código donde ha sido llamada la CALL.
Hay una opción que tiene OllyDBG y que nos puede facilitar este trabajo:
simplemente pulsando Alt+F9 (Execute till user code).
8.- Quiero que el código se ejecute hasta donde tengo el cursor puesto.Pinchamos (hasta que marque en color) sobre un determinado código y pulsamos simplemente F4.
IMPORTANTE:
9.- Ya he hecho los cambios en el OllyDBG, ahora quiero guardar todos los cambios en el mismo ejecutable.Esta pregunta la hace muchísima muchísima gente. Voy a explicar la teoría de cómo hay que modificarlo y explicaré la forma de hacerlo de manera muy SENCILLA con
OllyDBG sin utilizar ningún Editor Hexadecimal y por lo tanto sin calcular el Offset:
Imaginemos por ejemplo que en la dirección 401000 tenemos lo siguiente:
401000 PUSH EBP ;push ebp corresponde al byte 55h.
Bien, nosotros hemos modificado ese PUSH EBP (55h) y hemos querido dejar un NOP, entonces veríamos lo siguiente:
401000 NOP ;nop corresponde a 90h
Ya tenemos el cambio que queremos hecho. Ahora viene la pregunta:
¿Cómo puedo guardar el exe (dll o lo que sea) con este nuevo cambio que acabo de hacer? Con OllyDBG lo haremos en tres pasos:
1.-Pulsamos botón derecho (en cualquier lugar en la ventana de desensamblado) y elegimos:
Copy to executable --> All modifications
2.-Se abrirá una nueva ventana con 4 botones que nos dice lo siguiente: "Copy selection to executable file?" Pulsamos en el botón: "Copy All"
3.-Y finalmente en la nueva ventana que aparece pulsamos botón derecho y elegimos: "Save file".
De este modo tan sencillo ya lo tenemos modificado .
TEORÍA de este punto 9. Esto que voy a explicar lo considero muy importante, muy esencial y que todo el mundo, ya seas iniciado o no debe saber.
Voy a tratar el punto 9 pero sin OllyDBG y entendiendo todo, y lo vamos a modificar manualmente.
Voy a utilizar un programa fácil de conseguir y que nos servirá de guía: OllyDBG 1.10. Lo vamos a abrir con un editor de PE (encabezado). Hay muchísimos programas, cada uno que elija el que más le guste.
Nos vamos a ir a ver las secciones y si miramos las del OllyDBG encontraremos lo siguiente:
Name Virtual Offset Virtual Size Raw Offset o Raw Size o Flags
PointerToRawData SizeofRawData
.text 1000 AF000 600 AE800 60000020
.data B0000 5B000 AEE00 1D200 C0000040
.tls 10B000 1000 CC000 200 C0000040
.rdata 10C000 1000 CC200 200 50000040
.idata 10D000 2000 CC400 1E00 40000040
.edata 10F000 2000 CE200 1400 40000040
.rsrc 111000 36000 CF600 35A00 40000040
.reloc 147000 C000 105000 BE00 50000040
Columna por columna:
-
Name: Indica el nombre de la sección.
-
Virtual Offset o
Relative Virtual Address: Es la dirección virtual relativa a la Image Base donde se encuentra la sección. Muchas veces la veremos nombrada como
RVA (Relative Virtual Address. No hay que confundirla con la
Virtual Address ya que a esta última se le suma la Image Base. La mayoría de los programas tienen la Image Base igual a 400000h.
Ejemplo de esto último: (datos del OllyDBG que hemos abierto con un Editor PE)
Image Base: 400000h
RVA donde comienza la sección ".text": 1000
Por lo tanto la Dirección Virtual (Virtual Address) donde comienza la sección .text es:
Image Base + RVA = VA; VA = 400000 + 1000 =
401000.
Esto nos quiere decir que la sección .text comienza en la dirección virtual 401000. Se puede comprobar si abrimos un OllyDBG con otro OllyDBG y vamos a esta dirección: veremos que es la primera instrucción...
-
Virtual Size: Es el tamaño virtual de la sección. Por ej. el tamaño virtual de la sección .text son AF000h bytes.
-
Raw Offset o PointerToRawData: indica el desplazamiento dentro del archivo donde comienza la sección. Ahora que ya sabemos un poco voy a entrar un pelín en detalle. Sabemos lo siguiente:
-que la Image Base es 400000h
-que la sección .text comienza en el RVA 1000
-que la primera instrucción (desensamblarlo) es
JMP SHORT 00401012 que corresponde a los 2 bytes: EB 10
-que esta primera instrucción se encuentra en VA 401000
Ejemplo1
Pregunta: Estos dos bytes (EB 10) que se encuentran en RVA 1000, ¿Dónde se encuentran realmente en el archivo ejecutable?
Bien, esto nos lo dice:
Raw Offset o PointerToRawData. En este caso es sencillo ya que estos 2 bytes (EB 10), se encuentran justo en el inicio de la sección .text, por lo tanto, dichos bytes se encuentran en el archivo en el offset: 600h.
Para comprobar esto que acabo de decir, voy a abrir al OllyDBG en un editor hexadecimal y voy a ir al offset 600h:
000005F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000600 EB 10 66 62 3A 43 2B 2B 48 4F 4F 4B 90 E9 28 01 ë.fb:C++HOOK.é(.
Perfecto, ahí tenemos los dos bytes.
Ejemplo2
Bueno, acabamos de ver un ejemplo muy sencillo, vamos a hacer otro que es lo que nos vamos a encontrar normalmente, y es lo que hay que aprender a entender.
Voy a abrir el OllyDBG con el OllyDBG y me voy a ir a una dirección cualquiera...:
0046123E 8B 4E 14 MOV ECX,DWORD PTR DS:[ESI+14]
00461241 8B 53 14 MOV EDX,DWORD PTR DS:[EBX+14]
Tenemos de nuevo los siguientes datos:
-Image Base = 400000h
-RVA (.text) = 1000h
-Raw Offset = 600h
En la dirección virtual 46123E encontramos los bytes 8B 4E 14.
Como la Image Base es 400000, tenemos que:
46123E - 400000 = 6123E que es una dirección virtual relativa (RVA). Sabemos que la VA 46123E se encuentra dentro de la sección .text. ¿Cómo sé esto? Pues porque si miráis la tabla que puse del editor de PE tenemos que:
-La RVA del comienzo de la sección .text = 1000h
-El tamaño virtual (virtual size) de la sección .text = AF000
Por lo tanto 6123E es mayor que 1000 y menor que AF000, por esto se encuentra dentro de .text.
Sigo. Como la sección .text comienza (RVA) en 1000h tenemos que:
6123E - 1000 = 6023E que es el desplazamiento en la sección .text, por este motivo, podemos sumar 6023E al offset de inicio de la sección .text en el mismo ejecutable, así:
600h (Raw Offset) + 6023E (desplazamiento) = 6083E (offset buscado)
Veamoslo mirando un editor hexadecimal:
00060830 73 6D B8 01 00 00 00 EB 66 83 FA 06 75 2F 8B 4E sm¸....ëfƒú.u/‹N
00060840 14 8B 53 14 81 E2 FF 00 00 00 81 E1 FF 00 00 00 .‹S..âÿ....áÿ...
Viendo esto, podemos poner una fórmula general:
VA = Dirección Virtual que queremos saber dónde se encuentra en el ejecutable.
RVA (.sección) = Es la RVA del comienzo de la sección en la que se encuentra VA
Raw Offset (.sección) = Es el offset del comienzo de la sección en la que se encuentra VA.
ImageBase = Es la ImageBase
VA - ImageBase - RVA(.sección) + Raw Offset (.sección)
Con esta fórmula voy a hacer el último ejemplo:
Ejemplo3
VA = 4BF008 (bytes que contiene: 44 F2 4B...) Está dentro de la sección .data
RVA (.data) = B0000h
Raw Offset (.data) = AEE00h
Image Base = 400000h
4BF008 - 400000 - B0000 + AEE00 = BDE08 (offset buscado, veamos en un editor hexadecimal a ver:)
000BDE00 00 00 00 00 04 00 00 00 44 F2 4B 00 00 00 00 00 ........DòK.....
000BDE10 00 00 00 00 0F 00 00 00 0D 00 00 00 46 00 00 00 ............F...
SizeofRawData: Es el tamaño de la sección en el propio archivo ejecutable.
No quiero entrar más en detalle porque nos salimos de lo que se quiere explicar en este tutorial, pero esto que se ha mostrado pienso que tiene que quedar bien claro.