[Aportes indexados] Read&Write ProcessMemory

Estado
Cerrado para nuevas respuestas.

Zirelay.

Newbie Lvl 4
Buenas!

Ayer un amigo me pidió que lo ayude a cambiar la ip de un mod tp 5.0; recuerdo haber probado una vez y la ip no podías encontrarla a simple vista buscando en el binario la string.

Como mis conocimientos sobre cracking y asm son bastante escasos, se me ocurrió directamente editar la memoria una vez que el exe estuviera corriendo.

Para aprovechar la ocasión, les dejo el code de una consolita en C++ que hace uso de las apis ReadProcessMemory y WriteProcessMemory; no es gran cosa pero puede venir bastante bien a los principiantes como yo a aclarar un par de dudas sobre el uso de las mismas.

El programa básicamente hace tres cosas: levanta el cliente, abre el proceso para lectura/escritura, y lee y escribe la ip cambiándola a localhost.

He aquí server y cliente para testear: Server-Cliente TP5.0

El programa ya se encuentra compilado en la carpeta del cliente "launcher.exe", solo deben inciarlo y hará el resto.

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

using namespace std;;
using std::hex;

HANDLE hProc;
HWND hWnd;
DWORD pId;
int EstaticPtr = 0x006D50C8;
int RandomPtr;
int ipStrLen;

void LaunchClient(){
    
     TCHAR s[100];
     char str[100];
    
     DWORD a = GetCurrentDirectory(100, s);

     strcpy(str, s);
     strcat(str, "\\Cliente.exe");
     ShellExecute(NULL,"open",str,NULL,NULL,SW_SHOWNORMAL);
     cout << "Abriendo: " << str << endl;
}

void SeekPointers(){
  
     ReadProcessMemory(hProc, (void*)EstaticPtr, &RandomPtr, sizeof(DWORD),0);
        
     ipStrLen = RandomPtr -4;

}

int IsClient(){
    
     char n;
     bool is = 0;
    
     //cout << "Esperando para cargar IP: ";
     while (!is){
           hWnd = GetForegroundWindow();
           GetWindowThreadProcessId (hWnd, &pId);
           hProc = OpenProcess(PROCESS_VM_READ, FALSE, pId);
          
           SeekPointers();
          
           ReadProcessMemory(hProc,(void*)ipStrLen,&n, sizeof(BYTE), 0);
          
           if (n==38){
              ReadProcessMemory(hProc,(void*)RandomPtr,&n, sizeof(BYTE), 0);
              if (n==112){ is = 1; cout << endl; return pId; }
           }
           else {//Entonces no es cliente
                CloseHandle(hProc);
                Sleep(500);
           }
     }
}

void OpenProc(){
    
     pId = IsClient();
     hProc = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pId);   
}

void DataLocation(){
    
     cout << endl;
     cout << "ipStrLen: " << hex << uppercase << ipStrLen << endl;     
     cout << "RandomPtr: " << hex << uppercase << RandomPtr << endl;
}

void ReadIp(){
     
     int Len;
     int RandomPtrAux = RandomPtr;
     char ip;
     
     ReadProcessMemory(hProc,(void*)ipStrLen,&Len, sizeof(BYTE), 0);
     
     for(int i=0; i<Len/2; i++){
              ReadProcessMemory(hProc,(void*)RandomPtrAux,&ip, sizeof(BYTE), 0);
              cout << ip;
              RandomPtrAux = RandomPtrAux +2;
     }
}

void WriteMemory(){
    
     char NewStrLen = 18;
     char LocalHostStr[18] = {'\x31', '\x00', '\x32', '\x00', '\x37', '\x00',
                              '\x2E', '\x00', '\x30', '\x00', '\x2E', '\x00',
                              '\x30', '\x00', '\x2E', '\x00', '\x31', '\x00'};
          
     WriteProcessMemory(hProc,(void*)(ipStrLen),&NewStrLen, sizeof(BYTE), 0);
     WriteProcessMemory(hProc,(void*)(RandomPtr),&LocalHostStr, sizeof(LocalHostStr), 0);
}

void Bye(){
    cout << endl << "IP cambiada a: "; ReadIp(); cout << endl << endl;
    Sleep(5000);
}

int main(){
  
    LaunchClient();                              //Abre Cliente.exe desde el mismo directorio.
    OpenProc();                                  //Encuentra y accede a Cliente.exe
    SeekPointers();                              //Busca las direcciones de Lenght y String de la ip.
    //DataLocation();                            //*Seguimiento* (dice donde estan los punt).
    //cout << "IP por defecto: "; ReadIp();      //*Seguimiento* (muestra ip por defecto).
    WriteMemory();                               //Escribe la nueva ip.
    //cout << "Nueva IP: "; ReadIp();            //*Seguimiento* (muestra nueva ip)
    Bye();
}

Nota: La función IsClient es una forma improvisada de obtener el handle al proceso, ya que al no contar con un WindowName tomo el handle de la ventana activa, para eso entonces, tengo que entrar a comprobar que la memoria que voy a escribir es realmente la del cliente y no otra cosa.

Es el segundo programita que hago fuera del ámbito de la facu, ¡son bienvenidas las críticas!

IDE: CodeBlocks
 
Última edición:

0xDEADBEEF

Vicinity of obscenity
Ex-Staff
Estaria bien que expliques el significado de los opcodes, o de el read que haces, cuando comparas n contra esos valores hardcodeados, o porque iteras sobre el string cada 2 bytes.

Yo intuyo o se de donde vienen, pero quiza otras personas no.

Para entender la prueba de concepto se necesita entender el analisis previo que haces sobre el programa al cual vas a atacar.

Por lo demas me parece genial que lo aportes, ayuda a entender el funcionamiento del nivel bajo.
 
W

Wolftein

Invitado
Código:
[LIST=1]
[*]void WriteMemory(){
[*]     
[*]     char NewStrLen = 18;
[*]     char LocalHostStr[18] = {'\x31', '\x00', '\x32', '\x00', '\x37', '\x00',
[*]                              '\x2E', '\x00', '\x30', '\x00', '\x2E', '\x00',
[*]                              '\x30', '\x00', '\x2E', '\x00', '\x31', '\x00'};
[*]           
[*]     WriteProcessMemory(hProc,(void*)(ipStrLen),&NewStrLen, sizeof(BYTE), 0);
[*]     WriteProcessMemory(hProc,(void*)(RandomPtr),&LocalHostStr, sizeof(LocalHostStr), 0);
[*]}
[/LIST]
Código:
void Writememory()
{
   auto sbData = L"127.0.0.1";
   auto sbLen   = strlenW(sbData);

   WriteProcessMemory(hProc, (void*)(ipStrLen), &sbLen, sizeof(BYTE), 0)
   WriteProcessMemory(hProc, (void*)(RandomPtr), &sbData, sbLen * 0x02, 0)
}
 

Zirelay.

Newbie Lvl 4
Estaria bien que expliques el significado de los opcodes, o de el read que haces, cuando comparas n contra esos valores hardcodeados, o porque iteras sobre el string cada 2 bytes.

Yo intuyo o se de donde vienen, pero quiza otras personas no.

Para entender la prueba de concepto se necesita entender el analisis previo que haces sobre el programa al cual vas a atacar.

Por lo demas me parece genial que lo aportes, ayuda a entender el funcionamiento del nivel bajo.
La verdad que mirándolo con un poco más de objetividad me percato que no es la mejor forma de mostrar lo que pretendo.

Los valores del array son dato, no code; fué una manera improvisada de escribir la string en unicode, no se me ocurría otra cosa.

La función ReadIp es nefasta, debería haberla borrado. En el momento tenía la cabeza quemada y ahora que la veo denuevo no recuerdo por qué motivo la hice así.

Debería haber sido así para ser genérica:

Código:
void ReadIp(){
     
     int Len;
     int RandomPtrAux = RandomPtr;
     char ip; 
     
     ReadProcessMemory(hProc,(void*)ipStrLen,&Len, sizeof(BYTE), 0);
     
     for(int i=0; i<Len/2; i++){
              ReadProcessMemory(hProc,(void*)RandomPtrAux,&ip, sizeof(BYTE), 0);
              cout << ip;
              RandomPtrAux = RandomPtrAux +2;
     }
}

Respecto a iterar cada 2 bytes es porque tengo que escribir y dejar el siguiente byte en 'x00' (podría haber usado una función que me convierta la cadena pero andaba corto de tiempo para googlear e interpretar como usarla)

En fin, tengo experiencia casi nula programando; ésto lo hice porque el objetivo principal era cambiar la ip, y bueno, me las arreglé como pude con lo poco que sabía de la sintaxis y semántica de C++.

Ojalá en vacas de invierno tenga el tiempo suficiente para aprender más, me gustó bastante volver a programar después de casi 4 meses :p


Se puede modificar de la misma forma con el olly y guardar el exe jaj
Tiene una especie de "encriptación", lo digo entre comillas porque es muy pete, pero al fin y al cabo la encripta, y no se puede buscar tan facil; como no tenía ganas de dar vueltas con olly tocando cosas que ni sé que son, preferí optar por codear, porque sabia que por más que me llevara un rato lo iba a sacar andando.

Código:
[LIST=1]
[*]void WriteMemory(){
[*]    
[*]     char NewStrLen = 18;
[*]     char LocalHostStr[18] = {'\x31', '\x00', '\x32', '\x00', '\x37', '\x00',
[*]                              '\x2E', '\x00', '\x30', '\x00', '\x2E', '\x00',
[*]                              '\x30', '\x00', '\x2E', '\x00', '\x31', '\x00'};
[*]          
[*]     WriteProcessMemory(hProc,(void*)(ipStrLen),&NewStrLen, sizeof(BYTE), 0);
[*]     WriteProcessMemory(hProc,(void*)(RandomPtr),&LocalHostStr, sizeof(LocalHostStr), 0);
[*]}
[/LIST]
Código:
void Writememory()
{
   auto sbData = L"127.0.0.1";
   auto sbLen   = strlenW(sbData);

   WriteProcessMemory(hProc, (void*)(ipStrLen), &sbLen, sizeof(BYTE), 0)
   WriteProcessMemory(hProc, (void*)(RandomPtr), &sbData, sbLen * 0x02, 0)
}
much better, estoy seguro que con un poco más de experiencia podría reducir todo a casi la mitad; qué gracioso va a ser volver a leer el code algún día, seguramente quiera darme la cabeza contra la pared (?
 
Estado
Cerrado para nuevas respuestas.
Arriba