Dll Injection (Parte 2)
En la pasada parte de este articulo de programacion #2 vimos algunas de las apis necesarias para realizar el cometido de una inyeccion de una dll en el contexto de un proceso remoto, ahora veremos ya la aplicacion de las mismas.
Una de las funciones vistas crucial para lograr ejecutar esta tecnica es la funcion CreateRemoteThread, esta funcion no es mas que la funcion final en la cadena de funciones para crear un hilo. CreateRemoteThread termina invocando la funcion NtCreateThread en la libreria ntdll.dll, que asu vez invoca el servicio Nt NtCreateThread en el kernel (ntoskrnl.exe) este ultimo se encarga de crear el objeto tipo Thread necesario para el manejo y funcionamiento del mismo, el objeto que es el cuerpo del hilo creado. Es asi como esta funcion recaba un manejador o handle al proceso destino, el cual obtenemos mediante OpenProcess, la cadena es algo como:
Ahora bien, cuando un thread se crea en nuestro propio proceso, tenemos la certeza que el codigo ejecutado va a ejecutarse de la manera como lo programamos, ya que las variables y direcciones las tenemos localizadas en el contexto de memoria de nuestro proceso de la memoria virtual. Como con un thread o hilo remoto estaremos en un contexto diferente, las direcciones que querramos acceder no contendran la misma informacion que la del contexto de nuestro proceso, incluso podrian ser invalidas, recordemos el manejo de la memoria virtual, que permite que las direcciones apunten a diferentes paginas de la memoria fisica para cada proceso, diferentes mundos distintos de memoria, apuntando a una misma memoria ram.
La tecnica de inyeccion de una dll consiste en obligar a un proceso a cargar una dll, como bien aprendimos, para cargar una dll necesitamos usar la funcion LoadLibrary, pero en este caso haremos que el proceso remoto lo use sin que lo tenga en sus planes de hacerlo =), para cumplir esto, necesitamos crear un thread alterno en su contexto, ya con esto concluimos que necesitamos de crear un thread en el proceso donde queremos que cargue la dll usando CreateRemoteThread y hacer que ejecute la funcion LoadLibraryA.
HMODULE WINAPI LoadLibrary(
LPCTSTR lpFileName
);
Programando en lenguaje c o cualquier otro lenguaje, hemos visto la necesidad de alojar memoria dinamicamente, segun las necesidades de nuestro programa y no tener que estar haciendo uso de muchas variables declaradas o arreglos, asi bien, se haria con un malloc usando la libreria estandar, o hasta usando la funcion new en c++; estados dos funciones al final hacen uso de la apis de windows, la cual invoca a VirtualAlloc una api para reserver o alojar nueva memoria virtual con respecto a una nueva pagina de memoria fisica tomada del directorio de paginas de la misma. En este caso necesitamos tener un espacio de memoria en el proceso remoto, para ello no podriamos usar malloc, new o VirtualAlloc, para ello windows nos ofrece otra api llamada VirtualAllocEx, esta nos permite alojar memoria en el contexto de un proceso que no sea el nuestro, es la funcion que es invocada por VirtualAlloc usando como handle NtCurrentProcess ((HANDLE)0xFFFFFFFF). Veamos la definicion de VirtualAllocEx:
LPVOID VirtualAllocEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
Ahora ya explicada esa funcion necesitaremos de poder escribir en la memoria del proceso remoto, esto lo haremos con una funcion para depuradores de la api Win32 llamado WriteProcessMemory, veamos su definicion:
BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T* lpNumberOfBytesWritten
);
Ahora si, con todo esta teoria ya podemos empezar aplicar la tecnica =), lo que haremos es inyectar una dll llamada hack.dll en la unidad C:\ de nuestro disco en el proceso del buscaminas:
char DllPath[MAX_PATH]="C:\\hack.dll";
HWND Buscaminas;
DWORD BuscaminasPID;
HANDLE BuscaminasHandle;
HMODULE hKernel;
PVOID LoadLibraryAddress, RemoteVirtualAddress;
BOOL bSuccess;
HANDLE hRemoteThread;
/*Obtenemos la direccion base de la libreria kernel32 donde reside LoadLibraryA*/
hKernel=GetModuleHandle("kernel32.dll");
/*Buscamos en la libreria la funcion exportada*/
LoadLibraryAddress=(PVOID)GetProcAddress(hKernel, "LoadLibraryA");
/*Nota: Aqui no nos preocupamos por la memoria virtual del contexto del otro proceso con respecto a las funciones que acabos de recabar, ya que todas son proyectadas en la misma direccion de memoria en todos los procesos =)*/
/*Intentamos encontrar el handle a la ventana del buscaminas*/
Buscaminas=FindWindow(NULL, "Buscaminas");
if(!Buscaminas)
return; //error
/*Recabamos el processId del proceso que posee la ventana*/
GetWindowThreadProcessId(Buscaminas, &BuscaminasPID);
/*Abrimos una referencia al proceso con el process id obtenido*/
BuscaminasHandle=OpenProcess(PROCESS_ALL_ACCESS, FALSE, BuscaminasPID);
/*Alojamos memoria en el proceso remoto =)*/
RemoteVirtualAddress=VirtualAllocEx(BuscaminasHandle, NULL, strlen(DllPath), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
if(!RemoteVirtualAddress)
return; //error
/*Escribimos en el espacio remoto que acabamos de alojar el string al camino de la dll*/
bSuccess=WriteProcessMemory(BuscaminasHandle, RemoteVirtualAddress, DllPath, strlen(DllPath), NULL);
if(!bSuccess)
return; //error
/*Creamos el hilo remoto y pasamos de parametro la direccion de memoria donde se encuentra nuestra cadena de caracteres que tiene la ruta de nuestro ejecutable =D*/
hRemoteThread=CreateRemoteThread(BuscaminasHandle, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryAddress, (LPVOID)RemoteVirtualAddress, 0);
if(!hRemoteTHread)
return; //error
/*Esperamos a que el thread remoto termine de ejecutarse, este paso es opcional*/
WaitForSingleObject(hRemoteThread, INFINITE);
Y con esto terminamos este segundo articulo de programacion =D, espero que te haya gustado, jajaja, proximamente hare el tercero donde explicare una tecnica fundamental en la administracion del sistema operativo, recabar los procesos en el sistema, hasta la proxima xD.
No hay comentarios:
Publicar un comentario