[Tutorial] Usar Cheat Engine para modificar juegos + inyección de código

Iniciado por Mad Antrax, 1 Febrero 2013, 11:46 AM

0 Miembros y 4 Visitantes están viendo este tema.

Mad Antrax

#30
Puedes subir el ejecutable compilado? No tengo el VS para compilar el source

Edit: Ya veo que has subido tambien el exe compilado, espera unos minutos que lo reviso :P
No hago hacks/cheats para juegos Online.
Tampoco ayudo a nadie a realizar hacks/cheats para juegos Online.

MeTaD

Vale, gracias, le agregué más información al post anterior, revísalo porfa, y también te he mandado un PM, gracias de antemano.

Mad Antrax

#32
Cita de: MeTaD en 17 Febrero 2013, 20:24 PM
Vale, gracias, le agregué más información al post anterior, revísalo porfa, y también te he mandado un PM, gracias de antemano.

Bueno, he estado revisando tu programa.

El problema parece ser que es debido a Framework, como ya sabes, todos los programas creados con Visual Studio son interpretados por una VM, en VB6 la VM es MSVBVM60.DLL, en las versiones posteriores son ejecutados por las librerías y dependencias Framework.

Después de estar revisando un poco el ejecutable, las operaciones de incrementar o restar son ejecutadas evidentemente por la VM de VisualStudio (Framework), dichas librerías ejecutan y procesan el código a su manera, realmente no entiendo como demonios funciona internamente, lo que sí es seguro es que los punteros son asignados en espacios de memoria de forma aleatoria.

Cuando ejecuto tu programa, puedo encontrar el pointer (puntero) asignado a tu variable. Después de incrementar el valor, la variable "salta" y se almacena en otra dirección de memoria nueva (ésto es MUY raro y jamás lo había visto, es por culpa del maldito Framework), curiosamente, el pointer que he encontrado es capaz de seguir ese "salto" y continua mostrando el valor correcto de tu variable.

El problema viene aquí: Cuando ejecuto de nuevo el programa, el pointer que había encontrado antes ya no sirve (ésto es la primera vez que lo veo). He usado el pointer-scanner para comprobar si son punteros de multi-nivel, pero no es el caso.

También he probado de crear un AA script, funciona correctamente, pero cuando reinicio el programa, Framework interpreta el código de alguna forma extraña y deja inservible el AA script.

____________________________________

Mi conclusión es que Framework nos está jugando una mala pasada. Por alguna razón, cuando ejecutas el programa, asigna sus funciones en un rango aleatorio de la memoria (offsets). Con el resto de ejecutables que he trabajado, las variables se asignan de forma aleatoria, pero sus pointers y funciones (offsets) siempre ocupan la misma dirección relativa. Me explico:

Ejecuto por primera vez tu programa, tras encontrar la dirección, Framework hace lo siguiente:

003D06BE - FF 80 4C010000        - inc [eax+0000014C]

003D06BE = Es el offset encargado de incrementar tu variable
inc = Es la instrucción ASM que incrementa
[eax+0000014C] = La dirección de memoria con tu variable

La segunda vez que ejecuto tu programa ocurre lo siguiente:

005806BE - FF 80 4C010000        - inc [eax+0000014C]

El offset ha cambiado pasando de 003Dxxxx -> 0058xxxx, pongo la mano en el fuego que el culpable de éste cambio sin-sentido es debido al Framework.

Lamentablemente no puedo darte una solución a tu problema :( Deberíamos mover tu pregunta al foro oficial de CheatEngine, a ver si alguien puede lanzar un poco de luz a éste problema

__________________________________________

EDIT

Estoy revisando más a fondo tu problema. Parece ser que la función AOBSCAN() se puede encontrar el offset exacto que realiza el incremento para luego hacer una inyección de código o incluso dumpear la dirección de memoria donde se almacena tu variable.

El problema es que no soy muy experto en usar el AOBSCAN() bajo CE, estoy haciendo pruebas, pero creo que se puede conseguir :P
No hago hacks/cheats para juegos Online.
Tampoco ayudo a nadie a realizar hacks/cheats para juegos Online.

MeTaD

Cita de: ||MadAntrax|| en 17 Febrero 2013, 21:03 PM
Bueno, he estado revisando tu programa.

El problema parece ser que es debido a Framework, como ya sabes, todos los programas creados con Visual Studio son interpretados por una VM, en VB6 la VM es MSVBVM60.DLL, en las versiones posteriores son ejecutados por las librerías y dependencias Framework.

Después de estar revisando un poco el ejecutable, las operaciones de incrementar o restar son ejecutadas evidentemente por la VM de VisualStudio (Framework), dichas librerías ejecutan y procesan el código a su manera, realmente no entiendo como demonios funciona internamente, lo que sí es seguro es que los punteros son asignados en espacios de memoria de forma aleatoria.

Cuando ejecuto tu programa, puedo encontrar el pointer (puntero) asignado a tu variable. Después de incrementar el valor, la variable "salta" y se almacena en otra dirección de memoria nueva (ésto es MUY raro y jamás lo había visto, es por culpa del maldito Framework), curiosamente, el pointer que he encontrado es capaz de seguir ese "salto" y continua mostrando el valor correcto de tu variable.

El problema viene aquí: Cuando ejecuto de nuevo el programa, el pointer que había encontrado antes ya no sirve (ésto es la primera vez que lo veo). He usado el pointer-scanner para comprobar si son punteros de multi-nivel, pero no es el caso.

También he probado de crear un AA script, funciona correctamente, pero cuando reinicio el programa, Framework interpreta el código de alguna forma extraña y deja inservible el AA script.

____________________________________

Mi conclusión es que Framework nos está jugando una mala pasada. Por alguna razón, cuando ejecutas el programa, asigna sus funciones en un rango aleatorio de la memoria (offsets). Con el resto de ejecutables que he trabajado, las variables se asignan de forma aleatoria, pero sus pointers y funciones (offsets) siempre ocupan la misma dirección relativa. Me explico:

Ejecuto por primera vez tu programa, tras encontrar la dirección, Framework hace lo siguiente:

003D06BE - FF 80 4C010000        - inc [eax+0000014C]

003D06BE = Es el offset encargado de incrementar tu variable
inc = Es la instrucción ASM que incrementa
[eax+0000014C] = La dirección de memoria con tu variable

La segunda vez que ejecuto tu programa ocurre lo siguiente:

005806BE - FF 80 4C010000        - inc [eax+0000014C]

El offset ha cambiado pasando de 003Dxxxx -> 0058xxxx, pongo la mano en el fuego que el culpable de éste cambio sin-sentido es debido al Framework.

Lamentablemente no puedo darte una solución a tu problema :( Deberíamos mover tu pregunta al foro oficial de CheatEngine, a ver si alguien puede lanzar un poco de luz a éste problema

__________________________________________

EDIT

Estoy revisando más a fondo tu problema. Parece ser que la función AOBSCAN() se puede encontrar el offset exacto que realiza el incremento para luego hacer una inyección de código o incluso dumpear la dirección de memoria donde se almacena tu variable.

El problema es que no soy muy experto en usar el AOBSCAN() bajo CE, estoy haciendo pruebas, pero creo que se puede conseguir :P

Altamanete interesante a mi punto de vista el comprotamiento que vemos aquí, ¿no?, porcierto, estoy analizando con olly bajo este tutorial http://foro.elhacker.net/ingenieria_inversa/tutorialcreacion_de_trainers_con_ollydbg_y_cheat_engine-t342664.0.html y no sé por qué cuando le intento hacer el hardware BP no me permite volver a utilizar la ventana del programa (olly lo bloquea incluso antes de poner el BP)

--------------------

EDIT:


Solucioné lo del olly reiniciándolo... sigo chequeando a ver qué consigo...

Mientras más hago pruebas, más me desorienta... ahora CE cambió la dirección a la que tú hacias referencia como relatia... he aquí la muestra:
001D072A - 90 - nop
001D072B - 8B 45 F8  - mov eax,[ebp-08]
001D072E - FF 80 4C010000  - inc [eax+0000014C] <<
001D0734 - 8B 45 F8  - mov eax,[ebp-08]
001D0737 - 8B 80 40010000  - mov eax,[eax+00000140]

EAX=025A391C
EBX=025C80D8
ECX=025A391C
EDX=025C7238
ESI=025C7238
EDI=0267C32C
ESP=0034EEF8
EBP=0034EF08
EIP=001D0734


Lamento la molestia amigo, tengo mucha curiosidad con éste tema...

Mad Antrax

#34
Vale, ya he podido solucionar tu problema, al final he utilizado un AOBSCAN(), es una función algo compleja en CE, y en mis años que llevo utilizando CE nunca había tenido que recurrir a ella.

AOBSCAN devuelve el offset correspondiente a un array de bytes en memoria. Tu programa ejecuta la siguiente instrucción:

xxxxxxxx - FF 80 4C010000        - inc [eax+0000014C]

El offset lo pongo en xxxxxxxx ya que es aleatorio como ya vimos por culpa del Framework, los bytes ejecutados son siempre los mismos: FF 80 4C 01 00 00 así que podemos realizar una búsqueda y obtener la dirección desde donde se ejecuta el array de bytes (xxxxxxxx). El script que permite hacer esto es el siguiente:

[ENABLE]
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
label(addr)
registersymbol(addr)
aobscan(aob1,FF 80 4C 01 00 00)

newmem:
mov [eax+0000014C],9

originalcode:
inc [eax+0000014C]

exit:
jmp returnhere

aob1:
addr:
jmp newmem
nop
returnhere:

[DISABLE]
dealloc(newmem)
addr:
db FF 80 4C 01 00 00
unregistersymbol(addr)


El script en cuestión busca el array y devuelve el offset, a partir de ahí inyectamos nuestra instrucción en newmem, en mi caso copio 9 en eax+14C, consiguiendo un script que siempre establece en 10 el valor de tu variable al sumar. Y lo mejor es que funciona siempre en cada ejecución ya que aobscan funciona en códigos dinámicos (Framework)

Te dejo mi CE_Table para que lo pruebes en tu equipo. Prueba de sumar la variable y luego activa el script, verás que la variable se establece en 10. Funciona incluso cuando la variable "salta" a otra dirección.

http://www.mediafire.com/?mgzihnw673c719z

Para que funcione la tabla, primero pulsa el botón de sumar (al menos una vez) y ya podrás activar el script, vuelve a pulsar el botón sumar y verás como el valor se transforma en 10. Debería funcionar todas las veces que ejecutes el programa. A partir de aquí ya es sencillo crear un trainer con CE

_____________________

Edit, es posible crear un registersymbol para mostrar en CE la dirección exacta de tu variable, pero eso es algo que no se hacer todavía, si lo descubro te aviso :)
No hago hacks/cheats para juegos Online.
Tampoco ayudo a nadie a realizar hacks/cheats para juegos Online.

MeTaD

Eres tremendo hombre! ;-) ;-) ;-) ;-) ¿Por qué supusiste que se podría solucionar con AOBscan?, ¿AOBscan sólo existe en CE?, de ser así, ¿Cuál sería su equivalente en vb o C#?

Mad Antrax

#36
Cita de: MeTaD en 17 Febrero 2013, 22:17 PM
Eres tremendo hombre! ;-) ;-) ;-) ;-) ¿Por qué supusiste que se podría solucionar con AOBscan?, ¿AOBscan sólo existe en CE?, de ser así, ¿Cuál sería su equivalente en vb o C#?

Haz lo siguiente, ejecuta tu programa y el CE (sin mi tabla, ejecuta el CE completamente vacío).

1. Busca y encuentra la dirección con tu variable
2. Haz click derecho "Find out what writes to this address"
3. Pulsa el botón de sumar, aparecerá la instrucción:

002A06BE - FF 80 4C010000  - inc [eax+0000014C]

4. Pulsa en Show Disassembler
6. Aparece la instrucción, haz click drecho y copia los bytes:



7. Vuelve a la ventana principal de CE, pulsa NEW SCAN, Value Type -> Array of Byte
8. En la caja de texto pulsa Ctrl+V y dale a buscar:



Como ves, esa es la forma "manual" de usar AOBSCAN(), CE nos devuelve una dirección solamente (002A06BE) que curiosamente se corresponde al offset de mi instrucción:

002A06BE - FF 80 4C010000  - inc [eax+0000014C]

---------------------------------

Para automatizar todo esto en un script, se realiza llamando a la función aobscan(), digamos que mi script hace esos pasos anteriores de forma automática y sin que te enteres :)

---------------------------------

Aobscan() es una función interna de CE, no existe equivalente en C o VB, deberías de programarlo tu con las APIs ReadProcessMemory, supongo.
No hago hacks/cheats para juegos Online.
Tampoco ayudo a nadie a realizar hacks/cheats para juegos Online.

MeTaD

AoBSCAN significa Array of Bytes scan y también son conocidos como SigScans o Signature Scans...

Ya con estos datos me puse a navegar en internet y conseguí lo siguiente en el foro de CE:

[ USAGE ] ------------------------------------------------------------------------------
//
// Examples:
//
//      SigScan _sigScan = new SigScan();
//      _sigScan.Process = someProc;
//      _sigScan.Address = new IntPtr(0x123456);
//      _sigScan.Size = 0x1000;
//      IntPtr pAddr = _sigScan.FindPattern(new byte[]{ 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x55, 0xFC, 0x11 }, "xxxx?xx?", 12);
//
//      SigScan _sigScan = new SigScan(someProc, new IntPtr(0x123456), 0x1000);
//      IntPtr pAddr = _sigScan.FindPattern(new byte[]{ 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x55, 0xFC, 0x11 }, "xxxx?xx?", 12);
//

http://forum.cheatengine.org/viewtopic.php?p=5243058&sid=a83fb95aee8be17a7442f61861e3b004


Un código C# que aparentemente cumple la función de un AoBSCAN... ¿Me podrías decir qué datos poner en cada espacio? no domino completamente HEX ni direcciones de memoria para intentar averiguarlo yo mismo...

---------------------------------------------------

EDIT:

Cita de: ||MadAntrax|| en 17 Febrero 2013, 22:31 PM
Haz lo siguiente, ejecuta tu programa y el CE (sin mi tabla, ejecuta el CE completamente vacío).

1. Busca y encuentra la dirección con tu variable
2. Haz click derecho "Find out what writes to this address"
3. Pulsa el botón de sumar, aparecerá la instrucción:

002A06BE - FF 80 4C010000  - inc [eax+0000014C]

4. Pulsa en Show Disassembler
6. Aparece la instrucción, haz click drecho y copia los bytes:



7. Vuelve a la ventana principal de CE, pulsa NEW SCAN, Value Type -> Array of Byte
8. En la caja de texto pulsa Ctrl+V y dale a buscar:



Como ves, esa es la forma "manual" de usar AOBSCAN(), CE nos devuelve una dirección solamente (002A06BE) que curiosamente se corresponde al offset de mi instrucción:

002A06BE - FF 80 4C010000  - inc [eax+0000014C]

---------------------------------

Para automatizar todo esto en un script, se realiza llamando a la función aobscan(), digamos que mi script hace esos pasos anteriores de forma automática y sin que te enteres :)

---------------------------------

Aobscan() es una función interna de CE, no existe equivalente en C o VB, deberías de programarlo tu con las APIs ReadProcessMemory, supongo.

Gracias! me ha quedado claro cómo se mueve un AoB

Mad Antrax

Cita de: MeTaD en 17 Febrero 2013, 22:38 PM
AoBSCAN significa Array of Bytes scan y también son conocidos como SigScans o Signature Scans...

Ya con estos datos me puse a navegar en internet y conseguí lo siguiente en el foro de CE:

[ USAGE ] ------------------------------------------------------------------------------
//
// Examples:
//
//      SigScan _sigScan = new SigScan();
//      _sigScan.Process = someProc;
//      _sigScan.Address = new IntPtr(0x123456);
//      _sigScan.Size = 0x1000;
//      IntPtr pAddr = _sigScan.FindPattern(new byte[]{ 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x55, 0xFC, 0x11 }, "xxxx?xx?", 12);
//
//      SigScan _sigScan = new SigScan(someProc, new IntPtr(0x123456), 0x1000);
//      IntPtr pAddr = _sigScan.FindPattern(new byte[]{ 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x55, 0xFC, 0x11 }, "xxxx?xx?", 12);
//

http://forum.cheatengine.org/viewtopic.php?p=5243058&sid=a83fb95aee8be17a7442f61861e3b004


Un código C# que aparentemente cumple la función de un AoBSCAN... ¿Me podrías decir qué datos poner en cada espacio? no domino completamente HEX ni direcciones de memoria para intentar averiguarlo yo mismo...

Pues sintiéndolo mucho, no tengo ni idea :( Al parecer 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x55, 0xFC, 0x11 se traduce como aobscan(FF FF FF 51 55 FC 11) y supongo que la función devuelve la dirección encontrada. Deberías hacer pruebas o preguntar en ese mismo hilo (yo no tengo ni idea de C).

De todas fromas, porqué quieres hacer el trainer en C? CE trae su propio intérprete LUA para generar trainers, en el foro de CE hay muchísimos ejemplos sobre como generar trainers con CE LUA, pudiendo llamar a las funciones internas de aobscan de forma sencilla.

Por cierto, has probado de hacer el aobscan "manual" como te he explicado? Es la forma más sencilla para ver como funciona.
No hago hacks/cheats para juegos Online.
Tampoco ayudo a nadie a realizar hacks/cheats para juegos Online.

MeTaD

Cita de: ||MadAntrax|| en 17 Febrero 2013, 22:44 PM
Pues sintiéndolo mucho, no tengo ni idea :( Al parecer 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x55, 0xFC, 0x11 se traduce como aobscan(FF FF FF 51 55 FC 11) y supongo que la función devuelve la dirección encontrada. Deberías hacer pruebas o preguntar en ese mismo hilo (yo no tengo ni idea de C).

De todas fromas, porqué quieres hacer el trainer en C? CE trae su propio intérprete LUA para generar trainers, en el foro de CE hay muchísimos ejemplos sobre como generar trainers con CE LUA, pudiendo llamar a las funciones internas de aobscan de forma sencilla.

Por cierto, has probado de hacer el aobscan "manual" como te he explicado? Es la forma más sencilla para ver como funciona.

Si amigo, lo acabo de hacer y ha resultado como dijiste, el motivo por el cual quiero hacerlo en C# es porque quiero aprender cómo puede manejar la memoria un lenguaje interpretado como lo es C# bajo .net framework... probaré el código que acabo de conseguir y te cuento como me va... ¿Leíste el PM que te mandé?