Detectando y depurando IsDebuggerPresent en OllyDbg

La función IsDebuggerPresent nos permite conocer si nuestra aplicación está siendo depurada o ejecutada libremente. Se suele usar usar para detectar si alguien está depurando nuestra aplicación y de ser así impedir este procedimiento, pero esta no es una solución muy efectiva ya que es bastante simple saltarse esta restricción como lo veremos más adelante.

En la documentación de Windows podemos encontrar información más detallada sobre esta función. Lo que más nos va a importar de todo esto son los valores de retorno:
  • Si el proceso actual está corriendo en el contexto de un depurador [debugger], retornará un valor distinto a cero.
  • Si el proceso actual no está corriendo en el contexto de un depurador [debugger], retornará el valor cero.
El siguiente código es de un sencillo ejemplo donde se usa IsDebuggerPresent para detectar la presencia del debugger.

// IsDebuggerPresent.cpp: Defines the entry point
// for the console application.

#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
    bool depuradorActivo;
   
    depuradorActivo = IsDebuggerPresent();
   
    if(depuradorActivo)
    {
       printf("Depurando...\n\n");
    }
    else
    {
       printf("Ejecutando...\n\n");
    }

    system("PAUSE");
    return EXIT_SUCCESS;
}

Cuando la aplicación es ejecutada directamente se puede ver que aparece el mensaje correspondiente:


Ahora para probar la función IsDebuggerPresent vamos a la opción Debug -> Start Debugging de nuestro Visual Studio para iniciar el proceso de depurado de nuestro ejecutable.


Como se puede ver, nuestra aplicación ha detectado satisfactoriamente que se encuentra corriendo dentro de un depurador.



Ahora que hemos visto como funciona, vamos a ver cómo detectar que se está haciendo uso de de esta función. El primer paso es abrir el ejecutable con OllyDbg y ver las llamadas a las API que se están usando, para esto hacer clic derecho y seleccionar Search for -> Name in all modules.


Y aparecerá la siguiente ventana en la cual tecleamos IsDebuggerPresent, a medida que vamos escribiendo podremos observar que se va realizando una búsqueda hasta que encontramos lo que buscábamos entre las diferentes funciones que utiliza el ejecutable.


Con lo que tenemos la certeza de que en algún punto, va a intentar averiguar si está siendo analizado por un debugger. Vamos a poner un breakpoint para tener el control justo cuando se vaya a hacer uso de dicha función.


Y pulsamos F9 para lanzar el programa, que se detendrá justo cuando se vaya a hacer uso de la función.


Si agrandamos la imagen [click en ella] podemos ver que Olly nos indica en la esquina inferior derecha que el programa está pausado justo en la función IsDebuggerPresent().

Esta función pertenece a otro módulo (kernel32) por lo que deberemos retornar al programa principal para ver que sucede justo después de esa llamada.

Para ello vamos al menú 'Debug' y seleccionamos 'Execute till user code' o pulsamos ALT+F9, lo que nos devolverá al programa principal justo después de la llamada a IsDebuggerPresent()


Como se puede ver la siguiente orden que se va ejecutar es:

TEST EAX, EAX

Lo que hará que el programa verifique si EAX vale 0, para esto en EAX esta almacenado el resultado de la función IsDebuggerPresent(). Recordando lo indicado al inicio, ya que el programa se esta ejecutando en un debugger el valor retornado será distinto de cero, lo que normalmente es 1, dicho valor lo podemos ver en el registro EAX.


Como se puede ver en este momento el flag "Z" se encuentra con el valor "1", pero luego de avanzar unos pasos en el código haciendo uso de la tecla F8 hasta pasar la línea del TEST EAX, EAX, veremos que este flag cambia su valor a "0" y se pone en color rojo, lo que indica que acaba de ser modificado.


Ahora lo que podemos hacer es modificar el registro "Z" y cambiarlo por "1". Esto lo haremos haciendo doble clic sobre el registro "Z".


Luego de haber modificado el registro, podremos pulsar "F9" y dejar que el programa siga su flujo ya que en este momento hemos saltado la restricción del IsDebuggerPresent, con lo cual nuestro programa mostrará el mensaje como si se estuviera ejecutando fuera del debugger.


Comentarios