x-ray con xaray
Seguramente después de haber leido el título muchos estareís pensando «¿que narices será eso de x-ray?», quizá ya lo hayaís usado, aún sin saberlo, dado que es una técnica con una base muy sencilla e intuitiva y la cual nos puede ser útil en más de una ocasión tal y como demostró Rubén hace unos días con el crackme de erg0t.
En general, x-ray, es una técnica comunmente usada en labores de ingeniería inversa para atacar algoritmos de cifrado muy simple y es aplicable cuando conocemos parte de los datos que se encuentran debajo de la capa cifrada. En su tiempo fue un gran descubrimiento para los analístas de virus, ya que permitió evitar en algunos casos la costosa emulación de código máquina que de otra manera hubiera tenido que realizarse para poder descifrar algunos motores polimórficos. Actualmente se sigue utilizando para detectar algunos virus polimórficos, shellcodes, etc… teneís un excelente paper de Peter Ferrie y Frédéric Perriot en el cual podreís profundizar más en el fundamento de x-raying y en su historia.
Por otro lado os presento xaray, un cutre-programa, con el cual espero que los que lo deseeís podaís practicar con esta técnica para ver su funcionamiento y utilidad … y además os dejo un pequeño reto para el que tenga ganas 😉
La idea de xaray, más que la de tener un programa que te haga de todo, es la de tener una pequeña plantilla, sobre la que poder hacer modificaciones cuando necesitas usar alguna de las técnicas derivadas de x-ray, os explico un poco como funciona, es muy sencillo 🙂
En el código de ejemplo que encontrareís en el paquete de xaray, vereís algo como esto :
{
unsigned char buffer[] = "bpqaqafizigbpmlqzbgfzigbmuxtibmmvrwgqb";
unsigned char plainText [] = "secret";
unsigned char plainText2 [] = "dirty";
unsigned char plainText3 [] = "password";
add_string(plainText,sizeof(plainText)-1);
add_string(plainText2,sizeof(plainText2)-1);
add_string(plainText3,sizeof(plainText3)-1);
set_xcallback(lpcallback);
x_ray(buffer,sizeof(buffer));
free_strings();
}
Aunque en este ejemplo usamos xaray con cadenas de texto, xaray está preparado para manejar datos en raw, así que podeís utilizarlo sobre vuestros binarios favoritos ;-). El código creo que es bastante sencillo, en este caso lo que se hace es agregar una serie de palabras, las cuales creemos que podrían encontrarse bajo el texto cifrado, establecer una rutina callback que será llamada cada vez que se encuentre algo y llamar al motor de x-ray para que analice, posteriormente se libera la memoria usada por las palabras en texto plano.
La rutina callback debe devolver un valor al engine de xaray, existen dos opciones X_BREAK y X_CONTINUE, si devolvemos el primero el motor parará el análisis y si devolvemos el segundo continuará con él, por otro lado la estructura que recibe la función callback es la siguiente :
{
char *lpString; // Puntero a los bytes de la cadena en raw
size_t size; // Tamaño de la cadena
struct _plain_string *next; // Aunque es una lista enlazada este campo no es usado externamente.
}plain_string,*pplain_string;
typedef struct _x_ray_key
{
unsigned int keysize; // Tamaño de la clave
void *key; // Puntero a la clave
}x_ray_key,*px_ray_key;
typedef struct _x_ray_info
{
unsigned char *lpbuffer; // Buffer original
size_t buffsize; // Tamaño del buffer
unsigned int offset; // Desplazamiento sobre el buffer en el que se ha encontrado la palabra
unsigned int method_id; // Identificador del algoritmo que ha sido usado, recordad que están implementados varios
pplain_string pstring; // Puntero a una estructura que describe la cadena de la detección
x_ray_key xkey; // Puntero a una estructura que describe los datos de la clave encontrada
}x_ray_info,*px_ray_info;
Como veís podemos obtener a partir de ella todos los datos necesarios para trabajar con la detección, actualmente solo están implementados unos pocos algoritmos básicos:
– xor simple (byte a byte)
– xor incremental, la clave se va incrementando según se avanza por el buffer byte a byte
– add/sub (byte a byte)
– caesar
Aunque las claves que almacenamos con estos algoritmos son de tamaño 1 byte, como veís en la estructura x_ray_key, se soportaría la implementación de un algoritmo que tenga una clave de cualquier tamaño.
Implementar un nuevo algoritmo es muy sencillo también, para ello debereís escribir dos rutinas, una de ellas tiene que implementar el descifrado normal y la otra la detección usando x-ray, los prototipos de estas funciones son los siguientes:
typedef int (*decryptproc) ( unsigned char *lpdst, unsigned char *lpbuff, size_t buffsize, px_ray_info xinfo );
Además debemos agregar a la tabla de métodos las nuevas funciones :
{
xmethod_i x_ray;
decryptproc dproc;
char method_desc[MAX_METHOD_NAME_LENGTH];
}xmethod,*pxmethod;
Y eso es todo, os dejo por un lado el paquete de xaray con su codigo fuente, y un fichero cifrado, como pista os diré que es una imagen, a ver quien es el primero en sacarla 😉
Un saludo!,
Mario