Tema destacado: Únete al Grupo Steam elhacker.NET
Autor
|
Tema: [Source] Crypter Simple (Leído 3,818 veces)
|
Ferсhu
Desconectado
Mensajes: 1.213
Menos palabras y Mas codigos.
|
Hola, En base algunos post y viendo que a muchos les interesa el tema les traigo un ejemplo de un crypter muy simple, solo codifica la primera sección de codigo con un Xor, el q quiera puede modificar la encriptacion a su gusto pero la idea es mostrar como empezar. Bueno al grano, ya q en el codigo se explica un poco el funcionamiento. #include <stdio.h> #include <windows.h> void descifrar(unsigned char *inicio, unsigned char *final){ while(inicio<final){ *inicio=*inicio ^ 85; inicio++; } } int main(int argc, char *argv[]) { FILE *fp,*fn; IMAGE_DOS_HEADER dosheader; IMAGE_NT_HEADERS ntheader; IMAGE_SECTION_HEADER section; unsigned char c; unsigned char *buffer,buf[50],p[5],*func; unsigned long i,oep,inicio,final,pos,tam; fp=fopen("prueba.exe","rb+"); fn=fopen("cifrado.exe","wb"); // Copiamos el archivo a otro para trabajar con este. while(!feof(fp)){ putc(getc(fp),fn); } if(!fp){ printf("Error al abrir"); return 0;} // Guardamos la informacion q vamos a usar de la cabecera en estructuras. fseek(fp, 0x80,0); // empieza cabecera "PE..." fread(&ntheader, sizeof(ntheader), 1, fp); fread(§ion, sizeof(section), 1, fp); // direccion fisica de la sección y tamaño, en el ejecutable. printf("inicio Section code: %d\n",section.PointerToRawData); printf("Tamaño Section code: %d\n",section.SizeOfRawData); buffer=(unsigned char *)malloc(section.SizeOfRawData); // vamos hasta donde comienza el codigo de la sección q vamos a codificar. fseek(fp, section.PointerToRawData, 0); // leemos y hacemos una encriptacion simple. fread(buffer, section.SizeOfRawData, 1, fp); for(i=0;i<section.SizeOfRawData;i++)buffer[i]^=85; //Tamaño de la funcion q descifra tam = (long unsigned int) main - (long unsigned int)descifrar; //Usamos el final de la sección para meter nuestro codigo. pos=section.Misc.VirtualSize ; /* Bueno aca hay q explicar por q se hace esto. Es para emular la llamada a la funcion "descifrar" y q se comporte correctamente. Para eso lo q hacemos es crear los opcodes de: push "direccion final del codigo" push "direccion inicial del codigo" push "direccion de retorno de la funcion" // obviamente aca ponemos el OEP del prog Para hacerlo dinamico se crean los opcodes en base a las direcciones de OEP y de la sección usada. */ final = ntheader.OptionalHeader.ImageBase + section.VirtualAddress + section.Misc.VirtualSize; *((unsigned long *)p)=final; buffer[pos]=0x68; // opcode de push pos++; for(i=0;i<4;i++,pos++)buffer[pos]=p[i]; inicio = ntheader.OptionalHeader.ImageBase + section.VirtualAddress; *((unsigned long *)p)=inicio; buffer[pos]=0x68; // push pos++; for(i=0;i<4;i++,pos++)buffer[pos]=p[i]; oep=ntheader.OptionalHeader.ImageBase+ntheader.OptionalHeader.AddressOfEntryPoint; *((unsigned long *)p)=oep; buffer[pos]=0x68; // push pos++; for(i=0;i<4;i++,pos++)buffer[pos]=p[i]; // Obtenemos la direccion donde comienza la funcion y la guardamos. func=(unsigned char *) &descifrar; for(i=0;i<tam;i++,pos++)buffer[pos]=func[i]; // Cambiamos el OEP por el nuestro. Para q al cargarse el programa empieze ahi. ntheader.OptionalHeader.AddressOfEntryPoint=section.VirtualAddress+section.Misc.VirtualSize;; // Le damos permiso de escritura a la sección. Si no hacemos esto nos dara error. section.Characteristics = section.Characteristics | IMAGE_SCN_MEM_WRITE; // Vamos hasta la posicion de el header y reemplazamos con los nuevos. fseek(fn, 0x80,0); fwrite(&ntheader,sizeof(ntheader), 1, fn); fwrite(§ion, sizeof(section), 1, fn); fseek(fn, section.PointerToRawData , 0); fwrite(buffer, section.SizeOfRawData, 1, fn); // reemplazo con la sección codificada. fclose(fp); fclose(fn); printf("Codigo cifrado.\n"); return EXIT_SUCCESS; } By Ferchu Trate de hacerlo lo mas entendible posible, sin cosas raras ni caprichos. Seguramente cualkiera q tenga minimos conocimientos de ing inversa puede revertir el algoritmo ya q es muy simple, pero la idea no es hacer algo ultra complicado, sino aprender, como siempre. En el ejemplo se utiliza la misma sección para alojar el algoritmo q descifra, sin agrandarla ni nada, aprovechando q siempre se redondea y sobra espacio al final. Como seguro estaran pensando se puede cambiar el metodo de encriptacion por uno mas eficiente y repetir el procedimiento con otras secciones. Bueno espero q les sirva. Saludos!!
|
|
|
|
« Última modificación: 14 Marzo 2008, 02:22 por Adamantyum »
|
En línea
|
|
|
|
|
Override
|
Una pregunta fseek(fp, 0x80,0); // empieza cabecera "PE..."
por que te posicionas en la offset 0x80? no deberías posicionarte en la 0x3C y de ahi obtener la offset que apunta al inicio de la PE HEADER? Un saludo solo esa duda y buen código!
|
|
|
|
|
En línea
|
|
|
|
Ferсhu
Desconectado
Mensajes: 1.213
Menos palabras y Mas codigos.
|
por que te posicionas en la offset 0x80? no deberías posicionarte en la 0x3C y de ahi obtener la offset que apunta al inicio de la PE HEADER? me posiciono ahi para leer el Header NT, como veras dsp de eso se lee el archivo y se guarda el contenido en esa estructura. Si no se posiciona correctamente la informacion q se carga en la estructura seria invalida.
|
|
|
|
|
En línea
|
|
|
|
yovaninu
Desconectado
Mensajes: 309
|
me voy iniciando en esto, no me queda de otra y como imaginaran estoy lleno de dudas, por ejemplo, el codigo Adamntyum lo hice correr con un simple exe, en efecto se crea un segundo ejecutable de nombre cifrado.exe, pero al darle doble clic no hace nada, se supone que deberia ejecutar al igual que "prueba.exe" verdad?
|
|
|
|
|
En línea
|
|
|
|
|
Eternal Idol
|
Es tal como indicas Override. Ese campo al que aludis - e_lfanew - esta en la estructura IMAGE_DOS_HEADER, que - extrañamente - tiene una variable de ese tipo declarada en ese codigo pero no se usa para nada.
|
|
|
|
|
En línea
|
 La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
Ferсhu
Desconectado
Mensajes: 1.213
Menos palabras y Mas codigos.
|
extrañamente - tiene una variable de ese tipo declarada en ese codigo pero no se usa para nada. extrañamente la puse para usarla pero dsp no la necesite jajaj  me voy iniciando en esto, no me queda de otra y como imaginaran estoy lleno de dudas, por ejemplo, el codigo Adamntyum lo hice correr con un simple exe, en efecto se crea un segundo ejecutable de nombre cifrado.exe, pero al darle doble clic no hace nada, se supone que deberia ejecutar al igual que "prueba.exe" verdad? Teoricamente no deberias tener problema, aunke la primera sección de todas no sea de codigo, igual funciona ya q la descifra e igual vuelve al entry point, de todas formas este codigo no es para saltarse AV ni nada de eso, solo es para aprender y tener una minima idea.
|
|
|
|
|
En línea
|
|
|
|
invisible_hack
Desconectado
Mensajes: 981
Invisible_Hack™ Nick Registrado ^^
|
Excelente code  Si me permites, lo pondré en mi foro, con los respectivos créditos  Un saludo...
|
|
|
|
|
En línea
|
"Si no visitas mi blog, Chuck te dará una patada giratoria"
|
|
|
|
Eternal Idol
|
extrañamente la puse para usarla pero dsp no la necesite jajaj  Eso sera unicamente hasta que te encuentres un ejecutable cuya cabecera PE no este en esa direccion ...
|
|
|
|
|
En línea
|
 La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
|
Freeze.
|
Compilado con VC++ 6.0A mi me da error (de no enviar  ) pero supuestamente cifra. Voy a probar y posteo de nuevo 
|
|
|
|
|
En línea
|
|
|
|
Ferсhu
Desconectado
Mensajes: 1.213
Menos palabras y Mas codigos.
|
Si me permites, lo pondré en mi foro, con los respectivos créditos Si, no hay problema. Eso sera unicamente hasta que te encuentres un ejecutable cuya cabecera PE no este en esa direccion ...
Es verdad eso, deberia leer antes el offseet del pe, q esta en 3c, para q no tenga inconvenientes con otros archivos Compilado con VC++ 6.0
A mi me da error (de no enviar ) pero supuestamente cifra. El error q te da creo q es por la forma en la q obtengo la direccion de la funcion q descifra, igualmente tmb puede aver otros inconvenientes, yo uso dev-c++. tmb hay q aclarar q si sizeofrawdata es igual a virtualsize no va a sobrar nada de espacio y no va a funcionar (hay q agrandar la sección), eso pude pasar con la mayoria de los archivos q tiene windows.
|
|
|
|
« Última modificación: 17 Marzo 2008, 00:38 por Adamantyum »
|
En línea
|
|
|
|
Thor
Desconectado
Mensajes: 1.176
|
Interesante código. Una cosa, veo que para copiar al buffer los opcodes usas esto: *((unsigned long *)p)=final; buffer[pos]=0x68; // opcode de push pos++; for(i=0;i<4;i++,pos++)buffer[pos]=p[i]; Usando memcpy puede quedar mas legible: buffer[pos++]=0x68; // opcode de push memcpy(&buffer[pos], &final, sizeof(final)); Bueno, es lo de menos, ambas cosas creo que hacen lo mismo. Saludos.
|
|
|
|
|
En línea
|
|
|
|
|
Override
|
por que te posicionas en la offset 0x80? no deberías posicionarte en la 0x3C y de ahi obtener la offset que apunta al inicio de la PE HEADER? me posiciono ahi para leer el Header NT, como veras dsp de eso se lee el archivo y se guarda el contenido en esa estructura. Si no se posiciona correctamente la informacion q se carga en la estructura seria invalida. Ah ya capté  jojo ya te entendí jeje Es tal como indicas Override. Ese campo al que aludis - e_lfanew - esta en la estructura IMAGE_DOS_HEADER, que - extrañamente - tiene una variable de ese tipo declarada en ese codigo pero no se usa para nada.
Sí ese campo ya lo conocía =). Un saludo y que bueno que ya le estén metiendo a la PE Header jaja hace unos años no se veía stuff tan bueno sobre ese tema 
|
|
|
|
|
En línea
|
|
|
|
|
|
|
bastardCoder
|
Lo primero de todo felicidades por el codigo. Lo he compilado y probado con VC++ 6.0 y me peta al ejecutar el exe.
Concretametne me peta en la linea
for(i=0;i<tam;i++,pos++)buffer[pos]=func;
Saludos!
|
|
|
|
|
En línea
|
|
|
|
Ferсhu
Desconectado
Mensajes: 1.213
Menos palabras y Mas codigos.
|
Estoy casi seguro q es por q usas VC++, paso a explicar por que: el programa copia su propia funcion de la memoria hacia el archivo, para copiar esto, primero determina el tamaño de esa funcion: tam = (long unsigned int) main - (long unsigned int)descifrar; esto le resta la posicion donde comienza la funcion descifrar a la direccion donde comienza main. Es decir, esto es por que el compilador de dev-cpp escribe en el codigo las funciones en el orden tal cual aparecen en este codigo, primero "descifrar", inmediatamente luego la funcion main. El compilador de vc++ seguramente no hace eso, y al obtener el tamaño de la funcion de esa forma da cualquier numero, (si estan en posiciones opuesta da un numero negativo, q como seguramente sabes se va interpretar como un numero positivo muy grande), esto provoca error en el bucle al escribir en el array(en una posicion no valida) y tilda el prog. Soluciones: +Compila con Dev-cpp. o +Implementa una forma diferente de obtener el tamaño de la funcion. Saludos!!
|
|
|
|
|
En línea
|
|
|
|
|
|