Common Intermediate Language и системное программирование в Microsoft .NET

Приложение A

Разбить на страницы
Показывать лекцию целиком

Исходный код программы pegen

Исходный код программы pegen, выполняющей генерацию сборки .NET, размещен в четырех файлах:

  • macros.h

    Содержит макроопределения, которые используются в остальных файлах.

  • pe.h

    Интерфейс модуля генерации PE-файла.

  • pe.c

    Реализация модуля генерации PE-файла.

  • main.c

    Главный модуль, использующий модуль генерации для создания простейшей сборки .NET.

  • A.1. macros.h

    #ifndef MACROS_H
    #define MACROS_H
    
    #define SECTION_ALIGNMENT   	0x2000
    #define EXE_TYPE                0x1
    #define DLL_TYPE                0x0
    #define SIZEOF_JMP_STUB    	6
    #define SIZEOF_IMPORT_TABLE  	82
    
    #define CNT_CODE    0x00000020
    #define CNT_INITIALIZED_DATA  	0x00000040
    #define CNT_UNINITIALIZED_DATA 	0x00000080
    #define MEM_DISCARDABLE    	0x02000000
    #define MEM_EXECUTE      	0x20000000
    #define MEM_READ                0x40000000
    #define MEM_WRITE               0x80000000
    
    #define IMAGE_FILE_MACHINE_I386	0x014c
    
    #define IMAGE_SUBSYSTEM_WINDOWS_GUI  2 
    #define IMAGE_SUBSYSTEM_WINDOWS_CUI  3
    #define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9
    
    // Aligned to FileAlignment boundary
    #define SIZEOF_HEADERS(params)  \
        align(sizeof(struct HEADERS), params->FileAlignment)
    
    #define SIZEOF_TEXT(params) \
        align(params->SizeOfMetadata + params->SizeOfCilCode, \
        params->FileAlignment)
    
    #define SIZEOF_CLI(params) \
        align(sizeof(struct CLI_SECTION_IMAGE), params->FileAlignment)
    
    #define SIZEOF_RELOC(params)  \
        align(sizeof(struct RELOC_SECTION), params->FileAlignment)
    
    // Aligned to SectionAlignment boundary
    #define SIZEOF_HEADERS_M(params) \
        align(sizeof(struct HEADERS), SECTION_ALIGNMENT)
    
    #define SIZEOF_TEXT_M(params) \
        align(params->SizeOfMetadata + params->SizeOfCilCode, \
        SECTION_ALIGNMENT)
    
    #define SIZEOF_CLI_M  \
        align(sizeof(struct CLI_SECTION_IMAGE), SECTION_ALIGNMENT)
    
    #define SIZEOF_RELOC_M \
        align(sizeof(struct RELOC_SECTION), SECTION_ALIGNMENT)
    
    #define SIZEOF_METHODS(params) \
        align(params->SizeOfCilCode, SECTION_ALIGNMENT)
    
    // Not aligned
    #define SIZEOF_HEADERS_NOTALIGNED \
        sizeof(struct HEADERS)
    
    #define SIZEOF_CLI_NOTALIGNED  \
        sizeof(struct CLI_SECTION_IMAGE)
    
    #define SIZEOF_TEXT_NOTALIGNED(params) \
        params->SizeOfMetadata + params->SizeOfCilCode
    
    #define SIZEOF_CLI_HEADER \
        sizeof(struct IMAGE_COR20_HEADER)
    
    #define SIZEOF_RELOC_NOTALIGNED \
        sizeof(struct RELOC_SECTION)
    
    #define SIZEOF_DATA_DIRECTORY \
        sizeof(struct IMAGE_DATA_DIRECTORY)
    
    // RVA of section
    #define RVA_OF_TEXT   \
        align(sizeof(struct HEADERS), SECTION_ALIGNMENT)
    
    #define RVA_OF_CLI(params)  \
        RVA_OF_TEXT +     \
        align(params->SizeOfMetadata + params->SizeOfCilCode,
          SECTION_ALIGNMENT)
    
    #define RVA_OF_RELOC(params) \
        RVA_OF_CLI(params) + SIZEOF_CLI_M
    
    #define TYPE_OFFSET(a,b) \
        (a*0x1000 | b)
    
    #define OFFSETOF(s,m)  \
        (size_t)(((s *)0)->m)
    
    #endif

    A.2. pe.h

    #ifndef PE_H
    
    #include <stdio.h>
    
    // Block of input parameters
    struct INPUT_PARAMETERS {
      unsigned long      Type;    
      unsigned char      *metadata;
      unsigned char      *cilcode;
    
      unsigned long      SizeOfMetadata;
      unsigned long      SizeOfCilCode;
    
      unsigned long      ImageBase;
      unsigned long      FileAlignment;
      unsigned long      EntryPointToken;
      unsigned short     Subsystem;
    };
    typedef struct INPUT_PARAMETERS *PINPUT_PARAMETERS;
    
    void  make_file      (FILE *file, PINPUT_PARAMETERS inP);
    
    // Struct IMAGE_DATA_DIRECTORY
    struct IMAGE_DATA_DIRECTORY {
      unsigned long   RVA;
      unsigned long   Size;
    };
    
    typedef struct IMAGE_DATA_DIRECTORY *PIMAGE_DATA_DIRECTORY;
    
    struct IMAGE_SECTION_HEADER {
      unsigned char  Name[8];
      unsigned long  VirtualSize;
      unsigned long  VirtualAddress;
      unsigned long  SizeOfRawData;
      unsigned long  PointerToRawData;
      unsigned long  PointerToRelocations;
      unsigned long  PointerToLinenumbers;
      unsigned short NumberOfRelocations;
      unsigned short NumberOfLinenumbers;
      unsigned long  Characteristics;
    };
    
    struct HEADERS {
    
      char ms_dos_header[128];          // MS-DOS header
      unsigned long  signature;         // PE signature
    
      struct _IMAGE_FILE_HEADER {       // PE header
        unsigned short  Machine;
        unsigned short  NumberOfSections;
        unsigned long   TimeDateStamp;
        unsigned long   PointerToSymbolTable;
        unsigned long   NumberOfSymbols;
        unsigned short  OptionalHeaderSize;
        unsigned short  Characteristics;
      }PeHdr;
    
      struct _IMAGE_OPTIONAL_HEADER {      // optional PE header
        unsigned short  Magic;
        unsigned char   LMajor;
        unsigned char   LMinor;
        unsigned long   CodeSize;
        unsigned long   SizeOfInitializedData;
        unsigned long   SizeOfUninitializedData;
        unsigned long   EntryPointRVA;
        unsigned long   BaseOfCode;
        unsigned long   BaseOfData;
        unsigned long   ImageBase;
        unsigned long   SectionAlignment;
        unsigned long   FileAlignment;
        unsigned short  OSMajor;
        unsigned short  OSMinor;
        unsigned short  UserMajor;
        unsigned short  UserMinor;
        unsigned short  SubsysMajor;
        unsigned short  SubsysMinor;
        unsigned long   Reserved;
        unsigned long   ImageSize;
        unsigned long   HeaderSize;
        unsigned long   FileCheckSum;
        unsigned short  Subsystem;
        unsigned short  DllFlags;
        unsigned long   StackReserveSize;
        unsigned long   StackCommitSize;
        unsigned long   HeapReserveSize;
        unsigned long   HeapCommitSize;
        unsigned long   LoaderFlags;
        unsigned long   NumberOfDataDirectories;
      }OptHdr;
    
    struct IMAGE_DATA_DIRECTORY STUB1;     
    struct IMAGE_DATA_DIRECTORY IMPORT_DIRECTORY; // import directory
    struct IMAGE_DATA_DIRECTORY STUB2[3];
    struct IMAGE_DATA_DIRECTORY BASE_RELOC_DIRECTORY;
    struct IMAGE_DATA_DIRECTORY STUB3[6];
    struct IMAGE_DATA_DIRECTORY IAT_DIRECTORY;   // IAT directory
    struct IMAGE_DATA_DIRECTORY STUB4;
    struct IMAGE_DATA_DIRECTORY CLI_DIRECTORY;   // CLI directory
    struct IMAGE_DATA_DIRECTORY STUB5;
    
    struct IMAGE_SECTION_HEADER TEXT_SECTION; // .text section header
    struct IMAGE_SECTION_HEADER CLI_SECTION;  // .cli section header
    struct IMAGE_SECTION_HEADER RELOC_SECTION; // .reloc section header
    
    };
    
    typedef struct HEADERS *PHEADERS;
    
    // .CLI Section
    struct CLI_SECTION_IMAGE {
      
      struct _JMP_STUB {               // entry point
        unsigned short     JmpInstruction;
        unsigned long      JmpAddress;
      }JMP_STUB;
    
      struct _CLI_HEADER {              // CLI header
        unsigned long      cb;       
        unsigned short     MajorRuntimeVersion;
        unsigned short     MinorRuntimeVersion;
        struct IMAGE_DATA_DIRECTORY  MetaData;    
        unsigned long      Flags;      
        unsigned long      EntryPointToken;
        struct IMAGE_DATA_DIRECTORY  NotUsed[6];
      }CLI_HEADER;
    
      struct _IMPORT_TABLE {             // Import table
    
        /* Import Address Table */
        unsigned long      HintNameTableRVA2;
        unsigned long      zero2;
        /* Import Directory Entry */
        unsigned long      ImportLookupTableRVA;
        unsigned long      TimeDateStamp;
        unsigned long      ForwarderChain;
        unsigned long      NameRVA;
        unsigned long      ImportAddressTableRVA;
        unsigned char      zero[20];
      
        /* Import Lookup Table */
        unsigned long      HintNameTableRVA1;
        unsigned long      zero1;
    
        /* Hint/Name Table */
        unsigned short     Hint;
        char          Name[12];
    
        /* Dll name ("mscoree.dll") */
        char          DllName[12];
      }IMPORT_TABLE;
    
    };
    
    //.reloc Section
    struct RELOC_SECTION
    {
      unsigned long        PageRVA;
      unsigned long        BlockSize;
      unsigned short       TypeOffset;
      unsigned short       Padding;      
    };
    
    struct IMAGE_COR20_HEADER
    {
      unsigned long      cb;       
      unsigned short     MajorRuntimeVersion;
      unsigned short     MinorRuntimeVersion;
      struct IMAGE_DATA_DIRECTORY  MetaData;    
      unsigned long      Flags;      
      unsigned long      EntryPointToken;
      struct IMAGE_DATA_DIRECTORY  Resources;
      struct IMAGE_DATA_DIRECTORY  StrongNameSignature;
      struct IMAGE_DATA_DIRECTORY  CodeManagerTable;
      struct IMAGE_DATA_DIRECTORY  VTableFixups;
      struct IMAGE_DATA_DIRECTORY  ExportAddressTableJumps;
      struct IMAGE_DATA_DIRECTORY  ManagedNativeHeader;
    };
    
    #endif

    A.3. pe.c

    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include "pe.h"
    #include "macros.h"
    
    void  make_headers    (FILE* file, PINPUT_PARAMETERS inP);
    void  make_text_section  (FILE* file, PINPUT_PARAMETERS inP);
    void  make_cli_section  (FILE* file, PINPUT_PARAMETERS inP);
    void  make_reloc_section (FILE* file, PINPUT_PARAMETERS inP);
    
    unsigned long align(unsigned long x, unsigned long alignment)
    {
      div_t t = div(x,alignment);
      return t.rem == 0 ? x : (t.quot+1)*alignment;
    };
    
    void make_file (FILE* file, PINPUT_PARAMETERS inP)
    {
      make_headers(file, inP);      	// Stage 1
      make_text_section(file, inP); 	// Stage 2
      make_cli_section(file, inP);	// Stage 3
      make_reloc_section(file, inP);	// Stage 4
    }
    
    unsigned char msdos_header[128] = {
      0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 
      0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 
      0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 
      0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 
      0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 
      0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 
      0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 
      0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 
      0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, 
      0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, 
      0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    // initialize constant fields in HEADERS structure
    void make_headers_const(PHEADERS Hdr){
      memcpy(Hdr->ms_dos_header, msdos_header, 128);
    
      Hdr->signature = 0x00004550;
    
      Hdr->PeHdr.Machine = IMAGE_FILE_MACHINE_I386;
      Hdr->PeHdr.PointerToSymbolTable = 0;
      Hdr->PeHdr.NumberOfSymbols = 0;
      Hdr->PeHdr.OptionalHeaderSize = 0xe0;
    
      // Optional Header
      Hdr->OptHdr.Magic  = 0x010B;
      Hdr->OptHdr.LMajor = 6;
      Hdr->OptHdr.LMinor = 0;
      Hdr->OptHdr.SizeOfUninitializedData   = 0;
      Hdr->OptHdr.SectionAlignment      = SECTION_ALIGNMENT;
      Hdr->OptHdr.OSMajor = 4;
      Hdr->OptHdr.OSMinor = 0;
      Hdr->OptHdr.UserMajor = 0;
      Hdr->OptHdr.UserMinor = 0;
      Hdr->OptHdr.SubsysMajor = 4;
      Hdr->OptHdr.SubsysMinor = 0;
      Hdr->OptHdr.Reserved = 0;
      Hdr->OptHdr.FileCheckSum = 0;
      Hdr->OptHdr.DllFlags  = 0x400;
      Hdr->OptHdr.StackReserveSize  = 0x100000;
      Hdr->OptHdr.StackCommitSize = 0x1000;
      Hdr->OptHdr.HeapReserveSize = 0x100000;
      Hdr->OptHdr.HeapCommitSize = 0x1000;
      Hdr->OptHdr.LoaderFlags = 0;
      Hdr->OptHdr.NumberOfDataDirectories = 16;
    
      // TEXT section
      Hdr->TEXT_SECTION.PointerToRelocations = 0;
      Hdr->TEXT_SECTION.PointerToLinenumbers = 0;
      Hdr->TEXT_SECTION.NumberOfRelocations  = 0;
      Hdr->TEXT_SECTION.NumberOfLinenumbers  = 0;
      Hdr->TEXT_SECTION.Characteristics    = 0x60000020;
      
      // CLI section
      Hdr->CLI_SECTION.PointerToRelocations  = 0;
      Hdr->CLI_SECTION.PointerToLinenumbers  = 0;
      Hdr->CLI_SECTION.NumberOfRelocations  = 0;
      Hdr->CLI_SECTION.NumberOfLinenumbers  = 0;
      Hdr->CLI_SECTION.Characteristics    = 0x60000020;
    
      // .RELOC section
      Hdr->RELOC_SECTION.PointerToRelocations = 0;
      Hdr->RELOC_SECTION.PointerToLinenumbers = 0;
      Hdr->RELOC_SECTION.NumberOfRelocations = 0;
      Hdr->RELOC_SECTION.NumberOfLinenumbers = 0;
      Hdr->RELOC_SECTION.Characteristics   = 0x42000040;
    
      // initialize to 0
      memset(Hdr->STUB1.RVA, 0, SIZEOF_DATA_DIRECTORY);
      memset(Hdr->STUB2, 0, 3 * SIZEOF_DATA_DIRECTORY);
      memset(Hdr->STUB3, 0, 6 * SIZEOF_DATA_DIRECTORY);
      memset(Hdr->STUB4.RVA, 0, SIZEOF_DATA_DIRECTORY);
      memset(Hdr->STUB5.RVA, 0, SIZEOF_DATA_DIRECTORY);
    
    };
    
    // initialize HEADERS structure
    void make_headers(FILE* file ,PINPUT_PARAMETERS inP){
    
      struct HEADERS Hdr;
      char * image;
    
      make_headers_const(Hdr);
      Hdr.PeHdr.NumberOfSections = 3;
      Hdr.PeHdr.TimeDateStamp = (long)time(NULL);
      
      if(inP->Type == EXE_TYPE)
        Hdr.PeHdr.Characteristics = 0x010E;
      else 
        Hdr.PeHdr.Characteristics = 0x210E;
    
      Hdr.OptHdr.CodeSize = SIZEOF_TEXT_M(inP);
      Hdr.OptHdr.SizeOfInitializedData = SIZEOF_TEXT_M(inP);
      Hdr.OptHdr.EntryPointRVA = RVA_OF_CLI(inP);
      Hdr.OptHdr.BaseOfCode = RVA_OF_TEXT;
      Hdr.OptHdr.BaseOfData = 0;
      Hdr.OptHdr.ImageBase = inP->ImageBase;
      Hdr.OptHdr.FileAlignment = inP->FileAlignment;
      Hdr.OptHdr.ImageSize = RVA_OF_RELOC(inP) + SIZEOF_RELOC_M;
      Hdr.OptHdr.HeaderSize = SIZEOF_HEADERS(inP);
      Hdr.OptHdr.Subsystem = inP->Subsystem;
    
      // Import Directory
      Hdr.IMPORT_DIRECTORY.RVA    = RVA_OF_CLI(inP) + 
        OFFSETOF(struct CLI_SECTION_IMAGE,
          IMPORT_TABLE.ImportLookupTableRVA);
      Hdr.IMPORT_DIRECTORY.Size        = 0x53;
    
      // Import Address Directory
      Hdr.IAT_DIRECTORY.RVA    = RVA_OF_CLI(inP) + 
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.HintNameTableRVA2);
      Hdr.IAT_DIRECTORY.Size         = 0x08;
    
      // Base Reloc Directory
      Hdr.BASE_RELOC_DIRECTORY.RVA = RVA_OF_RELOC(inP);
      Hdr.BASE_RELOC_DIRECTORY.Size      = 0x0C;
    
      // CLI Directory
      Hdr.CLI_DIRECTORY.RVA    = RVA_OF_CLI(inP) + SIZEOF_JMP_STUB;
      Hdr.CLI_DIRECTORY.Size   = SIZEOF_CLI_HEADER;
    
      //TEXT section
      memset(Hdr.TEXT_SECTION.Name, 0, sizeof(Hdr.TEXT_SECTION.Name));
      strcpy((char*)Hdr.TEXT_SECTION.Name, ".text");
    
      Hdr.TEXT_SECTION.VirtualSize    = SIZEOF_TEXT_NOTALIGNED(inP);
      Hdr.TEXT_SECTION.VirtualAddress   = SIZEOF_HEADERS_M(inP);
      Hdr.TEXT_SECTION.SizeOfRawData   = SIZEOF_TEXT(inP);
      Hdr.TEXT_SECTION.PointerToRawData  = SIZEOF_HEADERS(inP);
      //END of initializing TEXT section
    
      //.cli section
      memset(Hdr.CLI_SECTION.Name, 0, sizeof(Hdr.CLI_SECTION.Name));
      strcpy((char*)Hdr.CLI_SECTION.Name, ".cli");
    
      Hdr.CLI_SECTION.VirtualSize     = SIZEOF_CLI_NOTALIGNED;
      Hdr.CLI_SECTION.VirtualAddress   = SIZEOF_HEADERS_M(inP) + 
                         SIZEOF_TEXT_M(inP);
      Hdr.CLI_SECTION.SizeOfRawData    = SIZEOF_CLI(inP);
      Hdr.CLI_SECTION.PointerToRawData  = SIZEOF_HEADERS(inP) + 
                         SIZEOF_TEXT(inP);
      //END of initializing CLI section
    
      //.RELOC section
      memset(Hdr.RELOC_SECTION.Name, 0, sizeof(Hdr.RELOC_SECTION.Name));
      strcpy((char*)Hdr.RELOC_SECTION.Name, ".reloc");
    
      Hdr.RELOC_SECTION.VirtualSize     = SIZEOF_RELOC_NOTALIGNED;
      Hdr.RELOC_SECTION.VirtualAddress  = RVA_OF_RELOC(inP);
      Hdr.RELOC_SECTION.SizeOfRawData   = SIZEOF_RELOC(inP);
      Hdr.RELOC_SECTION.PointerToRawData = SIZEOF_HEADERS(inP) +
                         SIZEOF_TEXT(inP) + SIZEOF_CLI(inP); 
      //END of initializing .RELOC section
    
      image = malloc(SIZEOF_HEADERS(inP));
    
      memset(image,0,SIZEOF_HEADERS(inP));
      memcpy(image,(char *)Hdr, SIZEOF_HEADERS_NOTALIGNED);
      fwrite(image,1,SIZEOF_HEADERS(inP),file);
      free(image);
    };
    
    // initialize .TEXT section
    void make_text_section(FILE * file, PINPUT_PARAMETERS inP) {
      char * image;
    
      image = malloc(SIZEOF_TEXT(inP));
      memset(image, 0, SIZEOF_TEXT(inP));
      memcpy(image, inP->metadata, inP->SizeOfMetadata);
      memcpy(image+inP->SizeOfMetadata, inP->cilcode, 
    			inP->SizeOfCilCode);
    
      fwrite(image, 1, SIZEOF_TEXT(inP), file);
      free(image);
    }
    
    // initialize .CLI section
    void  make_cli_section(FILE * file, PINPUT_PARAMETERS inP) {
      struct CLI_SECTION_IMAGE cls;
      char * image;
    
      //JMP_STUB
      cls.JMP_STUB.JmpInstruction = 0x25FF;
    
      cls.JMP_STUB.JmpAddress   = RVA_OF_CLI(inP) + 
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.Hint) + 
        inP->ImageBase;
    
      //CLI_HEADER
      cls.CLI_HEADER.cb           = SIZEOF_CLI_HEADER;
      cls.CLI_HEADER.MajorRuntimeVersion   = 2;
      cls.CLI_HEADER.MinorRuntimeVersion   = 0;
      cls.CLI_HEADER.MetaData.RVA      = RVA_OF_TEXT;
      cls.CLI_HEADER.MetaData.Size      = inP->SizeOfMetadata;
      cls.CLI_HEADER.Flags          = 1;
      cls.CLI_HEADER.EntryPointToken     = inP->EntryPointToken;
    
      memset(cls.CLI_HEADER.NotUsed, 0, 
    			 6*sizeof(struct IMAGE_DATA_DIRECTORY));
    
      //Import Table
      cls.IMPORT_TABLE.ImportLookupTableRVA  = RVA_OF_CLI(inP) + 	
    		OFFSETOF(struct CLI_SECTION_IMAGE, 
    			IMPORT_TABLE.HintNameTableRVA1);
    
      cls.IMPORT_TABLE.TimeDateStamp   = 0;
      cls.IMPORT_TABLE.ForwarderChain   = 0;
    
      cls.IMPORT_TABLE.NameRVA      = RVA_OF_CLI(inP) +
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.DllName);
    
      cls.IMPORT_TABLE.ImportAddressTableRVA = RVA_OF_CLI(inP) + 
        OFFSETOF(struct CLI_SECTION_IMAGE, 	IMPORT_TABLE.HintNameTableRVA2);
    
      memset(cls.IMPORT_TABLE.zero, 0, 20);
    
      cls.IMPORT_TABLE.HintNameTableRVA1 = (RVA_OF_CLI(inP) +
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.Hint)) ;
    
      cls.IMPORT_TABLE.zero1 = 0;
    
      cls.IMPORT_TABLE.HintNameTableRVA2 = (RVA_OF_CLI(inP) +
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.Hint));
    
      cls.IMPORT_TABLE.zero2 = 0;
    
      cls.IMPORT_TABLE.Hint = 0;
    
      if(inP->Type == EXE_TYPE) 
        strcpy(cls.IMPORT_TABLE.Name, "_CorExeMain");
      else 
        strcpy(cls.IMPORT_TABLE.Name, "_CorDllMain");
    
      strcpy(cls.IMPORT_TABLE.DllName, "mscoree.dll");
    
      image = malloc(SIZEOF_CLI(inP));
      memset(image, 0, SIZEOF_CLI(inP));
      memcpy(image, (char *) cls, SIZEOF_CLI_NOTALIGNED);
      fwrite(image,1, SIZEOF_CLI(inP),file);
      free(image);
    };
    
    // initialize .RELOC section
    void  make_reloc_section(FILE* file, PINPUT_PARAMETERS inP) {
      struct RELOC_SECTION  rls;
      char * image;
    
      rls.PageRVA   = RVA_OF_CLI(inP);
      rls.BlockSize  = SIZEOF_RELOC_NOTALIGNED;
      rls.TypeOffset  = TYPE_OFFSET(0x3,0x2);
      rls.Padding   = 0;
      
      image = malloc(SIZEOF_RELOC(inP));
      memset(image, 0, SIZEOF_RELOC(inP));
      memcpy(image, (char *)rls, SIZEOF_RELOC_NOTALIGNED);
      fwrite(image,1, SIZEOF_RELOC(inP),file);
      free(image);
    };

    A.4. main.c

    #include <stdlib.h>
    #include <stdio.h>
    
    #include "pe.h"
    #include "macros.h"
    
    // METADATA
    extern unsigned char metadata[] = {
      0x42, 0x53, 0x4A, 0x42, 0x01, 0x00, 0x01, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 
      0x76, 0x31, 0x2E, 0x31, 0x2E, 0x34, 0x33, 0x32, 
      0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 
      0xAC, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 
      0x23, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x73, 
      0x00, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 
      0x40, 0x00, 0x00, 0x00, 0x23, 0x55, 0x53, 0x00, 
      0x6C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 
      0x23, 0x42, 0x6C, 0x6F, 0x62, 0x00, 0x00, 0x00, 
      0x6C, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 
      0x23, 0x47, 0x55, 0x49, 0x44, 0x00, 0x00, 0x00, 
      0x7C, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 
      0x23, 0x7E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 
      0x01, 0x04, 0x00, 0x01, 0x01, 0x0E, 0x08, 0xB7, 
      0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89, 0x03, 
      0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 
      0x74, 0x68, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 
      0x2E, 0x65, 0x78, 0x65, 0x00, 0x3C, 0x4D, 0x6F, 
      0x64, 0x75, 0x6C, 0x65, 0x3E, 0x00, 0x63, 0x61, 
      0x6C, 0x63, 0x00, 0x6D, 0x73, 0x63, 0x6F, 0x72, 
      0x6C, 0x69, 0x62, 0x00, 0x53, 0x79, 0x73, 0x74, 
      0x65, 0x6D, 0x00, 0x43, 0x6F, 0x6E, 0x73, 0x6F, 
      0x6C, 0x65, 0x00, 0x57, 0x72, 0x69, 0x74, 0x65, 
      0x4C, 0x69, 0x6E, 0x65, 0x00, 0x52, 0x65, 0x61, 
      0x64, 0x4C, 0x69, 0x6E, 0x65, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x48, 0x00, 
      0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x1B, 0x2D, 0x61, 0x86, 
      0x33, 0x03, 0x08, 0x4F, 0xA8, 0x8A, 0x85, 0x73, 
      0x26, 0xD7, 0x2D, 0xDF, 0x00, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x00, 0x01, 0x47, 0x04, 0x00, 0x00, 
      0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x06, 0x00, 0x2F, 0x00, 0x28, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x14, 0x22, 
      0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x1A, 0x00, 
      0x01, 0x00, 0x01, 0x00, 0x09, 0x00, 0x41, 0x00, 
      0x13, 0x00, 0x09, 0x00, 0x37, 0x00, 0x05, 0x00, 
      0x04, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 
      0x00, 0x00, 0x88, 0x13, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00
    };
    
    // CIL CODE
    extern unsigned char cilcode[] = {
      0x56, 0x72, 0x01, 0x00, 0x00, 0x70, 0x28, 0x02, 
      0x00, 0x00, 0x0A, 0x28, 0x01, 0x00, 0x00, 0x0A, 
      0x28, 0x02, 0x00, 0x00, 0x0A, 0x2A
    };
    
    int main()
    {
      FILE *f;
    
      struct INPUT_PARAMETERS params;
    
      params.FileAlignment = 0x1000;
      params.SizeOfMetadata = sizeof(metadata);
      params.SizeOfCilCode = sizeof(cilcode);
      params.ImageBase = 0x400000;
      params.EntryPointToken = 0x06000001;
      params.Type = EXE_TYPE;
      params.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
      params.metadata = metadata;
      params.cilcode = cilcode;
    
      if(params.Type == EXE_TYPE){
        printf("File: hello.exe generated\n");
        f = fopen("hello.exe","wb");
      }
      else{
        printf("File: hello.dll generated\n");
        f = fopen("hello.dll","wb");
      }
    
      make_file(f, params);
    
      fclose(f);
      return 0;
    }
    Страницы:

    Исходный код программы pegen

    Исходный код программы pegen, выполняющей генерацию сборки .NET, размещен в четырех файлах:

  • macros.h

    Содержит макроопределения, которые используются в остальных файлах.

  • pe.h

    Интерфейс модуля генерации PE-файла.

  • pe.c

    Реализация модуля генерации PE-файла.

  • main.c

    Главный модуль, использующий модуль генерации для создания простейшей сборки .NET.

  • A.1. macros.h

    #ifndef MACROS_H
    #define MACROS_H
    
    #define SECTION_ALIGNMENT   	0x2000
    #define EXE_TYPE                0x1
    #define DLL_TYPE                0x0
    #define SIZEOF_JMP_STUB    	6
    #define SIZEOF_IMPORT_TABLE  	82
    
    #define CNT_CODE    0x00000020
    #define CNT_INITIALIZED_DATA  	0x00000040
    #define CNT_UNINITIALIZED_DATA 	0x00000080
    #define MEM_DISCARDABLE    	0x02000000
    #define MEM_EXECUTE      	0x20000000
    #define MEM_READ                0x40000000
    #define MEM_WRITE               0x80000000
    
    #define IMAGE_FILE_MACHINE_I386	0x014c
    
    #define IMAGE_SUBSYSTEM_WINDOWS_GUI  2 
    #define IMAGE_SUBSYSTEM_WINDOWS_CUI  3
    #define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9
    
    // Aligned to FileAlignment boundary
    #define SIZEOF_HEADERS(params)  \
        align(sizeof(struct HEADERS), params->FileAlignment)
    
    #define SIZEOF_TEXT(params) \
        align(params->SizeOfMetadata + params->SizeOfCilCode, \
        params->FileAlignment)
    
    #define SIZEOF_CLI(params) \
        align(sizeof(struct CLI_SECTION_IMAGE), params->FileAlignment)
    
    #define SIZEOF_RELOC(params)  \
        align(sizeof(struct RELOC_SECTION), params->FileAlignment)
    
    // Aligned to SectionAlignment boundary
    #define SIZEOF_HEADERS_M(params) \
        align(sizeof(struct HEADERS), SECTION_ALIGNMENT)
    
    #define SIZEOF_TEXT_M(params) \
        align(params->SizeOfMetadata + params->SizeOfCilCode, \
        SECTION_ALIGNMENT)
    
    #define SIZEOF_CLI_M  \
        align(sizeof(struct CLI_SECTION_IMAGE), SECTION_ALIGNMENT)
    
    #define SIZEOF_RELOC_M \
        align(sizeof(struct RELOC_SECTION), SECTION_ALIGNMENT)
    
    #define SIZEOF_METHODS(params) \
        align(params->SizeOfCilCode, SECTION_ALIGNMENT)
    
    // Not aligned
    #define SIZEOF_HEADERS_NOTALIGNED \
        sizeof(struct HEADERS)
    
    #define SIZEOF_CLI_NOTALIGNED  \
        sizeof(struct CLI_SECTION_IMAGE)
    
    #define SIZEOF_TEXT_NOTALIGNED(params) \
        params->SizeOfMetadata + params->SizeOfCilCode
    
    #define SIZEOF_CLI_HEADER \
        sizeof(struct IMAGE_COR20_HEADER)
    
    #define SIZEOF_RELOC_NOTALIGNED \
        sizeof(struct RELOC_SECTION)
    
    #define SIZEOF_DATA_DIRECTORY \
        sizeof(struct IMAGE_DATA_DIRECTORY)
    
    // RVA of section
    #define RVA_OF_TEXT   \
        align(sizeof(struct HEADERS), SECTION_ALIGNMENT)
    
    #define RVA_OF_CLI(params)  \
        RVA_OF_TEXT +     \
        align(params->SizeOfMetadata + params->SizeOfCilCode,
          SECTION_ALIGNMENT)
    
    #define RVA_OF_RELOC(params) \
        RVA_OF_CLI(params) + SIZEOF_CLI_M
    
    #define TYPE_OFFSET(a,b) \
        (a*0x1000 | b)
    
    #define OFFSETOF(s,m)  \
        (size_t)(((s *)0)->m)
    
    #endif

    A.2. pe.h

    #ifndef PE_H
    
    #include <stdio.h>
    
    // Block of input parameters
    struct INPUT_PARAMETERS {
      unsigned long      Type;    
      unsigned char      *metadata;
      unsigned char      *cilcode;
    
      unsigned long      SizeOfMetadata;
      unsigned long      SizeOfCilCode;
    
      unsigned long      ImageBase;
      unsigned long      FileAlignment;
      unsigned long      EntryPointToken;
      unsigned short     Subsystem;
    };
    typedef struct INPUT_PARAMETERS *PINPUT_PARAMETERS;
    
    void  make_file      (FILE *file, PINPUT_PARAMETERS inP);
    
    // Struct IMAGE_DATA_DIRECTORY
    struct IMAGE_DATA_DIRECTORY {
      unsigned long   RVA;
      unsigned long   Size;
    };
    
    typedef struct IMAGE_DATA_DIRECTORY *PIMAGE_DATA_DIRECTORY;
    
    struct IMAGE_SECTION_HEADER {
      unsigned char  Name[8];
      unsigned long  VirtualSize;
      unsigned long  VirtualAddress;
      unsigned long  SizeOfRawData;
      unsigned long  PointerToRawData;
      unsigned long  PointerToRelocations;
      unsigned long  PointerToLinenumbers;
      unsigned short NumberOfRelocations;
      unsigned short NumberOfLinenumbers;
      unsigned long  Characteristics;
    };
    
    struct HEADERS {
    
      char ms_dos_header[128];          // MS-DOS header
      unsigned long  signature;         // PE signature
    
      struct _IMAGE_FILE_HEADER {       // PE header
        unsigned short  Machine;
        unsigned short  NumberOfSections;
        unsigned long   TimeDateStamp;
        unsigned long   PointerToSymbolTable;
        unsigned long   NumberOfSymbols;
        unsigned short  OptionalHeaderSize;
        unsigned short  Characteristics;
      }PeHdr;
    
      struct _IMAGE_OPTIONAL_HEADER {      // optional PE header
        unsigned short  Magic;
        unsigned char   LMajor;
        unsigned char   LMinor;
        unsigned long   CodeSize;
        unsigned long   SizeOfInitializedData;
        unsigned long   SizeOfUninitializedData;
        unsigned long   EntryPointRVA;
        unsigned long   BaseOfCode;
        unsigned long   BaseOfData;
        unsigned long   ImageBase;
        unsigned long   SectionAlignment;
        unsigned long   FileAlignment;
        unsigned short  OSMajor;
        unsigned short  OSMinor;
        unsigned short  UserMajor;
        unsigned short  UserMinor;
        unsigned short  SubsysMajor;
        unsigned short  SubsysMinor;
        unsigned long   Reserved;
        unsigned long   ImageSize;
        unsigned long   HeaderSize;
        unsigned long   FileCheckSum;
        unsigned short  Subsystem;
        unsigned short  DllFlags;
        unsigned long   StackReserveSize;
        unsigned long   StackCommitSize;
        unsigned long   HeapReserveSize;
        unsigned long   HeapCommitSize;
        unsigned long   LoaderFlags;
        unsigned long   NumberOfDataDirectories;
      }OptHdr;
    
    struct IMAGE_DATA_DIRECTORY STUB1;     
    struct IMAGE_DATA_DIRECTORY IMPORT_DIRECTORY; // import directory
    struct IMAGE_DATA_DIRECTORY STUB2[3];
    struct IMAGE_DATA_DIRECTORY BASE_RELOC_DIRECTORY;
    struct IMAGE_DATA_DIRECTORY STUB3[6];
    struct IMAGE_DATA_DIRECTORY IAT_DIRECTORY;   // IAT directory
    struct IMAGE_DATA_DIRECTORY STUB4;
    struct IMAGE_DATA_DIRECTORY CLI_DIRECTORY;   // CLI directory
    struct IMAGE_DATA_DIRECTORY STUB5;
    
    struct IMAGE_SECTION_HEADER TEXT_SECTION; // .text section header
    struct IMAGE_SECTION_HEADER CLI_SECTION;  // .cli section header
    struct IMAGE_SECTION_HEADER RELOC_SECTION; // .reloc section header
    
    };
    
    typedef struct HEADERS *PHEADERS;
    
    // .CLI Section
    struct CLI_SECTION_IMAGE {
      
      struct _JMP_STUB {               // entry point
        unsigned short     JmpInstruction;
        unsigned long      JmpAddress;
      }JMP_STUB;
    
      struct _CLI_HEADER {              // CLI header
        unsigned long      cb;       
        unsigned short     MajorRuntimeVersion;
        unsigned short     MinorRuntimeVersion;
        struct IMAGE_DATA_DIRECTORY  MetaData;    
        unsigned long      Flags;      
        unsigned long      EntryPointToken;
        struct IMAGE_DATA_DIRECTORY  NotUsed[6];
      }CLI_HEADER;
    
      struct _IMPORT_TABLE {             // Import table
    
        /* Import Address Table */
        unsigned long      HintNameTableRVA2;
        unsigned long      zero2;
        /* Import Directory Entry */
        unsigned long      ImportLookupTableRVA;
        unsigned long      TimeDateStamp;
        unsigned long      ForwarderChain;
        unsigned long      NameRVA;
        unsigned long      ImportAddressTableRVA;
        unsigned char      zero[20];
      
        /* Import Lookup Table */
        unsigned long      HintNameTableRVA1;
        unsigned long      zero1;
    
        /* Hint/Name Table */
        unsigned short     Hint;
        char          Name[12];
    
        /* Dll name ("mscoree.dll") */
        char          DllName[12];
      }IMPORT_TABLE;
    
    };
    
    //.reloc Section
    struct RELOC_SECTION
    {
      unsigned long        PageRVA;
      unsigned long        BlockSize;
      unsigned short       TypeOffset;
      unsigned short       Padding;      
    };
    
    struct IMAGE_COR20_HEADER
    {
      unsigned long      cb;       
      unsigned short     MajorRuntimeVersion;
      unsigned short     MinorRuntimeVersion;
      struct IMAGE_DATA_DIRECTORY  MetaData;    
      unsigned long      Flags;      
      unsigned long      EntryPointToken;
      struct IMAGE_DATA_DIRECTORY  Resources;
      struct IMAGE_DATA_DIRECTORY  StrongNameSignature;
      struct IMAGE_DATA_DIRECTORY  CodeManagerTable;
      struct IMAGE_DATA_DIRECTORY  VTableFixups;
      struct IMAGE_DATA_DIRECTORY  ExportAddressTableJumps;
      struct IMAGE_DATA_DIRECTORY  ManagedNativeHeader;
    };
    
    #endif

    A.3. pe.c

    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include "pe.h"
    #include "macros.h"
    
    void  make_headers    (FILE* file, PINPUT_PARAMETERS inP);
    void  make_text_section  (FILE* file, PINPUT_PARAMETERS inP);
    void  make_cli_section  (FILE* file, PINPUT_PARAMETERS inP);
    void  make_reloc_section (FILE* file, PINPUT_PARAMETERS inP);
    
    unsigned long align(unsigned long x, unsigned long alignment)
    {
      div_t t = div(x,alignment);
      return t.rem == 0 ? x : (t.quot+1)*alignment;
    };
    
    void make_file (FILE* file, PINPUT_PARAMETERS inP)
    {
      make_headers(file, inP);      	// Stage 1
      make_text_section(file, inP); 	// Stage 2
      make_cli_section(file, inP);	// Stage 3
      make_reloc_section(file, inP);	// Stage 4
    }
    
    unsigned char msdos_header[128] = {
      0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 
      0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 
      0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 
      0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 
      0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 
      0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 
      0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 
      0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 
      0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, 
      0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, 
      0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    // initialize constant fields in HEADERS structure
    void make_headers_const(PHEADERS Hdr){
      memcpy(Hdr->ms_dos_header, msdos_header, 128);
    
      Hdr->signature = 0x00004550;
    
      Hdr->PeHdr.Machine = IMAGE_FILE_MACHINE_I386;
      Hdr->PeHdr.PointerToSymbolTable = 0;
      Hdr->PeHdr.NumberOfSymbols = 0;
      Hdr->PeHdr.OptionalHeaderSize = 0xe0;
    
      // Optional Header
      Hdr->OptHdr.Magic  = 0x010B;
      Hdr->OptHdr.LMajor = 6;
      Hdr->OptHdr.LMinor = 0;
      Hdr->OptHdr.SizeOfUninitializedData   = 0;
      Hdr->OptHdr.SectionAlignment      = SECTION_ALIGNMENT;
      Hdr->OptHdr.OSMajor = 4;
      Hdr->OptHdr.OSMinor = 0;
      Hdr->OptHdr.UserMajor = 0;
      Hdr->OptHdr.UserMinor = 0;
      Hdr->OptHdr.SubsysMajor = 4;
      Hdr->OptHdr.SubsysMinor = 0;
      Hdr->OptHdr.Reserved = 0;
      Hdr->OptHdr.FileCheckSum = 0;
      Hdr->OptHdr.DllFlags  = 0x400;
      Hdr->OptHdr.StackReserveSize  = 0x100000;
      Hdr->OptHdr.StackCommitSize = 0x1000;
      Hdr->OptHdr.HeapReserveSize = 0x100000;
      Hdr->OptHdr.HeapCommitSize = 0x1000;
      Hdr->OptHdr.LoaderFlags = 0;
      Hdr->OptHdr.NumberOfDataDirectories = 16;
    
      // TEXT section
      Hdr->TEXT_SECTION.PointerToRelocations = 0;
      Hdr->TEXT_SECTION.PointerToLinenumbers = 0;
      Hdr->TEXT_SECTION.NumberOfRelocations  = 0;
      Hdr->TEXT_SECTION.NumberOfLinenumbers  = 0;
      Hdr->TEXT_SECTION.Characteristics    = 0x60000020;
      
      // CLI section
      Hdr->CLI_SECTION.PointerToRelocations  = 0;
      Hdr->CLI_SECTION.PointerToLinenumbers  = 0;
      Hdr->CLI_SECTION.NumberOfRelocations  = 0;
      Hdr->CLI_SECTION.NumberOfLinenumbers  = 0;
      Hdr->CLI_SECTION.Characteristics    = 0x60000020;
    
      // .RELOC section
      Hdr->RELOC_SECTION.PointerToRelocations = 0;
      Hdr->RELOC_SECTION.PointerToLinenumbers = 0;
      Hdr->RELOC_SECTION.NumberOfRelocations = 0;
      Hdr->RELOC_SECTION.NumberOfLinenumbers = 0;
      Hdr->RELOC_SECTION.Characteristics   = 0x42000040;
    
      // initialize to 0
      memset(Hdr->STUB1.RVA, 0, SIZEOF_DATA_DIRECTORY);
      memset(Hdr->STUB2, 0, 3 * SIZEOF_DATA_DIRECTORY);
      memset(Hdr->STUB3, 0, 6 * SIZEOF_DATA_DIRECTORY);
      memset(Hdr->STUB4.RVA, 0, SIZEOF_DATA_DIRECTORY);
      memset(Hdr->STUB5.RVA, 0, SIZEOF_DATA_DIRECTORY);
    
    };
    
    // initialize HEADERS structure
    void make_headers(FILE* file ,PINPUT_PARAMETERS inP){
    
      struct HEADERS Hdr;
      char * image;
    
      make_headers_const(Hdr);
      Hdr.PeHdr.NumberOfSections = 3;
      Hdr.PeHdr.TimeDateStamp = (long)time(NULL);
      
      if(inP->Type == EXE_TYPE)
        Hdr.PeHdr.Characteristics = 0x010E;
      else 
        Hdr.PeHdr.Characteristics = 0x210E;
    
      Hdr.OptHdr.CodeSize = SIZEOF_TEXT_M(inP);
      Hdr.OptHdr.SizeOfInitializedData = SIZEOF_TEXT_M(inP);
      Hdr.OptHdr.EntryPointRVA = RVA_OF_CLI(inP);
      Hdr.OptHdr.BaseOfCode = RVA_OF_TEXT;
      Hdr.OptHdr.BaseOfData = 0;
      Hdr.OptHdr.ImageBase = inP->ImageBase;
      Hdr.OptHdr.FileAlignment = inP->FileAlignment;
      Hdr.OptHdr.ImageSize = RVA_OF_RELOC(inP) + SIZEOF_RELOC_M;
      Hdr.OptHdr.HeaderSize = SIZEOF_HEADERS(inP);
      Hdr.OptHdr.Subsystem = inP->Subsystem;
    
      // Import Directory
      Hdr.IMPORT_DIRECTORY.RVA    = RVA_OF_CLI(inP) + 
        OFFSETOF(struct CLI_SECTION_IMAGE,
          IMPORT_TABLE.ImportLookupTableRVA);
      Hdr.IMPORT_DIRECTORY.Size        = 0x53;
    
      // Import Address Directory
      Hdr.IAT_DIRECTORY.RVA    = RVA_OF_CLI(inP) + 
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.HintNameTableRVA2);
      Hdr.IAT_DIRECTORY.Size         = 0x08;
    
      // Base Reloc Directory
      Hdr.BASE_RELOC_DIRECTORY.RVA = RVA_OF_RELOC(inP);
      Hdr.BASE_RELOC_DIRECTORY.Size      = 0x0C;
    
      // CLI Directory
      Hdr.CLI_DIRECTORY.RVA    = RVA_OF_CLI(inP) + SIZEOF_JMP_STUB;
      Hdr.CLI_DIRECTORY.Size   = SIZEOF_CLI_HEADER;
    
      //TEXT section
      memset(Hdr.TEXT_SECTION.Name, 0, sizeof(Hdr.TEXT_SECTION.Name));
      strcpy((char*)Hdr.TEXT_SECTION.Name, ".text");
    
      Hdr.TEXT_SECTION.VirtualSize    = SIZEOF_TEXT_NOTALIGNED(inP);
      Hdr.TEXT_SECTION.VirtualAddress   = SIZEOF_HEADERS_M(inP);
      Hdr.TEXT_SECTION.SizeOfRawData   = SIZEOF_TEXT(inP);
      Hdr.TEXT_SECTION.PointerToRawData  = SIZEOF_HEADERS(inP);
      //END of initializing TEXT section
    
      //.cli section
      memset(Hdr.CLI_SECTION.Name, 0, sizeof(Hdr.CLI_SECTION.Name));
      strcpy((char*)Hdr.CLI_SECTION.Name, ".cli");
    
      Hdr.CLI_SECTION.VirtualSize     = SIZEOF_CLI_NOTALIGNED;
      Hdr.CLI_SECTION.VirtualAddress   = SIZEOF_HEADERS_M(inP) + 
                         SIZEOF_TEXT_M(inP);
      Hdr.CLI_SECTION.SizeOfRawData    = SIZEOF_CLI(inP);
      Hdr.CLI_SECTION.PointerToRawData  = SIZEOF_HEADERS(inP) + 
                         SIZEOF_TEXT(inP);
      //END of initializing CLI section
    
      //.RELOC section
      memset(Hdr.RELOC_SECTION.Name, 0, sizeof(Hdr.RELOC_SECTION.Name));
      strcpy((char*)Hdr.RELOC_SECTION.Name, ".reloc");
    
      Hdr.RELOC_SECTION.VirtualSize     = SIZEOF_RELOC_NOTALIGNED;
      Hdr.RELOC_SECTION.VirtualAddress  = RVA_OF_RELOC(inP);
      Hdr.RELOC_SECTION.SizeOfRawData   = SIZEOF_RELOC(inP);
      Hdr.RELOC_SECTION.PointerToRawData = SIZEOF_HEADERS(inP) +
                         SIZEOF_TEXT(inP) + SIZEOF_CLI(inP); 
      //END of initializing .RELOC section
    
      image = malloc(SIZEOF_HEADERS(inP));
    
      memset(image,0,SIZEOF_HEADERS(inP));
      memcpy(image,(char *)Hdr, SIZEOF_HEADERS_NOTALIGNED);
      fwrite(image,1,SIZEOF_HEADERS(inP),file);
      free(image);
    };
    
    // initialize .TEXT section
    void make_text_section(FILE * file, PINPUT_PARAMETERS inP) {
      char * image;
    
      image = malloc(SIZEOF_TEXT(inP));
      memset(image, 0, SIZEOF_TEXT(inP));
      memcpy(image, inP->metadata, inP->SizeOfMetadata);
      memcpy(image+inP->SizeOfMetadata, inP->cilcode, 
    			inP->SizeOfCilCode);
    
      fwrite(image, 1, SIZEOF_TEXT(inP), file);
      free(image);
    }
    
    // initialize .CLI section
    void  make_cli_section(FILE * file, PINPUT_PARAMETERS inP) {
      struct CLI_SECTION_IMAGE cls;
      char * image;
    
      //JMP_STUB
      cls.JMP_STUB.JmpInstruction = 0x25FF;
    
      cls.JMP_STUB.JmpAddress   = RVA_OF_CLI(inP) + 
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.Hint) + 
        inP->ImageBase;
    
      //CLI_HEADER
      cls.CLI_HEADER.cb           = SIZEOF_CLI_HEADER;
      cls.CLI_HEADER.MajorRuntimeVersion   = 2;
      cls.CLI_HEADER.MinorRuntimeVersion   = 0;
      cls.CLI_HEADER.MetaData.RVA      = RVA_OF_TEXT;
      cls.CLI_HEADER.MetaData.Size      = inP->SizeOfMetadata;
      cls.CLI_HEADER.Flags          = 1;
      cls.CLI_HEADER.EntryPointToken     = inP->EntryPointToken;
    
      memset(cls.CLI_HEADER.NotUsed, 0, 
    			 6*sizeof(struct IMAGE_DATA_DIRECTORY));
    
      //Import Table
      cls.IMPORT_TABLE.ImportLookupTableRVA  = RVA_OF_CLI(inP) + 	
    		OFFSETOF(struct CLI_SECTION_IMAGE, 
    			IMPORT_TABLE.HintNameTableRVA1);
    
      cls.IMPORT_TABLE.TimeDateStamp   = 0;
      cls.IMPORT_TABLE.ForwarderChain   = 0;
    
      cls.IMPORT_TABLE.NameRVA      = RVA_OF_CLI(inP) +
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.DllName);
    
      cls.IMPORT_TABLE.ImportAddressTableRVA = RVA_OF_CLI(inP) + 
        OFFSETOF(struct CLI_SECTION_IMAGE, 	IMPORT_TABLE.HintNameTableRVA2);
    
      memset(cls.IMPORT_TABLE.zero, 0, 20);
    
      cls.IMPORT_TABLE.HintNameTableRVA1 = (RVA_OF_CLI(inP) +
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.Hint)) ;
    
      cls.IMPORT_TABLE.zero1 = 0;
    
      cls.IMPORT_TABLE.HintNameTableRVA2 = (RVA_OF_CLI(inP) +
        OFFSETOF(struct CLI_SECTION_IMAGE, IMPORT_TABLE.Hint));
    
      cls.IMPORT_TABLE.zero2 = 0;
    
      cls.IMPORT_TABLE.Hint = 0;
    
      if(inP->Type == EXE_TYPE) 
        strcpy(cls.IMPORT_TABLE.Name, "_CorExeMain");
      else 
        strcpy(cls.IMPORT_TABLE.Name, "_CorDllMain");
    
      strcpy(cls.IMPORT_TABLE.DllName, "mscoree.dll");
    
      image = malloc(SIZEOF_CLI(inP));
      memset(image, 0, SIZEOF_CLI(inP));
      memcpy(image, (char *) cls, SIZEOF_CLI_NOTALIGNED);
      fwrite(image,1, SIZEOF_CLI(inP),file);
      free(image);
    };
    
    // initialize .RELOC section
    void  make_reloc_section(FILE* file, PINPUT_PARAMETERS inP) {
      struct RELOC_SECTION  rls;
      char * image;
    
      rls.PageRVA   = RVA_OF_CLI(inP);
      rls.BlockSize  = SIZEOF_RELOC_NOTALIGNED;
      rls.TypeOffset  = TYPE_OFFSET(0x3,0x2);
      rls.Padding   = 0;
      
      image = malloc(SIZEOF_RELOC(inP));
      memset(image, 0, SIZEOF_RELOC(inP));
      memcpy(image, (char *)rls, SIZEOF_RELOC_NOTALIGNED);
      fwrite(image,1, SIZEOF_RELOC(inP),file);
      free(image);
    };

    A.4. main.c

    #include <stdlib.h>
    #include <stdio.h>
    
    #include "pe.h"
    #include "macros.h"
    
    // METADATA
    extern unsigned char metadata[] = {
      0x42, 0x53, 0x4A, 0x42, 0x01, 0x00, 0x01, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 
      0x76, 0x31, 0x2E, 0x31, 0x2E, 0x34, 0x33, 0x32, 
      0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 
      0xAC, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 
      0x23, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x73, 
      0x00, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 
      0x40, 0x00, 0x00, 0x00, 0x23, 0x55, 0x53, 0x00, 
      0x6C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 
      0x23, 0x42, 0x6C, 0x6F, 0x62, 0x00, 0x00, 0x00, 
      0x6C, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 
      0x23, 0x47, 0x55, 0x49, 0x44, 0x00, 0x00, 0x00, 
      0x7C, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 
      0x23, 0x7E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 
      0x01, 0x04, 0x00, 0x01, 0x01, 0x0E, 0x08, 0xB7, 
      0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89, 0x03, 
      0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 
      0x74, 0x68, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 
      0x2E, 0x65, 0x78, 0x65, 0x00, 0x3C, 0x4D, 0x6F, 
      0x64, 0x75, 0x6C, 0x65, 0x3E, 0x00, 0x63, 0x61, 
      0x6C, 0x63, 0x00, 0x6D, 0x73, 0x63, 0x6F, 0x72, 
      0x6C, 0x69, 0x62, 0x00, 0x53, 0x79, 0x73, 0x74, 
      0x65, 0x6D, 0x00, 0x43, 0x6F, 0x6E, 0x73, 0x6F, 
      0x6C, 0x65, 0x00, 0x57, 0x72, 0x69, 0x74, 0x65, 
      0x4C, 0x69, 0x6E, 0x65, 0x00, 0x52, 0x65, 0x61, 
      0x64, 0x4C, 0x69, 0x6E, 0x65, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x48, 0x00, 
      0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x1B, 0x2D, 0x61, 0x86, 
      0x33, 0x03, 0x08, 0x4F, 0xA8, 0x8A, 0x85, 0x73, 
      0x26, 0xD7, 0x2D, 0xDF, 0x00, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x00, 0x01, 0x47, 0x04, 0x00, 0x00, 
      0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x06, 0x00, 0x2F, 0x00, 0x28, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x14, 0x22, 
      0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x1A, 0x00, 
      0x01, 0x00, 0x01, 0x00, 0x09, 0x00, 0x41, 0x00, 
      0x13, 0x00, 0x09, 0x00, 0x37, 0x00, 0x05, 0x00, 
      0x04, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
      0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 
      0x00, 0x00, 0x88, 0x13, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00
    };
    
    // CIL CODE
    extern unsigned char cilcode[] = {
      0x56, 0x72, 0x01, 0x00, 0x00, 0x70, 0x28, 0x02, 
      0x00, 0x00, 0x0A, 0x28, 0x01, 0x00, 0x00, 0x0A, 
      0x28, 0x02, 0x00, 0x00, 0x0A, 0x2A
    };
    
    int main()
    {
      FILE *f;
    
      struct INPUT_PARAMETERS params;
    
      params.FileAlignment = 0x1000;
      params.SizeOfMetadata = sizeof(metadata);
      params.SizeOfCilCode = sizeof(cilcode);
      params.ImageBase = 0x400000;
      params.EntryPointToken = 0x06000001;
      params.Type = EXE_TYPE;
      params.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
      params.metadata = metadata;
      params.cilcode = cilcode;
    
      if(params.Type == EXE_TYPE){
        printf("File: hello.exe generated\n");
        f = fopen("hello.exe","wb");
      }
      else{
        printf("File: hello.dll generated\n");
        f = fopen("hello.dll","wb");
      }
    
      make_file(f, params);
    
      fclose(f);
      return 0;
    }
    Вернуться к учебному плану