Intento de agregar sección a ejecutable

Iniciado por fary, 16 Septiembre 2011, 23:22 PM

0 Miembros y 1 Visitante están viendo este tema.

fary

Ya estoi aqui de nuevo, esta vez e intentado agregar una nueva sección a un ejecutable, sin exito  :xD

este es el código que tengo:

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

int main()
{
IMAGE_DOS_HEADER dh;
IMAGE_NT_HEADERS nth;

IMAGE_SECTION_HEADER * sección;
IMAGE_SECTION_HEADER nSeccion;
   // char * stub_dos -> Datos del STUB_DOS
   // char * dSecciones -> Datos de las secciones

FILE * archivo = fopen("c:\\windows\\system32\\calc.exe","r+b");
   if (archivo == NULL)
   {
       printf("Error al leer el archivo\n");
       system("PAUSE");

       return 1;
   }

fread(&dh,sizeof(dh),1,archivo); // Rellenamos IMAGE_DOS_HEADER

   char * stub_dos = (char*)malloc(dh.e_lfanew-0x40);

   fread(stub_dos,1,dh.e_lfanew-0x40,archivo); // Leemos el Stub DOS
   fread(&nth,sizeof(nth),1,archivo); // leemos nt headers

   sección = (IMAGE_SECTION_HEADER*)malloc(sizeof(IMAGE_SECTION_HEADER)*nth.FileHeader.NumberOfSections);

   fread(sección,sizeof(IMAGE_SECTION_HEADER),nth.FileHeader.NumberOfSections,archivo);

   char * dSecciones = (char*)malloc(nth.OptionalHeader.SizeOfImage);
   fread(dSecciones,nth.OptionalHeader.SizeOfImage,1,archivo); //leo todos los datos de las secciones.

   fclose(archivo); // terminamos de leer

   ZeroMemory(&nSeccion,sizeof(IMAGE_SECTION_HEADER));

   int A = sección[nth.FileHeader.NumberOfSections-1].VirtualAddress;
   int B = sección[nth.FileHeader.NumberOfSections-1].Misc.VirtualSize;
   int C = nth.OptionalHeader.SectionAlignment;

   strcpy((char*)nSeccion.Name,".fary"); // nombre de la nueva sección: .fary
   nSeccion.VirtualAddress = ((A+B)/C)*C+C;// direccion Virtual
   nSeccion.SizeOfRawData = 0x64; // tamaño de la sección: 100
   nSeccion.PointerToRawData = sección[nth.FileHeader.NumberOfSections-1].PointerToRawData + 0x64;  // direccion fisica
   nSeccion.Characteristics = 0x10000020;
   nSeccion.Misc.VirtualSize = 0x64;
   //nSeccion.VirtulSize

   nth.FileHeader.NumberOfSections += 1; // sumamos la nueva sección
   nth.OptionalHeader.SizeOfImage += 0x64;

   FILE * nuevo = fopen("NuevaCalc.exe","wb+");

   fwrite(&dh,sizeof(dh),1,nuevo);
   fwrite(stub_dos,dh.e_lfanew-0x40,1,nuevo);
   fwrite(&nth,sizeof(nth),1,nuevo);
   fwrite(sección,sizeof(IMAGE_SECTION_HEADER)*nth.FileHeader.NumberOfSections,1,nuevo);
   fwrite(&nSeccion,sizeof(IMAGE_SECTION_HEADER),1,nuevo);
   fwrite(dSecciones,nth.OptionalHeader.SizeOfImage,1,nuevo);

   char * DatosSeccion = (char*)malloc(0x64);
   ZeroMemory(DatosSeccion,0x64);

   fwrite(DatosSeccion,0x64,1,nuevo);

   fclose(nuevo);
system("PAUSE");
return 0;
}


Genera bien el nuevo archivo pero no pone bien los datos de la sección y ni que decir de ejecutarse (peta) XD. Así es como salen los datos de mi sección desde el lordPE:




haber si aguien sabe que ago mal...

saludos.
Un byte a la izquierda.

lucasluks1004

Yo tengo este codigo el cual no lo he podido revisar aun pero si lo probe y es funcional ,,ve este codigo capaz puedes sacar en donde te equivocaste :
Option Explicit


Const IMAGE_DOS_SIGNATURE As Integer = &H5A4D
Const IMAGE_NT_SIGNATURE As Long = &H4550


Private Type IMAGE_DOS_HEADER
    e_magic                 As Integer
    e_cblp                  As Integer
    e_cp                    As Integer
    e_crlc                  As Integer
    e_cparhdr               As Integer
    e_minalloc              As Integer
    e_maxalloc              As Integer
    e_ss                    As Integer
    e_sp                    As Integer
    e_csum                  As Integer
    e_ip                    As Integer
    e_cs                    As Integer
    e_lfarlc                As Integer
    e_onvo                  As Integer
    e_res(0 To 3)           As Integer
    e_oemid                 As Integer
    e_oeminfo               As Integer
    e_res2(0 To 9)          As Integer
    e_lfanew                As Long
End Type


Private Type IMAGE_FILE_HEADER
    Machine                 As Integer
    NumberOfSections        As Integer
    TimeDataStamp           As Long
    PointerToSymbolTable    As Long
    NumberOfSymbols         As Long
    SizeOfOptionalHeader    As Integer
    Characteristics         As Integer
End Type


Private Type IMAGE_DATA_DIRECTORY
  VirtualAddress As Long
  isize As Long
End Type


Private Type IMAGE_OPTIONAL_HEADER32
    Magic                   As Integer
    MajorLinkerVersion      As Byte
    MinorLinkerVersion      As Byte
    SizeOfCode              As Long
    SizeOfInitalizedData    As Long
    SizeOfUninitalizedData  As Long
    AddressOfEntryPoint     As Long
    BaseOfCode              As Long
    BaseOfData              As Long
    ImageBase               As Long
    SectionAlignment        As Long
    FileAlignment           As Long
    MajorOperatingSystemVer As Integer
    MinorOperatingSystemVer As Integer
    MajorImageVersion       As Integer
    MinorImageVersion       As Integer
    MajorSubsystemVersion   As Integer
    MinorSubsystemVersion   As Integer
    Reserved1               As Long
    SizeOfImage             As Long
    SizeOfHeaders           As Long
    CheckSum                As Long
    Subsystem               As Integer
    DllCharacteristics      As Integer
    SizeOfStackReserve      As Long
    SizeOfStackCommit       As Long
    SizeOfHeapReserve       As Long
    SizeOfHeapCommit        As Long
    LoaerFlags              As Long
    NumberOfRvaAndSizes     As Long
    DataDirectory(1 To 16) As IMAGE_DATA_DIRECTORY
End Type


Private Type IMAGE_SECTION_HEADER
    Name As String * 8
    VirtualSize As Long
    VirtualAddress As Long
    SizeOfRawData As Long
    PointerToRawData As Long
    PointerToRelocations As Long
    PointerToLinenumbers As Long
    NumberOfRelocations As Integer
    NumberOfLinenumbers As Integer
    Characteristics As Long
End Type


Private Type IMAGE_NT_HEADERS
    Signature As Long
    FileHeader As IMAGE_FILE_HEADER
    OptionalHeader As IMAGE_OPTIONAL_HEADER32
End Type

Private Function Align(ByVal dwValue As Long, ByVal dwAlign As Long) As Long

If dwAlign <> 0 Then
    If dwValue Mod dwAlign <> 0 Then
        Align = (dwValue + dwAlign) - (dwValue Mod dwAlign)
        Exit Function
    End If
End If

Align = dwValue
End Function

Private Function LastSectionRaw(Sections() As IMAGE_SECTION_HEADER) As Long
Dim i As Integer
Dim ret As Long

For i = LBound(Sections) To UBound(Sections)

    If Sections(i).SizeOfRawData + Sections(i).PointerToRawData > ret Then
        ret = Sections(i).SizeOfRawData + Sections(i).PointerToRawData
    End If

Next i

LastSectionRaw = ret
End Function

Private Function LastSectionVirtual(Sections() As IMAGE_SECTION_HEADER) As Long
Dim i As Integer
Dim ret As Long

For i = LBound(Sections) To UBound(Sections)

    If Sections(i).VirtualSize + Sections(i).VirtualAddress > ret Then
        ret = Sections(i).VirtualSize + Sections(i).VirtualAddress
    End If

Next i

LastSectionVirtual = ret
End Function

Public Function AddSection(ByVal szFile As String, ByVal NewSectionName As String, _
        ByVal NewSectionSize As Long, ByVal NewSectionCharacteristics As Long, _
        ByRef dwNewSectionRVA As Long, ByVal FailIfExists As Boolean) As Long
Dim hFile As Long, hMap As Long, lpMap As Long, x As Long
Dim i As Integer, k As Integer, FF As Integer

Dim DOSHeader As IMAGE_DOS_HEADER
Dim NTHeader As IMAGE_NT_HEADERS
Dim SectionHeader() As IMAGE_SECTION_HEADER

If Len(NewSectionName) < 1 Then Exit Function
If Len(NewSectionName) > 8 Then
    NewSectionName = Left$(NewSectionName, 8)
Else
    NewSectionName = NewSectionName & String(8 - Len(NewSectionName), Chr$(0))
End If

FF = FreeFile
Open szFile For Binary As #FF

Get #FF, , DOSHeader
If DOSHeader.e_magic = IMAGE_DOS_SIGNATURE Then

    Get #FF, 1 + DOSHeader.e_lfanew, NTHeader

    If NTHeader.Signature = IMAGE_NT_SIGNATURE Then

        ReDim SectionHeader(0 To NTHeader.FileHeader.NumberOfSections - 1) As IMAGE_SECTION_HEADER

        k = NTHeader.FileHeader.NumberOfSections - 1
        x = DOSHeader.e_lfanew + 24 + NTHeader.FileHeader.SizeOfOptionalHeader

        For i = LBound(SectionHeader) To UBound(SectionHeader)
            Get #FF, 1 + x, SectionHeader(i)

            If SectionHeader(i).Name = NewSectionName And FailIfExists = True Then Exit Function

            x = x + Len(SectionHeader(i))
        Next i

        If NTHeader.OptionalHeader.SizeOfHeaders >= x + Len(SectionHeader(0)) Then

            NTHeader.FileHeader.NumberOfSections = NTHeader.FileHeader.NumberOfSections + 1
            ReDim Preserve SectionHeader(0 To NTHeader.FileHeader.NumberOfSections - 1) As IMAGE_SECTION_HEADER

            With SectionHeader(NTHeader.FileHeader.NumberOfSections - 1)
                .Name = NewSectionName

                .Characteristics = NewSectionCharacteristics

                .PointerToRawData = Align(LastSectionRaw(SectionHeader), NTHeader.OptionalHeader.FileAlignment)
                .SizeOfRawData = Align(NewSectionSize, NTHeader.OptionalHeader.FileAlignment)

                .VirtualAddress = Align(LastSectionVirtual(SectionHeader), NTHeader.OptionalHeader.SectionAlignment)
                .VirtualSize = NewSectionSize
            End With

            'write new section
            NTHeader.OptionalHeader.DataDirectory(12).VirtualAddress = 0
            NTHeader.OptionalHeader.DataDirectory(12).isize = 0

            NTHeader.OptionalHeader.SizeOfImage = NTHeader.OptionalHeader.SizeOfImage + SectionHeader(k + 1).VirtualSize

            Put #FF, 1 + DOSHeader.e_lfanew, NTHeader
            Put #FF, 1 + x, SectionHeader(k + 1)

            Put #FF, SectionHeader(k + 1).PointerToRawData + SectionHeader(k + 1).SizeOfRawData, Chr$(0)
            AddSection = SectionHeader(k + 1).PointerToRawData
        End If
    End If
End If

Close #FF

End Function



Function AddFile2File(File2BeAdded As String, File2Add2 As String, SectionName As String)
Dim dwSettingsRVA As Long, dwSettingsRaw As Long
Dim Settings As String
Settings = (ReadFile(File2BeAdded))
dwSettingsRaw = AddSection(File2Add2, SectionName, Len(Settings), &HC0000040, dwSettingsRVA, True)
Open File2Add2 For Binary Access Write As #1
Put #1, dwSettingsRaw + 1, Settings
Close #1
End Function




Para llamarlo usa
Call AddFile2File(Text1.Text, App.Path & "\salida.exe", ".comoquieras")


Suerte...

fary

Cita de: lucasluks1004 en 18 Septiembre 2011, 18:54 PM...

pffff... es qeu mi problema creo que esta en cosa de punteros o algo así  :-\ y no lo logro encontrar.

saludos.
Un byte a la izquierda.

fary

#3
Tras seguir intentando y intentando no logro arreglarlo del todo (aunque lo otro ya lo arregle), aora parece que todo esta bien pero ejecuto el exe y no me funciona :S de seguro es un error tonto y minúsculo pero no logro dar con él.

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

DWORD align(DWORD number, DWORD alignment)
{
 if(number % alignment == 0)
   return number;
 else
   return (number / alignment) * alignment + alignment;
}

int main()
{
IMAGE_DOS_HEADER dh;
IMAGE_NT_HEADERS nth;

IMAGE_SECTION_HEADER * sección;
IMAGE_SECTION_HEADER nSeccion;
   // char * stub_dos -> Datos del STUB_DOS
   // char * dSecciones -> Datos de las secciones
   long TamanoSecciones = 0;
   int i;

FILE * archivo = fopen("c:\\Mad.exe","r+b");
   if (archivo == NULL)
   {
       printf("Error al leer el archivo\n");
       system("PAUSE");

       return 1;
   }

fread(&dh,sizeof(dh),1,archivo); // Rellenamos IMAGE_DOS_HEADER

   char * stub_dos = (char*)malloc(dh.e_lfanew-0x40);

   fread(stub_dos,1,dh.e_lfanew-0x40,archivo); // Leemos el Stub DOS
   fread(&nth,sizeof(nth),1,archivo); // leemos nt headers

   sección = (IMAGE_SECTION_HEADER*)malloc(sizeof(IMAGE_SECTION_HEADER)*nth.FileHeader.NumberOfSections);

   fread(sección,sizeof(IMAGE_SECTION_HEADER),nth.FileHeader.NumberOfSections,archivo);

   for (i=0;i<=nth.FileHeader.NumberOfSections-1;i++)
   {
       printf("%i\n",sección[i].SizeOfRawData);
       TamanoSecciones += sección[i].SizeOfRawData;
   }

   printf("%i\n",TamanoSecciones);

   char * dSecciones = (char*)malloc(TamanoSecciones);
   fread(dSecciones,TamanoSecciones,1,archivo); //leo todos los datos de las secciones.

   fclose(archivo); // terminamos de leer

   strcpy((char*)nSeccion.Name,".fary"); // nombre de la nueva sección: .fary
   nSeccion.VirtualAddress = align(sección[nth.FileHeader.NumberOfSections-1].VirtualAddress + sección[nth.FileHeader.NumberOfSections-1].Misc.VirtualSize, nth.OptionalHeader.SectionAlignment);
   nSeccion.SizeOfRawData = align(0x50, nth.OptionalHeader.FileAlignment);
   nSeccion.PointerToRawData = sección[nth.FileHeader.NumberOfSections-1].PointerToRawData + sección[nth.FileHeader.NumberOfSections-1].SizeOfRawData;//align(0x50,nth.OptionalHeader.FileAlignment);
   nSeccion.Characteristics = 0x60000020;
   nSeccion.Misc.VirtualSize = 0x50;

   nth.FileHeader.NumberOfSections += 1; // sumamos la nueva sección
   nth.OptionalHeader.SizeOfImage = align(0x50+nSeccion.VirtualAddress,nth.OptionalHeader.SectionAlignment);
    nth.OptionalHeader.SizeOfHeaders += 0x28;


   FILE * nuevo = fopen("Nuevo.exe","wb+");

   fwrite(&dh,sizeof(dh),1,nuevo);
   fwrite(stub_dos,dh.e_lfanew-0x40,1,nuevo);
   fwrite(&nth,sizeof(nth),1,nuevo);
   nth.FileHeader.NumberOfSections -= 1;
   fwrite(sección,sizeof(IMAGE_SECTION_HEADER)*nth.FileHeader.NumberOfSections,1,nuevo);
   fwrite(&nSeccion,sizeof(IMAGE_SECTION_HEADER),1,nuevo);
   fwrite(dSecciones,TamanoSecciones,1,nuevo);
   if (fseek(nuevo,0,SEEK_END) != 0)
   {
       printf("error\n");
   }

   char DatosSeccion[] = "Hola yo soy la sección de prueba, y ocupo exactamente la cantidad de 0x50 bytes.";
   fwrite(DatosSeccion,0x50,1,nuevo);

   fclose(nuevo);
system("PAUSE");
return 0;
}


Si alguien es tan amable de hecharle un ojo y explicarme porque no anda le estaría muy agradecido ;)

saludos.
Un byte a la izquierda.

karmany

qué error te sale ahora?

Cuando añades una nueva sección, en la misma no añades ningún byte, entonces no entiendo por qué pones:
nSeccion.SizeOfRawData = align(0x50, nth.OptionalHeader.FileAlignment);
alinearlo a filealignement se hace si realmente tienes bytes. Ponlo a cero directamente. (no he revisado completamente tu código, pero creo que no añades bytes, si me equivoco dímelo)

Además cuando añades una sección, realmente lo que haces es modificar los bytes en el encabezado pero no añades ninguno a no ser que lo hagas de verdad, como hago con Add PE bytes.

Mi código es muy diferente al tuyo y me lo tengo que leer entero para saber dónde has cometido el error.

Haz pruebas con tu programa y con LordPE y examinando los datos de la sección añadida verifica dónde está el error.

fary

Si añado datos... añado una pequeña cadena  :P. el problema está en que genera el ejecutable con menos peso y cambia datos de las secciones (osea el contenido) pero nose porque lo hace  :-\

saludos.
Un byte a la izquierda.

The Swash

#6
Código (cpp) [Seleccionar]
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

DWORD align(DWORD number, DWORD alignment)
{
   if(number % alignment == 0)
      return number;
   else
      return (number / alignment) * alignment + alignment;
}

int main()
{
  IMAGE_DOS_HEADER dh;
  IMAGE_NT_HEADERS nth;

  IMAGE_SECTION_HEADER * sección;
  IMAGE_SECTION_HEADER nSeccion;
   // char * stub_dos -> Datos del STUB_DOS
   // char * dSecciones -> Datos de las secciones
  long TamanoSecciones = 0;
  int i;

  FILE * archivo = fopen("c:\\Mad.exe","r+b");
  if (archivo == NULL)
  {
      printf("Error al leer el archivo\n");
      getchar();

      return 1;
  }

  fread(&dh,sizeof(dh),1,archivo); // Rellenamos IMAGE_DOS_HEADER

  char * stub_dos = (char*)malloc(dh.e_lfanew-0x40);

  fread(stub_dos,1,dh.e_lfanew-0x40,archivo); // Leemos el Stub DOS
  fread(&nth,sizeof(nth),1,archivo); // leemos nt headers

  sección = (IMAGE_SECTION_HEADER*)malloc(sizeof(IMAGE_SECTION_HEADER)*nth.FileHeader.NumberOfSections);

  fread(sección,sizeof(IMAGE_SECTION_HEADER),nth.FileHeader.NumberOfSections,archivo);

  /*for (i=0;i<=nth.FileHeader.NumberOfSections-1;i++)
  {
      printf("%i\n",sección[i].SizeOfRawData);
      TamanoSecciones += sección[i].SizeOfRawData;
  }*/
  TamanoSecciones =  (sección[nth.FileHeader.NumberOfSections-1].PointerToRawData + sección[nth.FileHeader.NumberOfSections-1].SizeOfRawData) - sección[0].PointerToRawData;

  fseek(archivo, dh.e_lfanew + 248 + (nth.FileHeader.NumberOfSections * 0x28)+0x28, SEEK_SET);

  char * dSecciones = (char*)malloc(TamanoSecciones + (nth.OptionalHeader.SizeOfHeaders - ftell(archivo)));
  int HeaderSize = nth.OptionalHeader.SizeOfHeaders - ftell(archivo);
  char * Header = (char*) malloc(HeaderSize);
  memset(Header,0, HeaderSize);
  memset(dSecciones, 0, TamanoSecciones);
  fread(Header, HeaderSize,1, archivo);
  fread(dSecciones,TamanoSecciones,1,archivo); //leo todos los datos de las secciones.

  fclose(archivo); // terminamos de leer

  memset(&nSeccion,0, 0x28);
  strncpy((char*)nSeccion.Name,".fary",5); // nombre de la nueva sección: .fary
  nSeccion.VirtualAddress = align(sección[nth.FileHeader.NumberOfSections-1].VirtualAddress + sección[nth.FileHeader.NumberOfSections-1].Misc.VirtualSize, nth.OptionalHeader.SectionAlignment);
  nSeccion.SizeOfRawData = align(0x50, nth.OptionalHeader.FileAlignment);
  nSeccion.PointerToRawData = sección[nth.FileHeader.NumberOfSections-1].PointerToRawData + sección[nth.FileHeader.NumberOfSections-1].SizeOfRawData;//align(0x50,nth.OptionalHeader.FileAlignment);
  nSeccion.Characteristics = 0x60000020;
  nSeccion.Misc.VirtualSize = 0x50;

  nth.FileHeader.NumberOfSections += 1; // sumamos la nueva sección
  nth.OptionalHeader.SizeOfImage = align(0x50+nSeccion.VirtualAddress,nth.OptionalHeader.SectionAlignment);
  //nth.OptionalHeader.SizeOfHeaders += 0x28;


  FILE * nuevo = fopen("Nuevo.exe","wb+");

  fwrite(&dh,sizeof(dh),1,nuevo);
  fwrite(stub_dos,dh.e_lfanew-0x40,1,nuevo);
  fwrite(&nth,sizeof(nth),1,nuevo);
  nth.FileHeader.NumberOfSections -= 1;
  fwrite(sección,sizeof(IMAGE_SECTION_HEADER)*nth.FileHeader.NumberOfSections,1,nuevo);
  fwrite(&nSeccion,sizeof(IMAGE_SECTION_HEADER),1,nuevo);
  fwrite(Header, HeaderSize,1, nuevo);
  fwrite(dSecciones,TamanoSecciones,1,nuevo);
  if (fseek(nuevo,0,SEEK_END) != 0)
  {
      printf("error\n");
  }
  int Size = nSeccion.SizeOfRawData;
  char DatosSeccion[0x1000] = "Hola yo soy la sección de prueba, y ocupo exactamente la cantidad de 0x50 bytes.\0"; //Debe tener la cantidad de bytes del SizeOfRawData
  fwrite(DatosSeccion,nSeccion.SizeOfRawData,1,nuevo);


  fclose(nuevo);
  system("PAUSE");
  return 0;
}


Tu primer error estaba a la hora de leer el resto de la cabecera, posterior no agregabas el tamaño del SizeOfRawData completo, de lo contrario se corrompe el exe.

Si es un ejecutable VB solo bastaría dejar BoundImport a 0 o moverlo más abajo.