<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SafetyBits &#187; Kernel Mode</title>
	<atom:link href="http://safetybits.net/category/kernel_mode/feed/" rel="self" type="application/rss+xml" />
	<link>http://safetybits.net</link>
	<description>Development &#38; Security Research</description>
	<lastBuildDate>Wed, 16 May 2012 17:37:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Localizando la EPROCESS</title>
		<link>http://safetybits.net/2008/10/31/localizando-la-eprocess/</link>
		<comments>http://safetybits.net/2008/10/31/localizando-la-eprocess/#comments</comments>
		<pubDate>Fri, 31 Oct 2008 17:07:00 +0000</pubDate>
		<dc:creator>sch3m4</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Kernel Mode]]></category>
		<category><![CDATA[MS Windows]]></category>
		<category><![CDATA[Programacion]]></category>

		<guid isPermaLink="false">http://safetybits.net/?p=59</guid>
		<description><![CDATA[<a href="http://safetybits.net/2008/10/31/localizando-la-eprocess/" title="Localizando la EPROCESS"></a>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 &#8230;<p class="read-more"><a href="http://safetybits.net/2008/10/31/localizando-la-eprocess/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://safetybits.net/2008/10/31/localizando-la-eprocess/" title="Localizando la EPROCESS"></a><p>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.</p>
<p><span style="color: #800000;"><em><strong>Localizar según el PID</strong></em></span></p>
<pre lang="C" line="1">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 &#038;&#038; aux!=proceso &#038;&#038; 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;
}</pre>
<p><span style="color: #800000;"><em><strong>Localizar según el nombre de la imagen</strong></em></span></p>
<pre lang="C" line="1">
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 &#038;&#038; aux!=proceso &#038;&#038; p!=0 &#038;&#038;
		     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;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://safetybits.net/2008/10/31/localizando-la-eprocess/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hooks.h</title>
		<link>http://safetybits.net/2008/10/31/hooksh/</link>
		<comments>http://safetybits.net/2008/10/31/hooksh/#comments</comments>
		<pubDate>Fri, 31 Oct 2008 16:42:58 +0000</pubDate>
		<dc:creator>sch3m4</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Kernel Mode]]></category>
		<category><![CDATA[MS Windows]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[Seguridad]]></category>

		<guid isPermaLink="false">http://safetybits.net/?p=49</guid>
		<description><![CDATA[<a href="http://safetybits.net/2008/10/31/hooksh/" title="Hooks.h"></a>“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 &#8230;<p class="read-more"><a href="http://safetybits.net/2008/10/31/hooksh/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://safetybits.net/2008/10/31/hooksh/" title="Hooks.h"></a><p>“<em>Hooks.h</em>” 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.</p>
<p>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:</p>
<pre lang="C">#define         NHOOKS  1//Numero de ganchos
unsigned short  SSDT_HOOKED=0;//Booleano
unsigned short  HOOKS_SSDT[NHOOKS]={0};//El estado de cada gancho</pre>
<p>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:</p>
<pre lang="C">#define ZwCPEx 1</pre>
<p>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:</p>
<pre lang="C">#define ZwQSI 2 //ZwQuerySystemInformation</pre>
<p>A continuación, el código de “Hooks.h” usando como ejemplo la API “ZwCreateProcessEx”:</p>
<pre lang="C">/** 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) &amp;MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
#define         UNHOOK_SYSCALL(_Function, _Hook, _Orig ) InterlockedExchange( \
(PLONG) &amp;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-&gt;MdlFlags = g_pmdlSystemCall-&gt;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&gt;=NHOOKS)
    {
        #ifdef DEBUG
        DbgPrint("ID de la funcion fuera de rango");
        #endif
        return;
    }

    if(!(SSDT_HOOKED || (!SSDT_HOOKED &amp;&amp; (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&lt;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&lt;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;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://safetybits.net/2008/10/31/hooksh/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

