sábado, 27 de marzo de 2010

El día que un CRC cambió mi vida parte IV

Lo prometido es deuda, finalizamos la saga del CRC con esta cuarta entrega.

En esta ocasión utilizaremos lo aprendido aplicado a un caso real.

El caso real perfectamente podría ser el acceso a un sistema o aplicación en el cual se pide un login de entrada.

Seremos capaces de distinguir si nuestra aplicación de acceso está siendo debugeada.

Si ejecutamos la aplicación cuyo source code está al final de la explicación, vemos que se nos pide un login de acceso, y como no lo tenemos, lo normal es que no podamos acceder, tal y como se muestra en la siguiente imagen:


En la próxima imagen vemos en que parte del desensamblado está la ‘zona caliente’, es decir, dónde una vez realizado el cálculo del login se compara el password que hemos introducido con el password válido y en función de la comparación darnos o no acceso al sistema:


Pues bien, justo en dónde hace la comparación pondremos un punto de ruptura y observamos como se comporta la aplicación ante este hecho:


Como veis hemos sido capaces de saber si están depurando nuestra aplicación haciendo uso de un CRC.

La explicación es muy sencilla, cuando se coloca un punto de ruptura en alguna parte del código, se manda una instrucción al debugger y este reemplaza el primer byte del código por el valor 0xCC. Este valor es el equivalente a la instrucción INT 3, la cual genera una interrupción cada vez que esta se ejecuta, pasándole el control al depurador para que detenga la ejecución normal de la aplicación. 

Como podemos intuir, previamente calculamos el CRC a la ‘zona caliente’ de nuestro código sin tener ningún punto de ruptura dándonos un valor de 0x442AE2AB, valor diferente al que se calcula cuando se puso el breakpoint tal y como se ve en la siguiente imagen:


Nuevamente vemos que el ingenio humano no tiene límites.

Para finalizar, anexo el código fuente del ejemplo:

/*****************************************************************************/
/*                                                                           */
/*  NOMBRE      : CRCy.c                                                     */
/*  AUTOR       : Longinos Recuero Bustos                                    */
/*  EMAIL       : lrecuero1@alumno.uned.es                                   */
/*  WEB         : http://longinox.blogspot.com/                              */
/*  FECHA       : 24/03/2010                                                 */
/*  LICENCIA    : GPL                                                        */
/*  DESCRIPCIÓN : Uso de un CRC como proteccion antidebug.                   */
/*                                                                           */
/*****************************************************************************/

/* INCLUSIÓN DE HEADERS ******************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* DEFINICIÓN DE CONSTANTES SIMBÓLICAS ***************************************/
#define INIT_ADDRESS 0x004013D7
#define CRC          0x442AE2AB

/* DEFINICIÓN DE TIPOS *******************************************************/

typedef enum
{
    FALSE = 0,
    TRUE
}TBoolean;

/* DEFINICIÓN DE PROTOTIPOS DE FUNCIONES *************************************/

TBoolean acceder( char *Nombre, char *Password );
void calculoCRCx( unsigned char byte, unsigned int *crc );

/* MAIN PROGRAM **************************************************************/

int main( int argc, char* argv[] )
{
 /* Definición de variables locales */
 char nombre[ 41 ];      // Nombre in.
 char password[ 60 ];    // Paswword in.
 int  i;                 // Indice del bucle.
 unsigned int   crc = 0; // CRC.
 unsigned char *p;

 /* Dirección de comienzo de la función acceder */
 p = ( unsigned char *)INIT_ADDRESS;

        /* Petición del Nombre */
 puts( "\nNombre [Max. 40 caracteres]: " );
 gets( nombre );

 /* Petición del password */
 puts( "\nPasword: " );
 gets( password );

 /* Calculamos el CRC de la zona caliente */
 for( i = 0; i < 225; i++ )
 {
  calculoCRCx( p[ i ], &crc );
 }

 if( CRC != crc )
 {
  /* Nos están depurando */
  puts( "\n\nMe estas debugeando? pues entonces ADIOS!!!!!\n\n" );
  return EXIT_FAILURE;
 }
 else
 {
  /* No estamos siendo depurados */
  if( acceder( nombre, password ) )
  {
   /* Acceso OK */
   puts( "\n\nACCESO OK!!!!! Eres un masterCraker\n\n" );
  }
  else
  {
   /* Acceso denegado */
   puts( "\n\nOPPSSSSS NO ES CORRECTO!!!!! Eres un calamardo\n\n" );
  }

  return EXIT_SUCCESS;
 }
}

/* FUNCIONES PRVADAS *********************************************************/

TBoolean acceder( char *Nombre, char *Password )
{
    char claveXOR[] = "cAlAmarDO tENtACUlO";
    unsigned int i, j, password = 1;

    for( i = 0, j = 0; i < strlen( Nombre ); i++ )
    {
        password *= ( Nombre[ i ] ^ claveXOR[ j ] ) % 0xDEADBEEF;
        password ^= 0xABADBABE;
        j = ( j + 1 ) % strlen( claveXOR );
    }

    if( password == ( unsigned int )atoi( Password ) )
    {
        return !FALSE;
    }
    else
    {
        return !TRUE;
    }
}

void calculoCRCx( unsigned char byte, unsigned int *crc )
{
    unsigned char i;
    unsigned int  polinomioGenerador  = 0x8005;
    TBoolean es_Bit_A_Uno;
    TBoolean es_MSB_CRC_A_Uno;

    /* Para cada byte del fichero... */
    for( i = 0; i < 8; i++ )
    {
     /* Se comprueba si el bit actual está a 1 */
     es_Bit_A_Uno = ( ( ( byte >> ( 7 - i ) ) & 1 ) == 1 );

        /* Se comprueba si el MSB actual del crc está a 1 */
        es_MSB_CRC_A_Uno = ( ( ( *crc >> 15 ) & 1 )  == 1 );

        *crc <<= 1;

        /* Si los booleanos son distintos uno de otro */
        if( es_MSB_CRC_A_Uno ^ es_Bit_A_Uno )
        {
         /* XOR entre el crc actual y el polinómio generador */
                *crc ^= polinomioGenerador;
        }
    }
}

Espero que os hayáis divertido tanto como lo he hecho yo con esta saga del CRC.

No hay comentarios:

Publicar un comentario