Ir al contenido



Foto

FileToCode o como incluir un archivo binario en nuestro código fuente.


  • Por favor identifícate para responder
2 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.915 mensajes
  • LocationMadrid - España

Escrito 23 febrero 2014 - 07:24

En algún momento habréis tenido la necesidad de que vuestra aplicación sea portadora de información referente a un archivo, ya sea una imagen, un archivo binario o, porqué no, un ejecutable. La forma habitual de hacer esto es haciendo uso del archivo de recursos pero hay otras formas. Os propongo incluir ese archivo binario en el código fuente del ejecutable y para la tarea os sugiero esta  pequeña aplicación escrita en C en la que, en esta ocasión, no hago uso de la API de Windows.

FileToCode es una pequeña utilidad para crear el código fuente necesario para incluir un archivo binario en nuestra aplicación, que posteriormente se encargará de restituir dicho archivo en disco. Genera un archivo de texto con el código fuente necesario para  definir un array  inicializado con los bytes del archivo binario que nos interese. En realidad genera dos archivos, uno en C y otro el pascal, así será válido para nuestro lenguaje favorito. Los nombres de los archivos serán los del archivo original más un guión y extensión C o Pas
respectivamente.

Para reconstruir el archivo original una aplicación deberá escribir en disco el array binario y asignar un nombre de archivo.

Para no sobrecargar de código, sólo expongo las funciones que generan el archivo en C y en pascal:

cpp
  1. //---------------------------------------------------------------------------
  2. // Escribe el código fuente en C
  3. int bFileToCode_C(char *Fuente, char *Destino)
  4. {
  5.   int  n = 0;
  6.   FILE *FFile = fopen(Fuente, "rb");
  7.   if(FFile==0) return n;
  8.   int Size = FileSize(FFile);
  9.   FILE *DFile = fopen(Destino, "wt");
  10.   BYTE b;
  11.   char *Name = ExtractFileName(QuitaExt(Destino));
  12.   fprintf(DFile, "int %sSize = %d;\n\n", Name, Size);
  13.   fprintf(DFile, "char %sBytes[%d] = \n{\n  ", Name, Size);
  14.   for(n=1; n<=Size; n++){
  15.     b = fgetc(FFile);
  16.     fprintf(DFile, "0x%02X, ", b);
  17.     if(n<Size && n%16 == 0) fprintf(DFile, "\n  ");
  18.   }
  19.   fseek(DFile, -2, SEEK_CUR);
  20.   fprintf(DFile, "\n};");
  21.  
  22.   fclose(FFile);
  23.   fclose(DFile);
  24.   return n;
  25. }
  26.  
  27. //---------------------------------------------------------------------------
  28. // Escribe el código fuente en pascal
  29. int bFileToCode_Pas(char *Fuente, char *Destino)
  30. {
  31.   int  n = 0;
  32.   FILE *FFile = fopen(Fuente, "rb");
  33.   if(FFile==0) return n;
  34.   int Size = FileSize(FFile);
  35.   FILE *DFile = fopen(Destino, "wt");
  36.   BYTE b;
  37.   char *Name = ExtractFileName(QuitaExt(Destino));
  38.   fprintf(DFile, "unit %s;\n\ninterface\n\nuses Windows;\n\nvar\n", Name);
  39.   fprintf(DFile, "%sSize: integer = %d;\n", Name, Size);
  40.   fprintf(DFile, "%sBytes: array [0..%d] of BYTE = \n(\n  ", Name, Size-1);
  41.   for(n=1; n<=Size; n++){
  42.     b = fgetc(FFile);
  43.     fprintf(DFile, "$%02X, ", b);
  44.     if(n<Size && n%16 == 0) fprintf(DFile, "\n  ");
  45.   }
  46.   fseek(DFile, -2, SEEK_CUR);
  47.   fprintf(DFile, "\n);\nimplementation\nend.");
  48.  
  49.   fclose(FFile);
  50.   fclose(DFile);
  51.   return n;
  52. }

Como ejemplo de uso vamos a reconstruir el mismísimo binario ejecutable de FileToCode.exe
En C la reconstrucción sería de la siguiente manera, aunque se pueden buscar otras variantes:

cpp
  1. #include <windows.h>
  2. #pragma hdrstop
  3. #include "FileToCode_.c"  // incluyo el fuente generado del archivo binario
  4.  
  5. // Función extractora
  6. void ExtractFile(char* FileName)
  7. {
  8.   HANDLE hFile = CreateFile(PCHAR(FileName), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  9.   _lwrite((HFILE)hFile, FileToCode_Bytes, FileToCode_Size);
  10.   CloseHandle(hFile);
  11. }
  12.  
  13. #pragma argsused
  14. int main(int argc, char* argv[])
  15. {
  16.   ExtractFile("FileToCode.exe");
  17.   return 0;
  18. }

Y en Delphi os propongo este ejemplo:

delphi
  1. program PruebaDelphi;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses
  6.   SysUtils, Windows,
  7.   FileToCode_ in 'FileToCode_.pas';  // incluyo el fuente generado del archivo binario
  8.  
  9. // Función extractora
  10. procedure ExtractFile(FileName: String);
  11. var
  12.   hFile: THANDLE;
  13. begin
  14.   hFile:= CreateFile(PCHAR(FileName), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  15.   _lwrite(hFile, @FileToCode_Bytes[0], FileToCode_Size);
  16.   CloseHandle(hFile);
  17. end;
  18.  
  19. begin
  20.   ExtractFile('FileToCode.exe');
  21. end.

De esta manera podréis portar con vuestro ejecutable el archivo que deseéis. Subo los binarios, fuentes y ejemplos.

Espero que este truco os sea de utilidad.


Saludos.
  • 0

#2 seoane

seoane

    Advanced Member

  • Administrador
  • 1.249 mensajes
  • LocationEspaña

Escrito 23 febrero 2014 - 02:29

:) Este truco ya lo he usado alguna vez (por ejemplo con SelfDecrypt), pero no deja de ser interesante.
  • 0

#3 ELKurgan

ELKurgan

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 548 mensajes
  • LocationEspaña

Escrito 24 febrero 2014 - 01:07

Muy interesante. Gracias por el aporte

(y)
  • 0