Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include <stdlib.h>
  2. #include <stdint.h>
  3. #include <string.h>
  4.  
  5. #define EPEP_INST
  6. #include "epep.h"
  7.  
  8. #define ERROR(epep) (printf("Error #%u from EPEP at " __FILE__ ": %u", epep.error_code, __LINE__), 1)
  9.  
  10. int main(int argc, char **argv) {
  11.         if (argc < 2) {
  12.                 printf("Usage:\n%s <filename>\n", argv[0]);
  13.                 return 0;
  14.         }
  15.         Epep epep = { 0 };
  16.         FILE *fp = fopen(argv[1], "rb");
  17.         if (!fp) {
  18.                 printf("File not found: %s\n", argv[1]);
  19.                 return 1;
  20.         }
  21.         if (!epep_init(&epep, fp)) {
  22.                 printf("Not PE");
  23.                 return 1;
  24.         }
  25.         printf("COFF File Header:\n");
  26.         printf("  Machine:              %04x\n", epep.coffFileHeader.Machine);
  27.         printf("  NumberOfSections:     %04x\n", epep.coffFileHeader.NumberOfSections);
  28.         printf("  TimeDateStamp:        %08x\n", epep.coffFileHeader.TimeDateStamp);
  29.         printf("  PointerToSymbolTable: %08x\n", epep.coffFileHeader.PointerToSymbolTable);
  30.         printf("  NumberOfSymbols:      %08x\n", epep.coffFileHeader.NumberOfSymbols);
  31.         printf("  SizeOfOptionalHeader: %04x\n", epep.coffFileHeader.SizeOfOptionalHeader);
  32.         printf("  Characteristics:      %04x\n", epep.coffFileHeader.Characteristics);
  33.         printf("\n");
  34.         if (epep.coffFileHeader.SizeOfOptionalHeader != 0) {
  35.                 printf("Optional Header:\n");
  36.                 printf("  Magic:                       %04x\n", epep.optionalHeader.Magic);
  37.                 printf("  MajorLinkerVersion:          %02x\n", epep.optionalHeader.MajorLinkerVersion);
  38.                 printf("  MinorLinkerVersion:          %02x\n", epep.optionalHeader.MinorLinkerVersion);
  39.                 printf("  SizeOfCode:                  %08x\n", epep.optionalHeader.SizeOfCode);
  40.                 printf("  SizeOfInitializedData:       %08x\n", epep.optionalHeader.SizeOfInitializedData);
  41.                 printf("  SizeOfUninitializedData:     %08x\n", epep.optionalHeader.SizeOfUninitializedData);
  42.                 printf("  AddressOfEntryPoint:         %08x\n", epep.optionalHeader.AddressOfEntryPoint);
  43.                 printf("  BaseOfCode:                  %08x\n", epep.optionalHeader.BaseOfCode);
  44.                 printf("  BaseOfData:                  %08x\n", epep.optionalHeader.BaseOfData);
  45.                 printf("  ImageBase:                   %016x\n", epep.optionalHeader.ImageBase);
  46.                 printf("  SectionAlignment:            %08x\n", epep.optionalHeader.SectionAlignment);
  47.                 printf("  FileAlignment:               %08x\n", epep.optionalHeader.FileAlignment);
  48.                 printf("  MajorOperatingSystemVersion: %04x\n", epep.optionalHeader.MajorOperatingSystemVersion);
  49.                 printf("  MinorOperatingSystemVersion: %04x\n", epep.optionalHeader.MinorOperatingSystemVersion);
  50.                 printf("  MajorImageVersion:           %04x\n", epep.optionalHeader.MajorImageVersion);
  51.                 printf("  MinorImageVersion:           %04x\n", epep.optionalHeader.MinorImageVersion);
  52.                 printf("  MajorSubsystemVersion:       %04x\n", epep.optionalHeader.MajorSubsystemVersion);
  53.                 printf("  MinorSubsystemVersion:       %04x\n", epep.optionalHeader.MinorSubsystemVersion);
  54.                 printf("  Win32VersionValue:           %08x\n", epep.optionalHeader.Win32VersionValue);
  55.                 printf("  SizeOfImage:                 %08x\n", epep.optionalHeader.SizeOfImage);
  56.                 printf("  SizeOfHeaders:               %08x\n", epep.optionalHeader.SizeOfHeaders);
  57.                 printf("  CheckSum:                    %08x\n", epep.optionalHeader.CheckSum);
  58.                 printf("  Subsystem:                   %04x\n", epep.optionalHeader.Subsystem);
  59.                 printf("  DllCharacteristics:          %04x\n", epep.optionalHeader.DllCharacteristics);
  60.                 printf("  SizeOfStackReserve:          %016x\n", epep.optionalHeader.SizeOfStackReserve);
  61.                 printf("  SizeOfStackCommit:           %016x\n", epep.optionalHeader.SizeOfStackCommit);
  62.                 printf("  SizeOfHeapReserve:           %016x\n", epep.optionalHeader.SizeOfHeapReserve);
  63.                 printf("  SizeOfHeapCommit:            %016x\n", epep.optionalHeader.SizeOfHeapCommit);
  64.                 printf("  LoaderFlags:                 %08x\n", epep.optionalHeader.LoaderFlags);
  65.                 printf("  NumberOfRvaAndSizes:         %08x\n", epep.optionalHeader.NumberOfRvaAndSizes);
  66.                 printf("\n");
  67.                 printf("Data directories:\n");
  68.                 for (size_t i = 0; i < epep.optionalHeader.NumberOfRvaAndSizes; i++) {
  69.                         char *dds[] = {
  70.                                 "Export Table",
  71.                                 "Import Table",
  72.                                 "Resource Table",
  73.                                 "Exception Table",
  74.                                 "Certificate Table",
  75.                                 "Base Relocation Table",
  76.                                 "Debug",
  77.                                 "Architecture",
  78.                                 "Global Ptr",
  79.                                 "TLS Table",
  80.                                 "Load Config Table",
  81.                                 "Bound Import",
  82.                                 "Import Address Table",
  83.                                 "Delay Import Descriptor",
  84.                                 "CLR Runtime Header",
  85.                                 "Reserved, must be zero"
  86.                         };
  87.                         EpepImageDataDirectory idd = { 0 };
  88.                         if (!epep_get_data_directory_by_index(&epep, &idd, i)) {
  89.                                 return ERROR(epep);
  90.                         }
  91.                         printf("  Data directory #%u:\n", i);
  92.                         printf("    Type:           %s\n", dds[i % 16]);
  93.                         printf("    VirtualAddress: %016x\n", idd.VirtualAddress);
  94.                         printf("    Size:           %016x\n", idd.Size);
  95.                         // Certificate table (4'th) data directory's VirtualAddress isn't a real RVA, it's a file offset
  96.                         // so it's actually outside of any section, so let's skip section name printing for it
  97.                         if (idd.VirtualAddress && i != 4) {
  98.                                 EpepSectionHeader sh = { 0 };
  99.                                 if (!epep_get_section_header_by_rva(&epep, &sh, idd.VirtualAddress)) {
  100.                                         return ERROR(epep);
  101.                                 }
  102.                                 printf("    Section:        %s\n", sh.Name);
  103.                         }
  104.                 }
  105.                 printf("\n");
  106.         }
  107.  
  108.         // Get string table useful to show long names of sections
  109.         size_t string_table_size = 1;
  110.         if (epep.kind == EPEP_OBJECT && !epep_get_string_table_size(&epep, &string_table_size)) {
  111.                 return ERROR(epep);
  112.         }
  113.         char *string_table = malloc(string_table_size);
  114.         if (epep.kind == EPEP_OBJECT && !epep_get_string_table(&epep, string_table)) {
  115.                 return ERROR(epep);
  116.         }
  117.  
  118.         printf("Section Table:\n");
  119.         for (size_t i = 0; i < epep.coffFileHeader.NumberOfSections; i++) {
  120.                 EpepSectionHeader sh = { 0 };
  121.                 if (!epep_get_section_header_by_index(&epep, &sh, i)) {
  122.                         return ERROR(epep);
  123.                 }
  124.                 printf("  Section #%u\n", i);
  125.                 if (epep.kind == EPEP_OBJECT && sh.Name[0] == '/') {
  126.                         printf("    Name:                 %s\n", &string_table[atoi(sh.Name + 1)]);
  127.                 } else {
  128.                         printf("    Name:                 %.*s\n", 8, sh.Name);
  129.                 }
  130.                 printf("    VirtualSize:          %08x\n", sh.VirtualSize);
  131.                 printf("    VirtualAddress:       %08x\n", sh.VirtualAddress);
  132.                 printf("    SizeOfRawData:        %08x\n", sh.SizeOfRawData);
  133.                 printf("    PointerToRawData:     %08x\n", sh.PointerToRawData);
  134.                 printf("    PointerToRelocations: %08x\n", sh.PointerToRelocations);
  135.                 printf("    PointerToLinenumbers: %08x\n", sh.PointerToLinenumbers);
  136.                 printf("    NumberOfRelocations:  %08x\n", sh.NumberOfRelocations);
  137.                 printf("    NumberOfLinenumbers:  %08x\n", sh.NumberOfLinenumbers);
  138.                 printf("    Characteristics:      %08x\n", sh.Characteristics);
  139.         }
  140.         printf("\n");
  141.         if (epep.kind == EPEP_OBJECT && epep.coffFileHeader.NumberOfSymbols != 0) {
  142.                 printf("Symbols:\n");
  143.                 for (size_t i = 0; i < epep.coffFileHeader.NumberOfSymbols; i++) {
  144.                         EpepCoffSymbol sym = { 0 };
  145.                         if (!epep_get_symbol_by_index(&epep, &sym, i)) {
  146.                                 return ERROR(epep);
  147.                         }
  148.                         printf("  Symbol #%u\n", i);
  149.                         if (sym.symbol.Zeroes == 0) {
  150.                                 printf("    Name:               %s\n", &string_table[sym.symbol.Offset]);
  151.                         } else {
  152.                                 printf("    Name:               %.*s\n", 8, sym.symbol.ShortName);
  153.                         }
  154.                         printf("    Value:              %08x\n", sym.symbol.Value);
  155.                         printf("    SectionNumber:      %04x\n", sym.symbol.SectionNumber);
  156.                         printf("    Type:               %04x\n", sym.symbol.Type);
  157.                         printf("    StorageClass:       %02x\n", sym.symbol.StorageClass);
  158.                         printf("    NumberOfAuxSymbols: %02x\n", sym.symbol.NumberOfAuxSymbols);
  159.                         for (size_t j = 0; j < sym.symbol.NumberOfAuxSymbols; j++) {
  160.                                 i++;
  161.                         }
  162.                 }
  163.                 printf("\n");
  164.         }
  165.         if (epep_has_import_table(&epep)) {
  166.                 printf("Import Directory Table:\n");
  167.                 for (size_t i = 0; i < 1024; i++) {
  168.                         EpepImportDirectory import_directory = { 0 };
  169.                         if (!epep_get_import_directory_by_index(&epep, &import_directory, i)) {
  170.                                 return ERROR(epep);
  171.                         }
  172.                         if (import_directory.NameRva == 0) {
  173.                                 break;
  174.                         }
  175.                         size_t name_max = 1024;
  176.                         char name[name_max];
  177.                         if (!epep_get_import_directory_name_s(&epep, &import_directory, name, name_max)) {
  178.                                 return ERROR(epep);
  179.                         }
  180.                         printf("  Import Directory #%lu:\n", i);
  181.                         printf("    Name:                  %s\n", name);
  182.                         printf("    ImportLookupTableRva:  %08x\n", import_directory.ImportLookupTableRva);
  183.                         printf("    TimeDateStamp:         %08x\n", import_directory.TimeDateStamp);
  184.                         printf("    ForwarderChain:        %08x\n", import_directory.ForwarderChain);
  185.                         printf("    ImportAddressTableRva: %08x\n", import_directory.ImportAddressTableRva);
  186.                         for (size_t j = 0; j < 1024 * 1024; j++) {
  187.                                 size_t lookup = 0;
  188.                                 if (!epep_get_import_directory_lookup_by_index(&epep, &import_directory, &lookup, j)) {
  189.                                         return ERROR(epep);
  190.                                 }
  191.                                 if (lookup == 0) {
  192.                                         break;
  193.                                 }
  194.                                 size_t name_max = 1024;
  195.                                 char name[name_max];
  196.                                 if (!epep_get_lookup_name_s(&epep, lookup, name, name_max)) {
  197.                                         return ERROR(epep);
  198.                                 }
  199.                                 printf("      Lookup:              %016x (%s)\n", lookup, name);
  200.                         }
  201.                 }
  202.                 printf("\n");
  203.         }
  204.         if (epep_has_export_table(&epep)) {
  205.                 if (!epep_read_export_directory(&epep)) {
  206.                         return ERROR(epep);
  207.                 }
  208.                 size_t name_max = 256;
  209.                 char name[name_max];
  210.                 strcpy(name, "undefined");
  211.                 if (!epep_get_dll_name_s(&epep, name, name_max)) {
  212.                         return ERROR(epep);
  213.                 }
  214.                 printf("Export Directory:\n");
  215.                 printf("  ExportFlags:           %08x\n", epep.export_directory.ExportFlags);
  216.                 printf("  TimeDateStamp:         %08x\n", epep.export_directory.TimeDateStamp);
  217.                 printf("  MajorVersion:          %04x\n", epep.export_directory.MajorVersion);
  218.                 printf("  MinorVersion:          %04x\n", epep.export_directory.MinorVersion);
  219.                 printf("  NameRva:               %08x (%s)\n", epep.export_directory.NameRva, name);
  220.                 printf("  OrdinalBase:           %08x\n", epep.export_directory.OrdinalBase);
  221.                 printf("  AddressTableEntries:   %08x\n", epep.export_directory.AddressTableEntries);
  222.                 printf("  NumberOfNamePointers:  %08x\n", epep.export_directory.NumberOfNamePointers);
  223.                 printf("  ExportAddressTableRva: %08x\n", epep.export_directory.ExportAddressTableRva);
  224.                 printf("  NamePointerRva:        %08x\n", epep.export_directory.NamePointerRva);
  225.                 printf("  OrdinalTableRva:       %08x\n", epep.export_directory.OrdinalTableRva);
  226.                 printf("  Exports:\n");
  227.                 for (size_t i = 0; i < epep.export_directory.AddressTableEntries; i++) {
  228.                         printf("    Export #%u:\n", i);
  229.                         size_t name_max = 1024;
  230.                         char name[name_max];
  231.                         printf("      Ordinal:      %u\n", epep.export_directory.OrdinalBase + i);
  232.                         if (epep_get_export_name_s_by_index(&epep, name, name_max, i)) {
  233.                                 printf("      Name:         %s\n", name);
  234.                         }
  235.                         EpepExportAddress ea = { 0 };
  236.                         if (!epep_get_export_address_by_index(&epep, &ea, i)) {
  237.                                 return ERROR(epep);
  238.                         }
  239.                         if (epep_export_address_is_forwarder(&epep, &ea)) {
  240.                                 size_t forwarder_max = 1024;
  241.                                 char forwarder[forwarder_max];
  242.                                 if (!epep_get_export_address_forwarder_s(&epep, &ea, forwarder, forwarder_max)) {
  243.                                         return ERROR(epep);
  244.                                 }
  245.                                 printf("      ForwarderRva: %08x (%s)\n", ea.ForwarderRva, forwarder);
  246.                         } else {
  247.                                 printf("      ExportRva:    %08x\n", ea.ExportRva);
  248.                         }
  249.                 }
  250.                 printf("\n");
  251.         }
  252.         if (epep_has_base_relocation_table(&epep)) {
  253.                 printf("Base Relocations:\n");
  254.                 EpepBaseRelocationBlock brb = { 0 };
  255.                 if (!epep_get_first_base_relocation_block(&epep, &brb)) {
  256.                         return ERROR(epep);
  257.                 }
  258.                 for (size_t i = 0; brb.offset; i++) {
  259.                         printf("  Base Relocation Block #%u:\n", i);
  260.                         printf("    PageRva:   %08x\n", brb.PageRva);
  261.                         printf("    BlockSize: %08x\n", brb.BlockSize);
  262.                         printf("    Relocations:\n");
  263.                         for (size_t j = 0; j < ((brb.BlockSize - 8) / 2); j++) {
  264.                                 char *strs[] = {
  265.                                         "IMAGE_REL_BASED_ABSOLUTE",
  266.                                         "IMAGE_REL_BASED_HIGH",
  267.                                         "IMAGE_REL_BASED_LOW",
  268.                                         "IMAGE_REL_BASED_HIGHLOW",
  269.                                         "IMAGE_REL_BASED_HIGHADJ",
  270.                                         "IMAGE_REL_BASED_MIPS_JMPADDR | IMAGE_REL_BASED_ARM_MOV32 | IMAGE_REL_BASED_RISCV_HIGH20",
  271.                                         "reserved, must be zero",
  272.                                         "IMAGE_REL_BASED_THUMB_MOV32 | IMAGE_REL_BASED_RISCV_LOW12I",
  273.                                         "IMAGE_REL_BASED_RISCV_LOW12S",
  274.                                         "IMAGE_REL_BASED_MIPS_JMPADDR16",
  275.                                         "IMAGE_REL_BASED_DIR64",
  276.                                 };
  277.                                 printf("      Relocation #%u:\n", j);
  278.                                 EpepBaseRelocation br = { 0 };
  279.                                 if (!epep_get_base_relocation_block_base_relocation_by_index(&epep, &brb, &br, j)) {
  280.                                         return ERROR(epep);
  281.                                 }
  282.                                 printf("        Type:   %01x (%s)\n", br.Type, strs[br.Type % (sizeof(strs) / sizeof(*strs))]);
  283.                                 printf("        Offset: %03x (%u)\n", br.Offset, br.Offset);
  284.                         }
  285.                         if (!epep_get_next_base_relocation_block(&epep, &brb)) {
  286.                                 return ERROR(epep);
  287.                         }
  288.                 }
  289.                 printf("\n");
  290.         }
  291.         if (epep.kind == EPEP_OBJECT) {
  292.                 for (size_t i = 0; i < epep.coffFileHeader.NumberOfSections; i++) {
  293.                         EpepSectionHeader sh = { 0 };
  294.                         if (!epep_get_section_header_by_index(&epep, &sh, i)) {
  295.                                 return ERROR(epep);
  296.                         }
  297.                         printf("  Relocations for section #%u", i);
  298.                         if (epep.kind == EPEP_OBJECT && sh.Name[0] == '/') {
  299.                                 printf(" (%s)\n", &string_table[atoi(sh.Name + 1)]);
  300.                         } else {
  301.                                 printf(" (%.*s)\n", 8, sh.Name);
  302.                         }
  303.                         for (size_t i = 0; i < sh.NumberOfRelocations; i++) {
  304.                                 EpepCoffRelocation rel = { 0 };
  305.                                 if (!epep_get_section_relocation_by_index(&epep, &sh, &rel, i)) {
  306.                                         return ERROR(epep);
  307.                                 }
  308.                                 printf("    COFF Relocation #%u\n", i);
  309.                                 printf("      VirtualAddress: %08x\n", rel.VirtualAddress);
  310.                                 printf("      SymbolTableIndex: %08x\n", rel.SymbolTableIndex);
  311.                                 printf("      Type: %04x\n", rel.Type);
  312.                         }
  313.                 }
  314.         }
  315.         if (epep.kind == EPEP_OBJECT) {
  316.                 for (size_t i = 0; i < epep.coffFileHeader.NumberOfSections; i++) {
  317.                         EpepSectionHeader sh = { 0 };
  318.                         if (!epep_get_section_header_by_index(&epep, &sh, i)) {
  319.                                 return ERROR(epep);
  320.                         }
  321.                         printf("  Linenumbers for section #%u", i);
  322.                         if (epep.kind == EPEP_OBJECT && sh.Name[0] == '/') {
  323.                                 printf(" (%s)\n", &string_table[atoi(sh.Name + 1)]);
  324.                         } else {
  325.                                 printf(" (%.*s)\n", 8, sh.Name);
  326.                         }
  327.                         for (size_t i = 0; i < sh.NumberOfLinenumbers; i++) {
  328.                                 EpepCoffLinenumber ln = { 0 };
  329.                                 if (!epep_get_section_line_number_by_index(&epep, &sh, &ln, i)) {
  330.                                         return ERROR(epep);
  331.                                 }
  332.                                 printf("    COFF Line Number #%u\n", i);
  333.                                 printf("      Type: %04x\n", ln.Type);
  334.                                 printf("      Linenumber: %08x\n", ln.Linenumber);
  335.                         }
  336.                 }
  337.         }
  338.         return 0;
  339. }
  340.