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
// // 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
// // 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).aspxy 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:
Código:
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 .
Proyecto vc6: http://www.mediafire.com/?8a65cuufh2dd4um