[?] Duda PE Crypter

Iniciado por MeCraniDOS, 1 Julio 2014, 00:53 AM

0 Miembros y 5 Visitantes están viendo este tema.

MeCraniDOS

Hello!   ;D

Estoy intentando entender la estructura PE para poder entender como se hacen los crypters y esas cosas, y me he quedado estancado en una parte, llevo dos dias buscando para no preguntar porque quizás es algo obvio...  :rolleyes:

Si yo quiero añadir una sección a un ejecutable, tengo que incrementar el NumberOfSections y el SizeOfImage, y luego añadir los datos de la nueva sección, lo estaba programando y tengo de momento esto


// ....
    IMAGE_DOS_HEADER DOS_Header;
    IMAGE_NT_HEADERS NT_Header;
    IMAGE_SECTION_HEADER *SECTION_Header;

    FILE *Archivo = fopen("Test.exe", "rb");

    if(Archivo)
    {

        CopyFile("Test.exe", "Backup.exe", TRUE);

        printf("Basic File Information\n\n");
        printf("File Name: Test.exe\n");

        /* Obtenemos el tamaño del fichero */
        fseek(Archivo,0, SEEK_END);
        unsigned long Tamanyo = ftell(Archivo);
        fseek(Archivo,0, SEEK_SET);

        printf("File Size: %lu (%lx)", Tamanyo, Tamanyo);

        /* Obtenemos la estructura DOS_HEADER */
        fread(&DOS_Header, sizeof(IMAGE_DOS_HEADER), 1, Archivo);

        /* Saltamos hasta la posicion donde empieza NT_HEADER, esa posicion se almacena en e_lfanew */
        fseek(Archivo, DOS_Header.e_lfanew, SEEK_SET);
        fread(&NT_Header, sizeof(IMAGE_NT_HEADERS), 1, Archivo);

        NT_Header.FileHeader.NumberOfSections += 1;
        //NT_Header.OptionalHeader.SizeOfImage +=;


        /* Reservamos memoria para las secciones */
        SECTION_Header = (IMAGE_SECTION_HEADER*)malloc(NT_Header.FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER));

        /* Guardamos las secciones */
        for(unsigned int i=0;i<NT_Header.FileHeader.NumberOfSections-1;i++)
        {
            fread(&SECTION_Header[i], sizeof(IMAGE_SECTION_HEADER), 1, Archivo);
        }

// ....

        free(SECTION_Header);

// ....


Entonces lo que había pensado era hacer esto:

// ....
    IMAGE_DOS_HEADER DOS_Header;
    IMAGE_NT_HEADERS NT_Header;
    IMAGE_SECTION_HEADER *SECTION_Header;

    FILE *Archivo = fopen("Test.exe", "rb+");

    if(Archivo)
    {

        CopyFile("Test.exe", "Backup.exe", TRUE);

        /* Obtenemos el tamaño del fichero */
        fseek(Archivo,0, SEEK_END);
        unsigned long Tamanyo = ftell(Archivo);
        fseek(Archivo,0, SEEK_SET);

        /* Obtenemos la estructura DOS_HEADER */
        fread(&DOS_Header, sizeof(IMAGE_DOS_HEADER), 1, Archivo);

        /* Saltamos hasta la posicion donde empieza NT_HEADER, esa posicion se almacena en e_lfanew */
        fseek(Archivo, DOS_Header.e_lfanew, SEEK_SET);
        fread(&NT_Header, sizeof(IMAGE_NT_HEADERS), 1, Archivo);

        NT_Header.FileHeader.NumberOfSections += 1;

        /* Reservamos memoria para las secciones (+1 para la nueva sección)*/
        SECTION_Header = (IMAGE_SECTION_HEADER*)malloc((NT_Header.FileHeader.NumberOfSections)*sizeof(IMAGE_SECTION_HEADER));

        /* Guardamos las secciones */
        for(int i=0;i<NT_Header.FileHeader.NumberOfSections-1;i++)
        {
            fread(&SECTION_Header[i], sizeof(IMAGE_SECTION_HEADER), 1, Archivo);
        }

        DWORD Tamanyo_RawData = 0x10;
        DWORD VirtualAddressEnd = SECTION_Header[NT_Header.FileHeader.NumberOfSections-2].VirtualAddress;

        /* Escribimos los datos de la nueva sección */

        BYTE NombreSeccion[8] = ".mecra";
        memcpy(SECTION_Header[NT_Header.FileHeader.NumberOfSections-1].Name, NombreSeccion, 8);

        SECTION_Header[NT_Header.FileHeader.NumberOfSections-1].SizeOfRawData = Tamanyo_RawData;
        SECTION_Header[NT_Header.FileHeader.NumberOfSections-1].PointerToRawData = Tamanyo;
        SECTION_Header[NT_Header.FileHeader.NumberOfSections-1].Characteristics = 0xE0000020;
        SECTION_Header[NT_Header.FileHeader.NumberOfSections-1].VirtualAddress = VirtualAddressEnd+NT_Header.OptionalHeader.SectionAlignment;
        SECTION_Header[NT_Header.FileHeader.NumberOfSections-1].Misc.VirtualSize = Tamanyo_RawData;

        /* Incrementamos el SizeOfImage */
        NT_Header.OptionalHeader.SizeOfImage += Tamanyo_RawData;

        /* Escribimos los datos en el archivo */

        //Nos situamos al inicio de la NT Header
        fseek(Archivo, DOS_Header.e_lfanew, SEEK_SET);

        //Escribimos la cabecera
        fwrite(&NT_Header, sizeof(IMAGE_NT_HEADERS), 1, Archivo);

        //Saltamos al Section Header
        fseek(Archivo, DOS_Header.e_lfanew + sizeof(IMAGE_NT_HEADERS), SEEK_SET);

        //Escribimos los datos y la cagamos porque nos cargamos lo que sigue al insertar la sección asi ^^
        for(int i=0;i<NT_Header.FileHeader.NumberOfSections;i++)
        {
            fwrite(&SECTION_Header[i], sizeof(IMAGE_SECTION_HEADER), 1, Archivo);
        }

// ....

        free(SECTION_Header);

// ....


Los que sepan del tema ya sabrán donde estoy fallando, y yo me hago una ligera idea  :huh: :huh:

Según he estado leyendo, tiene que haber espacio para poder insertar la sección, cosa que no compruebo, pero donde está el contenido de cada sección? Justo despues de IMAGE_SECTION_HEADER?

Lo que habia pensado era guardar el contenido que hay justo después de la última sección, insertar la mia, insertar el contenido que he guardado, y modificar de cada sección el PointerToRawData sumando el tamaño de la cabecera de la nueva sección, para apuntar de nuevo donde empieza la sección :rolleyes:

Si no se hace así, a ver si alguien me puede dar una idea de como se hace.. Tengo los conceptos un poco liados  :-\





Dos cositas mas  :silbar:

He estado leyendo el código de [Zero] de como añadir una sección..

http://foro.elhacker.net/analisis_y_diseno_de_malware/srcc_anadir_una_seccion-t261801.0.html

Y veo que utiliza

Citar
PIMAGE_DOS_HEADER;
PIMAGE_NT_HEADERS;
PIMAGE_SECTION_HEADER;

En vez de utilizar esto
Citar
IMAGE_DOS_HEADER;
IMAGE_NT_HEADERS;
IMAGE_SECTION_HEADER;

Hay alguna diferencia? (Ventajas)

PIMAGE_DOS_HEADER sería un puntero a IMAGE_DOS_HEADER?  :huh:

Y ya por último...  :laugh:

He visto en un crypter que he encontrado por internet esta rutina para descifrar una sección


//Rutina encargada de descifrar la sección cifrada
char uncryptroutine[] =       //21 bytes
    "\xB8\x00\x10\x40\x00"  //B8 00104000  MOV EAX, 401000    Section Start  ||Este valor será modificado
    "\x80\x30\xBB"          //8030 BB      XOR BYTE[EAX], BB  Key
    "\x40"                  //40           INC EAX
    "\x3D\x00\x45\x40\x00"  //3D 00454000  CMP EAX, 404500    Section End  ||Este valor será modificado
    "\x75\xF5"              //75 F5        JNZ SHORT -11      (Complemento a dos de 11 = F5)
    "\xB8\x00\x20\x40\x00"  //B8 00204000  MOV EAX, 402000    Pone en EAX el OEP || Este valor será modificado
    "\xFF\xE0";             //FFE0         JMP EAX            Salta al OEP


Se supone que eso son instrucciones en ASM? :huh: :huh:

Saludos

"La física es el sistema operativo del Universo"
     -- Steven R Garman

daryo

no se mucho del formato pe , pero te recomiendo que no uses fopen sino la api de windows createfile y readfile y writefile googleando encontre esto http://www.rohitab.com/discuss/topic/33006-detailed-guide-to-pe-infection/

Citar
Se supone que eso son instrucciones en ASM?

es una shellcode http://es.wikipedia.org/wiki/Shellcode ,
buenas

x64core


Cita de: MeCraniDOS en  1 Julio 2014, 00:53 AM
Según he estado leyendo, tiene que haber espacio para poder insertar la sección, cosa que no compruebo, pero donde está el contenido de cada sección? Justo despues de IMAGE_SECTION_HEADER?
Se puede añadir una sección sin problemas pero requiere más trabajo, se debe incrementar el tamaño de las cabeceras y realinear todas las secciones
y posiblemente actualizar RVAs a cualquier posible sección realineada esto es imposible si el ejecutable no tiene tabla de relocalización, bueno es 80%
imposible todo depende del tipo de ejecutable.

Cita de: MeCraniDOS en  1 Julio 2014, 00:53 AM
Lo que habia pensado era guardar el contenido que hay justo después de la última sección, insertar la mia, insertar el contenido que he guardado, y modificar de cada sección el PointerToRawData sumando el tamaño de la cabecera de la nueva sección, para apuntar de nuevo donde empieza la sección :rolleyes:

Si no se hace así, a ver si alguien me puede dar una idea de como se hace.. Tengo los conceptos un poco liados  :-\[/size]
Eso y muchas cosas más http://foro.elhacker.net/analisis_y_diseno_de_malware/taller_en_construccionsecciones_en_archivos_pe-t362515.0.html;msg1912797#msg1912797

Cita de: MeCraniDOS en  1 Julio 2014, 00:53 AM
Dos cositas mas  :silbar:

He estado leyendo el código de [Zero] de como añadir una sección..

http://foro.elhacker.net/analisis_y_diseno_de_malware/srcc_anadir_una_seccion-t261801.0.html

Y veo que utiliza

En vez de utilizar esto
Hay alguna diferencia? (Ventajas)
definiciones de tipo para punteros a las estructuras.

Cita de: MeCraniDOS en  1 Julio 2014, 00:53 AM

Se supone que eso son instrucciones en ASM? :huh: :huh:

Saludos




MeCraniDOS

Cita de: daryo en  1 Julio 2014, 01:11 AM
no se mucho del formato pe , pero te recomiendo que no uses fopen sino la api de windows createfile y readfile y writefile

Y eso?  :huh:


Cita de: x64Core en  1 Julio 2014, 08:09 AM
CitarSe supone que eso son instrucciones en ASM? :huh: :huh:

Saludos



Que bien, que yo sepa el ASM no es así (visualmente), pero ya me ha contestado daryo  :) :)

Cuando he dicho lo de la sección, era que mas o menos se lo que tengo que hacer, pero la lío tal y como lo hago, ya me habia leido el Taller en construcción que has pasado, y estaba intentando automatizar la Practica 1, agregar una sección, pero no se por donde seguir con el código porque siempre se rompe el ejecutable :huh:
"La física es el sistema operativo del Universo"
     -- Steven R Garman

x64core

Cita de: MeCraniDOS en  1 Julio 2014, 11:10 AM

Y eso?  :huh:





Que bien, que yo sepa el ASM no es así (visualmente), pero ya me ha contestado daryo  :) :)

Cuando he dicho lo de la sección, era que mas o menos se lo que tengo que hacer, pero la lío tal y como lo hago, ya me habia leido el Taller en construcción que has pasado, y estaba intentando automatizar la Practica 1, agregar una sección, pero no se por donde seguir con el código porque siempre se rompe el ejecutable :huh:

ah te referis a los bytes de las instrucciones. mejor lee el entero archivo de una vez y luego vas analizando las
cabeceras del ejecutable y demás cosas.


MeCraniDOS

#5
Era eso a lo que me refería, gracias  ;D

Otra pregunta, Karcrack me ha recomendado que monte el fichero en memoria y haga las modificaciones en memoria  :silbar:

He estado investigando sobre el tema, y me he hecho este mini código, pero no se si es del todo correcto...


   PIMAGE_DOS_HEADER DOS_Header;

   char Fichero[] = "Test.exe";

   HANDLE hFile = CreateFile((LPCTSTR)Fichero,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

   if(hFile == INVALID_HANDLE_VALUE)
   {
       printf("No se puede abrir el fichero: %s Error: %lu\n", Fichero, GetLastError());
       return EXIT_FAILURE;
   }

   HANDLE FMapped = CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, 0);

   if(FMapped == INVALID_HANDLE_VALUE)
   {
       printf("No se puede mapear el fichero en memoria. Error: %lu\n" , GetLastError());
       CloseHandle(hFile);
       return EXIT_FAILURE;
   }

   BYTE *FileMapped = (BYTE*)MapViewOfFile(FMapped, FILE_MAP_READ, 0, 0, 0);

   if(FileMapped == NULL)
   {
       printf("No se puede mapear el fichero en memoria. Error: %lu\n" , GetLastError());
       CloseHandle(FMapped);
       CloseHandle(hFile);
       return EXIT_FAILURE;
   }

   DOS_Header = (PIMAGE_DOS_HEADER)&FileMapped[0];

   // ....


Alguien me puede decir si es la manera correcta de cargar el ejecutable en memoria? (Mapear el archivo en memoria) O si hay alguna manera mas fácil..  ;D

Buenas noches!  :D
"La física es el sistema operativo del Universo"
     -- Steven R Garman

x64core

Cita de: MeCraniDOS en  2 Julio 2014, 00:42 AM
Era eso a lo que me refería, gracias  ;D

Otra pregunta, Karcrack me ha recomendado que monte el fichero en memoria y haga las modificaciones en memoria  :silbar:

He estado investigando sobre el tema, y me he hecho este mini código, pero no se si es del todo correcto...


   PIMAGE_DOS_HEADER DOS_Header;

   char Fichero[] = "Test.exe";

   HANDLE hFile = CreateFile((LPCTSTR)Fichero,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

   if(hFile == INVALID_HANDLE_VALUE)
   {
       printf("No se puede abrir el fichero: %s Error: %lu\n", Fichero, GetLastError());
       return EXIT_FAILURE;
   }

   HANDLE FMapped = CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, 0);

   if(FMapped == INVALID_HANDLE_VALUE)
   {
       printf("No se puede mapear el fichero en memoria. Error: %lu\n" , GetLastError());
       CloseHandle(hFile);
       return EXIT_FAILURE;
   }

   BYTE *FileMapped = (BYTE*)MapViewOfFile(FMapped, FILE_MAP_READ, 0, 0, 0);

   if(FileMapped == NULL)
   {
       printf("No se puede mapear el fichero en memoria. Error: %lu\n" , GetLastError());
       CloseHandle(FMapped);
       CloseHandle(hFile);
       return EXIT_FAILURE;
   }

   DOS_Header = (PIMAGE_DOS_HEADER)&FileMapped[0];

   // ....


Alguien me puede decir si es la manera correcta de cargar el ejecutable en memoria? (Mapear el archivo en memoria) O si hay alguna manera mas fácil..  ;D

Buenas noches!  :D

¿Porqué mapear el archivo? Suponiendo que se quiere agregar la sección al ejecutable y luego guardar la nueva imagen en disco
simplemente leer la imagen CreateFile+ReadFile

MeCraniDOS

Cita de: x64Core en  2 Julio 2014, 04:38 AM
¿Porqué mapear el archivo? Suponiendo que se quiere agregar la sección al ejecutable y luego guardar la nueva imagen en disco
simplemente leer la imagen CreateFile+ReadFile

Es como he visto que lo hacen los que dominan mucho del tema  :huh:

http://foro.elhacker.net/analisis_y_diseno_de_malware/srcc_rebuildpe-t262602.0.html


http://foro.elhacker.net/analisis_y_diseno_de_malware/srcc_anadir_una_seccion-t261801.0.html

http://foro.elhacker.net/analisis_y_diseno_de_malware/srcc_ampliar_seccion_ejecutable-t261800.0.html


En los códigos que hay ahí se trabaja desde memoria, y en funciones que he visto en otras webs, también trabajan mapeando el archivo y trabajando desde memoria :rolleyes:
"La física es el sistema operativo del Universo"
     -- Steven R Garman

x64core

Cita de: MeCraniDOS en  2 Julio 2014, 14:54 PM
Es como he visto que lo hacen los que dominan mucho del tema  :huh:

http://foro.elhacker.net/analisis_y_diseno_de_malware/srcc_rebuildpe-t262602.0.html


http://foro.elhacker.net/analisis_y_diseno_de_malware/srcc_anadir_una_seccion-t261801.0.html

http://foro.elhacker.net/analisis_y_diseno_de_malware/srcc_ampliar_seccion_ejecutable-t261800.0.html


En los códigos que hay ahí se trabaja desde memoria, y en funciones que he visto en otras webs, también trabajan mapeando el archivo y trabajando desde memoria :rolleyes:

Para mi el mapear el archivo es innecesario sino que alguien diga porque es necesario mapearlo.

Karcrack

Cita de: x64Core en  3 Julio 2014, 09:34 AM
Para mi el mapear el archivo es innecesario sino que alguien diga porque es necesario mapearlo.
No es necesario mapearlo. En mi opinión es más sencillo trabajar cuando te olvidas de buffers. No tienes que usar una cosa para leer y otra para escribir, sencillamente trabajas con punteros y luego lo reflejas en disco...