Tutorial: Crear un parche 1 (desde otro proceso)

Iniciado por 85, 6 Marzo 2013, 04:09 AM

0 Miembros y 1 Visitante están viendo este tema.

85

NIVEL: Beginner
La continuación de este tutorial:
http://foro.elhacker.net/programacion_cc/tutorial_crear_un_parche_1-t384060.0.html

En este caso contamos con 2 ejecutables .EXE ;
dummy.EXE va a ser el proceso víctima y parche1_externo.EXE
va a ser el proceso atacante, por decirlo así..


Cuando se abre el 2do ejecutable mencionado, el proceso atacante queda a la espera de encontrar al proceso víctima.








Dummy.EXE
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// 2013
//

///////////////////

#include<windows.h>
#include<stdio.h>

//////////////////////
//////////////////////

DWORD dwPatchPlace = 0x00000000;
BYTE Opcode_JZ = 0x74;

///////////
////////////////////

void Target(){

while(1){


#define MASTERNUM 85
int master=0x99999997;
char* ingreso = new char[256];

system("cls");
printf("Ingrese la llave maestra\n");
scanf("%s", ingreso);

if(!strcmpi(ingreso, new char[]= "key85\0")){

master = 85;
}

delete []ingreso;
if(master==MASTERNUM)
{
printf("FELICITACIONES! USTE HA INGRESADO\n");
printf("\n");
system("pause");
break;
}

// if(GetAsyncKeyState(VK_END)) break;// En otro hilo
if(!strcmpi(ingreso, new char[]= "exit\0")) break;
}
}

//
void Check()//Función que representa un método de seguridad
{
if(*(PBYTE)dwPatchPlace != Opcode_JZ)
{
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("Memoria alterada!, se sale del programa..\n");
printf("\n");
system("pause");
ExitProcess(45);
}
}

/////////

int main(){

SetConsoleTitle("Dummy");

dwPatchPlace=(DWORD)GetModuleHandle(NULL);//Retorna la BaseAddress

//Sumamos el offset obtenido del desensamblado
dwPatchPlace+=0x00001000;
dwPatchPlace+=0x6C;

//Logs

printf("LOG DE SEGURIDAD PRIMARIO:\n");
printf("0x%X\n",(DWORD)GetModuleHandle(NULL));
printf("0x%X\n",dwPatchPlace);
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("\n");
system("pause");

//Llamamos a la función
Target();

printf("LOG DE SEGURIDAD SECUNDARIO:\n");
printf("0x%X\n",(DWORD)GetModuleHandle(NULL));
printf("0x%X\n",dwPatchPlace);
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("\n");
system("pause");

//Se deja que las comprobaciones de seguridad sigan su curso
Check();

return 0;
}


parche1_externo.EXE
Código (cpp) [Seleccionar]


//
// By 85
// GetModuleBase (googleada en 5 segundos XD)
// elhacker.net
// etalking.com.ar
// 2013
//

///////////////////

#include<windows.h>
#include<stdio.h>
#include<tlhelp32.h>

//////////////////////

HANDLE hProcess;  
HANDLE hModule;
DWORD dwPatchPlace = 0x00000000;
BYTE Opcode_JZ = 0x74;
BYTE Opcode_JNZ = 0x75;
BYTE pReaden;

///////////

VOID Patch() {

// printf("0x%X\n",pReaden);
// system("pause");

if(!hProcess) return;
if(pReaden!=Opcode_JZ) return;

DWORD dwOldProtect;
   VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   PAGE_EXECUTE_WRITECOPY,
                   &dwOldProtect );

   WriteProcessMemory( hProcess,
                       (LPVOID)dwPatchPlace,
                       &Opcode_JNZ,
                       1,
                       NULL );

   VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   dwOldProtect,
                   &dwOldProtect );
}

//
////////////////////

DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId)
{
  MODULEENTRY32 lpModuleEntry = {0};
  HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId );

  if(!hSnapShot)
     return NULL;
  lpModuleEntry.dwSize = sizeof(lpModuleEntry);
  BOOL bModule = Module32First( hSnapShot, &lpModuleEntry );
  while(bModule)
  {
  //printf("%s\n",lpModuleEntry.szModule);
     if(!strcmp( lpModuleEntry.szModule, lpModuleName ) )
     {
        CloseHandle( hSnapShot );
        return (DWORD)lpModuleEntry.modBaseAddr;
     }
     bModule = Module32Next( hSnapShot, &lpModuleEntry );
  }
  CloseHandle( hSnapShot );
  return NULL;
}

int main(){

// We have to replace JZ with JNZ.

//TODO: Obtener privilegios
//

char l_exe[] = {'d','u','m','m','y','.','e','x','e',0};
char l_window[] = {'D','u','m','m','y',0};
HWND hwnd;          
hwnd = FindWindow(0, l_window);    
if (!hwnd)    
{        
printf("Abre %s ahora.\n", l_exe);        
while (1)      
{            
Sleep(1000);            
hwnd = FindWindow(0, l_window);            
if (hwnd) break;
if (GetAsyncKeyState(VK_END)>0) ExitProcess(45);
}            
}

unsigned long pid;    
GetWindowThreadProcessId( hwnd, &pid);    
// hProcess=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,0,pid);
// hProcess=OpenProcess(PROCESS_VM_WRITE|PROCESS_VM_OPERATION,0,pid);
hProcess=OpenProcess(PROCESS_ALL_ACCESS,0,pid);

HANDLE baseAddress = (HANDLE)GetModuleBase(l_exe, pid);
if(!baseAddress)
{
printf("No se obtubo la baseAddress!\n");
system("pause");
ExitProcess(45);
}

//Lugar del parche
dwPatchPlace=(DWORD)baseAddress;
dwPatchPlace+=0x00001000;
dwPatchPlace+=0x6C;

//Logs
printf("hProcess: 0x%X\n",hProcess);
printf("pid: %d\n",pid);
printf("dwPatchPlace: 0x%X\n",dwPatchPlace);
// printf("0x%X\n",*(PBYTE)dwPatchPlace);//No se puede hacer esto para otro proceso
if(ReadProcessMemory(hProcess,(void*)(dwPatchPlace),&pReaden,sizeof(pReaden),0))
{
printf("Lugar antes de parchear: 0x%X\n",pReaden);
}
else
printf("ReadProcessMemory failed: %d\n",GetLastError());

system("pause");

//Se procede a parchear el proceso objetivo
Patch();

if(ReadProcessMemory(hProcess,(void*)(dwPatchPlace),&pReaden,sizeof(pReaden),0))
{
printf("Lugar luego de parchear: 0x%X\n",pReaden);
}
else
printf("ReadProcessMemory failed: %d\n",GetLastError());


CloseHandle(hProcess);
system("pause");
return 0;
}

//


La finalidad es la misma que la primer parte del tutorial, es decir parchear un OPCODE en la memoria del proceso víctima. Las novedades son que se hizo desde otro proceso por lo que SI se tuvo que usar ReadProcessMemory y WriteProcessMemory (Sin mencionar las otras API's).

Para detectar si la ventana del proceso víctima se encuentra abierta se ha usado FindWindow.

Para obtener un manejador (handle) del proceso víctima usamos OpenProcess.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx

Algo también que van a querer saber:
Citar
To open a handle to another local process and obtain full access rights, you must enable the SeDebugPrivilege privilege. For more information, see Changing Privileges in a Token.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms717797(v=vs.85).aspx

y conocer los posibles derechos de acceso a un proceso:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx

Al terminar las operaciones se debe cerrar el handle del proceso.

Sobre la forma de buscar los procesos activos, se usó la función googleada 'GetModuleBase' que utiliza TOOLHELP32, para obtener la dirección base:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686832(v=vs.85).aspx

Recuerden que son dos procesos separados con sus espacios de direcciones respectivos, por lo cual se requiere ReadProcessMemory para leer la memoria de otro proceso, y para modificarla, WriteProcessMemory.

O sea que algo como esto:

printf("0x%X\n",*(PBYTE)dwPatchPlace);//No se puede hacer esto para otro proceso


No sirve porque la dirección guardada en dwPatchPlace es del proceso víctima, no del proceso atacante.
Por eso se pasa como parámetro a ReadProcessMemory.

Si quieren saber como obtener su propia 'dwPatchPlace' de un programa cualquiera, van a tener que desensamblarlo (mejor si no está protegido) o en otro caso depurarlo en funcionamiento con un depurador como el OllyDBG.
Es decir, el tutorial da por sabido que cada uno ya sabe lo que quiere parchear y adonde debe parchear. El tutorial apunta a cómo se parchea.

Disculpen si faltan cosas en este humilde tutorial, pero es para beginners por lo tanto si faltan cosas pueden aportarlas  ;D.

Proyecto vc6: http://www.mediafire.com/?8a65cuufh2dd4um
Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/