OpenSec Development & Security Research

31Oct/080

Localizando la EPROCESS

En ciertas ocasiones, cuando estamos programando en modo kernel en sistemas Windows, nos es necesario localizar la EPROCESS de algún proceso para conocer alguno/s de sus datos. Las siguientes funciones, devuelven la dirección de memoria de la EPROCESS del proceso indicado, o bien por el PID del proceso, o por el nombre de la imagen.

Localizar según el PID

unsigned long BuscaEPROCESSPidDKOM(unsigned int Pid)
{
	unsigned long 	eproc,aux,proceso,ret;
	PLIST_ENTRY 	lista;
	unsigned int 	idProceso=0;

	eproc=(unsigned long)PsGetCurrentProcess();//estamos en "System"
	//tenemos los punteros al siguiente y al anterior
	lista=(LIST_ENTRY*)(eproc+0×88);
	aux=(unsigned long)lista->Blink;
	proceso=(unsigned long)lista;
	idProceso=*((int *)(proceso+0×84));

	while(proceso!=0 && aux!=proceso && Pid!=idProceso)//recorremos la lista
	{
		proceso-=0×88;
		ret=proceso;
		idProceso=*((int *)(proceso+0×84));
		//avanzamos
		lista=lista->Flink;
		proceso=(unsigned long)lista;
	}
	if(Pid!=idProceso)
	{
		ret=0;
	#ifdef DEBUG
		DbgPrint("DKOM: Coincidencia no encontrada");
	}else{
		DbgPrint("DKOM: Coincidencia PID=%d",Pid);
	#endif
	}
	return ret;
}

Localizar según el nombre de la imagen

unsigned long BuscaEPROCESSNombreDKOM(unsigned char *Nombre)
{
	unsigned long 		eproc,aux,proceso,ret=0;
	PLIST_ENTRY 		lista;
	unsigned char    	*p;

	eproc=(unsigned long)PsGetCurrentProcess();//estamos en "System"
	//tenemos los punteros al siguiente y al anterior
	lista=(LIST_ENTRY*)(eproc+0×88);
	aux=(unsigned long)lista->Blink;
	proceso=(unsigned long)lista;
	p=(unsigned char *)(proceso+0×174);

	/* Recorremos la lista (comparando con la longitud del proceso
	   que nos dice el sistema, y no con el de el usuario */
	while(proceso!=0 && aux!=proceso && p!=0 &&
		     strncmp(Nombre,p,strlen(Nombre))!=0)
	{
		proceso-=0×88;
		ret=proceso;
		p=(unsigned char *)(proceso+0×174);
		//avanzamos
		lista=lista->Flink;
		proceso=(unsigned long)lista;
	}
	if(strncmp(Nombre,p,strlen(Nombre))!=0)
	{
		ret=0;
	#ifdef DEBUG
		DbgPrint("DKOM: Coincidencia no encontrada");
	}else{
		DbgPrint("DKOM: Coincidencia: %s",Nombre);
	#endif
	}
	return ret;
}
31Oct/082

Hooks.h

Hooks.h” es una cabecera escrita en lenguaje C, que recopila las funciones más importantes a la hora de realizar ganchos en modo kernel (en sistemas MS Windows), y que nos permite llevar cierto orden a la hora de saber cuántas y qué funciones, están enganchadas en la SSDT del kernel de Windows.

Básicamente, su comodidad reside en la relación existente entre las funciones, y tres variables declaradas que nos ayudan a llevar un control de los ganchos:

#define         NHOOKS  1//Numero de ganchos
unsigned short  SSDT_HOOKED=0;//Booleano
unsigned short  HOOKS_SSDT[NHOOKS]={0};//El estado de cada gancho

Cada función está definida con un valor entero, el cual usaremos en nuestras funciones y con el que movernos en el array “HOOKS_SSDT” para saber el estado del gancho. Ejemplo:

#define ZwCPEx 1

Para usar más funciones, basta con modificar el código de “Hooks.h” para que trabaje con ellas de la misma manera que lo hace con “ZwCreateProcessEx”, y definirlas con un ID único para cada funcion. Aprovechando la declaración anterior de “ZwCPEx”, la siguiente funcion podria ser:

#define ZwQSI 2 //ZwQuerySystemInformation

A continuación, el código de “Hooks.h” usando como ejemplo la API “ZwCreateProcessEx”:

/** ESTRUCTURAS Y VARIABLES PARA REALIZAR LOS GANCHOS **/
#pragma pack(1)
typedef struct ServiceDescriptorEntry {
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase;
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()

__declspec(dllimport)  ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
PMDL            g_pmdlSystemCall;
PVOID           *MappedSystemCallTable;
#define         SYSTEMSERVICE(_function)  \
KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]
#define         SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
#define         HOOK_SYSCALL(_Function, _Hook, _Orig ) _Orig = \
(PVOID) InterlockedExchange((PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
#define         UNHOOK_SYSCALL(_Function, _Hook, _Orig ) InterlockedExchange( \
(PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

/** Para llevar un control de los ganchos **/
#define         NHOOKS  1//Numero de ganchos
unsigned short  SSDT_HOOKED=0;//Booleano
unsigned short  HOOKS_SSDT[NHOOKS]={0};//El estado de cada gancho

/*
 * FUNCION PARA ENGANCHAR LA SSDT Y SOBRE ESTA, ENGANCHAR
 * NUESTRAS FUNCIONES
 */
NTSTATUS HookSSDT()
{
	NTSTATUS    ret=STATUS_UNSUCCESSFUL;

	g_pmdlSystemCall=MmCreateMdl(NULL,KeServiceDescriptorTable.ServiceTableBase,
				     KeServiceDescriptorTable.NumberOfServices*4);
	if(g_pmdlSystemCall)
	{
		MmBuildMdlForNonPagedPool(g_pmdlSystemCall);
		g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
		MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
		SSDT_HOOKED=1;
		ret=STATUS_SUCCESS;
		#ifdef DEBUG
		DbgPrint("SSDT Enganchada");
		#endif
	}
	#ifdef DEBUG
	else
	DbgPrint("Error al enganchar SSDT");
	#endif

	return ret;
}

/*
 * ENGANCHA UNA FUNCION DETERMINADA POR EL PARAMETRO "ID"
 * EN LA SSDT
 * (Ver cabeceras)
 */
void Hook(unsigned int ID)
{
    NTSTATUS ret;

    if(ID>=NHOOKS)
    {
        #ifdef DEBUG
        DbgPrint("ID de la funcion fuera de rango");
        #endif
        return;
    }

    if(!(SSDT_HOOKED || (!SSDT_HOOKED && (ret=HookSSDT())==STATUS_SUCCESS)))
    {
        #ifdef DEBUG
        DbgPrint("SSDT NO enganchada, y no se pudo enganchar");
        #endif
        return;
    }

    /* Deshabilitamos las interrupciones y
     * desactivamos la proteccion contra escritura
     * mediante el registro CR0 del micro
     */
    _asm
    {
        cli
        mov eax,cr0
        and eax,not 10000h
        mov cr0,eax
    }

    switch(ID)
    {
        #ifdef ZwCPEx
        case ZwCPEx:
            HOOK_SYSCALL(ZwCreateProcessEx,ZwCreateProcessExHACK,ZwCreateProcessExORIG);
            HOOKS_SSDT[ID]=1;
            #ifdef DEBUG
            DbgPrint("%d Enganchada",ID);
            #endif

            break;
        #endif
    }

    /* Habilitamos las interrupciones y
     * activamos la proteccion contra escritura
     * mediante el registro CR0 del micro
     */
    _asm
    {
        mov eax,cr0
        or eax,10000h
        mov cr0,eax
        sti
    }

	return;
}

/*
 * FUNCION PARA ENGANCHAR TODAS LAS FUNCIONES DEFINIDAS, EN LA SSDT
 */
void HookAll()
{
    unsigned int i;

    for(i=0;i<NHOOKS;i++)
    Hook(i);

    return;
}

/*
 * FUNCION PARA DESENGANCHAR UNA FUNCION DETERMINADA POR EL
 * PARAMETRO "ID" DE LA SSDT.
 * (Ver cabeceras)
 */
void UnHook(unsigned int ID)
{
    if(!SSDT_HOOKED)
    return;

    /* Deshabilitamos las interrupciones y
     * desactivamos la proteccion contra escritura
     * mediante el registro CR0 del micro
     */
    _asm
    {
        cli
        mov eax,cr0
        and eax,not 10000h
        mov cr0,eax
    }

    switch(ID)
    {
        #ifdef ZwCPEx
        case ZwCPEx:
            if(HOOKS_SSDT[ID]==1)
            {
                UNHOOK_SYSCALL(ZwCreateProcessEx,ZwCreateProcessExORIG,ZwCreateProcessExHACK);
                HOOKS_SSDT[ID]=0;
                #ifdef DEBUG
                DbgPrint("Desenganchada");
                #endif
            }
            break;
        #endif
    }

    /* Habilitamos las interrupciones y
     * activamos la proteccion contra escritura
     * mediante el registro CR0 del micro
     */
    _asm
    {
        mov eax,cr0
        or eax,10000h
        mov cr0,eax
        sti
    }

    return;
}

/*
 * FUNCION PARA DESENGANCHAR LA SSDT, ASEGURANDONOS PREVIAMENTE
 * DE QUE NO HAY FUNCIONES ENGANCHADAS. EN CASO DE HABERLAS, LAS
 * DESENGANCHA.
 */
void UnHookSSDT()
{
    unsigned int i;

    //Nos aseguramos de deshacer los ganchos
    for(i=0;i<NHOOKS;i++)
    if(HOOKS_SSDT[i])
    UnHook(i);

    if(g_pmdlSystemCall)
    {
        MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
        IoFreeMdl(g_pmdlSystemCall);
        SSDT_HOOKED=0;
        #ifdef DEBUG
        DbgPrint("SSDT liberada");
        #endif
    }

    return;
}
   
Estadisticas y contadores web gratis
Contadores Gratis