Tutorial de Cheat Engine para Juegos
Tutorial de Cheat Engine para Juegos
Hola a todos, os traigo un completo tutorial para que aprendáis a utilizar Cheat
Engine (a partir de ahora CE). Algunos quizás conozcan ésta herramienta para hacer
trampas en algunos juegos, lo que a lo mejor no sabían es que es una herramienta
MUY completa, con un debbuger genial, comparador de estructuras e inyección de
código.
Para enseñar como funciona CE, he programado una especia de "video juego" en
VB6. Lo he programado especialmente para éste tutorial, así que no esperéis que sea
un juego divertido, jajaja.
El juego es muy sencillo y he añadido las típicas características que podéis encontrar
en el 90% de los juegos actuales: Tiempo, Vida o Magia, Objetos en un inventario,
etc...
Nuestro objetivo será aprender a usar CE de forma básica para modificar la memoria
de un proceso. Cuando tengáis algo de soltura, os enseñaré a inyectar código en un
juego para conseguir mejores "trucos". Os iré enseñando paso por paso con capturas
de pantalla lo que debéis hacer.
2. Ahora aparece una ventanita mostrando los procesos en ejecución, por norma
general, los procesos abiertos en último lugar a parecen al final del listado. Buscamos
el nombre del juego y hacemos doble-click (OPEN)
3. Ahora ya tenemos el proceso abierto, volvemos al juego y empezaremos a "trucar".
Nos vamos a centrar en el tiempo. Abajo tienes un botón para poder pausar el juego,
esto facilita un poco las cosas. Pulsamos pausa y miramos que valor tenemos en el
tiempo, en mi caso lo he pausado en 81
4. Vamos a la ventana del CE, en la parte central hay 3 recuadros, son los más
importantes y ahí especificaremos la búsqueda que queremos realizar. Empezaremos
poniendo:
Value: 81
Scan Type: Exact Value
Value Type: All
En "Value Type" ponemos "All". Normalmente el 90% de los juegos usan variables
de tipo 4-byte, es lo más común, pero en mi juego de ejemplo, las variables son de 2-
byte. Por eso, si tienes dudas y no sabes que valor tiene una variable, lo mejor es
poner All y CE buscará todas las posibilidades.
1. Quita la pausa en el juego y deja que el valor siga decreciendo, en mi caso dejo que
llegue hasta 79 y pulso de nuevo pausa para dejarlo ahí quieto.
Value: Quitamos el 81 y ponemos 79 (en tu caso por el valor que salga en tu pantalla)
Scan Type: Exact Value (Al ser un número conocido, ponemos un valor exacto)
Value type: All
Y ahora pulsamos el segundo botón que pone: NEXT SCAN. Ojo y no pulses NEW
SCAN, ya que borrarías las anteriores 438 direcciones encontradas y tendrías que
empezar de nuevo:
En mi caso CE ha devuelto solo 2 direcciones encontradas
60EAFC:1
60EAFC:2
=========================================
Bueno, hasta aquí la primera lección, es lo más fácil y sencillo de CE, supongo que la
mayoría ya domináis éste tipo de función. Si veo que el hilo ha tenido buena
aceptación me animaré a hacer las siguientes partes:
1. Uso básico de CE
1.1 Buscar una variable y modificar el valor/frezee
1.2 Buscar una variable de valor desconocido
1.3 Buscar una variable de valor desconocido (difícil)
2. Inyección de código
3. Creación de un trainer
4. Comparar estructuras
Por el momento hemos llegado al 1.1 Prueba de realizar este sencillo tutorial y
comenta en el hilo como te ha ido, si tienes problemas o dudas. Para los más
animados, os podéis avanzar e intentar trucar vuestra salud/vida, haciendo que la barra
roja no decrezca. Os dejo una pista: Trabajar con Unknow initial value y usar los
tipos Decreased value o Increased. Si no os sale no pasa nada, ya que lo explicaré en
la próxima lección
Parte 2
Bueno, aquí os presento la parte 2 del tutorial
Pulsa el botón Usar poción HP y en CE cambia el tipo por Increased Value, ésto
buscará las direcciones que hayan aumentado, reduciendo mucho la búsqueda. Puedes ir
jugando con el botón de recibir daño o usar poción y usar búsquedas en Increased o
Decreased.
Si lo haces bien, encontrarás unas 3 o 4 direcciones, cuando tienes poquitas direcciones
puedes probar a modificar una de ellas y ver si realmente has acertado. En el caso de
éste juego, la variable de "vida" es un valor comprendido entre 0 y 1000, así que en el
caso de la foto es el valor 584 (001D1026), los otros valores son variables internas que
utiliza el control gráfico de la barra roja. Hacemos doble click en la dirección para
mandarla abajo, cambiamos la descripción para poder identificarla sin problema y
cambiamos su valor a 1000 haciendo doble click en value, volvemos al juego y
pulsamos a recibir daño para comprobar si funciona.
Como verás, la vida vuelve a 1000 y sigue decreciendo. Si quisieras "trucar" la vida
puedes marcar la casilla como ya vimos en el tutorial n1 con el tiempo, haz la prueba,
marca la casilla para hacer freeze a la variable y vuelve a desmarcarla.
Ahora te enseñaré a usar el Debugger para trabajar con una dirección encontrada.
Hacemos click derecho en la variable y pulsamos "Find out what writes to this
address"
Aparecerá un mensaje de advertencia, básicamente nos avisa que el debugger de CE se
acoplará al proceso, pulsamos YES y aparecerá la ventana del debugger
A simple vista el debugger parece simple e inútil, pero no lo subestimes, es MUY
memory
Vamos a investigar que nos ha devuelto CE, os copio el resultado de mi debugger:
EAX=72A101F2
EBX=72A1A274
ECX=001D1026
EDX=00000209
ESI=004144E8
EDI=001D0FF0
ESP=0012F3C4
EBP=0012F49C
EIP=72A35F55
mov [ecx],ax mueve 1F2 (498) a la dirección de la vida, realmente el debugger nos ha
mostrado EXACTAMENTE la instrucción correcta que escribe en nuestra vida. Ahora
lo que podemos hacer es nopear la instrucción, CE permite hacer ésta tarea de forma
muy fácil. Marcamos la instrucción en la ventana del debugger y pulsamos en Replace.
Para ser un poco ordenados, escribimos lo que hace nuestro replace: Invencible
Bueno, pues hasta aquí el paso nº2, intenta realizar todos los pasos, aprendelos y
comprende cada opción que te he enseñado, al finalizar éste tutorial habrás aprendido:
Buscar valores desconocidos
Buscar valores usando Decrease e Increase
Acoplar el debugger a una dirección de memória
Usar el debugger y la información que nos muestra
Nopear una instrucción con Replace
Usar el CodeList (Advanced Options) para manejar los nopeos
Ahora solo falat terminar el paso 3 del tutorial, donde os enseñaré a usar el Debugger de
CE a fondo y finalmente inyectar código ASM, crear script's y trainers.
Parte 3
Bueno, aquí está la tercera y última parte de mi tutorial, ésta parte va a ser algo
extensa ya que intentaré hablar sobre muchos temas a la vez, espero que se pueda
entender todo. Para ello utilizareoms un nuevo "juego" a modo de ejemplo llamado
MoneyBag:
El juego empieza con 1750 monedas, el único botón que hay sirve para gastar el
dinero, cada vez que lo pulses gastará 5 monedas. Nuestro principal objetivo será
modificar el programa para que el dinero aumente en lugar de decrecer cada vez que
pulsemos el botón (inyección de código).
Bueno, empezaremos con lo más sencillo, abrir el juego y CE, buscar la dirección que
almacena el dinero. Como pista os diré que el dinero es del tipo byte-2, pero si no
estáis seguros podéis configurar la búsqueda en All, os dejo un pantallazo:
Como podéis observar, ya he encontrado la dirección correcta y la he pasado a la parte
inferior, he cambiado la descripción para no equivocarme. Una vez que tenéis la
dirección en la parte inferior, podéis cambiar el valor manualmente haciendo click con
el ratón y apretando la tecla "Enter", el valor cambiado se verá reflejado
automáticamente en el juego.
Ahora hazemos click derecho en la dirección y seleccionamos "Find out what writes
to this address", aceptamos el mensaje de advertencia y se nos abrirá la ventana del
debugger, dicha ventana estará en blanco
Volvemos al juego y pulsamos "Gastar Dinero", el dinero decrecerá y en nuestra
ventana aparecerá la sección de código que ha modificado nuestra dirección llamada
"DINERO"
00402C10 - 0F80 D6000000 - jo moneybag_tutorial.exe+2CEC
00402C16 - 66 3B C7 - cmp ax,di
00402C19 - 66 89 46 34 - mov [esi+34],ax <<
00402C1D - 7F 04 - jg moneybag_tutorial.exe+2C23
00402C1F - 66 89 7E 34 - mov [esi+34],di
EAX=000006CC
EBX=0000000A
ECX=0012000A
EDX=00000003
ESI=00615F20
EDI=00000000
ESP=0012F4F0
EBP=0012F5A4
EIP=00402C1D
Template Cheat Table: Nos añade las secciones [ENABLE] y [DISABLE] para
la creación de un script
Template Code Inject: Nos añade el código original para poder ser modificado
(inyectado)
Para usar las plantillas correctamente has de añadir primero una y luego la otra, en el
mismo orden que te indico, no lo hagas al revés! Empezamos con el menú:
Template/Cheat Table framework code, aparecerá ésto:
Una vez que tenemos el Cheat Table puesto, añadimos la última plantilla:
Template/Code Injection. Nos aparecerá un mensaje:
Ésta ventana nos pregunta la dirección del salto, aceptamos el valor que nos muestra
por defecto: pulsamos Ok y el código se completa:
Una vez que ya tenemos las 2 plantillas insertadas, guardaremos el script en nuestro
CE, para ello pulsamos el menú: File/Assign to current cheat table y cerramos la
ventana de "Auto Asemble", NO pulses el botón "Execute", simplemente cierra la
ventana pulsando la [X], vuelve a la ventana principal de CE, debería estar así:
Se ha creado una nueva entrada en la parte interior que contiene nuestro AA script,
hazemos doble-click encima de <script> para abrir la ventana del AA y poder
modificarlo:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
originalcode:
mov [esi+34],ax
jg moneybag_tutorial.exe+2C23
exit:
jmp returnhere
"moneybag_tutorial.exe"+2C19:
jmp newmem
nop
returnhere:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"moneybag_tutorial.exe"+2C19:
mov [esi+34],ax
jg moneybag_tutorial.exe+2C23
//Alt: db 66 89 46 34 7F 04
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)
originalcode:
add ax,A
mov [esi+34],ax
jg moneybag_tutorial.exe+2C23
exit:
jmp returnhere
"moneybag_tutorial.exe"+2C19:
jmp newmem
nop
returnhere:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"moneybag_tutorial.exe"+2C19:
mov [esi+34],ax
jg moneybag_tutorial.exe+2C23
//Alt: db 66 89 46 34 7F 04
Como puedes observar, he añadido un add ax,A justo antes del mov, eso hará que el
dinero aumente en 5 en lugar de disminuir. Recuerda que cuando pulsamos el botón, el
programa resta 5 y lo muestra, con mi modificación el programa restará 5, luego
La primera ventana es para crear el trainer y la segunda nos muestra la GUI del
trainer, pulsamos "Add Hotkey" en la primera ventana para añadir una tecla
automática a nuestro AA script. Nos pedirá que seleccionemos el item de nuestra table
que queremos "trabajar", así que seleccionamos el "Auto Assemble script"
Al pulsar nos aparece la ventana del Hotkey:
Aquí lo único que debéis saber es la diferencia entre crear el trainer Gigantic o Tiny,
la versión Gigantic ocupará bastante (unos 3 MB) y la Tiny ocupara unos pocos bytes
(50 KB), la diferencia será que para la versión tiny, el usuario necesitará tener
instalado CE en su PC, la gigantic es completamente stand-alone. En nuestro caso
nos da igual, así que puedes usar Tiny si te apetece. Una vez generado, puedes cerrar
por completo el CE y el juego, ya tendrás tu trainer:
Para probarlo, abre de nuevo el juego MoneyBag, y con el trainer ejecutado, pulsa tu
tecla de hotkey "Q", verás como el trainer se ilumina indicando que el script se ha
inyectado, prueba a usar el MoneyBag y verás que el dinero aumenta!! Vuelve a
pulsar "Q" para descativar el script y el juego volverá a la normalidad.
Con un poco de programaciones se pueden crear trainers muy vistosos como hacen los
principales grupos Paradox, Theta, BlackxXx, etc...
Curso Avanzado de
Cheat Engine
# Introducción
# Buscar Address
# Conceptos Básicos
# VEH Debugger
# Pointers
# Creando el cheat GODMODE (intento fallido)
# Shared Codes
# Diseccionar Shared Code
# Creando el cheat GODMODE (auto-assemble)
# Diseccionar Estructuras
# Localizar estructuras dinámicas
# AoB to Memory Data
# Script VBS - AoB Pattern generator
# Bonus: Comparar estructuras con WinMerge
# TeleportHack
# Despedida
BUSCAR ADDRESS
CONCEPTOS BÁSICOS
Primero de todo voy a presentar lo que será nuestro objeto de estudio, nada más y
nada menos que Hack, Slash, Loot. Un juego tipo roguerlike basado en un sistema de
combates por turnos que nos ayudará a entender cada una de las partes del tutorial.
El juego es un sencillo ejecutable de apenas 10MB que no necesita instalación. No
puedo postear el link directo de descarga ya que el juego es de pago (aprox 5€), pero
creo que no os costará demasiado hacer una búsqueda en “la baía del barco pirata”
para encontrarlo. En el tutorial trabajaremos con la versión 8.0 de Hack, Slash, Loot.
Para empezar, yo he seleccionado el arquero, pulsamos el último botón de la derecha
para iniciar el juego. Puedes seleccionar otro personaje si lo deseas. El juego se
maneja con el ratón; es un roguerlike así que al tratarse de un juego “por turnos” no
nos tendremos que preocupar en pausar el juego mientras lo reversamos, Hack,
Slash, Loot (a partir de ahora HSL) es el juego ideal para explicar en un tutorial
como éste:
Abajo del todo aparecen los stats de mi jugador, primero de todo hay que marcarse
un objetivo, en mi caso nuestro objetivo será crear un cheat de tipo godmode
(invulnerable). Cada juego es diferente, y cada cheater trabaja de forma diferente.
Hay varios caminos que conducen al mismo lugar, cualquier comino es válidos
siempre y cuando consigamos cumplir nuestro objetivo. Cuando un juego muestra
claramente los puntos de vida (HP) a mi me gusta localizar el address que almacena
la vida y bloquearla, otro método válido sería buscar la instrucción que modifica la
vida y nopear, otro método es localizar los puntos de vida que te van a restar al
recibir un golpe y setearlos a 0. Hay muchos métodos/caminos, y todos son válidos.
Yo os explicaré los 3 métodos.
En mi caso han aparecido 990 direcciones con el valor 30. Lo que realizaremos ahora
es buscar algún enemigo y dejaremos que nos haga daño para reducir nuestros puntos
de vida, por suerte he aparecido al lado de un enemigo, así que haré click con el
ratón encima de mi personaje para “pasar el turno” y conseguir que me hagan daño:
Bien, el maldito kobold me ha pegado una zurra y ahora mi personaje tiene 14
puntos de vida, así que realizo la segunda búsqueda en CE:
Bien! De las 990 direcciones encontradas al inicio, ahora solo tengo 2! No necesito
hacer más búsquedas, solo tengo que probar cual de las 2 direcciones almacena la
vida. Hacemos click derecho en la primera dirección y selleccionamos la opción
“Change value of selected address”, en el cuadro emergente ponemos un número
cualquiera, por ejemplo 40 y miramos si nuestra vida a aumentado.
En mi caso he fallado, la dirección 0101FD98 no es la correcta, ya que si establezco
su valor a 40, automáticamente se vuelve a poner con 14. Así que pruebo con la
segunda:
Sí! Como podemos observar, la vida ha aumentado a 40, así que en mi ordenador, la
dirección 03651910 almacena los puntos de vida. El único problema que tenemos
ahora es que esa dirección no es estática. Si apagamos y encendemos el juego de
nuevo, la dirección de los puntos de vida habrá cambiado por otra y tendría que
volver a buscarla. ¿Cómo podemo evitar tener que buscar siempre una dirección no
estática? Con los Pointers. Siguiente capítulo…
POINTERS
No voy a extenderme mucho hablando de los punteros (pointers), pero básicamente
son una especie de “cajita” en la que el juego almacena la dirección de otro address.
Nuestro objetivo es localizar el pointer (la cajita) que almacena la dirección de
nuestra vida, así aunque la dirección cambie, el pointer siempre apuntará a la
dirección correcta.
Para ello utilizaremos una función propia del CE llamada Pointer Scan. Necesitamos
primero de todo localizar la dirección actual de nuestra vida, en mi ejemplo es la
dirección 03651910. Hacemos doble-click encima de la direcció encontrada para
mandarla en la parte inferior, pulsamos botón derecho encima y seleccionamos “Find
out what accesses this address”:
Nos preguntará si queremos iniciar el debugger, le decimos que sí, aparecerá una
ventanita pequeña. Ahora volvemos al juego y jugamos un poco, movemos el
personaje por la pantalla y luchamos con algún enemigo (intentando que nos hagan
un poco de daño), tras recibir unos golpes volvemos a la ventanita del CE y
encontraremos algo similar a esto:
En mi caso el debugger ha encontrado 4 instrucciones que han accedido a la
dirección 03651910. Lo que tenemos que realizar ahora es buscar un patrón
repetitivo. A simple vista me llama la atención el patrón [???+50]. En cada línea hay
un [eax+50] o [ebx+50] ¿Qué significa? Hacemos click en una instrucción, yo he
escogido la instrucción SUB, abajo aparece una porción de las instrucciones así
como el estado de los registros:
El resultado de dicha suma es 3651910 que se corresponde a nuestra dirección con
los puntos de vida. Todo esto lo hemos realizado para conocer que tipo de pointer
tendremos que buscar, os recomiendo que abráis un documento de texto para ir
anotando los valores. En ésta instrucción, EBX apunta a la estructura base de nuestro
jugador. El offset +50 de dicha estructura almacena los puntos de vida, tal que así:
EBX = 036518C0 (PLAYER STRUCTURE)
EBX+50 = 3651910 (PLAYER HP VIDA)
El pointer que tenemos que buscar ha de terminar con el offset +50 ya que es el
patrón que hemos visto con el debugger, anotad en vuestro fichero algo así como:
Cerramos el debugger y volvemos a la ventana principal del CE, con nuestro address
mostrando la vida del jugador. Hacemos click derecho encima del address y
seleccionamos Pointer Scan:
Se nos abrirá una ventana con muchas opciones. En la parte superior nos pregunta
que dirección queremos buscar. Automáticamente CE ha rellenado el address de
nuestra vida (3651910) ya que lo que queremos es buscar cualquier pointer que
apunte a nuestra vida. Más abajo tendremos que cambiar las opciones que he
señalado en rojo. Primero le indicaremos al pointer-scan que nuestro pointer debe
terminar con el offset +50 (es lo que descubrimos con el debugger!) Luego
parametrizamos la complejidad del pointer, para juegos de éste tipo, con un nivel
entre 1-5 es suficiente, el tamaño puede ir desde 1024 a 2048. Para nuestro ejemplo
yo he puesto nivel = 3 y tamaño = 1024.
Pulsamos OK y nos preguntará donde guardar el fichero de pointers, mi
recomendación es que hagáis una sub-carpeta para almacenar el pointer, yo le he
puesto el nombre de vida. Tras unos segundos se iniciará el scaneo de pointers y nos
dará un resultado:
Wow 85 punteros. En algunos juegos, la primera búsqueda de pointers puede
devolver más de 5 millónes de resultados (es normal), para lograr encontrar el
pointer correcto se necesitan realizar varios escaneos consecutivos.
Bien, ya hemos realizado la primera búsqueda y nos ha devuelto 85 punteros. Lo que
realizaremos ahora es cerrar el juego por completo y lo volveremos a abrir.
Volveremos abrir el proceso de HSL y realizaremos de nuevo la búsqueda manual
del address con los puntos de vida:
Como podéis observar, la antigua dirección 03651910 ya no muestra la vida real del
jugador, ahora la vida se almacena en la nueva dirección 038388B0 (que abremos
buscado manualmente tal y como hemos visto en el inicio de éste tutorial). Ya hemos
encontrado la nueva dirección con los puntos de vida, así que pulsamos click derecho
encima de la dirección y seleccionamos Pointer Scan de nuevo:
ATENCIÓN! Ahora se ha vuelto a abrir la misma ventana de antes, con las opciones
del pointer. Lo que hay que hacer es CERRAR ésta ventana ya que no queremos
iniciar una nueva búsqueda, si no continuar la búsqueda con los resultados
anteriores:
Se nos habrán cargado los pointers anteriores (en mi caso 85), así que realizaremos
una búsqueda utilizando estos 85 punteros de referencia:
Se nos abrirá una ventana más pequeña, aquí indicaremos el valor de la nueva
dirección que debería tener el pointer, introduciremos la nueva address que hace
referencia a los puntos de vida, en mi caso 038388B0:
Pulsamos OK (nos preguntará donde guardar los resultados, podéis guardar con el
mismo nombre o con un nombre nuevo) tras unos segundos nos reducirá los
resultados según el valor buscado:
Bieeeen, 1 solo resuntado. Seguro que ese es nuestro pointer! Además el offset
termina en +50 tal y como hemos configurado. Hacemos doble-click en el resultado
y el pointer se mandará a nuestra tabla de CE:
Podemos ver como CE muestra los pointers con el carácter P->, si ahora reiniciamos
el juego, el pointer nos mostrará la dirección de nuestra vida, podremos editar,
congelar o trabajar con la dirección.
Hasta aquí el tutorial sobre pointers, practicad y veréis que no es tan complicado
como parece.
CREANDO EL CHEAT GODMODE
(PRIMER INTENTO FALLIDO)
Bueno, ya que hemos encontrado el address de nuestra vida y que, además, tenemos
el pointer estático de dicho address, podemos establecer un valor y marcar la casilla
para “congelarlo”, así obtendríamos lo que sería una especia de godmode:
Lo único que no me gusta de éste método es que si luchamos contra un enemigo muy
poderoso y de un solo golpe nos quita -700 puntos de vida… terminaremos muriendo
ya que la velocidad de refresco del CE nunca será superior a la del juego. Para evitar
eso y conseguir un godmode más real podemos hacer muchas cosas, pero yo
recomiendo las siguientes:
• Detectar el valor de daño que nos aplicarán y establecerlo siempre a 0
• Detectar la instrucción que modifica o resta los puntos de vida y cambiarla por un
NOP
Ambos métodos son correctos y yo los aconsejo ya que son “mejores” que setear un
pointer a un valor fijo. Para ello pulsaremos click derecho en nuestro pointer (que
apunta a la address de los puntos de vida) y miraremos que instrucciones escriben en
dicha dirección:
Al tratarse de un pointer, CE nos preguntará si queremos mirar la instrucción que
modifica el pointer o la instrucción que modifica la dirección a la que apunta nuestro
pointer. Siempre, siempre, siempre escogeremos la segunda opción:
Nos volverá a salir la pequeña ventanita del debugger, que estará vigilando a ver que
instrucción escribirá sobre el address del pointer (los puntos de vida). Volvemos al
juego y jugamos unos cuantos turnos hasta recibir un poco de daño, cuando hayamos
recibido daño, volvemos a la ventanita del debugger y encontraremos lo siguiente:
La ventana nos muestra que la instrucción 00550474 ha modificado nuestra vida,
ademas nos enseña el código ASM que realiza la acción de modificar sub
[ebx+50],eax y el estado de todos los registros, vámos a interpretar:
POINTER VIDA = 37490B0
INSTRUCCIÓN = SUB [EBX+50],EAX
EBX = 03749060
EAX = 7
Lo que está ocurriendo aquí es la llamada a la instrucción SUB (substract / restar) el
valor de EAX a la dirección [EBX+50]
EBX+50 = 03749060 + 50 = 37490B0 (Pointer Address Vida)
En resumen, resta el valor de EAX=7 a nuestra dirección de memoria que almacena
los puntos de vida, por lo que dicha instrucción me quita 7 puntos de vida.
Perfecto, ahora ya entra la genialidad de cada uno para reversar dicha instrucción.
Hay varias formas y todas son válidas:
• Cambiar el SUB por un ADD (así en cada golpe, la vida aumentará)
• Cambiar EAX por 0, quedaría así: sub [ebx+50],0 (así en cada golpe, la vida
disminuye en 0)
• Nopear la instrucción cambiando el sub [ebx+50],eax por varios NOP
De las 3 opciones que os he propuesto, la primera de todas parece la más sencilla.
Además a parte de conseguir un godmode, nuestra vida aumentaría en cada golpe.
Vámos a probar. Pulsamos el botón “Show disassembler” para abrir la ventana de
Memory View:
CE ya nos ha posicionado en la instrucción 00550474, así que hacemos click derecho
en la instrucción y seleccionamos “Assemble” para editarla:
Y cambiamos la palabra SUB por ADD:
Os recomiendo que hagáis click derecho de nuevo sobre la instrucción y os guardéis
la dirección en el fichero de texto:
Así tendréis guardada la dirección para más tarde y ahorraremos tiempo, en mi caso
es [Link]+150474. Cerramos el Memory View y la ventanita del
debugger, dejando solo la ventana principal del CE y el juego. Iniciamos un nuevo
combate para ver si funciona nuestro “hack”:
670 puntos de vida! En lugar de disminuir ha aumentado! Bien somos unos hackers-
cheaters-crackers de la elite profesional, pero… si intentas matar a tu enemigo
haciendo click encima del kobold, verás que por una extraña circunstancia no puedes
matarlo… ¿Qué raro, no? Si miramos bien, el juego nos muestra la vida de nuestro
enemigo si lo seleccionamos con el ratón:
Horror! La vida del enemigo también aumenta! ¿Cómo es eso posible? Bueno, esto
por desgracia suele ocurrir. El programador del juego está utilizando la misma
función para restar vida al jugador y a los enemigos, por eso al haber cambiado el
SUB por el ADD, tanto la vida del jugador como la de los enemigos aumenta en cada
golpe. Éste efecto se le conoce como Shared Code (código compartido) ya que la
instrucción [Link]+150474 es compartida por más de una dirección de
memoria. ¿Hay alguna forma de solucionar éste problema? Sí, sigue leyendo…
SHARED CODES
Primero de todo vamos a dejar el juego como estaba, quitando el ADD que pusimos
anteriormente por el SUB original, abrimos el Memory View:
Si hemos cerrado el CE quizás ya no estemos encima de la instrucción original,
copiamos la instrucción de nuestras notas (en mi caso [Link]+150474) y
hacemos:
Nos situaremos delante de la instrucción, hacemos doble-click encima (o click
derecho / “Assemble”) y cambiamos el ADD por el SUB original, así todo estará en
su sitio.
Ahora lo que os voy a enseñar es un método para comprobar si una misma
instrucción modifica más de una dirección de memoria, para ello pulsamos botón
derecho encima de la instrucción y seleccionamos “Find out what addresses this
instruction accesses”
Si lo hemos hecho bien, la instrucción quedará marcada en verde y aparecerá una
ventana. Sin cerrar la ventana, volvemos al juego e intentamos forzar que dicha
instrucción trabaje. Para ello iniciaos un combate hasta recibir algo de daño y causar
nosotros daño al enemigo:
Y aquí tenemos el resultado, han aparecido 2 direcciones que han sido accedidas por
la misma instrucción, la primera (104D3490) tiene valor 70 y se corresponde con la
vida del enemigo (ver foto). La segunda dirección (037490B0) es la dirección de mi
vida, además su valor coincide con la vida de mi personaje (ver foto). Está más que
claro que ésta instrucción ha modificado ambas direcciones, por lo que si cambiamos
el SUB por un ADD afectará tanto a mi vida como a la vida de los enemigos.
Bueno, pulsamos STOP para que CE deje de observar la instrucción (la instrucción
ya no estará marcada en verde) y dejamos la ventanita con las 2 direcciones abierta).
Ahora que ya conocemos el método para saber cuando estamos delante de un Shared
Code os explicaré como diseccionar la estructura del jugador y la del enemigo para
buscar diferencias y poder aplicar un ADD en el caso que sea el jugador y un SUB
en el caso de un enemigo.
Se nos abrirá una mini ventana con el estado de los registros, hacemos lo mismo con
la dirección del enemigo y ponemos las 2 ventanas una al lado de la otra:
Nos fijamos en los registros EBX, naturalmente EBX apunta al inicio de la estructura
de cada jugador (nuestro player y el enemigo). Si miramos con más atención, el
registro ESI tiene el mismo valor que EBX en el caso del Player pero en el caso del
Enemigo ESI no vale lo mismo que EBX.
Pues de ésta forma tan sencilla acabamos de inventarnos un método para conocer
cuando la instrucción está modificando el address del player o del enemigo, dicho
método es una simple comparación:
CMP EBX,ESI
JNE ENEMIGO
Se nos abrirá un editor de Auto-Assemble (a partir de ahora AA), podemos escribir a
mano todo el script pero CE tiene un par de plantillas que nos ahorrarán mucho
trabajo, hay que usar los siguientes menús, hay que hacerlo en el mismo orden que os
explicaré:
Hacemos doble click encima del script y se volverá a abrir la ventana del Auto-
Assemble, desde aquí ya podremos modificar el script para conseguir un godmode
como dios manda (valga la redundancia), vámos a identificar cada parte del código:
Teniendo éstas 3 partes bien identificadas queda muy claro que escribiremos nuestro
código bajo la etiqueta NEWMEM, el resto no lo queremos modificar. En el espacio
que tenemos entre NEWMEM y ORIGINALCODE escribimos lo siguiente:
CMP EBX,ESI
JNE ORIGINALCODE
MOV EAX,0
Ahora activamos el script haciendo click en el recuadro y luchamos con algún
enemigo. Verás que si eres golpeado, tu vida no decrece. En cambio si golpeas a un
enemigo, su vida decrecerá con normalidad. Desactiva el script y abre el Memory
View, hacemos un GoTo Address "[Link]"+150474, aparecerá el
código original:
Ahora pulsamos el script para activarlo y miramos que ocurre en dicha instrucción:
El código original ha sido sustituido por un jmp 02C50000 (en tu caso podrá ser otro
address), hagamos click derecho en el jmp y seleccionamos Follow para ver que hay
ahí:
Lo que encontramos tras ese jmp es el código ASM que hemos inyectado con el
Auto-Assemble script, aquí se ve muy claro como trabaja CE, si desactivamos el
script, dicha zona de memoria será borrada.
DISECCIONAR ESTRUCTURAS
En éste caso he creado una estructura llamada player que contiene 4 variables (id,
nombre, mana, health). Así es como están programados la gran mayoría de video-
juegos. Las estructuras están cargadas en memoria (tiempo de ejecución). Nuestro
objetivo será conocer el address de la estructura de nuestro jugador para poder
diseccionarla con una herramienta (base-address). Sigamos con el tutorial…
Primero de todo trabajaremos con el juego “original”, así que el script de godmode lo
dejamos desactivado. Tenemos ya nuestro pointer que apunta a la dirección de los
puntos de vida del jugador. Hacemos click derecho encima del pointer y
seleccionamos “Find out what writes to this address”:
Al tratarse de un pointer nos preguntará si queremos mirar la instrucción que escribe
encima del pointer o la instrucción que escribe el address de nuestro pointer. Siempre
escogeremos la segunda opción. Se abrirá la ventana del debugger así que volvemos
al juego y dejamos que un enemigo nos golpee, acto seguido volvemos a la ventanita
y nos aparecerá nuestra instrucción famosa:
Si hacemos click en ella nos aparece abajo toda la información. Pulsamos el botón
“More Information”
Nos aparece un recuadro con información adicional, he subrallado una frase
importante que nos indica CE… nos está calculando cual es la direcció probable de
nuestra estructura, en mi caso nos indica 03918860, así que hacemos click derecho
encima para copiar la dirección:
Perfecto, ya tenemos la base-address de la estructura de nuestro jugador, ya podemos
diseccionarla! Cerramos la ventana de “More Information” y la ventanita del
debugger. Nos situamos en la ventana principal de CE, pulsamos en Memory View y
luego en el menú: “Tools / Dissect data & structures”:
Se abrirá una ventana grande de color blanco, en la parte superior podremos escribir
una address. Lo que hay que hacer es escribir la base-address de nuestra estructura
(en mi caso 03918860):
Vámos al menú: “Structures / Define New structure”. Nos preguntará que nombre
queremos asignar, puedes poner lo que quieras, yo puse PLAYER. A continuación
nos preguntará si queremos que CE rellene automáticamente la estructura:
Le diremos YES para ahorrarnos trabajo, jeje. Luego nos preguntará el tamaño. Por
defecto CE asigna 4096 offsets. Bajo mi punto de vista son demasiados, así que yo lo
bajo a 1024 o 2048:
Finalmente, tras definir el tamaño, CE cogerá la base-address de la estructura y la
diseccionará 1024 offsets, obtendremos lo siguiente:
No nos asustemos, vámos a interpretar la información que nos proporciona CE…
¿recuerdas que offset corresponde a los puntos de vida? Puedes mirar las notas o el
pointer que tenemos en la tabla:
Pues sí, la vida está situata en el offset +50, si miramos la estructura diseccionada
veremos que se corresponde al valor del pointer y a los puntos de vida:
Ahora a partir de aquí es cuestión de “tocar, explorar y probar”. Mi recomendación
personal es que cerca de un offset válido se encuentran el resto de offsets de la
estructura. Lo primero que ahoremos es poner un nombre a los offsets conocidos, por
el momento solo conocemos el offset +50 así que damos doble-click encima y le
pones un nombre:
Ahora lo interesante sería poder detectar que offsets se corresponden al ataque,
rango, magia, defensa, etc… estoy seguro que esos offsets estarán cerca de la vida
(+50) así que miraré los offsets cercanos y los compararé con mi jugador:
Me llama la atención el offset +34… tiene un valor de 40 que coincide con los 40
puntos de daño en el juego:
Así que hacemos click derecho encima del offset +34 y seleccionamos la opción
“Change Value” e introducimo un nuevo valor, por ejemplo 77
BINGO! El offset +34 es el encargado de almacenar el daño (Melee Attack) así que
hacemos doble-click para editarlo y apuntamos el offset a nuestras notas:
Está clarísimo que los offsets entre +34 y +50 serán los otros stats, así que iremos
editando cada offset para conocer su valor en el juego y lo anotaremos en nuestra
disección y en nuestras notas. Así me ha quedado a mi:
Bueno, ya tengo la estructura diseccionada al completo, hay otros offsets, quizás
alguno esté almacenando algo interesante, pero eso ya lo veremos más adelante.
Ahora ya tenemos la estructura diseccionada con los offsets principales. Solo nos
queda poder calcular automáticamente la base-address de nuestra estructura para
luego sumar +50 +34 +etc… e ir sacando cada una de las direcciones importantes.
¿Cómo lo hacemos? Pues tendremos que encontrar un patrón que no sidentifique la
base-address de la estructura de nuestro jugador. Empezemos…
LOCALIZAR ESTRUCTURAS DINÁMICAS
Sabemos que la instrucción [Link]+150474 modifica el offset +50 de
nuestra estructura, así que abrimos el Memory View, hacemos click derecho y
pulsamos “GoTo Address”:
Estaremos delante de la instrucción famosa SUB que se encarga de restar la vida, así
que pondremos un breakpoint en dicha instrucción (si pulsas F5 se pone el
Breakpoint) o podemos hacer click derecho y seleccionar “Toggle Break Point”. Se
nos quedará marcada la instrucción en verde indicando que hay un breakpoint:
Ahora volvemos al juego, iniciamos una pelea y dejamos que el enemigo nos golpee,
verás que el juego se queda “congelado” ya que el breakpoint ha detenido la
ejecución del juego así que volvemos a CE y nos encontraremos lo siguiente:
A la derecha aparece el stack y los registros. Lo que nos interesa son los registros
para poder conocer la base-address de nuestra estructura. La instrucción es sub
[ebx+50],eax por lo que el valor de EBX nos mostrará la base-address, en mi caso
03918860. Pulsamos click-derecho sobre EBX y seleccionamos “Show in hex view”:
Automáticamente, en la parte inferior (Hex Dump) nos mostrará la dirección de EBX
(03918860), en mi caso:
Lo que tenemos que hacer ahora es coger esos bytes y copiarlos a nuestras notas. Yo
siempre cojo 3 líneas. Para ello con el ratón seleccionamos desde el primer byte
hasta el último (se quedarán marcados en rojo) y pulsamos Ctrl+C para copiar, a
continuación los pegamos en nuestro fichero de texto:
Esos son los bytes que se corresponden a la base-address de la estructura de nuestro
personaje. Ahora hay que repetir todos éstos pasos un mínimo de 3 veces. Para ello
pulsaremos F9 en la ventana de Memory View para continuar la ejecución a partir
del Breakpoint y luego cerraremos por completo el juego. Abriremos de nuevo el
juego, iniciaremos una nueva partida y volveremos a seleccionar el proceso de Hack,
Slash, Loot para trabajar con CE. A partir de aquí hay que repetir los pasos de éste
tutorial, es decir:
• Iniciar el Memory View
• Ir a la instrucción que modifica la estructura, en nuestro caso
[Link]+150474
• Poner un Breakpoint
• Iniciar un combate en el juego hasta recibir daño
• Mirar los registros (EBX) y hacer “Show in hex view”
• Copiar los bytes al fichero de texto
• Cerrar el juego y volverlo a iniciar para empezar de nuevo
Estos pasos los he realizado 5-6 veces y al final he conseguido las siguientes líneas:
Ahora solo tenemos que calcular un patrón válido partiendo de éstas muestras. Se
puede hacer a mano, pero para los más perezosos he programado un script en
lenguaje VBS que realizará el cálculo automáticamente
SCRIPT VBS - AOB PATTERN GENERATOR
El código VBS está en pastebin, solo tienes que copiarlo en un notepad y guardarlo
con extensión *.vbs
[Link]
Set oWSH = CreateObject("[Link]")
Set oFSO = CreateObject("[Link]")
T = InputBox("Enter array of bytes nº 1:")
T = T & vbcrlf & InputBox("Enter array of bytes nº 2:")
X=3
While MsgBox("Do you want to introduce another array of bytes?", vbYesNo, "AoB
Pattern Generator") = vbYes
T = T & vbcrlf & InputBox("Enter array of bytes nº " & X &":")
X = X + 1
Wend
F = ""
W=0
X=0
For i = 1 To Len(AoB(0))
For u = 1 To UBound(AoB)
If Mid(AoB(u), i, 1) <> Mid(AoB(0), i, 1) Then
F = F & "?"
W = W + 1
X = 1
Exit For
End If
Next
If X <> 1 Then F = F & Mid(AoB(0), i, 1)
X = 0
Next
'MsgBox F
If MsgBox("AoB Patter Generator finished" & vbcrlf & vbcrlf & "Do you want to
open [Link] file?", vbYesNo, "AoB Pattern Generator") = vbYes Then
[Link] "[Link] [Link]"
End If
El script comparará todos los bytes y buscará un patrón. Si un byte no coincide será
sustituido por el carácter ?. Al final, mi script me dice que el Array of Bytes (AoB)
es:
18 12 BB 00 0? 00 00 00 ?? ?? ?? 0? ?? ?? ?? 0? 03 00 00 00 03 00 00 00 ?? 00 00 00
?? 00 00 00 0? 00 00 00 ?? ?? ?? 0? 00 00 00 00 ?? ?? ?? ??
Como puedes observar, se puede calcular fácilmente a mano, solo hay que sustituir
los bytes que no son iguales por un simbolo de interrogación. Ahora ya tenemos un
array de bytes que identificará la base-address de la estructura. Volvemos al CE,
abrimos el Memory View y nos vamos al editor de Auto-Assemble (Ctrl+A) en el
menu “Tools”, en el editor pegamos el siguiente código:
[ENABLE]
aobscan(player, 18 12 BB 00 0? 00 00 00 ?? ?? ?? 0? ?? ?? ?? 0? 03 00 00 00 03 00
00 00 ?? 00 00 00 ?? 00 00 00 0? 00 00 00 ?? ?? ?? 0? 00 00 00 00 ?? ?? ?? ??)
label(_player)
registersymbol(_player)
player:
_player:
[DISABLE]
unregistersymbol(_player)
Solo tendrás que sustituir el array AoB por el valor que hayas encontrado. Una vez
copiado el texto vamos al menu: “File / Asign to current cheat table” para añadir el
script a la tabla, obtendremos lo siguiente:
Mi recomendación es que edites los nombres para no confundirte:
El script es muy sencillo, cuando lo activamos lanzamos un AoB Scan (buscar un
array de bytes) y le indicamos que busque nuestro patrón de bytes, CE localizará la
coincidencia y nos devolverá el resultado en la etiqueta _player. Eso significará que
podremos utilizar la etiqueta _player para referirnos al inicio de la estructura (base-
address).
Volvemos al CE y seleccionamos “Add Address Manually”
En el recuadro hay que poner la dirección que queremos añadir, como la dirección es
dinámica, introduciremos la variable _player, añadimos tambien una descripción
para no confundirnos:
Pulsamos OK y se añadirá la dirección:
Actualmente CE no reconoce la dirección _player, por eso no muestra nada. Ahora lo
que haremos es activar el script con el AoB y sucederá la magia…
Tachan!! CE ha ejecutado el AoB, ha buscado el patrón de bytes y ha devuelto el
resultado en la variable _player, ahora CE ya sabe el valor de dicha dirección y nos
muestra 0FF3AAA0 que se corresponde al actual base-addres de la estructura de
nuestro personaje. A partir de aquí ya tenemos el camino hecho, solo falta
completarlo.
Desactivamos el script y volvemos a pulsar “Add Address Manually”, añadiremos
ahora la siguiente dirección:
La explicación es sencilla; estamos añadiendo una nueva dirección que será base-
address+50 que según nuestras notas se corresponde al offset de la vida. Hacemos lo
propio con los offsets encontrados:
• +50 = HP
• +40 = DEF
• +34 = Melee Atk
• +38 = Range Atk
• +3c = Magic Atk
• +44 = Melee Dmg
• +48 = Range Dmg
• +4c = Magic Dmg
Obtendremos lo siguiente:
Ahora que ya tenemos todos los offset introducidos solo falta activar el script AoB
para recoger la estructura:
BAMP! De un solo golpe ya tenemos todos los valores. Además como estamos
usando un AoB Scan, en la próxima ejecución del juego CE buscará la base-address
y la guardará en _player, por lo que podremos visualizar y editar las direcciones
dinámicas de la estructura de nuestro jugador.
Os recomiendo que con vuestro ratón ordenéis la tabla y dejéis todos los offsets
“dentro” del script:
Para luego hacer click derecho en el script y seleccionar:
Así los offsets permanecerán ocultos si el script está desactivado y se mostrarán
cuando activemos el script.
Bueno, pues de ésta forma se consigue encontrar un patrón de bytes que apunte a una
estructura dinámica para luego sacar los offsets estáticos de su interior. Practicad!
BONUS: COMPARAR ESTRUCTURAS CON WINMERGE
TELEPORT HACK
Ya que hemos llegado hasta aquí nos podemos esforzar un poco más para terminar
de rizar el rizo. Os voy a explicar como utilizar el programa WinMerge para
comparar 2 estructuras y buscar los offsets de forma casi automática. Primero de
todo nos descargamos WinMerge de su web y lo instalamos: [Link]
Nuestro objetivo es crear un Teleport Hack, la mayoría de juegos almacenan en la
propia estructura del personaje su posición en el plano X / Y. Si se trata de un juego
en 3D tendremos un tercer eje llamado Z. En el caso de Hack, Slash, Loot, solo
habrá 2 coordenadas para posicionar al jugador, vámos a intentar sacarlas.
Abrimos CE, abrimos el proceso de HSL y cargamos nuestra tabla con el pointer, los
scripts en Auto-Asemble y la estructura diseccionada.
Pulsamos el script “Search Player Structure”, la función AoB Scan hará su trabajo y
nos devolverá la estructura rellenada:
Hemos activado el script para cargar la base-address de la estructura de nuestro
jugador en la variable _player. Ahora abrimos el Memory View y vamos al menú
“Tools / Dissect data & structures”:
En el recuadro para la base-address podemos poner _player, CE se encargará de
interpretar la variable. Abrimos el menú “Structures” y seleccionamos la estructura
que ya hicimos en el capitulo anterior:
CE nos mostrará la estructura _player con sus offsets:
Ahora, sin tocar nada más, abrimos el menú: “File / Save values (Ctrl+S)” y
guardamos con un nombre, por ejemplo “struct_1.txt”
A continuación volvemos al juego y desplazamos nuestro personaje un par de
casillas, asegurando que mueves tanto el eje X como el Y (por ejemplo, moviéndote
una casilla arriba y otra a la derecha). Volvemos a la ventana de “Structure dissect” y
pulsamos de nuevo menú: “File / Save values (Ctrl+S)” para guardar la estructura,
pondremos otro nombre, por ejemplo “struct_2.txt”
Ahora ya tenemos 2 ficheros de texto con la misma estructura pero con el personaje
en 2 posiciones diferentes. Toca hacer trabajar a WinMerge para conocer las
diferencias de ambos ficheros:
Cargamos los 2 ficheros para comparar y pulsamos Aceptar, WinMerge nos mostrará
cualquier línea que esté diferente:
Y aquí tenemos claramente las diferencias, offsets +18 +1C. En la primera estructura
tenian el valor de 48/14 y luego han pasado a 47/15. Ahora solo queda identificar
que offset es la X o la Y y crear la dirección manual como ya vimos anteriormente:
Finalmente guardamos los cambios en nuestra tabla, activamos el script y nos
movemos por la pantalla para ver funciona. Los valores de X/Y se pueden editar a
mano para desplazar al jugador por la pantalla. También se podría crear un Auto-
Assemble script que almacene la posición actual de X/Y y luego con un hotkey
volver a setear los offsets al valor guardado para hacer un teleport-hack. Pero eso ya
es algo más avanzado y tengo demasiado sueño como para seguir expllicando cosas.
DESPEDIDA
Bueno, hasta aquí el tutorial, espero que os haya gustado, me ha tomado 2 días
escribirlo, tomar las fotos y maquetarlo. Espero que lo disfruten y puedan probar
todas y cada una de las cosas que he explicado. Nos vemos por el foro…
MadAntrax – 26/04/2014
[eof]
Descargar PDF:
[Link]
** Intentaré hablar con el-brujo para ver si existe alguna forma automática de
traducir el tutorial a BB-Code y postearlo en el foro, por el momento posteo el ZIP
para que lo podáis descargar.