elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


 


Tema destacado: Deseas probar algunas mejoras a la interfaz del foro? Prueba cake! acerca de


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse)
| | |-+  [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] 2 Ir Abajo Respuesta Imprimir
Autor Tema: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)  (Leído 7,059 veces)
vladek

Desconectado Desconectado

Mensajes: 55


Ver Perfil
[Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« en: 23 Junio 2009, 20:10 »

[Tutorial C++] Lectura/Escritura de detos de una aplicación (externa) | Con ejercicio.

Este tutorial tiene fines totalmente didácticos. No me responsabilizo por cómo se pueda utilizar el mismo.
IMPORTANTE : Cualquier tipo de error que encuentren el el tutorial, posteenlo. De esta manera aprendemos todos.
IMPORTANTE : La parte de programación en C++ fue realizada en Visual C++ 6.0

Hoy intentaremos leer/escribir datos de una dirección de memoria dinámica (Para no complicar tanto los primeros usos de las funciones que veremos. La próxima lo integraremos con memoria estática, con punteros.)

Conocimientos previos básicos requeridos

*C/C++
*Saber qué son las direcciones de memoria

Un poco de información antes de comenzar

¿Qué son las direcciones de memoria dinámicas?

La memoria dinámica es un espacio de almacenamiento que se solicita en tiempo de ejecución. Esto quiere decir que estas direcciones, las cuales se solicitan "al momento" no siempre serán iguales. Varían, a diferencia de las direcciones de memoria estáticas (las que veremos en el próximo tutorial).

¿Qué es un puntero?

Un puntero o apuntador es una variable que referencia una región de memoria; en otras palabras es una variable cuyo valor es una dirección de memoria.
Mas claro que eso, imposible.

¿Qué es un HANDLE?

Un handle (en español "manejador") es una referencia a un objeto.
Wikipedia no podría ser mas claro :
Los handles son usados cuando una aplicación hace referencia a bloques de memoria u objetos manejados por otro sistema.

HWND se usa para referenciar a una ventana (pertenece a user32)
HANDLE para referenciar a un objeto. (pertenece a kernel32)

¿Qué software necesito?

AppLectura.exe : Una muy simple aplicación diseñada por mi, de la cual leeremos y escribiremos datos.

Cheat Engine 5.5 : Es un scanner de memoria. Nos ayudará a encontrar la dirección de memoria del dato que queremos leer/modificar.

Comenzando

1) Abramos AppLectura.exe

Como podemos ver es un programa simple. Tiene una variable llamada número cuyo valor se va elevando a medida que le sumamos números. Por ejemplo : al principio vale 0. Ingreso 2, presiono ENTER. Ahora vale 2. Si ingreso 5 y presiono Enter nuevamente, ahora vale 7. Se entiende verdad?

Esto será muy útil para poder encontrar la dirección de memoria correcta, ténganlo en cuenta.

El objetivo de este tutorial es obtener la dirección de memoria en la que está ese número para poder leerlo/modificarlo a nuestro gusto.

2) ¿Cómo obtenemos su dirección de memoria?. Abramos Cheat Engine

Cheat Engine, como dije, sirve para escanear la memoria de un programa. Analizará la memoria del programa en búsqueda de lo que le hayamos pedido.
Una vez abierto Cheat Engine, debemos decirle en qué proceso debe buscar.
Hacemos click en el botón que tiene el dibujo de una pc, justo debajo de "File".
En la lista buscamos AppLectura.exe (si lo habían cerrado, ábranlo y presionen "process list" para refrescar la lista) y le damos doble click.



Muy bien. Ahora viene lo interesante.
Como podrán ver en AppLectura.exe, el valor actual de "número" es 0 :



Para comenzar entonces, sumémosle 1 a número. (En AppLectura obviamente, ingresamos 1 y presionamos Enter)



Ahora que número tiene un valor, vamos a CheatEngine.
a) En "Value :" colocamos 1.
b) Es un valor decimal el que vamos a buscar, por lo tanto la casilla (checkbox) "Hex" debe estar deshabilitada.
c) Presionamos "New Scan".
d) En Memory Scan Options seleccionamos "All" (para hacer una búsqueda mas amplia).

Nos quedaría así :



Ahora presionemos First Scan.
Tendremos una lista de direcciones de memoria :



Tenemos demasiados resultados como para intentar descubrir cuál es la direccion que necesitamos.
Por lo tanto, cambiemos el valor de "número".
Vamos a AppLectura.exe y sumémosle 33 (Ingresamos 33 y presionamos Enter).
Ahora número vale 34

Vamos a CheatEngine.
En "Value : " ingresamos 34 y apretamos Next Scan.



Perfecto. Podemos estar seguros que ésa es nuestra dirección.
PD : Recordá que estamos trabajando con memoria dinámica, no deberías preocuparte si ves una dirección de memoria diferente.

Anoten esa dirección en un bloc de notas.
En mi caso 0012FF64

Ya podemos cerrar el Cheat Engine.

3) Construyendo nuestra aplicación, y leyendo datos de AppLectura.exe

Inicien un nuevo proyecto, una aplicación de consola win32 en blanco.
Agreguen un .cpp (en mi caso le puse main.cpp)
Escribamos un esqueleto básico para una aplicación de consola win32.

Código:
#include <iostream>

int main()
{
system("pause > nul");
return 0;
}

Primero utilizaremos la función FindWindow para obtener el handle a la ventana de AppLectura. El primer parámetro de FindWindow será nulo ya que no conocemos el nombre de la clase de la ventana de AppLectura.exe. El segundo parámetro es el título de la ventana de la cual queremos obtener el handle.
Ustedes se preguntarán, para qué quiero obtener su handle?
Al obtener su handle, obtenemos la id del proceso y al obtener la id del proceso, obtenemos el handle del proceso el cual es necesario para leer/modificar direcciones de memoria externas con ReadProcessMemory y WriteProcessMemory.

Código:
#include <iostream>
#include <windows.h>

int main()
{
HWND hVentana;
if (!(hVentana = FindWindow(NULL,"AppLectura")))
{
MessageBox(NULL,"No se pudo encontrar la ventana","Error",MB_OK);
}
system("pause > nul");
return 0;
}

Ahora obtengamos el ID y finalmente el handle :

Código:
#include <iostream>
#include <windows.h>

int main()
{
HWND hVentana;
DWORD pid;
HANDLE hProcess;
if (!(hVentana = FindWindow(NULL,"AppLectura")))
{
MessageBox(NULL,"No se pudo encontrar la ventana","Error",MB_OK);
return -1;
}
if (!(GetWindowThreadProcessId(hVentana,&pid)))
{
MessageBox(NULL,"No se pudo encontrar el ID del proceso","Error",MB_OK);
return -1;
}
if (!(hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,pid)))
{
MessageBox(NULL,"No se pudo obtener el handle del proceso","Error",MB_OK);
return -1;
}
system("pause > nul");
return 0;
}
Se entiende?
Usé FindWindow para encontrar el handle de la ventana.
Luego GetWindowThreadProcessId para obtener el id del proceso.
Luego OpenProcess para obtener el handle del proceso.
Para poder usar GetWindowThreadProcessId necesité usar FindWindow, ya que un parámetro es el handle de la ventana. Para OpenProcess necesité usar GetWindowThreadProcessId, ya que un parámetro es el id del proceso.
Espero ser claro, no es tan complicado como parece.

Ya podemos usar ReadProcessMemory
Vamos a explicar los parámetros de ReadProcessMemory.
ReadProcessMemory(HANDLE hProcess,LPCVOID lpBaseAddress,LPVOID lpBuffer,SIZE_T nSize,SIZE_T *lpNumberOfBytesRead)

HANDLE hProcess = Handle al proceso.
LPCVOID lpBaseAddress = Puntero constante(ya que la función no lo va a modificar) del cual se van a leer los datos (nuestra direccion de memoria)
LPVOID lpBufer = Puntero a la dirección (variable) que será usado como buffer (para guardar la lectura).
SIZE_T nSize = El numero de bytes que se van a leer (en esto se puede ser mas específico luego de usar la función por primera vez).
SIZE_T lpNumberOfBytesRead = Un puntero a la variable que recibe la cantidad de bytes leídos.

Una vez explicado esto :

Código:
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
HWND hVentana;
DWORD pid;
HANDLE hProcess;
DWORD buffer;
DWORD BytesT;
if (!(hVentana = FindWindow(NULL,"AppLectura")))
{
MessageBox(NULL,"No se pudo encontrar la ventana","Error",MB_OK);
return -1;
}
if (!(GetWindowThreadProcessId(hVentana,&pid)))
{
MessageBox(NULL,"No se pudo encontrar el ID del proceso","Error",MB_OK);
return -1;
}
if (!(hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,pid)))
{
MessageBox(NULL,"No se pudo obtener el handle del proceso","Error",MB_OK);
return -1;
}
ReadProcessMemory(hProcess,(LPCVOID)0x0012FF64,&buffer,sizeof(buffer),&BytesT);
cout << "Numero vale : " << buffer << endl;
system("pause > nul");
return 0;
}

Perfecto. Si compilamos y ejecutamos, vemos que siempre nos dirá el valor actual de la direccion de memoria de AppLectura.exe

Ahora trataremos de modificar el valor de "numero" de AppLectura.exe
Es decir, modificar el contenido de la direccion de memoria.
Esto se hace con WriteProcessMemory.
Vamos a explicar los parametros de WriteProcessMemory.
WriteProcessMemory(HANDLE hProcess,LPVOID lpBaseAddress,LPCVOID lpBuffer,SIZE_T nSize,SIZE_T *lpNumberOfBytesWritten)

HANDLE hProcess = Handle al proceso.
LPVOID lpBaseAddress : Puntero a la direccion de memoria que se va a modificar.
LPCVOID lpBuffer : Puntero constante(ya que no se modificara su contenido) a la variable que contiene los datos para escribir a la direccion de memoria.
SIZE_T nSize = Numero de bytes que serán escritos.
SIZE_T *lpNumberOfBytesWritten = Puntero a una variable que almacenará la cantidad de bytes transferidos.

Explicado esto, podemos hacer el código :

Código:
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
HWND hVentana;
DWORD pid;
HANDLE hProcess;
DWORD buffer;
DWORD BytesT;
long Numero_Nuevo = 500;
if (!(hVentana = FindWindow(NULL,"AppLectura")))
{
MessageBox(NULL,"No se pudo encontrar la ventana","Error",MB_OK);
return -1;
}
if (!(GetWindowThreadProcessId(hVentana,&pid)))
{
MessageBox(NULL,"No se pudo encontrar el ID del proceso","Error",MB_OK);
return -1;
}
if (!(hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,pid)))
{
MessageBox(NULL,"No se pudo obtener el handle del proceso","Error",MB_OK);
return -1;
}
if (!(ReadProcessMemory(hProcess,(LPCVOID)0x0012FF64,&buffer,sizeof(buffer),&BytesT)))
{
MessageBox(NULL,"No se pudo leer la direccion de memoria","Error",MB_OK);
return -1;
}
cout << "Numero vale : " << buffer << endl;
cout << "Numero de bytes leidos : " << BytesT << endl;
if (!(WriteProcessMemory(hProcess,(LPVOID)0x0012FF64,&Numero_Nuevo,sizeof(Numero_Nuevo),&BytesT)))
{
MessageBox(NULL,"No se pudo escribir la direccion de memoria","Error",MB_OK);
return -1;
}
cout << "Se escribio con exito la direccion de memoria" << endl;
cout << "Se le dio el siguiente valor : " << Numero_Nuevo << endl;
cout << "Numero de bytes escritos : " << BytesT << endl;
cout << "Presione una tecla para salir..." << endl;
system("pause > nul");
return 0;
}

Donde Numero_Nuevo es una variable que creamos. Le di un valor de 500 (este es el valor que se le dará a "numero" de AppLectura.exe).
Compilemos y ejecutemos.

En este momento entonces tenemos abierto por un lado, AppLectura.exe y por el otro nuestra nueva aplicación.
Nuestra nueva aplicación (si todo fue bien) ya debe haber modificado el valor de la dirección de memoria de AppLectura.exe a 500.

¿Cómo comprobamos esto?

En AppLectura.exe ingresemos por ejemplo 2 y presionemos Enter. Tendría que dar de resultado 502 (Ya que nuestra nueva aplicación cambio su valor por 500).
Si ingresaramos 10 y luego enter valdría 510.

En esta screen ya le sumé el numero 2.


Funciona perfecto.

------------------------------------------------------------------------------------------
Agradecimientos

A Eternal Idol por su ayuda con el tema de los Handles.
------------------------------------------------------------------------------------------
Con esto ya tienen para practicar.

En el próximo tutorial veremos cómo utilizar los punteros estáticos, para que nuestra aplicación pueda leer los datos desde cualquier computadora y no nos tengamos que preocupar por la memoria dinámica.

Si tienen alguna duda pregunten y trataré de ayudarles en lo que pueda.



« Última modificación: 23 Junio 2009, 20:15 por vladek » En línea

h0oke


Desconectado Desconectado

Mensajes: 2.059


Coder ~


Ver Perfil WWW
Re: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« Respuesta #1 en: 23 Junio 2009, 20:16 »

+1
Básicos y simples, lo he leído muy por encima y parece interesante.
Espero que sigas con esto  ;)


En línea

vladek

Desconectado Desconectado

Mensajes: 55


Ver Perfil
Re: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« Respuesta #2 en: 23 Junio 2009, 20:18 »

Gracias Emt.dev
Me alegro que te guste.

Un saludo.
En línea

h0oke


Desconectado Desconectado

Mensajes: 2.059


Coder ~


Ver Perfil WWW
Re: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« Respuesta #3 en: 23 Junio 2009, 20:19 »

Supongo que seguiras con dll injection verdad?
En línea

vladek

Desconectado Desconectado

Mensajes: 55


Ver Perfil
Re: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« Respuesta #4 en: 23 Junio 2009, 20:22 »

Si si tambien.
Con este tutorial quería demostrar  que no sólo se pueden utilizar datos de otro programa utilizando DLL Injection.

Pero ya haré otro de inyección de DLL  :P
En línea

h0oke


Desconectado Desconectado

Mensajes: 2.059


Coder ~


Ver Perfil WWW
Re: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« Respuesta #5 en: 23 Junio 2009, 20:35 »

Lo que me interesaría sería la parte de calculos de offset. Esta parte digamos que la puedes hacer directamente con el CE. Esto es una cosa que no practico desde hace mucho tiempo, ya que generalmente la utilizaba para el hacking de juegos, pero ciertas veces no se podía modificar directamente la memoria y creo que había que crear un puntero para que la dirección se mantenga estática, me gustaría que expliques esta parte.

Éxitos!
En línea

vladek

Desconectado Desconectado

Mensajes: 55


Ver Perfil
Re: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« Respuesta #6 en: 23 Junio 2009, 20:40 »

Si, estaba guardando el Offset para el próximo tutorial (estaba a punto de ponerlo en este mismo)
Puede ser en cualquiera de los dos tutos, en estos de ReadProcessMemory y WriteProcessMemory o en el otro.
Va a ser mejor en estos de ReadProcessMemory porque generalmente lo sumas para obtener la dirección de memoria deseada.
También voy a tratar de obtener la ImageBase o la dirección base del programa con C++.

PD : Para practicar también podemos averiguar el Offset en Cheat Engine y sumarlo en C++.

Solías hackear juegos? Yo también, hacía DLL Hacks para GunZ ijji.
« Última modificación: 23 Junio 2009, 20:43 por vladek » En línea

h0oke


Desconectado Desconectado

Mensajes: 2.059


Coder ~


Ver Perfil WWW
Re: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« Respuesta #7 en: 23 Junio 2009, 20:50 »

Citar
Solías hackear juegos?
Si ^^ con esto me introduje y me empezó a gustar la informática.
Citar
Para practicar también podemos averiguar el Offset en Cheat Engine y sumarlo en C++
Me parece una buena idea. Además podrías sumar partes de los codes de Mazard para profundizar un poco las técnicas, pero por el momento está muy bien lo que haces ya que estas dando una introducción. Es por eso que deseo que tu proyecto avance y llegues a crear un tuto completo hasta técnicas avanzadas. Además no tendrás problemas en consultar si tienes dudas, ya que expertos como E0N, EI, Mazard, Karman, seguramente responderán tus dudas.
En línea

vladek

Desconectado Desconectado

Mensajes: 55


Ver Perfil
Re: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« Respuesta #8 en: 23 Junio 2009, 20:51 »

Si, a decir verdad no soy un experto en Assembler ni Debugging.
También estoy aprendiendo.
Pero bueno por algo se empieza no?  :P
En línea

braulio--
Wiki

Desconectado Desconectado

Mensajes: 896


Imagen recursiva


Ver Perfil WWW
Re: [Tuto-C++] Lectura/Escritura de datos de una aplicación externa. (Con ejercicio)
« Respuesta #9 en: 23 Junio 2009, 21:11 »

Me encantan tus tutos, sigue así
A ver si haces alguno de infeccion de ejecutables
« Última modificación: 23 Junio 2009, 21:23 por char *braulio23; » En línea

Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
[Ayuda] Modificar aplicacion externa
Programación C/C++
.mokk. 1 946 Último mensaje 6 Febrero 2011, 22:32
por Eternal Idol
Redireccionar descargas de una aplicación externa
Hacking Avanzado
mrsnake 1 1,109 Último mensaje 28 Agosto 2011, 00:51
por Luna71c0
¿Ejecutar una aplicacion externa en memoria?
Java
Seritx 1 1,457 Último mensaje 15 Marzo 2012, 21:00
por sapito169
Sobre lectura de varios datos a la vez
Java
zonahurbana 9 1,849 Último mensaje 3 Marzo 2014, 13:04
por ThinkByYourself
Problema lectura de datos
Programación C/C++
Ockdatone 3 533 Último mensaje 11 Febrero 2014, 13:51
por eferion
Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines