Test: WinXP SP3
Considerando los tutoriales anteriores que no usaban una DLL,
http://foro.elhacker.net/programacion_cc/tutorial_crear_un_parche_1-t384060.0.html
http://foro.elhacker.net/programacion_cc/tutorial_crear_un_parche_1_desde_otro_proceso-t384798.0.html
... o bien la cargaban por medio de un LoadLibrary en el ejecutable víctima. En realidad, la mayoría de las veces nadie va a cargar nuestra DLL voluntariamente por lo que va a ser necesario forzar al proceso víctima a que la cargue, o también se puede hacer que el sistema operativo lo haga.
Podemos crear un cargador (Loader), y hacer lo que se conoce como inyección de DLL.
CreateRemoteThread
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682437(v=vs.85).aspx
Con esta función podemos crear un hilo en un proceso víctima y hacer que se haga un LoadLibrary de nuestra DLL.
Una cosa, esto es una técnica muy conocida y si la finalidad es hacer un hack lo que va a pasar es que cualquier antivirus o sistema de seguridad va a detectarlo. Por eso, esta creo que es la forma que más se conoce para cargar una DLL en un proceso víctima, pero no es ni la única ni la mejor.
Pero si la finalidad es cargar una DLL en algún proceso que no involucre por ejemplo, un sistema antitrampas, entonces no hay drama.
Los parámetros 4 y 5 de CreateRemoteThread son los que hacen evidente lo que pasa. Se le pasa la dirección de LoadLibrary y luego una dirección en el proceso víctima en donde se ha escrito el nombre de nuestra DLL.
Es decir que cuando se ejecute el hilo en el proceso remoto va a ejecutarse LoadLibrary cargando nuestra DLL.
Fuera de esa explicación básica sólo queda dejar la información necesaria para hacer algo así:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366890(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366894(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682437(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686736(v=vs.85).aspx
El código del inyector:
Código
// // By 85 // elhacker.net // etalking.com.ar // 2013 // /////////////////// #include<windows.h> #include<stdio.h> #include<tlhelp32.h> ////////////////////// HANDLE hProcess; typedef DWORD ((__stdcall*Add_t)(void *));//Typedef para el argumento 4 de CreateRemoteThread ///////////////// bool fileExists(const char* filename) { WIN32_FIND_DATA finddata; HANDLE handle = FindFirstFile(filename,&finddata); return (handle!=INVALID_HANDLE_VALUE); } ////////////////////////////////// int main(){ // We have to replace JZ with JNZ in another process. const char* dll_name = "hack.dll\0"; if(!fileExists(dll_name)) { printf("La DLL no se encuentra!\n"); system("pause"); ExitProcess( 0 ); } 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("El proceso objetivo debe estar corriendo!\n"); system("pause"); ExitProcess( 0 ); } Add_t AddLoadLibrary = (DWORD(__stdcall *)(void *))GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA"); unsigned long pid; GetWindowThreadProcessId( hwnd, &pid); HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, pid); HANDLE hModule = VirtualAllocEx( hProcess, 0, sizeof(dll_name), MEM_COMMIT, PAGE_EXECUTE_READWRITE ); WriteProcessMemory( hProcess, hModule, (LPVOID)dll_name, sizeof(dll_name), NULL ); CreateRemoteThread( hProcess, NULL, 0, AddLoadLibrary, hModule, 0, NULL ); CloseHandle( hProcess ); VirtualFreeEx(hProcess, (LPVOID)hModule, 0, MEM_RELEASE); //Los loaders deben generalmente cerrarse inmediatamente luego de cargar la dll en el proceso foráneo //ExitProcess( 0 ); return 0; } //////////////
El código de la DLL atacante:
Código
// // By 85 // elhacker.net // etalking.com.ar // 2013 // ////////////////////// #define WIN32_LEAN_AND_MEAN #include<windows.h> #include<stdio.h> #include<stdlib.h> ///////////////////////////////////// DWORD dwPatchPlace = 0x00000000; BYTE Opcode_JZ = 0x74; BYTE Opcode_JNZ = 0x75; /////////// inline void Patch(){//Función de parche if(*(PBYTE)dwPatchPlace!=Opcode_JZ) return; DWORD dwOldProtect; VirtualProtect( (LPVOID)dwPatchPlace, 1, PAGE_EXECUTE_WRITECOPY, &dwOldProtect ); WriteProcessMemory( GetCurrentProcess(), (LPVOID)dwPatchPlace, &Opcode_JNZ, 1, NULL ); VirtualProtect( (LPVOID)dwPatchPlace, 1, dwOldProtect, &dwOldProtect ); } //////////////////////// void Thread(void) { dwPatchPlace=(DWORD)GetModuleHandle(NULL);//Retorna la BaseAddress //Sumamos el offset obtenido del desensamblado dwPatchPlace+=0x00001000; dwPatchPlace+=0x6C; //Logs printf("\nYou have the DLL inside! (Frases memorables XD)\n"); printf("0x%X\n",(DWORD)GetModuleHandle(NULL)); printf("0x%X\n",dwPatchPlace); printf("0x%X\n",*(PBYTE)dwPatchPlace); printf("\n"); system("pause"); Patch(); } /// bool WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID) { if (fdwReason==DLL_PROCESS_ATTACH) { //Creamos un hilo local en el proceso objetivo (proceso local) CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)Thread, NULL, NULL, NULL ); } return(true); } //
Y el código del programa ‘Dummy’:
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; }
Otras formas de cargar DLL’s:
AppInit_DLLs
Agregar o utilizar imports
DLL wrappers
DBG API
SetWindowsHookEX
Usar un driver (modo kernel)
Otras..
Project:
http://www.mediafire.com/?24yxijb4ce66jiv
Nota: La descarga no tiene virus, debe ser que se detecta el uso de CreateRemoteThread.
No iba a dejar imágenes pero dejo una que explica como se usan los archivos del ejemplo:
Por una cuestión de construcción, se debe abrir el programa 'dummy' en primer lugar y luego el inyector de DLL.
Saludos