Está en la página 1de 171

INTRODUCCIÓN AL CRACKING CON OLLYDBG PARTE 11

Bueno, ya nos queda ver los hardware breakpoints, los condicionales y los message breakpoints, para
terminar con los tipos de breakpoints.

HARDWARE BREAKPOINTS

Los HARDWARE BREAKPOINTS o (HBP) son una propiedad física del procesador, realmente yo no
conozco la arquitectura de los mismos para explicarla, pero es como si tuviera varias entradas en las
cuales vos le podes poner las direcciones en las cuales querés que el programa se detenga y el al ir
ejecutando compara y al hallar la dirección parara.

Tenemos la posibilidad de poner cuatro HBP, a la vez al poner el quinto OLLYDBG nos pedirá que
elijamos cual de los 4 existentes queremos borrar.

Como siempre usemos el CRACKME DE CRUEHEAD para practicar

Existen HBP ON EXECUTION, ON WRITE y ON ACCESS son las tres posibilidades existentes.

Poner un HB ON EXECUTION cumple la misma función que poner un BPX en una dirección, salvo que
el HBP no cambia código y es mas difícil que sea detectado, eso si hay programas que tienen trucos que
nos borran los HBP, esos trucos y la forma de contrarrestarlos los veremos en próximas entregas.

Si quiero poner un HBP EXECUTION en 401013, marco la línea, hago click derecho y elijo
BREAKPOINT-HARDWARE ON EXECUTION

También puedo tipear en la commandbar

Con lo cual el HBP estará puesto.


OLLYDBG tiene una ventana especial para que podamos ver y manejar los HBP, para ello vamos a
DEBUG-HARDWARE BREAKPOINTS

Allí tenemos la ventana de los HBP, si apretamos FOLLOW nos mostrara en el listado donde esta
colocado el mismo, y con DELETE podremos borrarlo.

Ahora apreto F9 para correr el programa

Y para en 401013

Como vemos se comporta como un BPX común, si realizamos la misma prueba que hicimos con el BPX
de escribir MOV EAX, DWORD PTR DS:[401013] y lo ejecutamos vemos que el código no ha sido
cambiado.
Cambio EIP a 401000 con NEW ORIGIN HERE y apreto F7

Vemos que los bytes son E8 A6 04 00, los lee al revés y nos muestra 00004A6E8, sin cambios, así que
verificamos que no hay cambios de código.

A su vez podemos reiniciar el OLLYDBG veremos que el HBP se mantiene colocado

Lo borramos y colocamos uno en MessageBoxA como hicimos con el BPX directo en la api

Ahora lo vemos en la lista de HBP

No repetiremos lo mismo pero sabemos que si corremos el programa y le colocamos un user y pass, y lo
aceptamos, parara en la api MessageBoxA de la misma forma que lo hemos hecho antes con BPX
comunes.

Los HBP ON ACCESS y ON WRITE solo pueden abarcar 1, 2 o 4 bytes de largo, por mas que
marquemos zonas en el dump mas largas, solo tomara como máximo los primeros 4 bytes de la misma
veamos el ejemplo.
Reinicio y borro todos los HBP que quedaron, y tratare de colocar un HBP ON ACCESS en la dirección
4020CA

Voy a ver dicha dirección en el DUMP

Allí esta ahora marco los primeros 4 bytes

Y hago click derecho

Veo que haya marcado la zona que haya marcado, me aparece solo en este caso la opción de colocarlo en
un solo byte a partir de 4020CA o dos bytes (WORD), la opción de 4 bytes va de cuatro en cuatro así que
si uno de casualidad elije una dirección intermedia no aparecerá, como en este caso,

Vemos que si hago click derecho en el byte siguiente y elijo HARDWARE ON ACCESS, solo aparece la
opción BYTE

Y en el siguiente ya me aparece nuevamente la opción DWORD o sea que abarque cuatro bytes.
El tema es que si yo quiero que pare cuando guarda o lee en 4020CA, con que haya un HBP en un solo
byte es suficiente pues al intentar guardar o leer en la dirección parara igual.

Vuelvo a 4020CA y coloco un HBP ON ACCESS- BYTE

Vemos que en la lista nos marca el tamaño 1 o sea un BYTE

Doy RUN

Allí nos dice OLLY que paro por el HBP 1 o sea el primero de la lista de los HBP.
Veo que para en la línea siguiente a donde guarda o lee, eso ocurre con los HBP ON ACCESS y ON
WRITE siempre debemos recordar que se pasan una instrucción y paran en la instrucción siguiente.

Y para justo después de guardar, a diferencia del MEMORY BREAKPOINT que hubiera parado en
401007, justo en la instrucción que lo activa.

Bueno lo mismo se puede realizar con los HBP ON WRITE, en ese caso solo parara cuando guarda no
cuando lea, y en la instrucción siguiente a la que lo activa.

BREAKPOINT CONDICIONALES

Son en realidad una variante de los BPX comunes, solo que al activarse OLLYDBG chequera si alguna
condición que le colocamos se cumple y en ese caso parara, si no se cumple seguirá corriendo como si no
existiera.

Veamos un ejemplo

Reiniciamos el OLLY y borramos todos los HBP si quedo alguno del ejemplo anterior y colocare un BPX
CONDICIONAL o BREAKPOINT CONDICIONAL en 40100E, para ello marco la línea, hago click
derecho y elijo BREAKPOINT CONDICIONAL.

Me sale la ventanita para que escriba la condición


Pondré que pare si EAX vale 400000, o sea la condición será EAX==400000

En la ayuda del OLLYDBG nos muestra los símbolos que podemos utilizar, en este caso el igual, se
representa por dos símbolos igual consecutivos.

Vemos que en el caso de un BPX CONDICIONAL se cambia a color rosado, apreto F9

Vemos que paro y OLLYDBG nos dice

Si vemos EAX vemos que vale 400000, lo cual fue la condición para que se detuviese

Si reinicio y borro el BPX CONDICIONAL y ahora coloco otro pero que pare si EAX==500000 por
ejemplo
Y doy RUN

Vemos que el crackme se ejecuta y no para en el BREAKPOINT ya que siempre al pasar por allí, vale
EAX=400000 y la condición no es cumplida, por lo tanto no se detiene.

Si vamos a HELP-CONTENTS

Allí a BREAKPOINTS y luego a expression


OLLYDBG nos mostrara ejemplos de expresiones que pueden ser usadas en las condiciones

BREAKPOINT CONDICIONAL LOG

Es un BPX condicional igual que el anterior, solo que en este caso podemos activar que nos loguee o nos
guarde ciertos valores al pasar por el BPX CONDICIONAL, en este caso las opciones son muchísimas,
probaremos en el caso de una API que tiene varios accesos y queremos que loguee o nos guarde ciertos
datos al pasar por ella.
Usamos el ejemplo de la api pero puede ser colocado un BPX CONDICIONAL LOG en cualquier
dirección sea api o no, reiniciemos el OLLY.

Vamos a la dirección de la api, ya sabemos como CLICK DERECHO-GOTO EXPRESSION


Allí estamos ahora hacemos CLICK DERECHO- BREAKPOINT- CONDICIONAL LOG

Vemos que nos aparece una ventana con más opciones

En este caso no haremos que pare en la api, solo que nos loguee ciertos datos de interés.
Como no queremos que pare no colocamos ninguna CONDICIÓN y en la opción PAUSE PROGRAM
elegimos que no pare nunca o sea ponemos la marca en NEVER.
Luego en LOG VALUE OF EXPRESIÓN ponemos que nos guarde el valor de [esp] que escribimos en el
renglón EXPRESSION, que como sabemos será la dirección de retorno al programa desde la api, ya que
es el valor superior del stack, por lo tanto en la segunda opción LOG VALUE OF EXPRESIÓN elegimos
ALWAYS para que la LOGUEE siempre, y en el tercer renglón nos da la opción si queremos LOGUEAR
los argumentos o parámetros de la función o api, pues no estará de mas, ponemos ALWAYS tambien.

Vamos a la ventana LOG o L

Y limpiamos la misma para ver claro lo que guarde el programa a partir de aquí con CLICK DERECHO-
CLEAR WINDOW.

Vemos que también allí esta la opción de guardar lo logueado, en una fila de texto, si lo necesitamos lo
podemos activar allí.
Ahora doy RUN con f9

Llego a la ventana del crackme y aun no hay en el LOG nada sobre nuestra api pues aun no paso por la
misma.

Vamos a REGISTER y pongamos un user y pass cualquiera.

Al apretar OK

Vemos allí que nos muestra aun sin haberse detenido el OLLY, la info de la MessageBoxA, primero el
valor superior del stack que es 40137D o sea la dirección de retorno de la api, y luego los parámetros de
la misma, en este caso que es un call desde 401378, el texto, el titulo etc.

En este caso nos muestra solo una información pero que tal si una api se ejecuta 100 veces por ejemplo,
podemos loguear todas a una fila de texto, pero si queremos que pare en una sola determinada de toas
esas veces en ese caso, debemos usar la CONDICION.

Si tuviera aquí una lista con la info de 100 veces diferentes que paro el programa en esa api, puedo
colocarle algún dato que me da la info en la condición, por ejemplo la dirección de retorno en este caso, la
puedo usar como condición y de esa forma solo parara de las 100, en la que regrese a 40137d, las que son
llamadas de otras direcciones del programa no parara.

Para ello reinicio el OLLY y voy nuevamente a la api y ahora pongo un BPX CONDICIONAL LOG así.
Cambio la tilde para que solo pare cuando se cumpla la condición (ON CONDITION) y escribo la
condición o sea que solo pare cuando [esp] sea igual a 40137D.
En esta forma solo parara cuando pase por la api y sea el valor superior del stack 40137d el cual es la
dirección de retorno de la api y me asegura que solo parara en esa.

Corramos el programa pero ahora cuando vayamos a REGISTER coloquemos un nombre con números
como ricnar456 y password 989898

Recordamos que cuando poníamos un nombre que tenia números, paraba 2 veces en la api messageboxa,
apretemos OK

Vemos que salio la primera MessageBoxA pero no paro OLLY en ella, vemos en el log la dirección de
retorno es 4013C1 y no se activa la condición por ello no paro.
Al apretar aceptar

Ahí si en la segunda vez que va a la api, se cumple la condición y para.

Vemos que en la parte superior del stack esta el valor 40137d que fue el que activo el BPX
CONDICIONAL LOG.

De cualquier forma OLLYDBG guardo el LOG de ambas ocasiones en que se detuvo

Ahí se ve claro que la segunda vez la dirección de retorno fue 40137D y nos muestra en el mismo LOG
que la segunda vez se detuvo.

Bueno creo que con esto tienen para practicar un rato, aun quedan los MESSAGE BREAKPOINTS pero
no quiero matarlos, lo dejamos para la parte 12 y luego de los MESSAGE BPX le prometo seguir
crackeando un poco para no aburrirlos, pero esto deben saberlo antes de continuar.
Hasta la parte 12
Ricardo Narvaja
27 de noviembre de 2005
INTRODUCCIÓN AL CRACKING CON OLLYDBG parte 12

Veremos la forma práctica de usar los MENSAJES en WINDOWS.

Tengo esta cita que define un poco que son los mensajes en WINDOWS

Los mensajes en Windows son usados para comunicar la mayoría de los sucesos, al menos en los niveles
básicos. Si quieres que una ventana o control (el cual es una ventana especializada) haga algo, debes
enviarle un mensaje. Si otra ventana quiere que vos hagas algo, entonces te envía un mensaje. Si ocurre
un evento, como cuando el usuario mueve el mouse, presiona el teclado, etc... entonces el sistema la envía
un mensaje a la ventana afectada. Dicha ventana recibe el mensaje y actúa adecuadamente.

O sea que como ya sabemos, podemos en OLLYDBG trabajar poniendo BPX en las apis que realizan la
mayoría de las funciones del programa, pero muchas veces resulta mas directo poner Breakpoints en estos
mensajes que el programa envía directo al sistema llamados MESSAGE BREAKPOINTS o BMSG por la
sigla que se utilizaba en SOFTICE para poder tipearlos.

Existe un Bucle de mensajes en todo programa compuesto por varias apis, que no profundizaremos aquí,
dichas apis se ocupan del tratamiento de los mensajes, el que quiera profundizar el tema, este es un
tutorial bastante completo de cómo funcionan, aunque para el cracking no es necesario, profundizar tanto,
mas vale saber que dichos mensajes existen y son procesados y en cual colocar BMSG para obtener un
buen resultado.

http://winprog.org/tutorial/es/message_loop.html

Veremos como ejemplo el caso siguiente: para hallar seriales queremos que el programa rompa al apretar
en el botón que ingresa nuestro nombre y serial, para luego analizar que operaciones realiza con ellos.
Si abrimos el Crackme de Cruehead en OLLYDBG.

Vamos a ver primero el método con las apis, para ello miramos las apis que importa el programa, a ver
cual es la encargada de realizar el trabajo de traer el texto que tipeamos para su procesamiento y futura
comparación.

Para ello en el listado hacemos CLICK DERECHO-SEARCH FOR-NAME (LABEL) IN CURRENT


MODULE
Las apis mas usadas para ingresar texto son GetDlgItemTextA y GetWindowTextA, así que miraremos
allí si están

Vemos que usa la api GetDlgItemTextA por lo cual seguro la utilizara para ingresar el texto

Pongamos un BP en dicha api

Bueno una vez colocado el BPX en la api corremos el programa y vamos a ingresar nuestro user y pass
Al apretar OK para en nuestro BREAKPOINT

Si miramos el stack

Vemos que uno de lo parámetros de la api es el buffer, allí guardara el texto que estamos ingresando.

Veamos el BUFFER en el DUMP con FOLLOW IN DUMP o yendo al DUMP y haciendo GOTO
EXPRESSION=40218E
Allí lo vemos vacío pues aun no se ejecuto la api

Así que ejecutemos la api hasta el RET con DEBUG- EXECUTE TILL RETURN

Miramos que en el DUMP que la api guardo allí nuestro nombre.

Si doy RUN nuevamente con F9 vuelve a parar en la api


Esta ves el buffer es 40217e veamos en el dump

Ahora hago EXECUTE TILL RETURN

Y ingresa mi serial.

Ya comprendemos que para la búsqueda de seriales correctos, debemos detenernos en donde ingresa
nuestro nombre y serial o los datos que se nos pidan, mas adelante veremos como seguir hasta hallar el
serial correcto.

Bueno hemos parado en el punto en que ingresa nuestro user y serial con apis, ahora veamos como
hacerlo con BMSG, ya que muchos programadores sabedores de que para obtener el serial debemos
detenernos aquí, para complicar las cosas, no utilizan apis para ingresar el texto si no que lo hacen
mediante mensajes de Windows.

Quitemos los BREAKPOINTS que colocamos yendo a la ventana B y borrando todos con REMOVE

Corramos nuevamente el programa y lleguemos hasta la ventana de ingresar el user y serial


Una de las diferencias entre trabajar con apis y con BMSG es que en las apis podemos poner un BPX al
inicio del programa si sabemos que api utiliza, en cambio para poner BMSG debe estar creada la ventana,
antes no podemos poner BMSG en ella.

Para colocar el BMSG vamos a la ventana W o WINDOWS sin pausar el programa que continua
RUNNING.

Si la ventana WINDOWS se encuentra vacía, debemos hacer CLICK DERECHO – ACTUALIZE

Buscamos el BOTÓN, allí vemos marcada la línea en CLASS dice BUTTON y el titulo es OK como en
nuestro BOTON.

Hacemos CLICK DERECHO en esa línea y elegimos MESSAGE BREAKPOINT ON CLASSPROC


Vemos que nos sale esta ventanita la cual tiene para elegir que tipo de mensaje podemos utilizar si
desplegamos el menú MESSAGES

Vemos que hay BMSG genérico para texto, Mouse, portapapeles, botones, cuando uno no sabe bien cual
es el mensaje que se ultiliza el programa, puede intentar usar las opciones genéricas, pero en mi caso,
usare el BMSG exacto, sigo bajando en el menú desplegable, ya que los años me han enseñado que
cuando se hace click en un botón, se envía un mensaje WM_LBUTTONDOWN, primero cuando
apretamos con el botón izquierdo por eso la L de LEFT y luego WM_LBUTTONUP cuando soltamos el
botón izquierdo, así que pondremos el BMSG en este ultimo evento al soltar el botón, que es el 202.
Quedaría así

Elegido el tipo de mensaje 202 WM_LBUTTONUP, ponemos la marca en BREAK ON ANY WINDOW,
y en PAUSE PROGRAM, que pare ON MESSAGE o sea cuando se ejecute el mensaje que elegimos, y
abajo LOG WINPROC ARGUMENTS, ya que nunca viene mal que loguee los argumentos de algo.

Vemos que como elegimos en cualquier ventana lo coloco en los dos botones que hay OK y CANCEL, no
hay problema, ahora apretemos OK.
Aquí es donde se pierden muchos porque dicen que parando con este método, quedan en el medio de la
nada ya que la dirección de retorno, no pertenece al programa pero retornar es muy sencillo.

Sabemos que el programa se ejecuta en la sección que comienza en 401000, así que pongo un BPM ON
ACCESS en dicha sección para que pare cuando ejecute algo allí.

Al dar RUN paramos allí


SIN QUITAR EL BPM ON ACCESS voy apretando F9 lo cual será como ir ejecutando línea a línea pero
solo las instrucciones de esta sección.

Vemos que enseguida luego de ejecutar dos veces hasta el RET caemos en las llamadas a
GetDlgItemTextA que leen el user y serial que tipeamos, de forma que llegamos al mismo lugar sin haber
utilizado BPX en las apis en este caso.
Si el programa no hubiera utilizado apis para entrar el texto, hubiéramos llegado con los BMSG al mismo
punto donde ingresara el texto y podremos empezar a trabajar la rutina del serial lo cual veremos en
próximas partes.

En el caso que quisiéramos parar al apretar una tecla, podemos intentarlo también borramos el BPM ON
ACCESS haciendo CLICK DERECHO-REMOVE MEMORY BREAKPOINT en cualquier parte del
listado.
Y vamos a la ventana B y borramos los BMSG anteriores con REMOVE

Ponemos el programa a correr nuevamente y llegamos a la ventana de ingresar el user y serial pero esta
vez no ingresamos nada.

Vamos a la ventana W

Y repetimos el procedimiento anterior pero esta vez eligiendo


El tipo de mensaje 101 o sea WM_KEYUP para que pare cuando soltamos la tecla.

Apretamos una tecla para escribir el nombre en la ventana de user y serial y vemos que en este caso no
para, porque el programa no procesa los mensajes de la presión tecla por tecla, pero es bueno saberlo
porque hay programas que si lo hacen, y comparan carácter por carácter a medida que tipeamos, y por eso
hay que tener en cuenta para esos casos esa opción.

Ahora esto trae otros interrogantes, podemos hacer que OLLY nos liste los mensajes que utiliza el
programa sin parar, de forma de luego poder utilizar el BMSG que sabemos que funcionara, pues es
utilizado?

Pues es sencillo, lo que tenemos que hacer es utilizar un BMSG que sabemos que funciona, como en este
caso el 202 y poner un BMSG en el y que se detenga como hicimos en el primer caso, quitamos todos los
BPX en la ventana B y repetimos hasta que pare al apretar el botón OK por BMSG 202
WM_LBUTTONUP
Lo colocamos y apretamos OK en la ventana de ingresar el serial.

Vemos que allí paro ahora modificaremos las cosas para que loguee todos los mensajes utilizados por los
botones.

Vamos a la ventana B

Allí esta el BMSG, así que haré CLICK DERECHO-EDIT CONDITION


Vemos que el BMSG es un BREAKPOINT CONDICIONAL, cuya condicion es que [esp +8] sea 202 en
este caso o sea WM_LBUTTONUP, si vemos el stack

Allí esta el valor 202 en [esp +8]

Si tienen dudas que es ESP +8 hacen doble click aquí

En la direccion de la parte superior del stack


Y cambia la numeración relativa a ESP, allí vemos que es “$ + 8” o “ESP + 8”

Bueno la cuestión es que en [esp+8] esta el numero del BMSG que necesitamos saber asi que cambiamos
en la ventana del BREAKPOINT.

Para que loguee el valor que se encuentra en EXPRESSION en este caso [esp + 8], que no pare o sea en
PAUSE PROGRAM ponemos NEVER y LOG VALUE OF EXPRESSION y LOG FUNCTION
ARGUMENTS pues no esta demás en ambos que los loguee ALWAYS o sea SIEMPRE.

Aceptamos y vamos a colocar nuestro nombre y serial nuevamente al apretar OK miramos el LOG y
vemos la lista de mensajes que usa el programa en los botones con sus nombres y números.
Allí vemos como dije que utiliza el 201 WM_LBUTTONDOWN y luego 202 WM_LBUTTONUP, y que
no utiliza los de tecla WM_KEYUP o WM_KEYDOWN jeje.

Para hacer un logueador genérico para todo el programa (botones, ventanas etc) se deben hacer
condicional breakpoints en las apis que manejan mensajes. Podemos utilizar las apis TranslateMessage y
DefWindowProcA que se complementan en su logueo.

Si quieren un reporte completo pueden poner un breakpoint condicional en las dos apis, veamos como se
hace eso.

Para hacer rápido tipeo en la commandbar BP TranslateMessage y BP DefWindowProcA.

Y
Con eso ponemos dos BPX en las apis ahora los transformaremos en condicionales vamos a la ventana B
y hacemos click en el primero FOLLOW IN DISSASSEMBLER.

Ahora que estamos en la dirección, colocamos el BREAKPOINT CONDICIONAL LOG.

Poniendo como expresión a loguear MSG que es el valor del tipo de BMSG por ejemplo en
WM_LBUTTONUP era 202 en ese caso MSG=202

Ponemos que no pare nunca y que loguee siempre y realizamos el mismo trabajo en la otra api.
Ya tenemos convertidos los BPX en CONDICIONALES

y si queremos que ya que los resultados serán muchos se loguee a una fila txt en el LOG.

Hacemos click derecho LOG TO FILE

Y elegimos el nombre del archivo de texto que lo guardara, ahora damos RUN.
Vemos el resultado del LOGUEO completo de todos los mensajes, los cuales se guardan en una fila txt, la
cual luego podemos mirar con detenimiento para ver cual BMSG nos conviene mas colocar y en donde ya
que el listado nos muestra cada mensaje en que ventana, boton, etc se aplica.

Sabiendo manejar correctamente los BMSG puede ser una gran ayuda ya lo veremos en casos de NAGS
que se utiliza el WM_CLOSE para que pare cuando se cierra la msima y mil usos mas hay mensajes para
casi todos los eventos que pueden ocurrir en una ventana.

Espero que lo hayan entendido y les sirva, en la próxima parte terminaremos de hallar el serial valido para
el CRACKME DE CRUEHEAD

Hasta la parte 13
Ricardo Narvaja
30 de noviembre de 2005
INTRODUCCION AL CRACKING CON OLLYDBG PARTE 13

TRABAJANDO PESCANDO Y REVIRTIENDO SERIALES

Creo que una de los temas mas candentes de hoy en día es el tema de hallar seriales, sobre todo luego de
que existen fuertes encriptaciones que pueden llegar a complicar la cosa, igual iremos paso a paso desde
el caso mas simple al mas complejo, tratando de practicar bastante para poder afianzar los conceptos de
trabajar con seriales.

Bueno esta primera parte del trabajo con seriales lo dedicaremos a los HARDCODED, que son los
seriales que no son calculados a partir de un nombre, o sea es un serial fijo que puede ser un texto, un
numero pero es siempre el mismo y muchas veces son sencillos otras no tanto, se tiene el concepto que
son los mas fáciles de hallar jeje, por eso empezamos por este tipo, pero hay de todo fáciles y mas
difíciles ya verán los ejemplos en esta parte.

Tenemos cuatro ejemplos para practicar, dos haremos en esta parte 13 y los dos mas difíciles en la parte
14.

El primero de los cuatro que veremos es el llamado LECCION 13 HARDCODED 1, que se encuentra
adjunto con la teoría es el caso mas simple, abrámoslo en OLLYDBG.

Allí esta en el inicio, el caso mas simple de los HARDCODED es el que aparece la clave correcta en las
STRINGS o CADENAS DE TEXTO que utiliza el programa, miremos si aquí aparece.

Para hallar las cadenas de texto o strings, hacemos click derecho SEARCH FOR – ALL REFERENCED
TEXT STRINGS.
Los resultados son

Pues allí se ve la palabra FIACA que puede ser la clave, si no tenemos ganas de trabajar podemos probar
algunas strings que salen en la lista y por ahí acertamos, pero este método no es aconsejable, por las
siguientes causas:

1)En este caso hay 2 strings, pero hay programas que tienen miles de strings, y probar una por una puede
llevar a la locura total, así que aunque vemos allí el posible serial correcto, haremos como que hay mil
strings y que no sabemos cual es.

2) Hay programas que ponen strings tramposas en la lista que no son la clave y que al tipearlas al ingresar
un serial provocan algún perjuicio ya que son trampas para crackers, así que lo mejor es asegurarse y
verificar que es el serial correcto llegando hasta la comparación entre lo que tipeas y la string correcta.

Lo primero es mirar las apis que utiliza con click derecho-SEARCH FOR- NAME (LABEL) IN
CURRENT MODULE

Ahí salen las apis utilizadas por el programa, veamos si hay alguna conocida
Allí vemos que utiliza GetDlgItemTextA, seguro la usara para ingresar el serial que nosotros tipeamos y
MessageBoxA para sacar los mensajes de si es correcto o incorrecto nuestro serial, pongamos un BPX en
cada una de dichas apis.

En ambas click derecho – TOGGLE BREAKPOINT ON IMPORT o en la commandbar

Bueno pulsemos F9 para correr el crackme

Allí sale la ventana para tipear el serial, pongamos un nombre cualquiera por ejemplo narvajita jeje

Apretemos Verificar y vemos que para en el OLLYDBG en uno de los BPX que colocamos
Si miramos el stack, vemos que paro en la api GetDlgItemTextA para ingresar el serial, allí en los
parámetros de la api, vemos la dirección del BUFFER donde guardara el serial que ingresa, en este caso
es 403010.

Así que veamos esa dirección en el DUMP haciendo click derecho – FOLLOW IN DUMP en la misma

Allí esta visible el BUFFER, y esta vacío pues aun no se ha ejecutado la api

Hagamos EXECUTE TILL RETURN para que llegue al RET de la misma.


Ahora estamos en el RET

Y la api guardo en el BUFFER el serial que ingrese

Pues allí lo tengo

Si apreto F7 y vuelvo al programa

Ya vemos viendo que estamos llegando a la comparación y al salto condicional que según salte o no me
llevara a los MessageBoxA de “Mal Muy MAL” o “Muy BIEN” obviamente si ese salto condicional lo
cambio por un JMP 401087, lo obligo siempre a saltar al cartel de MUY BIEN y programa parcheado y
resuelto, pero aquí yo quiero hallar el serial, así que veamos que compara.

En 401066 moverá a EBX el contenido de la memoria 403010 como es un DWORD solo moverá los 4
bytes pero es suficiente, veamos que hay en 403010 en el dump.
Marco la linea y hago click derecho FOLLOW IN DUMP-MEMORY ADDRESS y vere que esta leyendo

En la aclaración veo que esta leyendo 7672616E que son los 4 bytes que se encuentran en el contenido de
403010 leídos al revés como vimos, y son los primeros 4 bytes del serial falso que yo tipee los cuales
mueve a EBX.

Ahora apreto F7 y paso a la siguiente línea

Aquí vemos que compara EBX que como recordaran son los primeros 4 bytes de mi serial falso, con el
contenido de la dirección 403008, veamos que hay allí en el dump, de la misma forma que hicimos en la
línea anterior.
Vemos que esta leyendo los 4 primeros bytes de la palabra FIACA, comparándolos con los primeros
cuatro bytes que tipee, por lo cual deduzco que si ambos fueran iguales en esta comparación, se activaría
el flag Z, al ser la diferencia entre ambos cero, y el JE saltaría, mandándome el cartel de MUY BIEN, por
ahora como no son iguales recibiré el escarmiento jeje,

Como no fueron iguales no salta y va directo al cartel MAL MUY MAL, pues apretemos F9

Nos para en la otra api MessageBoxA

Y ya vemos que nos va a decir MAL MUY MAL en los parámetros de la api.

Demos run o F9

Como vemos salio el cartel malo, aceptémoslo y escribamos la clave correcta FIACA.
Apreto VERIFICAR y repito el proceso anterior hasta llegar a la comparación

Como antes compara EBX con el contenido de 403008

Ya la aclaración nos muestra que son iguales, por lo cual se restaran y dará cero el resultado el flag Z se
activara al ejecutar la comparación con f7

Allí lo vemos y como el JE salta al estar el FLAG Z activo.

Vemos como en este caso saltara al MessageBoxA de MUY BIEN veamos con F9

Allí veo en el stack cuando para en la api, que va a salir el cartel bueno
Bueno aunque olvidamos cambiarle el titulo a la ventana pero no importa hallamos el serial correcto de
nuestro primer y mas sencillo hardcoded.

El siguiente es el mismo crackme que me facilito mi amigo REDHAWK, este segundo es el original que
me hizo, el anterior lo modifique un poco yo jeje (por eso por vagancia no le cambie el titulo del
MessageBoxA correcto jejeje)

Abramos el LECCION 13 HARDCODED 2 en el OLLYDBG

Como ven es muy similar pero en las strings no aparece la clave correcta.
No se ve FIACA, ni ninguna otra posible por ahí jeje

Igual en este la clave es otra, no es FIACA, jeje.

Pues como ya sabemos como es el procedimiento directamente vayamos a la parte de la comparación

Ponemos un BPX allí en 401064 y doy RUN

Allí tipeamos un serial falso en este caso LUCKY

Apreto VERIFICAR
Y para en el BPX veremos que compara en este caso, esta pasando a EBX el contenido de la memoria
40300C, veámosla en el DUMP.

Allí vemos que al ejecutar la línea, moverá los 4 bytes a EBX, siempre invirtiéndolos ya vimos que
cuando lee de la memoria y pasa el contenido a un registro se invertirán.

Apreto F7 y allí están en EBX , al ser un MOV EBX, DWORD PTR DS: [40300C] se mueven solo
cuatro bytes (DWORD)

En este caso vario apenas la cosa, pasara a EDX el contenido de 40204B, veamos que hay allí.

Esta pasando los cuatro bytes que corresponden a la string 9898 que en este caso es el serial correcto ya
que compara estos 4 bytes con los 4 primeros de LUCKY y si son iguales verificamos que salta a la zona
de MUY BIEN, en este caso no saltara, pero si llegamos hasta poder volver a ingresar la clave y tipeamos
9898.
Apreto VERIFICAR

En la comparación de EBX y EDX ambos son iguales son 38393839 que son los bytes correspondientes a
la cadena 9898 que ingresamos y por supuesto saltara al cartel MUY BIEN.

Vemos que en este que hizo mi amigo si sale el titulo BRAVO, jeje ya que no estaba vago como yo, jua
jua, la cuestión que sacamos el serial correcto también, que en este caso es 9898.

Ahora iremos incrementando la dificultad tenemos dos hardcoded mas difíciles ya no tan directos, el
ultimo no apto para cardiacos pero bueno pueden ir viendo en ellos, como se aplican las técnicas de
crackeo para casos mas difíciles.
Como ustedes pensaron que yo solo iba a trabajar y ustedes nada, pues no, aquí trabajamos todos, hay un
tercer crackme que harán ustedes (mielecrackme1.zip), que queda como tarea para la próxima parte 14, en
la cual estará resuelto y explicado por mi, al igual que los otros dos que tenemos pendientes, lo que si les
aconsejo hacerlo pues la parte 14 vendrá en un rar con password y el password para abrirlo, será el serial
correcto de este crackme, jeje así que deben trabajar si o si (Que malvado jeje)

Como ayuda les digo que la api lstrcmpA que utiliza este crackme, es una api que se utiliza directamente
para comparar strings, cuando lleguen a esa api, verán en los parámetros en el stack, las dos strings
comparadas por la misma.

En la parte 14 les mostrare bien como funciona y seguiremos con los dos hardcoded, mas difíciles, pero
antes deben practicar con algo sencillo, por eso el crackme que agregue aquí y que es obligatorio para
seguir adelante jeje. (malo, malo eres jeje)

Hasta la parte 14
Ricardo Narvaja
03 de diciembre de 2005
INTRODUCCIÓN AL CRACKING CON OLLYDBG PARTE 14

Bueno antes que nada vamos a explicar como se soluciona el crackme que deje como tarea en la parte 13.

Allí esta el mielecrackme abierto en OLLYDBG, y detenido en el ENTRY POINT, veamos las apis que
utiliza con SEARCH FOR-NAME (LABEL) IN CURRENT MODULE.

Aquí están las apis utilizadas

Allí están las apis que son importantes, GetWindowTextA para ingresar el serial que tipeamos, lstrcmpA
como les anticipe en la parte anterior para comparar strings y MessageBoxA para mostrar el mensaje de si
colocamos el serial correcto o no.

Podemos poner un BPX en esas apis, para parar cuando ingresa nuestro serial falso, pero en este caso que
es bien sencillo, podemos hacer mas rápido si miramos las STRINGS que utiliza el programa.
Haciendo SEARCH FOR – ALL REFERENCED TEXT STRINGS sale la lista de STRINGS o
CADENAS DE TEXTO usadas por el programa veamos.

Allí vemos las strings de que acertamos y las que muestra cuando fallamos, si hacemos doble click en
alguna de ellas, nos llevara a la zona de los MessageBoxA, probemos haciendo doble click en YOU
ENTERED THE RIGHT PASSWORD (has ingresado el password correcto)

Allí vemos la zona caliente.

Primero GetWindowTextA como dijimos para ingresar el serial que tipeamos, luego lstrcmpA para
comparar con el serial correcto, y luego según si son iguales continua al MessageBoxA, con la leyenda
YOU ENTERED THE RIGHT PASSWORD, y si no son iguales salta al otro MessageBoxA, MAYBE,
YOU SHOULD TRY AGAIN, IT´S SO EASY, que intentemos de nuevo que es fácil.
Así que pondremos un BPX, allí en el CALL a la api lstrcmpA, para ver que compara.

Ahora si corro el programa con F9

Sale la ventana para ingresar el serial y ponemos uno cualquiera por ejemplo 989898.

Al apretar CHECK para en el BPX que colocamos.

Vemos que OLLY nos aclara los parámetros, los cuales son las dos STRINGS que comparara, en este
caso vemos que compara la que tipee “989898”, con la palabra “cannabis.

Al apretar F8 para ejecutar el CALL de la api

El resultado dicha api lo muestra en EAX, si es FFFFFFFF o sea -1, es que las strings no son iguales.
Como el resultado de la comparación no es cero, no se activa el FLAG Z, y el JNZ salta ya que el FLAG
Z es cero. (Recordar que JNZ salta si el FLAG Z es cero porque es el inverso de JZ que salta cuando el
FLAG Z esta activo o 1)

Pues allí salta y va al cartel de error, así que ya sabemos que compara con la palabra cannabis, o sea que
este es el serial correcto doy RUN nuevamente, acepto el cartel malo.

Y vuelvo a la ventana para ingresar el serial esta vez tipeo el serial correcto, cannabis.

Apreto el botón CHECK y para en el BPX.

Veo que va a comparar ambas strings y estas son iguales, apreto F8 para ejecutar el CALL de la api.

Ahora al ser ambas strings iguales el resultado de la api que guarda en EAX es cero, por lo cual se activa
el FLAG Z.
Y el JNZ en este caso no salta al estar el FLAG Z activo.

Allí no va a saltar y va a ir al cartel de que acertamos demos RUN.

Pues esta es la solución del crackme que deje como tarea de la parte 13, jeje, el serial es la palabra
“cannabis”

Sigamos ahora avanzando con HARDCODED SERIALS mas difíciles nos quedan para ver dos.

El caso siguiente es un paso mas, en este ya no compara directamente el serial que tipeamos sino que
realiza algunas operaciones antes de comparar veamos el ejemplo, este es el crackmeeasy, abrámoslo en
OLLYDBG.

Ya sabemos como ver las apis que utiliza, así que en la lista vemos GetDlgItemTextA, pongámosle un
BPX en dicha api.
En la commandbar tipeo

Ahora doy RUN con F9 y aparece la ventana para ingresar el serial

Allí tipeo mi serial falso

Y apreto el botón Check y para en la api

En el stack miro los parámetros


Allí vemos el BUFFER donde guardara el serial falso, marco esa línea y hago CLICK DERECHO-
FOLLOW IN DUMP

Allí esta el buffer vacío, porque aun no se ejecuto la api, así que hago DEBUG-EXECUTE TILL
RETURN

Con lo cual ejecuto la api y llego al RET de la misma.

Apreto F7 para volver al programa

Y veo que en el BUFFER esta ahora el serial falso que ingrese.


Allí veo una larga rutina con un numero constante, que si alguno tuvo la idea de probar si es el serial
correcto ya sabrá que no lo es jeje.

Allí mueve 401222 a EAX y en el registro EAX vemos que dicha dirección apunta a la string del numero
constante.

En la siguiente línea como EAX vale 401222 ,

MOV EDX,DWORD PTR DS:[EAX]

En realidad es similar a

MOV EDX,DWORD PTR DS:[401222]


O sea que mueve el contenido de 401222 a EDX.

En la aclaración del OLLY se ve bien que son los 4 primeros bytes del numero 10445678951

Al ejecutar la línea con F7 se mueven a EDX (siempre se moverán al revés al mover de la memoria a un
registro)

La siguiente línea esos bytes que están en EDX los mueve a [EBP-30]

En la aclaración del OLLY vemos que [EBP-30] es en mi maquina 240f9e4, lo busco en el DUMP

Al ejecutar con F7 se copiaran allí los bytes que estaban en EDX

Luego
Mueve a EDX los siguientes cuatro bytes del número constante

La aclaración del OLLY lo muestra, en este caso [eax+4] es en este caso el contenido de 401226 y al
ejecutar con F7 mueve los 4 bytes siguientes a EDX.

Y los copia a continuación de donde copio los anteriores

En realidad lo que esta haciendo es copiar ese numero de a 4 bytes a otra parte de la memoria

Y aquí copia los últimos 4 bytes

Quedando el número completo copiado allí.

Allí vemos que un poco mas abajo se acerca a una llamada a la api memset, allí vemos los parámetros en
OLLYDBG

Tiene tres valores (n, c y s)

s es la dirección de inicio
n que es la cantidad de bytes que van a llenar
c es el valor con el cual se va a llenar esa zona

En el stack se ven mejor en este caso los parámetros, o sea que llenara con ceros (c ), 8 bytes (n) a partir
de s (240f9f0).

Al ejecutar la api con F8, allí vemos que lleno de ceros, los 8 bytes a partir de 240f9f0 que es la dirección
de inicio s.

Mas abajo vemos una llamada a lstrlen, que es una api que calcula el largo de una string lleguemos hasta
el call a la misma.

En el stack vemos los parámetros

O sea nos dará el largo de la string que comienza en 240f9E4, que es el numero constante famoso jeje.

Al pasar con F8 el call a dicha api en EAX nos devuelve el largo de la string

Vemos que el largo es 0B que es 11 decimal, que es el largo del número constante.

Allí le resta uno a EAX o sea 0B-1 y como es LEA mueve ese valor directo a EDX o sea que EDX vale
0A.

En la siguiente línea compara EDX que vale 0A con el contenido de [EBX-10] que es cero.
Pues como cero es mas bajo que 0A en la comparación, salta y va a 40135C.

En la próxima línea mueve a EAX el puntero a nuestro serial falso, allí vemos que luego de ejecutar con
F7, EAX apunta a nuestro serial falso 98989898

En la siguiente línea mueve a EDX cero

En la siguiente línea

Como EAX apunta al inicio de nuestro serial falso, le suma en este caso EDX que vale cero posiblemente
para hacer un LOOP que se ira actualizando incrementando EDX a 1, 2 etc y recorrer de esa forma todos
los bytes de nuestro serial falso uno a uno en dicho LOOP.

Como ya sabemos que MOVSX en el caso de números positivos mueve el byte a EDX y si es positivo
llenara el resto con ceros, y si es negativo con efes jeje.
En este caso no hay problema mueve el primer byte de mi serial falso el 39 a EDX al ejecutar la línea
vemos que EDX vale 39.

La siguiente línea es un LEA

Y como EDX vale 39, le resta 14 y como es un LEA mueve el resultado directo a EAX.

O sea que la operación que realizo es tomar 39 que es el valor hexa del primer carácter de mi serial, y le
resto 14 y quedo por ahora en 25, el cual esta en EAX.

La siguiente línea mueve el valor EBP-30 que en mi maquina es 240f9E4 que apunta al inicio del numero
constante guardado a EDX.

Al apretar F7
Queda EDX apuntando al inicio del número constante.

Aquí vemos que mueve a ECX el valor cero y en cada pasada que haga en el LOOP se incrementará,
permitiendo a ECX+EDX apuntar a los distintos bytes del numero constante.

Ahí vemos como ECX por ahora vale cero y EDX apunta al inicio del numero, moverá a EDX en este
primer paso por esta línea, el primer byte del numero vemos en la aclaración del OLLYDBG.

Que mueve el byte 31 que corresponde al 1 en ASCII, es la primera cifra del número constante.

Allí llegamos a una comparación como recordamos

En EAX esta el valor del primer byte de mi serial falso 39 al cual le resto 14, quedando en EAX el valor
25, y en EDX el primer byte del numero constante o sea 31

Por lo tanto vemos que

CMP EAX,EDX

En realidad es

CMP (PRIMER BYTE DE MI SERIAL FALSO – 14), PRIMER BYTE DEL NUMERO CONSTANTE

CMP 25,31

Y al ser la diferencia entre ambos miembros diferente de cero, no se activa el FLAG Z y salta el JNZ.
Como estoy utilizando el serial falso, la comparación no es igual, solo serán iguales ambos miembros
cuando usemos el serial correcto ya que es el valor que hace que la comparación llegue a ser una
igualdad.

CMP (PRIMER BYTE DE MI SERIAL CORRECTO – 14), 31

Ya que la condición es que ambos miembros sean iguales

PRIMER BYTE DEL SERIAL CORRECTO-14= PRIMER BYTE DEL NUMERO CONSTANTE

Por lo tanto

PRIMER BYTE DEL SERIAL CORRECTO= PRIMER BYTE DEL NUMERO CONSTANTE +14

PRIMER BYTE DEL SERIAL CORRECTO = 31 + 14

PRIMER BYTE DEL SERIAL CORRECTO =45 que corresponde a E en ASCII.

O sea que la primera letra del serial es E.

Esta afirmación si repetimos el loop vemos que se cumple byte a byte

PRIMER BYTE DEL SERIAL CORRECTO= PRIMER BYTE DEL NUMERO CONSTANTE +14

SEGUNDO BYTE DEL SERIAL CORRECTO= SEGUNDO BYTE DEL NUMERO CONSTANTE +14

TERCER BYTE DEL SERIAL CORRECTO= TERCER BYTE DEL NUMERO CONSTANTE +14

Y así sucesivamente

Siguiendo la misma lógica, a cada byte del numero constante, le sumamos 14 y obtenemos el valor del
byte correspondiente a nuestro serial correcto.

31 30 34 34 35 36 37 38 10445678
39 35 31 00 00 00 00 00 951.....

31 +14=45 es la letra E en ASCII

30 + 14= 44 es la letra D en ASCII

34 + 14= 48 es la letra H en ASCII

34 + 14= 48 es la letra H en ASCII

35 + 14= 49 es la letra I en ASCII

36 + 14 = 4A es la letra J en ASCII

37 + 14= 4B es la letra K en ASCII

38 + 14 = 4C es la letra L en ASCII

39 + 14 = 4D es la letra M en ASCII
35 + 14= 48 es la letra I en ASCII

31 +14=45 es la letra E en ASCII

Por lo cual el serial correcto es

EDHHIJKLMIE

Pongámoslo en la ventana del serial borrando todos los BPX.

Apretemos Check

Les dejo como tarea recorrer el loop completo, ver como va actualizando los contadores y como va
incrementando los bytes del numero constante y del serial falso, y como llega al cartel de correct o de
incorrect.

No es tan easy el crackme jeje ya que recién están empezando, pero creo que si lo practican pueden
sacarle buen jugo.

Bueno aquí tienen la tarea sencilla para la parte 15 es otro crackme llamado SPLISH, solo tienen que
hallar en la parte de HARDCODED el serial correcto y con el serial abrirán la parte 15 jeje sigo
malísimo, pero les digo que este crackme no se parece en nada a este anterior que hice, es bien sencillo,
ya iremos practicando mas difíciles de a poco.

Ricardo Narvaja
05 de diciembre de 2005
INTRODUCCIÓN AL CRACKING CON OLLYDBG PARTE 15

Bueno antes de seguir con el ultimo hardcoded, mostraremos la solución del que quedo pendiente como
tarea, el SPLISH que es bien sencillo.

Abrámoslo en OLLYDBG.

Allí arranco en OLLYDBG y se detuvo en el ENTRY POINT.

Si vemos las apis que utiliza con click derecho SEARCH FOR-NAME (LABEL) IN CURRENT
MODULE

Vemos la lista de apis que utiliza


Vemos que utiliza las apis GetWindowTextA para ingresar el serial y MessageBoxA, para mostrar el
cartel de si acertamos o no, podríamos aquí poner un BPX en ambas apis, pero veamos que nos muestra la
lista de STRINGS que usa el programa.

Hago en el listado click derecho SEARCH FOR-ALL REFERENCED TEXT STRING

Allí vemos el texto del cartel de Congratulaciones, que nos muestra cuando colocamos el serial correcto,
por lo tanto hagamos doble click allí, a ver donde usa ese texto, así estaremos en la zona caliente o cerca.

Allí vemos la zona donde trabaja con el serial que introducimos

Vemos la entrada de texto con la api GetWindowTextA y los MessageBoxA con sus respectivos textos de
si acertamos o no.
Pues pongamos un BPX alli, en el call a la api GetWindowTextA para comenzar desde donde se
introduce el serial que tipeamos.

Corro el crackme con F9 o RUN

Como solo pedimos por ahora solucionar la parte de HARDCODED, tipearemos un serial falso, allí en la
parte superior y apretamos el botón CHECK HARDCODED.

Para en el BPX que habíamos colocado

Allí vemos tanto en el stack como en las ayudas que nos muestra el OLLY que el BUFFER donde
guardara el serial que tipeamos, esta en 403215.
Así que vayamos al dump a ver el buffer.

Allí esta el buffer donde guardara el serial que tipeamos, apretemos F8 para ejecutar el CALL a la api.

Como al ejecutar con F8, ejecuta todo el call con la api incluida, pues ya tenemos el serial falso guardado
en el BUFFER.

Bueno la próxima línea moverá 401353 a EAX, (recordar que los LEA no mueven el contenido de la
dirección de memoria, si no solo el resultado de lo que hay entre corchetes, en este caso moverá 401353)
Veamos en el DUMP dicha dirección, en la línea hacemos click derecho FOLLOW IN DUMP-
MEMORY ADDRESS lo que nos muestra en el DUMP la dirección de memoria 401353.

Pues 401353 apunta a la string “HARDCODED”, apretemos F7 para que se ejecute el LEA.
Al ejecutar queda EAX con el valor 401353 y al lado nos aparece la aclaración de que dicha dirección
apunta a una string en este caso “HARDCODED”

La siguiente línea mueve otra dirección a EBX en este caso 403215.

Al apretar F7, EBX quedara valiendo 403215

Y OLLYDBG nos muestra a la derecha, que esa dirección apunta a la string “98989898”, que es mi serial
falso y que se ve en el dump si hago como en la instrucción anterior.

Allí esta 403215 apunta a nuestro serial falso

La siguiente linea compara si el primer BYTE del contenido de EAX es cero, como EAX vale 401353
Sabemos porque lo vimos en el DUMP que el contenido son los bytes de la cadena HARDCODED.

Allí esta el primer Byte es 48, en la aclaración OLLYDBG también nos dice que esta leyendo el 48 que
corresponde a la H en ASCII de la primera letra de la palabra HARDCODED, ve si es cero, como no es
cero continuara.

Como la comparación no activo el FLAG Z al no ser ambos miembros iguales, pues el JE siguiente no
saltara, recordar que JE solo salta al estar activado el FLAG Z.

Pues continuamos con F7

Aquí vemos con una visión mas ampliada, que ahora moverá el primer byte de [EAX] que es el 48 que
corresponde a la palabra HARDCODED y en la siguiente línea moverá [EBX] que corresponde al primer
byte de mi serial falso y los comparara si no son iguales salta a 4013D2 que es el cartel de SORRY,
PLEASE TRY AGAIN.

Verifiquemos que esto es asi

Apreto F7 y mueve a CL el valor 48


CL como recordamos es el registro que corresponde a los dos ultimas cifras de ECX, alli movio el 48, lo
vemos en la imagen resaltado.

En la siguiente mueve a DL el primer byte de mi serial falso

Al ejecutar con F7 vemos el 39 en DL

Ahora compara CL con DL

La aclaración del OLLYDBG no deja dudas, compara el 39 que es el 9 de la primera cifra de mi serial
falso con H que es la primera cifra de HARDCODED.
Vemos que al no ser iguales salta al cartel de error, si fueran iguales y no saltara lo cual podemos hacer
fácil cambiando el FLAG Z con doble click.

Ahora Z vale 1 como si en la comparación ambos bytes fueron iguales y la resta entre ambos dio cero y
activo el FLAG Z o cero.

Vemos que en este caso INCREMENTA EAX y EBX y salta con un JMP al inicio del LOOP

Ahora EAX apunta al segundo byte de HARDCODED y vemos que el loop se repetirá comparando byte a
byte, hasta que sea cero el contenido de EAX o sea cuanto se terminen los bytes de la palabra
HARDCODED ya que en una string, luego de su ultimo carácter, hay un cero.

Pues entonces al incrementar EAX y EBX ira leyendo y comparando los segundos bytes, si son iguales,
repetira el loop y hará lo mismo con los terceros y asi, una vez que se completo la palabra HARDCODED
si todos los bytes en la comparación CL con DL han sido iguales, no saltará a mostrar el mensaje de
SORRY y llego aquí

Como EAX ya termino de apuntar a todos los bytes de la palabra HARDCODED pues llego al cero del
final de la string veamos.

Allí EAX apunta a 40135C que en el DUMP vemos que es el cero al final de la string entonces al ser la
comparación ambos miembros iguales

El JE salta y nos saca del LOOP


Y nos lleva al cartel de CORRECTO (porque cambiamos los flags Z de las comparaciones byte a byte
jeje)

Por supuesto yo lo hice invirtiendo en cada comparación de CL con DL el flag Z, para que el programa
crea que son iguales si no saltará al cartel malo y no llegaré aqui, pero de todas formas ya sabemos
entonces que el serial correcto es la palabra HardCoded respetando mayúsculas y minúsculas porque
tienen diferente valor ASCII.

Quito todos los BPX y tipeo el serial que halle, y al apretar CHECK HARDCODED

Otro vencido, si ustedes están leyendo esto pues, felicitaciones también para ustedes pues lo han vencido
también, si no no podrían leer esta lección y si el password del rar se los paso un amigo, mejor releer todo
y practicar que haciendo trampa no se aprende, jeje.

Bueno pues vamos con el ultimo HARDCODED y terminamos ya con esto, para pasar el siguiente tema
en la parte 16.

Bueno el siguiente crackme es algo diferente a los anteriores es al llamado SAMBO y lo arrancamos en
OLLYDBG.
Nos sale este cartelito de OLLYDBG que nos avisa que algo pasa, alli dice que la fila se auto-
descomprime o se auto modifica, lo que en la jerga del cracking se llama una fila empacada, comprimida
o empaquetada, lo cual estudiaremos en profundidad mas adelante, pero igual podemos a pesar de que
este empacada, correrla en OLLYDBG y tratar de hallar el hardcoded serial.

Aceptamos el aviso de OLLYDBG y llegamos al EP.

Otro avisito en este caso antes de analizar OLLYDBG nos avisa que es un programa empacado,
comprimido, encriptado y que analizar eso es mas inútil que cenicero de moto, jeje, pues el programa se
ira desempacando mientras corre, por lo cual, elegimos NO, para que no lo analice por ahora.

Pues si alli estamos en las primeras líneas del crackme, vemos como curiosidad que el crackme no esta
ejecutando como los desempacados la primera sección después del header que comienza en 401000

Como la dirección del Entry Point es 4d4001

Vamos a ver que sección esta ejecutando, así que voy a VIEW-MEMORY o apreto el botón M.
Vemos que el programa se esta ejecutando en la sección que comienza en 4D4000 y su largo es 2000,
pues 4d4001, es una dirección de memoria perteneciente a esa seccion.

Pues eso era lo que avisaba OLLYDBG que el ENTRY POINT esta fuera de la sección code

La sección CODE empieza en 401000, allí vemos resaltada la palabra CODE y nosotros estamos
ejecutando la dirección 4D4001 que pertenece a otra sección, OLLYDBG nos aviso de esto que es una
característica de muchos programas empacados.

La sección en la cual esta el ENTRY POINT corresponde al desempacador y una vez que se ejecuta y
realiza su trabajo, salta a la sección code donde se ejecuta el programa en si.

Pues entonces hagamos F9 o RUN

Al aparecer la ventana del crackme, para ingresar el serial, sabemos que el programa ya esta desempacado
en memoria y esta ejecutándose ahora en la sección code, por lo cual podemos poner un BPM ON
ACCESS en dicha sección, para que pare allí cuando ejecute alguna línea de la misma.
Al tratar de volver a la ventana del crackme, para OLLYDBG en la sección code o primera sección
después del header.

Veo que ahora que esta descomprimido el programa en memoria, puedo analizarlo entonces, en el listado
hago click derecho

Vemos que OLLYDBG nos muestra el código analizado ahora perfectamente.

Ahora que estamos en la sección code, podemos ver que apis usa el programa, esto no lo podíamos hacer
en el inicio, pues en ese momento solo nos mostraría las apis que usa el desempacador, y no las que usa el
programa, ahora no hay problema.
Ughh que mal trago una terrible lista y ninguna conocida, veamos la lista de strings, aclaramos que esto
tampoco se podía hacer en el inicio pues estábamos en otra sección y además las strings estaban
empacadas junto con el programa así que no veríamos nada.

En una terrible lista vemos


YOU DID IT, una de las strings del cartel de felicitación

Bueno hay una comparación y un salto vemos strings de felicitación y de error aunque no hay
MessageBoxA por aquí.

Pongamos un BPX en el salto condicional para verificar si es el salto decisivo, quitemos el BPM ON
ACCESS con click derecho
Y demos RUN

En la ventana del crackme tipeamos Narvajita o el serial falso que quieran.

Apreto el botón Test-o-Doom

Vemos que salta apretemos F9

Pues sale el cartel de que lo lograste y si aceptamos


Te dice que era un chiste y que no acertaste nada jeje, demos RUN nuevamente lleguemos a la ventana y
lleguemos de nuevo al salto apretando el botón Test-o-Doom.

Invirtamos el salto a ver si sale el cartel de felicitaciones, para ver si es esto verdaderamente lo que
decide.

Al hacer doble click en el flag Z no saltara doy RUN

Y sale el cartel de felicitación, así que por aquí es donde decide las cosas, veamos la comparación antes
del salto.
Es un TEST CL,CL que solo testea si CL es cero o uno, así que la comparación se realiza antes,
posiblemente en el CALL que esta justo antes pongamos un BPX alli.

Demos RUN y volvamos a la ventana y apretemos nuevamente el botón Test para que pare ahora en el
CALL.

Una vez que paro como soy curioso miro un poco alrededor jeje

Si miro en el stack veo mi serial falso allí, veamos en el DUMP haciendo FOLLOW IN DUMP en el
mismo.

Mi ojo de cracker ve por ahí una string con forma de posible serial correcto, podría probar a ver si es pero
por ahora seguiré con el método de buscarlo a fondo sin intentar.

Si alguna vez comparara o operara con mi serial falso dentro del CALL, pues poniendo un BPX ON
ACCESS en el mismo, parara cuando el programa quiera hacer algo con el, o sea al acceder al mismo
para cualquiera operación o comparación que desee realizar.

Así que marco mi serial falso y hago click derecho


Con lo cual si doy RUN y dentro del call accede a mi serial falso, parara OLLYDBG.

Apreto F9

Vemos que no para, quizás la comparación sea antes, así que o bien podemos ir poniendo BPX en los
calles que están mas arriba de este y repetir el método o bien empleamos el método de parar justo cuando
el programa ingresa el serial, aquí no utiliza la api GetWindowTextA pero tenemos nuestros Mensajes de
Windows los cuales seguro nos servirán.

Quito el BPM ON ACCESS

Así que para hacer rápido pongo un BP TranslateMessage

Y doy RUN

Allí para en la api, así que hago click derecho


Y en la ventana tipeamos la condición MSG==202 que era el valor de WM_LBUTTONUP

Y ponemos las tildes para que pare ON CONDITION y que loguee siempre todo.

Allí esta en rosado el BPX CONDICIONAL doy RUN

Llego a la ventana del crackme y para evitar confusiones cambio el serial por si quedo el anterior en la
memoria.
y al apretar el botón para en mi BPX CONDICIONAL

Allí esta paro en WM_LBUTTONUP

Volvamos al programa con EXECUTE TILL RETURN

Apreto F7 y vuelvo al programa

Aquí se me abren dos posibilidades poner un BPM ON ACCESS en la primera sección para con f9 ir
saltando y ver cuando llega a la rutina de comparación del serial, lo cual me parece un poco complejo
porque aquí ya vi que la rutina del serial es bastante larga y me pasare saltando jeje.

La otra posibilidad es ver si el serial que tipee ya ingreso en la memoria, como es un serial nuevo pues si
esta en la memoria, no es porque quedo de antes si no que ya ingreso, así que voy a la ventana M.

Que además de permitirme ver las secciones me permite buscar una cadena en toda la memoria, así que
hago click derecho SEARCH
Y en la ventana que aparece, en la parte ASCII tipeo mi serial falso.

Apreto OK para que busque en toda la memoria.

Pues la primera ocurrencia es aquí puedo repetir con CTRL+L y no hallara mas ocurrencias, ni en la
sección que se abrió ni en el resto de la memoria.

Pues pongo un BPM ON ACCESS en mi serial falso pues en algún momento accederá a el para leer,
operar o comparar.

Y apreto F9

Para aquí donde lo copiara a su ubicación la que habíamos visto en el ultimo CALL
Sabemos que el REP MOVS copiara el contenido de ESI a EDI, así que veamos EDI en el DUMP,
haciendo click derecho en EDI-FOLLOW IN DUMP.

Allí lo copiara el REP MOVS apretemos F8 para que lo haga

Al llegar con F8 al RET lo habrá copiado entero, y pongo ahora el BPM ON ACCESS en mi serial falso
aquí

Al dar RUN para aquí

Justo en la comparación jeje


ESI apunta a mi serial falso y EDI apunta al correcto que es 1556555

Si quitamos todos los BPX

Pues allí esta el cartel de felicitación

Ahora para intentar pues no hemos visto aun el tema, por lo cual la siguiente lección no estará con
password, si no para intentar y divertirse, el que quiere intentar el crackme de cruehead hallar un serial
para su nombre pues puede hacerlo, o sea en user pone su nombre y halla el serial correcto, en la próxima
parte empezaremos con crackmes USER y SERIAL y el primero que resolveremos será ese, así que a no
frustrarse si no pueden, que es un tema no visto aun, así que tómenlo como diversión si pueden con el ,
pues felicitaciones, si no pueden, lo aprenden en la próxima parte.
Hasta la parte 16
Ricardo Narvaja
08 de diciembre de 2005
INTRODUCCIÓN AL CRACKING CON OLLYDBG PARTE 16

Comenzaremos en esta parte con los crackmes que a diferencia de los hardcoded como hasta ahora, el
serial es variable y depende del nombre que ingresamos, y es calculado a partir de el.

El mecanismo para solucionarlos es muy similar, pero veremos algunos ejemplos para que quede claro.

En la parte anterior los anime a que intenten hallar para su propio nombre, el serial correcto para el
CRACKME DE CRUEHEAD y bueno, ese será el primero que haremos, así ven como se soluciona y si
estaban en el buen camino, y si lo solucionaron pues mis mas gratas felicitaciones.

Abramos el crackme de cruehead en OLLYDBG.

Allí estamos detenidos en el ENTRY POINT

Veamos las apis que utiliza para ingresar el texto del serial que tipeamos

Probamos colocando un BP en dicha api a ver si se detiene cuando ingresa el nombre y serial correcto

Damos RUN

Al apretar OK para en la api y en el stack vemos los parámetros


El buffer donde guardara el texto que ingresa esta en 40218E, veamos esa dirección en el dump, hacemos
click derecho - FOLLOW IN DUMP en la línea del stack que nos informa del buffer.

Allí esta, aun vacío porque no se ejecuto la api, así que hagamos DEBUG- EXECUTE TILL RETURN y
como estamos en el RET de la api hago F7 para volver al programa.

Vemos que en el buffer guardo mi nombre a partir del cual realizara operaciones y creara la clave correcta
para el mismo, si quisiéramos hacer un keygen, deberíamos estudiar a partir de aquí las operaciones que
realiza el programa para desde un nombre cualquiera, calcular la clave correcta, pero como este no es el
caso, dejaremos que el programa genere la clave correcta y trataremos de ver si compara con el serial que
tipeamos damos RUN nuevamente.

Para por segunda vez en la api, el nuevo BUFFER para la entrada del serial que tipee es 40217E, así que
lo busco en el dump.

Allí esta justo arriba del otro, ejecuto la api con EXECUTE TILL RETURN y para volver al programa
desde el RET apreto F7.

Allí ingreso nuestro serial falso, a partir de este punto el programa comparara el serial falso con el
correcto que calculo a partir de mi nombre, así que podemos colocar un BPM ON ACCESS en este serial
falso para ver que hace el programa con el.
Marco los bytes y hago click derecho – BREAKPOINT –MEMORY ON ACCESS y doy RUN

Vemos que para allí cuando el programa lee el primer byte de mi serial falso y lo mueve a BL si apreto
F7.

Allí esta en BL el valor 39 de mi primer byte, debemos perseguir lo que el programa realiza con el, y en
lo posible ir anotando para no perdernos si realiza operaciones matemáticas con el mismo.

Allí testea si es cero, para salir del loop al encontrar el final de la string, sigamos con f7

Como no es cero no salta y llega a SUB BL,30


Al restarle 30, queda en BL el valor numérico decimal, del primer carácter de nuestro serial falso que es
9.

En la siguiente línea multiplica EDI con EAX.

Dichos valores estaban inicializados EAX en 0A justo al inicio de la rutina y EDI antes de entrar al loop
se coloco a cero con XOR EDI,EDI

Allí esta de donde surgen ambos valores, al apretar f7 si recordamos la definición de IMUL con dos
operandos, en dicho caso multiplica ambos considerando el signo, y guarda el resultado en el primer
operando o sea EDI en este caso.

Por eso guarda el resultado en EDI el cual queda a cero.


Luego le suma a EDI el valor de EBX

Quedando el EDI el valor 9, a no desesperar que esto parece difícil pero ya verán que no lo es en la
próxima línea INC ESI, incrementa ESI para retornar al inicio del LOOP con el JMP y poder leer el
siguiente byte de mi serial falso.

Luego de volver a colocar en AL el valor 0A, ahora lee el segundo byte de mi serial falso, ahí vemos que
moverá a BL el valor 38 al igual que antes, testeara si es cero, le restara 30, y llegamos a la IMUL.

Vemos que multiplica EDI que tiene el valor que arrastra de la pasada anterior con 0A y el resultado lo
guardara en EDI veamos.
EDI queda en 5A en la siguiente línea le suma EBX

O sea que va realizando operaciones y va juntando el resultado en EDI, para los que son ya asiduos al
cracking ya sabrán que hace aquí, lo explicaremos.

Lo mas sencillo es poner un BP en la salida del loop apretemos F9 y cuando se detiene veo que EDI vale

Si hago doble click en EDI


El valor de EDI es un valor hexadecimal, en la segunda línea veo su valor decimal, que corresponde a mi
serial falso o sea lo que ha hecho con todo este loop (que es un loop bien conocido para los asiduos al
cracking jeje ya lo ven y saben que a la salida estará el valor HEXA del serial falso.

O sea en resumidas cuentas si tipee

98989898 lo primero transformo esto en el número decimal 98989898 y luego lo transformo a hexa
quedando 5E6774A.

En la siguiente línea se hace EDI XOR con 1234

Queda en mi caso 5E6657E sigamos traceando, lo mueve a EBX y llega al RET.

Vemos que al volver del ret llega a la comparación EAX con EBX, lleguemos allí, ese era el salto que
decidía si era correcto o no así que estamos bien,
Al llegar vemos que compara el valor que calculó que esta en EBX con EAX que vale 547B

Como EAX es un valor determinado del programa y EBX es calculado a partir de mi serial falso el cual
es incorrecto obviamente, aquí no hay igualdad.

Si EBX fuera igual a EAX el programa saltaría a CORRECTO, por lo tanto debemos analizar como llegar
a que allí haya una igualdad.

Veamos nuestras anotaciones

EBX= (Valor hexadecimal del serial falso) XOR 1234

Como yo quiero que EBX sea igual que EAX, en dicho caso se verificara la igualdad y estaremos en el
caso correcto

Si EAX=EBX

Reemplazo EBX por EAX ya que son iguales

EAX=(Valor hexadecimal del serial correcto) XOR 1234

Y ya no es más serial falso porque el serial que hace que EBX y EAX sean iguales es el serial correcto.

Despejo

EAX XOR 1234= (Valor hexadecimal del serial correcto)

Y EAX es un dato pues lo tengo de la comparación EAX=547B

547B XOR 1234 = (Valor hexadecimal del serial correcto)

Si soluciono el XOR

464F = (Valor hexadecimal del serial correcto)

Si 464F es el valor correcto hexadecimal, si lo paso a decimal tendré mi serial para tipear
Apreto decimal

Ese es el serial correcto para narvaja quitemos todos los BPM y BPs

Apreto OK

Y obtuve el serial para mi nombre

Esta es una forma de solucionarlo, otra forma de pensarlo que se llega a la misma soluciones es esta

Si a mi serial falso le hace operaciones y lo transforma a esas operaciones las llamamos función F

F (serial falso) =EBX

O sea que a mi serial falso le realiza ciertas operaciones llamadas F y lo convierte en EBX el cual
comparará.

El otro miembro de la comparación que es EAX sigue el mismo parámetro


F (serial verdadero)=EAX

Aplicando las mismas operaciones al serial verdadero en este caso llego al valor de EAX, por lo tanto si
tengo EAX ya que es un dato de la comparación y tengo las operaciones realizadas.

Para hallar el serial verdadero deberé a EAX realizarle las operaciones opuestas para hallar el serial
verdadero.

Serial verdadero= (funciones opuestas de F ) EAX

O sea si fuera que a mi serial falso se le sumo un valor para llegar a la comparación, este se lo deberé
restar a EAX y así siempre debo realizarle las mismas operaciones pero opuestas.

En este caso la operación opuesta de XOR es la misma XOR ya que es una operación inversible

Por lo cual

XOR EAX será realizar la función opuesta de F y me dará el valor hexa de mi serial correcto, a partir del
cual, pasándolo a decimal obtendré el serial verdadero.

Esto que parece mucho palabrerío no lo es tanto, de ambas formas despejando o realizando las
operaciones opuestas normalmente se puede llegar al serial correcto, salvo que se use una operación que
no tiene opuesta, ya veremos esos casos.

Veamos otro caso el del ya visto SPLISH pero en el modo USER-NAME ya que la parte HARDCODED
ya la hemos hecho.

Arrancamos el SPLISH en OLLYDBG y estamos en el ENTRY POINT

Veamos las apis que utiliza

La conocida GetWindowTextA pongamos un BPX en dicha api

Y demos RUN con F9


Alli tipeamos el nombre y serial falso y apretamos el boton NAME/SERIAL CHECK

Para en la api veamos el BUFFER

Buscamos el BUFFER en el DUMP

Allí está vacío aun, hagamos EXECUTE TILL RETURN para llegar al RET y luego F7 para volver al
programa.
Vemos que en este caso ingreso primero el serial falso, así que marcamos el mismo y ponemos un BPM
ON ACCESS.

Damos RUN

Para de nuevo en la api para ingresar el nombre, como esto por ahora no nos interesa damos RUN
nuevamente.

Para en esta rutina

La primera línea mueve nuestro primer byte del serial falso si ejecutamos

Luego tenemos la siguiente instrucción CDQ, ya que no la explicamos veamos que dice nuestro amigo
GOOGLE, el puede ayudar tipeamos en el buscador de GOOGLE CDQ ENSAMBLADOR.
En este caso igual no es necesario ya que EDX es cero y esta preparado para obtener el resto de la
división pero como es un loop por si acaso siempre mejor antes de una IDIV usar el comando CDQ para
preparar los registros EDX y EAX para la misma.

Pues dividirá EDX:EAX por ECX y el resultado va a EAX y el resto a EDX bueno este es todo el truco
vemos que el byte nuestro vale 39 y lo dividirá por ECX que es 0A

Veamos que ocurre

Allí esta el resultado de la división esta en EAX y es 5 y el resto esta en EDX y es 7

Vemos que en la próxima línea guarda el resto de la división en 40324D veámoslo en el DUMP
Allí lo guardara ejecuto con f7

Allí esta el 7 guardado

Vemos que EBX que era cero es incrementado y comparado con 6 para salir del loop por ahora no son
iguales por lo tanto repite.

Allí va leer el segundo byte

De nuevo lo divide por 0a y guarda el resto


A continuación del otro byte lo guardara

Bueno vemos que no hay variación realiza la misma operación en todos los bytes.

Y sale del loop al no saltar el JNZ que nos retornaba al inicio del mismo.

Llegamos allí y vemos los mensajes de correcto o incorrecto por lo cual ya sabemos que estamos cerca.
Luego hay dos LEA que mueven direcciones a ESI y EDI

ESI apunta a donde guardo los restos y EDI apunta a algo interesante jeje?

Sigamos

Vemos que EBX vale cero y lo compara con 7 y si es igual


Saltaría al cartel correcto lo que pasa que hay un loop y en el medio otro JNZ de las comparaciones que si
una sola falla nos llevara antes al cartel de incorrecto.

Bueno veamos que compara

A EAX moverá el primer byte que apunta EDI que es 02 y a ECX mueve el primer byte de mis restos o
sea 7.

Y si vemos que si el resto del primer byte hubiera sido 02 la comparación seria exitosa.

En mi caso para hallar el resto

39= 5 .0A + 7

Ya que el resultado de 39 dividido 0a daba 5 con resto 7, eso quiere decir que al multiplicar 0a por 5 me
da 32 y al sumarle 7 me da 39 lo cual se ve reflejado en esa formula

39= 5 x 0A + 7

Como el resto correcto debería ser dos para el caso del serial correcto

BYTE CORRECTO= 5 x 0A + 2

BYTE CORRECTO= 32 +2 = 34

O sea 34 que es el numero 4 en ASCII


También podemos ver que si al realizar

BYTE CORRECTO= 5 x 0A + 2

Al realizar 5 x 0A + 2 se pasa de los números posibles de una cifra (de 30 a 39) en ese caso es porque el
resultado de la división no era cinco sino 4 por lo cual disminuimos y intentamos nuevamente con

BYTE CORRECTO= 4 x 0A + RESTO

Bueno ya calculamos nuestro primer byte es 34 o sea 4 en ASCII

Vemos los otros bytes correctos que va a comparar con mis restos.

Con 02 ya calculamos

Sigamos con 08

BYTE CORRECTO= 5 x 0A + 8

BYTE CORRECTO= 32 + 8

En este caso da 40 se pasa del máximo numero decimal que es 39 ( 9 en ASCII) así que disminuyamos a

BYTE CORRECTO= 4 x 0A + 8

BYTE CORRECTO= 28 + 8 = 30 que es 0 en ASCII

Si hacemos la prueba vemos que 30 dividido 0A da 4 con resto 8

Pues ya tenemos el segundo byte correcto que es 30 o sea 0 en ASCII

Si realizamos lo mismo byte a byte

El siguiente es 08, así que se repite lo mismo será 30 o sea 0 en ASCII

El siguiente es 03

BYTE CORRECTO= 5 x 0A + 3

BYTE CORRECTO= 32+ 3= 35 o sea el 5 en ASCII

El siguiente es el 05

BYTE CORRECTO= 5 x 0A + 5

BYTE CORRECTO= 32+ 5= 37 o sea el 7 en ASCII

El siguiente es 5 nuevamente, así que repite el 37 o sea 7 en ASCII


El ultimo es 3 que ya sabíamos era 35 o sea 5 en ASCII

Por lo cual el serial correcto para narvaja seria 4005775 quitando todos los BPM y BPX y dando RUN

Apreto el botón NAME/SERIAL CHECK

Otro adentro jeje

El crackme para practicar por ahora será uno de solo serial hardcoded de a poco iremos aumentando por
supuesto con el serial correcto se activa la parte 17, así que a buscar que este es muy fácil, el crackme es
el MEXCRK1.ZIP y esta adjunto con la lección.

Que tengan suerte así pueden llegar a la parte 17

Ricardo Narvaja
11 de diciembre de 2005
INTRODUCCION AL CRACKING CON OLLYDBG PARTE 17

Bueno antes que nada, vamos a solucionar el crackme MEXCRK1.ZIP pendiente que es muy
sencillo.
Abrámoslo en OLLYDBG y por supuesto para en el Entry Point

Veamos las strings referentes que utiliza el programa, haciendo click derecho

Se ven entre las strings las siguientes

Podemos hacer click en la de correcto o en la de incorrecto, para ver la zona caliente.

Vemos allí la zona caliente, un Call y dentro se decide ya que a la vuelta del mismo hay un JE
que salta a WRONG CODE DUDE o a THANKS YOU MADE IT, o sea que es el salto decisivo.
Pongo un BPX un poco antes del CALL en 42d534, y doy RUN

Allí tipeo mi serial falso, en la parte superior donde dice ENTER SERIAL #

En mi caso tipeo Narvajita.

Si entro traceando dentro del CALL veo que compara mi serial falso Narvajita, con la string
Benadryl.

Bueno ya llegamos a la comparación, así que el serial correcto es la palabra Benadryl si damos
RUN nuevamente quitando todos los BPXs
Allí vemos como nos felicita por haber hallado el serial correcto y felicitaciones porque si
llegaron aquí también lo han sacado ustedes.

Bueno vamos a hacer el ultimo user, name ya que en la próxima parte comenzaremos con un
nuevo tema.

Uno de los lectores de este curso, tuvo problemas con un programita que en realidad es un juego
que se llama canasta 5.0 y que ira adjunto al tutorial.

El me comentaba que se le quemaron los papeles porque siempre, en los tutes vemos casos de
user y name que se ingresan apretando un botón y en este caso, solo hay que tipear y si lo que tipeas es
correcto, el botón OK se habilita pues esta deshabilitado.

Si instalamos el programa y vamos al about

Y si vale 20 dolares amigo, jeje, oferta 19,95.


Vemos el botón ENTER LICENSE

Allí dice que el botón OK se habilitara cuando se coloque la combinación correcta jeje.

Arranquémoslo en OLLYDBG.

Allí vemos el ENTRY POINT

Uff la lista de apis es larguisima y las strings


Hay por ahí algunas pero obviamente el botón OK se debe habilitar y si no, no muestra nada así
que el tema de las strings lo dejamos jeje.

Corramos el OLLYDBG y lleguemos hasta la ventana de registración y veamos cual es uno de


los métodos de ataque este tipo de protección.
Tipeo un nombre, supongo que aceptara cualquier nombre si no veremos mas adelante, ahora
tipearé una LICENSE KEY rara, de 6 letras pongámosle WMYXSZ, apreto la W

Ahora apreto la M

Ya apreté dos letras que pasa si busco en la memoria la string WM

Apreto el botón M para ir a VIEW-MEMORY y busco la string WM


En este caso habilito con la tilde CASE SENSITIVE para que busque exacto WM solo mayúsculas, así
hay menos ocurrencias.

Luego de que para dos o tres veces en palabras que comienzan con WM, y que sigo buscando con
CTRL+L y si termina una sección salgo y sigo buscando mas abajo en la ventana M, llego a esta
ocurrencia que muestra WM en mayúscula y solo, y además abajo esta el texto que muestra de que se
habilitara el botón OK cuando apretemos el serial correcto.

Busquemos esta zona en el dump

Recordemos que a las direcciones que comienzan con letra, como en este caso la C debemos ponerle un
cero delante si no el OLLYDBG no las reconocerá.

Para estar seguros que esta es la zona donde va guardando el serial, escribamos el siguiente carácter del
serial WMYXSZ, o sea tipeo la Y.
Al tipearla, veo en el dump que se agrego y que halle la zona donde va guardando el serial, por lo tanto,
pongamos allí un BREAKPOINT MEMORY ON ACCESS que abarque 6 cifras ya que sabemos que son
6.

Ahora doy RUN

Me aparece la ventana pongo el carácter siguiente que es X.


Ahora si para cuando lo va a guardar a continuación

Allí copiara de ESI a EDI, al apretar F8

Luego para nuevamente cuando copia al stack, los cuatro bytes que entramos hasta ahora.

Lo copiara a 12E79C al apretar F8

Ya que el BREAKPOINT MEMORY ON ACCESS lo tenemos usando, podemos colocar un


HARDWARE BPX ON ACCESS
Si traceo un poco veo que mueve al stack también mi nombre

Antes justo del nombre esta 0E que es el largo del mismo, y lo compara con cero

Como no es cero continua


Luego vienen comparaciones del nombre con personas que están en la lista negra, o sea mejor no ser
TNO, afdad etc jeje.

Al dar RUN nuevamente

Para en una comparación allí, y vemos que compara con el serial

Y podemos probar si es el serial correcto quitando todos los BPM y BPX y HARDWARE BPX

Al colocarlo se habilito el botón y al apretarlo estamos registrados jeje, otra opción que no voy a
detenerme a explicar aquí, pero no es muy difícil, es usar WM_KEYUP cosa de que cada vez que
apretamos una tecla pare OLLYDBG y podamos seguir el valor del byte que tipeamos, aunque
lógicamente es mas engorroso, este método si nos funciona es mucho mas sencillo.

Bueno los dejo descansar un poco, la próxima parte ya veremos un poco mas de teoría, acompañada de
ejemplos para poder ir avanzando mas en conocimientos lo cual derivara en programas mas complejos
resueltos.

Hasta la parte 18
Ricardo Narvaja
15 de diciembre de 2005
INTRODUCCIÓN AL CRACKING CON OLLYDBG PARTE 18

Bueno, en la parte anterior había comentado que iba aquí a empezar otro tema que seria el tema de la
detección del OLLYDBG, por los programas que ejecutamos en el, lo que comúnmente se llama
antidebugging, como evitarlo manualmente, y con los plugins disponibles en cada caso y con ejemplos.

Pero eso con ese tema comenzare en la parte 19, ya que surgió entre varios seguidores del curso que me
escribieron al mail, el pedido de que haga un ejemplo mas de crackme sin botones, como el de la parte
anterior, y si es posible usando la otra técnica la de WM_KEYUP .

Bueno así que usaremos un crackme que me facilito Stzwei, gracias por el mismo, llamado
crackme_4stz.exe y que por supuesto estará adjunto con este tutorial.

Abramos el crackme en OLLYDBG

Allí esta parado en el Entry Point, veamos las strings referentes ya que no esta empacado.

Allí vemos las Strings que usa el programa


Nada interesante por aquí, veamos las apis
Uff muchísimas para mi gusto, bueno corrámoslo para llegar a la ventana donde se ingresa el serial,
apreto F9.

Vemos que no hay botón de registro, así que tipeo un nombre completo

Y pondré un BPX CONDICIONAL LOG en TranslateMessage, primero coloco un BPX común


Y cuando voy a acceder al crackme, para solo en el BP allí lo edito.

Si alguien no se acuerda el valor correspondiente al WM que vamos a usar, pues vamos a la ventana W,
que nos muestra las ventanas del programa.

Y nos aparece la lista de ventanas, en cualquiera, total es solo para averiguar el valor numérico, hacemos
click derecho

Y nos aparece la ventana de los MESSAGE BREAKPOINTS con el menú desplegable de los WM
Buscamos en la lista WM_KEYUP

Vemos que es 101, así que cancelamos todo esto que fue solo para averiguar ese valor numérico y
volvemos al BREAKPOINT CONDICIONAL LOG en TranslateMessage.
Y allí coloco MSG==101 (recordar el doble signo igual), también podía haber escrito allí si no encuentro
el valor, MSG==WM_KEYUP y funcionara, pero a mi me gusta mas usar valores numéricos, cada uno
puede hacer como quiera en ese punto.

Bueno allí quedo nuestro BPX transformado en CONDICIONAL LOG (color rosa)

Demos RUN y tecleo la primera letra de mi serial falso

Y allí se detiene el OLLYDBG en el BPX CONDICIONAL.

Vemos allí los parámetros de la api, en 12ff78 hay una estructura que guarda los valores del la tecla que
aprete en este caso 39, que corresponde al numero 9.

Veamos en el DUMP dicha posición de memoria, haciendo click derecho en dicha dirección y eligiendo
FOLLOW IN DUMP.
Vemos que conseguimos parar y identificar cuando ingresa el byte el problema es que es un programa en
DELPHI lo cual veremos mas adelante y si pongo un BPM ON ACCESS en ese byte, dará mil vueltas
antes de llegar a la comparación, por lo cual, el método que vimos la vez anterior se aplica mucho mejor
aquí y antes de enloquecer pues lo usaremos, de cualquier forma ya saben como parar el programa cuando
ingresa por teclado, y como localizar el byte, seguramente en otro crackme que no sea en DELPHI, se
podrá seguir mas fácilmente con un BPM ON ACCESS en el mismo, hasta la comparación.

Y doy RUN

Tipeo 9898, iré a la ventana M y buscare en toda la memoria

Hago click derecho- SEARCH


Y busco la string 9898

La primera ocurrencia es en el stack apreto CTRL + L varias veces a ver cuantas aparece en el mismo.

Una zona vez ya que nos aparece en amarillo la palabra ITEM NOT FOUND debajo, salgamos de esta
sección y volvamos a la ventana M

Llego hasta aquí buscando, así que sigamos para abajo con CTRL + L

Allí aparece por primera vez en esta sección hagamos CTRL + L para ver si aparece de nuevo

No, no aparece de nuevo si miro en la zona donde esta la ocurrencia


Veo un posible serial 418507, igual le pongo un BPM on ACCESS al lugar de la ocurrencia a ver si es
este el que comparara.

Doy RUN

Para alli y vemos que copiara mi nombre

Lo que vemos que cada vez que tipeo va copiando de nuevo mas abajo mi serial falso y cada vez lo va
machacando con mi nombre, y con el carácter siguiente vuelve a copiar el serial bueno mas abajo y asi
hasta que tipeo los 6 caracteres del serial falso y ahí si cuando están los 6 caracteres a la vista poniendo un
BPM en ellos.

Para justo en la comparación


Allí vemos que ESI y EDI apuntan al serial falso y al verdadero

Los cuales son comparados de a 4 bytes en ese loop, probemos si el serial hallado es el correcto

Vemos que a pesar de todo es un crackme difícil ya que es un momento justo, que hay que agarrarlo ya
que va variando la posición del serial falso y hay que agarrarlo con el BPM justo cuando recién lo escribe
en su nueva posición, para poder parar en la comparación.

Otra posibilidad es la siguiente veo que con 4 bytes aparece esto


Con 5 Bytes escribe justo abajo

Pues voy poniendo BPM ON WRITE en la zona justo abajo, donde va a escribir cuando ingrese el
próximo carácter

Seguro cuando ingrese el próximo carácter, lo escribirá aquí, así que doy RUN
Allí escribio primero el posible serial bueno

Damos RUN

Y luego para cuando copia el serial falso, ahora si que paro apenas se copio, puedo ponerle un BPM on
ACCESS al serial falso y al dar RUN para justo en la comparación, nuevamente.

Bueno creo que este fue un caso difícil para cualquier método por lo movedizo de la zona donde guarda el
serial.

Bueno les dejare un ejercicio, este será hallar el serial del CRACKME DE CRUEHEAD 2, esto será el fin
del primer capitulo de la INTRODUCCIÓN a partir de la parte 19 empezaremos con nuevos temas, y el
resolver este sencillo crackme será como la graduación del primer capitulo, recuerden que para abrir el rar
de la parte 19 necesitaran del serial verdadero del crackme de cruehead 2 es bien sencillo.

Hasta la parte 19
Ricardo Narvaja
19 de diciembre de 2005
INTRODUCCION AL CRACKING EN OLLYDBG parte 19

DETECCION DEL OLLYDBG – IsDebuggerPresent

Como dijimos la parte anterior, nos concentraremos en la forma de evitar manualmente y por
medio de plugins la detección de OLLYDBG por medio del programa que esta siendo debuggeado, de
forma tal de poder trabajarlo tranquilamente ya que la mayoría de los programas, cuando detectan que hay
un debugger trabajando sobre ellos, se cierran o comienzan a funcionar en forma diferente por lo cual
hay que lograr evitar por todos los medios la detección de OLLYDBG por parte del programa victima.

Esta primera parte tratara sobre la detección por medio de la api IsDebuggerPresent, la cual es la
mas comun de todas.

Para ello utilizaremos el Crackme1.exe que esta adjunto a esta leccion, lo arrancamos en
OLLYDBG.

Recordemos que mi OLLYDBG por ahora solo tiene el plugin COMMAND BAR, por lo cual,
no tiene cargado ningún plugin que pueda evitar la detección por medio de la api IsDebuggerPresent, pero
como funciona dicha detección?

Si corremos el crackme con F9 vemos que no solo no abre la ventana del crackme si no que se
cierra el programa.

OLLYDBG nos indica en la parte inferior que el programa termino, y ni siquiera vimos la
ventana del crackme, jeje, que ocurre aquí, muy sencillo el crackme utiliza el método mas conocido para
detectar que esta siendo debuggeado que es llamar a la api IsDebuggerPresent.

Reiniciemos el crackme y veamos si la susodicha esta en la lista de las apis que utiliza la victima,
haciendo click derecho en el listado y eligiendo ..
Vemos la lista de apis usadas

Y si parece que la usa jeje

Pongamos un BP en dicha api a ver si para el programa cuando la utilice.

Damos Run y para en la api


Vemos en el stack que es una api sin parámetros, lo único que consulta es si el programa esta
siendo debuggeado o no, para los que tienen dudas con alguna api y su funcionamiento, lo mejor es
consultar el archivo WINAPIS32 que esta en mi http en herramientas.

http://www.ricnar456.dyndns.org

user:hola
pass:hola

y allí en la carpeta HERRAMIENTAS/V-W-X-Y-Z esta el archivo que contiene la


especificación de las apis mas importante publicada por Microsoft, no están todas pero si la gran mayoría,
el único problema es que esta en ingles, y es un poquito complicado de entender para el que no esta
acostumbrado, pero a partir de ahora, para irnos acostumbrando, veremos las definiciones de las apis allí.

http://www.ricnar456.dyndns.org/HERRAMIENTAS/V-W-X-Y-Z/winapi32%20NEW.rar

user:hola
pass:hola

El archivo zip, contiene un archivo de extensión HLP que es el que nos interesa lo ejecutamos.

Allí se abrió, ahora como buscamos la api que nos interesa?


Vamos a INDICE

Allí en la barra a medida que vamos tipeando el nombre de la api, va buscando las que coinciden
con la letra que tipeamos

Bueno allí la hallamos hacemos doble click en IsDebuggerPresent


Bueno allí esta la aclaración y traducimos

La api IsDebuggerPresent indica cuando el proceso que la llamo, esta bajo el contexto de un
debugger o sea siendo debuggeado.

Luego dice que esta api o función es exportada por la KERNEL32.dll, que no tiene parámetros
como vimos, y en RETURN VALUES o sea en valores de retorno, dice que si el programa esta siendo
debuggeado el retorno es un valor distinto de cero, y si no lo esta es cero.

Bueno esa información es muy importante, ejecutemos la api hasta el RET a ver donde devuelve
la información.

Allí llegue al RET si veo los registros


El que esta en rojo o sea que cambio es EAX, como casi todas las apis, devuelven en EAX el
valor de retorno, así que EAX es igual a 1 lo cual le dice al programa que esta siendo debuggeado.

Probemos que ocurre si lo cambiamos a mano y ponemos EAX=0 o sea que no esta siendo
debuggeado.

Demos RUN ahora

Vemos que vuelve a parar en la api, así que llegamos al ret nuevamente y cambiamos EAX a
cero.

Vemos que el programa arranca, o sea que toda su detección se basa en dicha api, reiniciémoslo
y cuando pare en IsDebuggerPresent, veamos que hace con el valor que le devuelve la api.
Allí paro nuevamente lleguemos hasta el ret, podemos tracear con f8 pues la api es cortita.

Allí esta, al llegar al RET, vale EAX=1, volvamos al programa con f8 nuevamente.

Vemos que la primera vez no es llamado desde el mismo ejecutable si no de una dll que es
uxtheme, demos RUN a ver la segunda vez que para en la api.

Ahí paro la segunda vez, llego hasta el RET, y vuelvo al programa traceando con f8.

Llega aquí, y allí hay un JE que testea si EAX se cero o no, veamos.
Vemos que el JE al ser EAX diferente de cero no salta, observamos también que si saltara
continua la ejecución del programa con GetDlgItem leyendo de la ventana del crackme.

Como no salta continua al JMP, el cual no es evitado, y aquí si se puede aplicar bien la palabra el
crackme me tiro fuera, vemos que el JMP nos lleva bien lejos, posiblemente a cerrar el programa.

Continuemos traceando a ver donde va

Vemos que va a la api PostQuitMessage miremos en el winapis32


Traducción esta api pasa un mensaje para cerrar la ventana, jeje o sea esta api postea un mensaje
WM_QUIT o sea es una indicación de que esta cerrando cosas, haciendo las valijas y se ira.

Al volver del mismo

Y si tenemos paciencia de tracear bastante mientras va cerrando todo, observaremos que llegara
a la api ExitProcess que es la que cierra el proceso.(si no tienen paciencia le ponen un BP ExitProcess y
parara en ella)

Así que ya vimos que el salto que esta al volver de la api IsDebuggerPresent es el que toma la
decisión de si corre o se cierra, una solución podría ser parchearlo, reiniciemos el programa y lleguemos
al salto decisivo.

Allí esta y como habíamos visto tenia que saltar siempre, por lo cual lo cambiamos a JMP,
tecleando la barra espaciadora y escribiendo JMP 4011b2.
Allí esta, vemos que ahora evita el JMP que va a cerrar el programa y el mismo continua
funcionando.

Guardemos los cambios en un archivo con otro nombre, hagamos click derecho

Y en la nueva ventana que se abre hagamos nuevamente click derecho


Lo guardo con el nombre crackme1p, así tengo los dos el original y el parcheado.

Ahora abramos el parcheado en OLLYDBG para ver si corre en el mismo, sin poner ningún BP
ni nada

Corre perfectamente, así que ya sabemos hacer correr un programa cambiando EAX al volver de
IsDebuggerPresent, también sabemos parchear para que corra y no tengamos que tomarnos el trabajo de
hacerlo a mano.

Con este crackme no tendremos problema, para parchearlo y que corra, aunque por supuesto hay
métodos mas sencillos usando plugins que nos evitan realizar todo este trabajo, pero es bueno conocer
como funcionan las cosas.

Ahora la pregunta que alguien se podría hacer es la siguiente volvamos al original y miremos la
api.

Son tres tristes MOV y con eso la api determina si esta siendo debuggeado el programa o no.
Lo primero que se me viene a la cabeza es, porque el programa no podría ejecutar estas tres
líneas mezcladas entre su código, las cuales le devolverían en EAX el valor 1 si esta siendo debuggeado,
probemos reiniciemos el crackme original y en el entry point escribamos.

MOV EAX,DWORD PTR FS:[18]


MOV EAX,DWORD PTR DS:[EAX+30]
MOVZX EAX,BYTE PTR DS:[EAX+2]

Podemos copiar y pegar cada línea de aquí.

Allí tenemos las tres líneas escritas.

Vemos que cuando paso la ultima instrucción, EAX se puso a 1 en la misma forma que lo hace
en la api.

Y obviamente nunca el programa parara en la api IsDebuggerPresent, pues nunca fue llamada, e
igual detecto que esta siendo debuggeado.
Por ello es muy importante determinar que es lo que lee la api o mejor dicho esas tres líneas
famosas.

En concreto cuando un programa arranca el sistema guarda en una dirección de memoria


determinada un uno si detecta que el programa esta siendo debuggeado y un cero si no lo esta, ese byte es
el que leen las tres líneas estas y por supuesto la api también.

Como podemos localizarlo al byte?, pues vayamos nuevamente a la primera línea de estas tres y
miremos paso a paso lo que hace.

La primera línea es

Pues aquí explicaremos lo más sencillo posible algo de teoría, en el OLLYDBG vemos aquí

En la ventana de los registros un valor muy importante, no quiero dar nombres difíciles pero ese
valor apunta a una estructura que guarda información muy importante sobre el programa que arranco,
vayamos a ver en el DUMP dicha dirección (en su maquina puede estar en otra dirección solo vayan a la
dirección que les indica olly allí)

Esta estructura se llama TEB O TIB y guarda buena información que si consultamos nos puede
ayudar muchísimo con el programa, en la TIB podemos ver por ejemplo donde comienza y donde termina
el stack del programa.
Si vemos en M la sección del stack

Vemos que comienza en 12d000 y termina justo antes de donde se inicia la sección siguiente en
130000.

Hay muchos otros valores interesantes como el primero, que veremos mas detalladamente
cuando estudiemos las excepciones, pero como adelanto si miramos en el stack ese valor 12ffE0 en mi
maquina.

Lo busco en el stack

Vemos que esta marcado como END OF SEH CHAIN, por ahora no diremos mas de el, pero si
que esta relacionado con las excepciones.

Una cosa interesante de este TIB es que existe una nomenclatura para acceder al cualquier valor
del mismo, por ejemplo este valor que marque antes seria Fs: [0] .
Ese seria Fs: [0], si en la command bar buscamos el valor de fs: [1], ese seria

Por lo tanto:

Fs: [0] en si es el contenido en mi maquina de 7ffdf000


Fs: [1] en si es el contenido en mi maquina de 7ffdf001
…………………………………………………………………….
…………………………………………………………………….
Fs: [18] en si es el contenido en mi maquina de 7ffdf018

Pues ese es el valor que lee en la primera línea la api, si recordamos

O sea veamos el contenido de 7ffdf018 o sea FS:[18]

Es ese valor, o sea que el valor que guarda el TIB en FS : [18] es el valor que OLLYDBG nos
mostraba en los registros el puntero al inicio del TIB, que lo almacena allí.
O sea que en la primera línea, solo muevea EAX el puntero al inicio del TIB, para enterarse
donde esta ubicado en tu maquina, y eso esta en fs: [18] por lo tanto si ejecuto la línea con f8, moverá ese
valor a EAX.

Bueno ahora en EAX ya tenemos el inicio del TIB

Ahora en la siguiente linea

A EAX le suma 30 o sea seria en mi maquina 7ffdf000 + 30 =7ffdf030

El contenido de dicho valor es fs:[30]

O sea mueve a EAX el contenido de 7ffdf030 o fs:[30], dicho contenido en mi maquina es


7ffdc000 no confundir con el inicio del TIB no es el mismo valor.
Pues este es un puntero a otra cosa, vayamos a esa dirección en el dump

Allí la vemos la siguiente y ultima línea

Le suma 2 a EAX o sea

7FFDC000 + 2= 7FFDC002

Y mueve el byte que contiene esa dirección a EAX y dicho byte es el byte buscado,y ya lo
hallamos manualmente es en mi maquina el que esta en la dirección 7FFDC002 (en su maquina puede
cambiar la dirección realizar el mismo proceso para hallarlo)

Allí el sistema guardo el byte 1 que lee la api, inclusive en su misma maquina puede variar de
posición al reiniciar, pero siempre lo pueden hallar rápidamente con este método, reiniciemos el crackme.

Esta vez no escribimos nada a ver si localizamos el byte a mano y si lo ponemos a cero a mano,
y veremos si el programa corre, pues la api leerá dicho byte y si esta a cero, pues devolverá cero, jeje.

1)BUSCAR EL INICIO DEL TIB en la ventana de los registros del OLLYDBG


Ver el TIB en el dump (ya no esta en la misma posición que arranco la vez anterior)

Busco fs: [30] o sea le sumo 30 al inicio del TIB y hallo su contenido

El contenido es 7ffde000 ese lo busco en el dump

Y le sumo 2 y allí esta el byte (muchos dirán para que tamaña explicación si los programas
cuando arrancan en EBX, esta siempre el puntero a esta zona, jeje o sea EBX= fs:[30], jeje)
Bueno pero es bueno saber el método entero, porque por ahí uno no esta al inicio del programa y
quiere hallar el byte a mano y no sabe que valor tenia EBX en el arranque, pero bueno este es el método
completo, ahora pongamos a cero el byte.

Bueno pongamos un BP IsDebuggerPresent a ver si funciona

Traceemos hasta el RET


Y vemos que EAX que es el valor de retorno de la api vale cero o sea que al cambiar el bytea
mano, el programa cree que no esta siendo debuggeado tanto por el uso de la api o por la lectura del byte
sin la api.

Y por supuesto corre perfectamente.

Obviamente hay muchos plugins que hacen este trabajo, uno de ellos es el plugin HideDebbuger
1.23f que pueden descargar desde mi http aquí

http://www.ricnar456.dyndns.org/HERRAMIENTAS/L-M-N-%D1-O-
P/Plugins_Olly/HideDebugger123f.zip

Una vez descargado copian la dll en la carpeta de plugins

COPIANDO jeje

Allí esta debajo del otro

Ahora reinicio el OLLYDBG


Veo que en las opciones del plugin

Viene ya marcado para evitar que detecte por el byte de IsDebuggerPresent o sea hace el trabajo
que nosotros hicimos a mano lo pone a cero siempre, apretamos SAVE y las otras opciones por ahora las
dejamos deshabilitadas, a medida que las vayamos estudiando, las veremos.

Arranco de nuevo el crackme y me fijo ya que EBX apunta a la zona del byte

Hago EBX-FOLLOW IN DUMP


Y vemos que el plugin hizo todo, lo puso a cero acabando con este tipo de protección, quizás
hubiera sido mas sencillo hacer esto solo, pero creo que comprender el porque de las cosas es muy
importante por eso la explicación completa creo que viene bien.

Hasta la parte 20.


Ricardo Narvaja
21 de diciembre de 2005
INTRODUCCION AL CRACKING CON OLLYDBG PARTE 20

El siguiente truco ANTIOLLYDBG que veremos en esta oportunidad es la detección del mismo, por el
nombre del proceso del OLLYDBG, pero antes de todo les diré una configuración del OLLYDBG que
aun no hemos tocado y que es muy importante en este caso.

Si vamos a DEBUGGING OPTIONS-SECURITY

Allí lo mejor es poner las tres tildes y que cargue siempre la información, verán que con las tres tildes
puestas cuando pongan BPX en una api y reinicien el OLLYDBG, el BPX continuara puesto, lo cual evita
tener que repetir el proceso de ponerlos uno a uno cada vez que reiniciamos.
Estrictamente no conozco el funcionamiento interno completo del OLLYDBG pero en la practica lo que
sucede es eso con las tres tildes, los BPX en las apis se mantienen luego de reiniciarlo.

Así esta mejor para mi gusto, es menos molesto, ahora si, comenzamos con el tema de antidebugging por
el nombre del proceso.

Deteccion del OLLYDBG por el nombre del proceso

Cuando corremos el OLLYDBG si miramos la lista de procesos con CTRL + ALT + SUPR

Vemos que el nombre del proceso esta allí muy claro en la lista de los mismos, que le impide a un
programa revisar todos los procesos y si encuentra alguno que se llame OLLYDBG, cerrarlo, pues nada,
jeje.

Usaremos un crackme que no resolveremos por ahora porque es un nivel levemente superior al actual, así
que lo veremos mas adelante, pero estudiaremos en el la técnica de cómo detectan los programas a
OLLYDBG por el nombre del proceso, como evitarlo manualmente y como evitarlo definitivamente jeje.
El crackme que adjunto es el DAXXOR el cual si dejamos un OLLYDBG corriendo vacío y corremos
fuera de OLLY el famoso DAXXOR, veremos que el crackme corre pero cierra el OLLYDBG, lo mismo
que si lo corremos en OLLYDBG, también lo cierra y por supuesto se acaba todo.

Estudiemos como hace esto, abrámoslo en OLLYDBG.

Allí esta en el ENTRY POINT, y veamos las apis que utiliza.

Bueno hay unas cuantas, pero aquí hay otra protección agregada y es que el crackme no tiene cargadas en
el inicio las apis que usara para detectar al OLLYDBG, y las cargara a medida que corra, de paso
explicaremos también este método de protección que en si, no te permite ver todas las apis que usara, en
la lista de NAMES, pero por otra lado tiene como contrapartida que el que se da cuenta del truco y
descubre las apis que va cargando el programa a medida que corre, sabrá a ciencia cierta que esas apis son
las IMPORTANTES, pues por algo el programa las oculta para que no aparezcan en la lista.

Esto casi siempre es evidente cuando un programa que no esta empacado como en este caso, hace uso de
la api GetProcAddress
GetProcAddress se utiliza, para que el programa cargue nuevas apis, que no están en la lista para poder
usarlas, ya veremos un uso intensivo y mas detallado de esta api en el capitulo de desempacado, pero por
ahora pongamos un BP en dicha api.

Y demos RUN

Cada vez que para vemos que esta pidiendo por medio de la api GetProcAddress, la dirección en nuestra
maquina de una determinada api la primera que pide es en este caso, __CPPdebugHook que no pertenece
al truco que estamos estudiando por lo cual damos RUN nuevamente.

Así vamos pasando con F9 hasta que encontremos apis relacionadas con el truco, aquí vemos la api
EnumProcesses que es usada, así que lo que hacemos es llegar hasta el RET de GetProcAddress la cual
nos devuelve en EAX la dirección de la api solicitada en nuestra maquina y allí le ponemos un BPX,
veamos, lleguemos al RET con EXECUTE TILL RETURN.

Allí en EAX devuelve la dirección en mi maquina de la api solicitada, en mi caso es 76BB3A9A en sus
maquinas puede variar.
Por otro lado veo que OLLYDBG no identifica la api que no esta en la lista de NAMES, por lo cual no se
puede poner BP directos al nombre de la api, si no que hay que poner el BP en la dirección.

Ahora si lo toma

Ya tenemos puesto el BP en la api sospechosa, sigamos corriendo OLLYDBG, para ver si carga mas apis.

Hmm enumera los módulos de un proceso, hmm repito el procedimiento anterior llego al RET y le pongo
un BPX a la dirección que me muestra EAX.

Para no tipear mucho si estoy en el RET directamente pongo

Que me servirá para colocarle BPX a todas las apis cuando este en el RET .

Otra sospechosa le pongo BP de la misma forma que a las anteriores, y doy RUN y para en
EnumProcesses

El comentario a la derecha con el nombre de la api se lo agregue yo, haciendo doble click en esa zona nos
permite agregar un comentario.
Esto lo realizo en todas las apis que el programa va cargando y veo sospechosas cuando le pongo un
BPX cosa de que cuando pare, sepa que api era, pues el OLLYDBG no me aclarara nada al no ser una api
de las de la lista.

Si busco en el WINAPIS32 esta api no figura, por lo tanto busco en GOOGLE

Y en la pagina de Microsoft normalmente se encuentran, es este caso la pagina es

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/enumprocesses.asp
Bueno aquí dice que la susodicha api, nos devolverá el PROCESS IDENTIFIER o PID de cada proceso
que esta corriendo, pues bien veamos antes que es el PID ese, jeje.

Cada proceso que corre esta identificado con un número que varia cada vez que se arranca un proceso, si
vemos en la lista de procesos

Vemos que el OLLYDBG en este caso tiene un PID de 724 decimal ya que esta utilidad trabaja con
números decimales, pero bueno si queremos saber el PID del OLLYDBG en hexa con la calculadora de
Windows.

Apreto el boton hex para pasar a HEXA

2D4 será el PID del OLLYDBG, pueden verificar que si lo cierran al OLLYDBG y lo vuelven a abrir el
PID variara, pues cada proceso al reiniciarse recibirá otro PID.

Tampoco tendremos la suerte en este caso de que OLLYDBG nos muestre los parámetros de la api pues
para OLLYDBG no existe la misma.
Sabemos por la pagina de Microsoft que los tres parámetros son estos

O sea que en 12eDe4 guardara la lista de PIDs de todos los procesos que corren en mi maquina, hagamos
execute till return para llegar al ret de la api y ver en el dump si los guarda alli.

Ahí esta la lista de PIDs y esta el de mi OLLYDBG snif, snif

Pongo un BPM ON ACCESS allí para ver cuando lo usa, veamos

Ahora si doy RUN


Vemos que para allí y va a usar la api OpenProcess que verifica si un proceso esta corriendo, y si esta
corriendo te devuelve su handle o manejador.

Que diferencia hay entre el PID y el handle, muy sencillo, el PID es un identificador genérico, en toda tu
maquina, en cualquier proceso el PID del OLLYDBG será el mismo mientras no se reinicie, en mi caso
será 2d4, ahora el handle, como su nombre lo indica es un manejador, o sea que es un numero que te
devuelve el sistema para que tu programa pueda manejar ese proceso, y el numero puede variar para cada
programa, es como una solicitud para controlarlo, si no la pedís no tendrás el numerito y no lo podrás
controlar, si lo pedís el sistema te devolverá el manejador y lo podrás manejar y hacerle guarradas jeje.

Veamos mas detalladamente la definición de OpenProcess en el WinApis32, la misma tiene muchos


parámetros pero lo que nos interesa es esto.

O sea devolverá el manejador del proceso que esta corriendo, en resumidas cuentas es lo que el programa
quiere saber en este caso.

Traceemos con f8 hasta pasar la api

Y en EAX devuelve el handle o manejador del OLLYDBG que en mi caso es 58.

El mismo OLLYDBG nos muestra los HANDLES con los cuales esta trabajando el programa en la
ventana H.

Vemos que allí aparece el 58 y el TYPE o tipo es PROCESS o PROCESO, así que el programa maneja el
handle 58 que pertenece a un proceso en este caso al OLLYDBG.
Si otro proceso usara EnumProcess para hallar el PID en este momento seria el mismo 2d4 mientras no se
termine el proceso OLLYDBG, ahora si pide al sistema un handle o manejador para dicho proceso, será
cualquier otro numero pues, los handles son particulares de cada proceso.

En este caso el peligro para nuestro OLLYDBG es que el programa ya tiene un manejador, con ello puede
hacer lo que quiere, lo que si aun no sabe que pertenece a OLLYDBG solo que es un proceso y que esta
corriendo, ahora debe verificar el nombre del mismo para determinar si este proceso es OLLYDBG,
obviamente esto lo realiza con cada PID que obtiene de la lista de procesos, nosotros salteamos todos y
llegamos hasta cuando trabaja con el OLLYDBG al haber puesto un BPM ON ACCESS en su PID.

Continuemos traceando con f8

Vemos que allí llega a la otra api que nos quiso ocultar en este caso EnumProcessModules, en la misma
pagina de MICROSOFT vemos el detalle de esta api.

O sea que ahora va a buscar de este proceso que esta investigando, la lista de handles de los módulos que
usa, lleguemos con f7 hasta la api.

En el stack vemos los parámetros


Según nuestro amigo HILL los handles de cada modulo se guardaran allí, vemos justo arriba el 58
perteneciente al handle del proceso OLLYDBG que es el parámetro superior.

Aquí hay una cosita que aclarar, cuando pedimos handle de los módulos el sistema nos devuelve la
dirección base o donde comienza dicho proceso en la memoria, en este caso nos devuelve 400000 ya que
el proceso OLLYDBG comienza allí.

Ahora continúo traceando y veo que llega a la tercera api ocultada

GetModuleBaseNameA

O sea que con esto quiere hallar el nombre del modulo, ya que esta api, en el parámetro lpBaseName,
abre un buffer para guardar el nombre del modulo que corresponde a esa base que averiguo antes, veamos
lleguemos hasta la api.
En el stack los parámetros son:

El 58 que es el handle del OLLYDBG, el 400000 que es la base del modulo principal, y el buffer estará
guardado en 12ECE0, asi que veamos esa zona en el dump.

Jeje ya tiene ahora que llega hasta el RET el nombre del proceso y realiza esto con cada uno de los
procesos que corren en tu maquina, pues ahora comparara el nombre a ver si es OLLYDBG.exe si en este
caso hubiera sido OPERA.EXE por ejemplo, pues lo dejara tranquilo seguramente jeje.

Ahora llega a CloseHandle donde cierra el manejador o sea que el 58 desaparecerá de la lista de handles.

Pues si, por ahora no podrá hacerle trastadas pues no tiene el handle abierto, pero no nos confiemos
sigamos adelante.
Vemos que llega a un CALL entremos a el con F7

Allí lee la primera letra de OLLYDBG (4F) y la pone en el stack con PUSH y entra a otro CALL
entremos también.

Vemos que en este call no realiza nada demasiado importante salimos y llegamos al segundo.

Entramos en el
Ahh acá si esta comparando el nombre del proceso que obtuvo, con el nombre OLLYDBG.exe y si son
iguales ir a a kaput, jeje en este caso eran iguales veremos que hace, lleguemos al RET

Allí si no son iguales, EAX será diferente de cero y saltara y no pasara nada pero si EAX es igual a cero
como en nuestro caso.

No salta y va a OpenProcess a hallar un handle nuevamente para matarlo.


Si ejecuto con f8

Le volvió a asignar el sistema el numero 58, así que sigamos

Como vemos llega a la api TerminateProcess auxilio esta por morir mi OLLYDBG a la cual le pasa el
handle 58.

Y al apretar f8, adiós OLLYDBG se cerro todo, con eso investigamos como funciona la detección por
nombre.

Bueno ya me canse lo haremos un poco a lo maton jeje, reinicio el OLLYDBG y pongo un BP en


OpenProcess
Allí para, si modifico la api para que siempre devuelva cero, el programa pensara que no hay procesos
corriendo y no tendrá el handle de ninguno para cerrar, podemos cambiar las ultimas líneas de la api.

Con eso, la api siempre devolverá cero quitemos todos los Bps, y debemos ya que el programa genera
muchas excepciones y aun no hemos visto el tema excepciones, para que corra poner las tildes en
DEBUGGING OPTIONS- EXCEPTION de esta forma.

Por ahora coloquen las tildes de esta forma para que el programa salte solo las excepciones ya que son
muchísimas y vivirán haciendo SHIFT +f9 para pasarlas, de esta forma las que están tildadas las pasara
automático el OLLYDBG sin parar, demos RUN.

Y si así corre perfectamente, pero también podemos hacer lo siguiente:


Cambiemos el JNZ por JMP, así evitamos la protección

El programa arranca y muestra la ventana veamos que pasa cuando apreto TRY

Sale el cartel de error perfectamente eso quiere decir que la protección ANTIDEBUGGER ha sido
vencida.

De cualquier manera esto no es lo que se hace habitualmente para vencer esta protección, simplemente
copiando el ejecutable OLLYDBG.exe a otra carpeta y cambiándole el nombre por ejemplo a
PIRULO.exe y volviéndolo a su carpeta original, de forma que queden ambos el OLLYDBG.exe original
y el PIRULO.exe y usando este ultimo, el programa al comparar nunca encontrara el nombre de ningún
proceso llamado OLLYDBG, ya que ahora se llamara proceso PIRULO y con eso es vencida esta
protección completamente, de cualquier forma creo que es bueno que sepan como funciona por eso la
explicación.

Es importante recordar que aunque usemos un OLLYDBG renombrado, debemos dejar el original en la
misma carpeta si no habrá problemas con los plugins.

Hay una parte que el programa posiblemente acceda cuando colocamos un serial bueno, que llama a
nuevas apis para una detección diferente, dicha detección la veremos en próximas partes detalladamente.
Hasta la próxima parte 21
Ricardo Narvaja
24 de diciembre de 2005
FELIZ NAVIDAD

También podría gustarte