Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

htpehead.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      htpehead.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include "formats.h"
00022 #include "htapp.h"
00023 #include "htatom.h"
00024 #include "htcoff.h"
00025 #include "htctrl.h"
00026 #include "htendian.h"
00027 #include "hthex.h"
00028 #include "htiobox.h"
00029 #include "htnewexe.h"
00030 #include "htpe.h"
00031 #include "htpehead.h"
00032 #include "httag.h"
00033 #include "htstring.h"
00034 #include "snprintf.h"
00035 
00036 #include "pestruct.h"
00037 
00038 #include <string.h>
00039 
00040 static int_hash pe_optional_magics[] =
00041 {
00042         {COFF_OPTMAGIC_ROMIMAGE, "ROM image"},
00043         {COFF_OPTMAGIC_PE32, "PE/PE32"},
00044         {COFF_OPTMAGIC_PE64, "PE32+/PE64"},
00045         {0, 0}
00046 };
00047 
00048 static int_hash pe_subsystems[] =
00049 {
00050         {0, "generic"},
00051         {PE_SUBSYSTEM_NATIVE, "native"},
00052         {PE_SUBSYSTEM_WINDOWS_GUI, "Windows GUI"},
00053         {PE_SUBSYSTEM_WINDOWS_CUI, "Windows CUI"},
00054         {PE_SUBSYSTEM_OS2_CUI, "OS/2 CUI"},
00055         {PE_SUBSYSTEM_POSIX_CUI, "POSIX CUI"},
00056         {PE_SUBSYSTEM_CE_GUI, "Windows CE GUI"},
00057         {PE_SUBSYSTEM_EFI_APPLICATION, "EFI"},
00058         {PE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, "EFI/boot"},
00059         {PE_SUBSYSTEM_EFI_RUNTIME_DRIVER, "EFI/runtime"},
00060         {0, 0}
00061 };
00062 
00063 static ht_mask_ptable pemagic[] = {
00064         {"magic",                                               STATICTAG_EDIT_DWORD_LE("00000000")},
00065         {0, 0}
00066 };
00067 
00068 static ht_mask_ptable pe32header[] = {
00069         {"optional magic",                              STATICTAG_EDIT_WORD_LE("00000014")" "STATICTAG_DESC_WORD_LE("00000014", ATOM_PE_OPTIONAL_MAGICS_STR)},
00070         {"major linker version",                        STATICTAG_EDIT_BYTE("00000016")},
00071         {"minor linker version",                        STATICTAG_EDIT_BYTE("00000017")},
00072         {"size of code",                                STATICTAG_EDIT_DWORD_LE("00000018")},
00073         {"size of data",                                STATICTAG_EDIT_DWORD_LE("0000001c")},
00074         {"size of bss",                         STATICTAG_EDIT_DWORD_LE("00000020")},
00075         {"entry point",                         STATICTAG_EDIT_DWORD_LE("00000024")},
00076         {"code base",                                   STATICTAG_EDIT_DWORD_LE("00000028")},
00077         {"data base",                                   STATICTAG_EDIT_DWORD_LE("0000002c")},
00078         {0, 0}
00079 };
00080 
00081 static ht_tag_flags_s pe_dll_characteristics[] =
00082 {
00083         {-1, "PE - dll characteristics"},
00084         {0,  "[00] * reserved"},
00085         {1,  "[01] * reserved"},
00086         {2,  "[02] * reserved"},
00087         {3,  "[03] * reserved"},
00088         {11,  "[11] do not bind"},
00089         {13,  "[13] WDM driver"},
00090         {15,  "[15] image is terminal server aware"},
00091         {0, 0}
00092 };
00093 
00094 static ht_mask_ptable pe32header_nt[] = {
00095         {"image base",                                  STATICTAG_EDIT_DWORD_LE("00000030")},
00096         {"section alignment",                   STATICTAG_EDIT_DWORD_LE("00000034")},
00097         {"file alignment",                              STATICTAG_EDIT_DWORD_LE("00000038")},
00098         {"major OS version",                    STATICTAG_EDIT_WORD_LE("0000003c")},
00099         {"minor OS version",                    STATICTAG_EDIT_WORD_LE("0000003e")},
00100         {"major image version",                 STATICTAG_EDIT_WORD_LE("00000040")},
00101         {"minor image version",                 STATICTAG_EDIT_WORD_LE("00000042")},
00102         {"major subsystem version",             STATICTAG_EDIT_WORD_LE("00000044")},
00103         {"minor subsystem version",             STATICTAG_EDIT_WORD_LE("00000046")},
00104         {"Win32 version",                               STATICTAG_EDIT_DWORD_LE("00000048")},
00105         {"size of image",                               STATICTAG_EDIT_DWORD_LE("0000004c")},
00106         {"size of headers",                             STATICTAG_EDIT_DWORD_LE("00000050")},
00107         {"checksum",                                    STATICTAG_EDIT_DWORD_LE("00000054")},
00108         {"subsystem",                                   STATICTAG_EDIT_WORD_LE("00000058")" "STATICTAG_DESC_WORD_LE("00000058", ATOM_PE_SUBSYSTEMS_STR)},
00109         {"dll characteristics",                 STATICTAG_EDIT_WORD_LE("0000005a")" "STATICTAG_FLAGS("0000005a", ATOM_PE_DLL_CHARACTERISTICS_STR)},
00110         {"stack reserve",                               STATICTAG_EDIT_DWORD_LE("0000005c")},
00111         {"stack commit",                                STATICTAG_EDIT_DWORD_LE("00000060")},
00112         {"heap reserve",                                STATICTAG_EDIT_DWORD_LE("00000064")},
00113         {"heap commit",                         STATICTAG_EDIT_DWORD_LE("00000068")},
00114         {"loader flags",                                STATICTAG_EDIT_DWORD_LE("0000006c")},
00115         {"number of directory entries", STATICTAG_EDIT_DWORD_LE("00000070")},
00116         {0, 0}
00117 };
00118 
00119 static ht_mask_ptable pe64header_nt[] = {
00120         {"image base",                  STATICTAG_EDIT_QWORD_LE("0000002c")},
00121         {"section alignment",           STATICTAG_EDIT_DWORD_LE("00000034")},
00122         {"file alignment",              STATICTAG_EDIT_DWORD_LE("00000038")},
00123         {"major OS version",            STATICTAG_EDIT_WORD_LE("0000003c")},
00124         {"minor OS version",            STATICTAG_EDIT_WORD_LE("0000003e")},
00125         {"major image version",         STATICTAG_EDIT_WORD_LE("00000040")},
00126         {"minor image version",         STATICTAG_EDIT_WORD_LE("00000042")},
00127         {"major subsystem version",     STATICTAG_EDIT_WORD_LE("00000044")},
00128         {"minor subsystem version",     STATICTAG_EDIT_WORD_LE("00000046")},
00129         {"Win32 version",               STATICTAG_EDIT_DWORD_LE("00000048")},
00130         {"size of image",               STATICTAG_EDIT_DWORD_LE("0000004c")},
00131         {"size of headers",             STATICTAG_EDIT_DWORD_LE("00000050")},
00132         {"checksum",                    STATICTAG_EDIT_DWORD_LE("00000054")},
00133         {"subsystem",                   STATICTAG_EDIT_WORD_LE("00000058")" "STATICTAG_DESC_WORD_LE("00000058", ATOM_PE_SUBSYSTEMS_STR)},
00134         {"dll characteristics",         STATICTAG_EDIT_WORD_LE("0000005a")},
00135         {"stack reserve",               STATICTAG_EDIT_QWORD_LE("0000005c")},
00136         {"stack commit",                STATICTAG_EDIT_QWORD_LE("00000064")},
00137         {"heap reserve",                STATICTAG_EDIT_QWORD_LE("0000006c")},
00138         {"heap commit",                 STATICTAG_EDIT_QWORD_LE("00000074")},
00139         {"loader flags",                STATICTAG_EDIT_DWORD_LE("0000007c")},
00140         {"number of directory entries", STATICTAG_EDIT_DWORD_LE("00000080")},
00141         {0, 0}
00142 };
00143 
00144 static ht_mask_ptable pe32header_nt_dirs[] = {
00145         {"export directory             (rva/size)", STATICTAG_EDIT_DWORD_LE("00000000")" "STATICTAG_EDIT_DWORD_LE("00000004")" "STATICTAG_REF("0000000000000000", "03", "raw")" "STATICTAG_REF("0000000100000000", "04", "cook")},
00146         {"import directory             (rva/size)", STATICTAG_EDIT_DWORD_LE("00000008")" "STATICTAG_EDIT_DWORD_LE("0000000c")" "STATICTAG_REF("0000000000000001", "03", "raw")" "STATICTAG_REF("0000000200000000", "04", "cook")},
00147         {"resource directory           (rva/size)", STATICTAG_EDIT_DWORD_LE("00000010")" "STATICTAG_EDIT_DWORD_LE("00000014")" "STATICTAG_REF("0000000000000002", "03", "raw")" "STATICTAG_REF("0000000300000000", "04", "cook")},
00148         {"exception directory          (rva/size)", STATICTAG_EDIT_DWORD_LE("00000018")" "STATICTAG_EDIT_DWORD_LE("0000001c")" "STATICTAG_REF("0000000000000003", "03", "raw")},
00149         {"security directory           (rva/size)", STATICTAG_EDIT_DWORD_LE("00000020")" "STATICTAG_EDIT_DWORD_LE("00000024")" "STATICTAG_REF("0000000000000004", "03", "raw")},
00150         {"base relocation table        (rva/size)", STATICTAG_EDIT_DWORD_LE("00000028")" "STATICTAG_EDIT_DWORD_LE("0000002c")" "STATICTAG_REF("0000000000000005", "03", "raw")},
00151         {"debug directory              (rva/size)", STATICTAG_EDIT_DWORD_LE("00000030")" "STATICTAG_EDIT_DWORD_LE("00000034")" "STATICTAG_REF("0000000000000006", "03", "raw")},
00152         {"description string           (rva/size)", STATICTAG_EDIT_DWORD_LE("00000038")" "STATICTAG_EDIT_DWORD_LE("0000003c")" "STATICTAG_REF("0000000000000007", "03", "raw")},
00153         {"machine value (GP)           (rva/size)", STATICTAG_EDIT_DWORD_LE("00000040")" "STATICTAG_EDIT_DWORD_LE("00000044")" "STATICTAG_REF("0000000000000008", "03", "raw")},
00154         {"thread local storage (TLS)   (rva/size)", STATICTAG_EDIT_DWORD_LE("00000048")" "STATICTAG_EDIT_DWORD_LE("0000004c")" "STATICTAG_REF("0000000000000009", "03", "raw")},
00155         {"load configuration directory (rva/size)", STATICTAG_EDIT_DWORD_LE("00000050")" "STATICTAG_EDIT_DWORD_LE("00000054")" "STATICTAG_REF("000000000000000a", "03", "raw")},
00156         {"bound import directory       (ofs/size)", STATICTAG_EDIT_DWORD_LE("00000058")" "STATICTAG_EDIT_DWORD_LE("0000005c")" "STATICTAG_REF("000000040000000b", "03", "raw")},
00157         {"import address table (IAT)   (rva/size)", STATICTAG_EDIT_DWORD_LE("00000060")" "STATICTAG_EDIT_DWORD_LE("00000064")" "STATICTAG_REF("000000000000000c", "03", "raw")},
00158         {"delay import descriptor      (rva/size)", STATICTAG_EDIT_DWORD_LE("00000068")" "STATICTAG_EDIT_DWORD_LE("0000006c")" "STATICTAG_REF("000000000000000d", "03", "raw")},
00159         {"COM+ runtime header          (rva/size)", STATICTAG_EDIT_DWORD_LE("00000070")" "STATICTAG_EDIT_DWORD_LE("00000074")" "STATICTAG_REF("000000000000000e", "03", "raw")" "STATICTAG_REF("0000000f00000000", "04", "cook")},
00160         {"reserved (15)                (rva/size)", STATICTAG_EDIT_DWORD_LE("00000078")" "STATICTAG_EDIT_DWORD_LE("0000007c")" "STATICTAG_REF("000000000000000f", "03", "raw")},
00161         {0, 0}
00162 };
00163 
00164 static ht_view *htpeheader_init(bounds *b, ht_streamfile *file, ht_format_group *group)
00165 {
00166         ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)group->get_shared_data();
00167 
00168         FILEOFS h=pe_shared->header_ofs;
00169         ht_pe_header_viewer *v=new ht_pe_header_viewer();
00170         v->init(b, DESC_PE_HEADER, VC_EDIT | VC_SEARCH, file, group);
00171         register_atom(ATOM_COFF_MACHINES, coff_machines);
00172         register_atom(ATOM_COFF_CHARACTERISTICS, coff_characteristics);
00173         register_atom(ATOM_COFF_SECTION_CHARACTERISTICS, coff_section_characteristics);
00174         register_atom(ATOM_PE_OPTIONAL_MAGICS, pe_optional_magics);
00175         register_atom(ATOM_PE_SUBSYSTEMS, pe_subsystems);
00176         register_atom(ATOM_PE_DLL_CHARACTERISTICS, pe_dll_characteristics);
00177 
00178         ht_mask_sub *s;
00179         ht_collapsable_sub *cs;
00180         
00181         s=new ht_mask_sub();
00182         s->init(file, 0);
00183         char info[128];
00184         ht_snprintf(info, sizeof info, "* PE header at offset %08x", h);
00185         s->add_mask(info);
00186         v->insertsub(s);
00187 
00188         /* FIXME: */
00189         bool pe_bigendian = false;
00190         
00191         s=new ht_mask_sub();
00192         s->init(file, 1);
00193         s->add_staticmask_ptable(pemagic, h, pe_bigendian);
00194         
00195         /* COFF header */
00196         s->add_staticmask_ptable(coffheader, h+4, pe_bigendian);
00197         cs=new ht_collapsable_sub();
00198         cs->init(file, s, 1, "COFF header", 1);
00199         v->insertsub(cs);
00200         
00201         /* optional header */
00202         s=new ht_mask_sub();
00203         s->init(file, 2);
00204         word opt;
00205         file->seek(h+24);
00206         file->read(&opt, 2);
00207         opt = create_host_int(&opt, 2, little_endian);
00208         switch (opt) {
00209                 case COFF_OPTMAGIC_PE32:
00210                 case COFF_OPTMAGIC_PE64: {
00211                         bool pe32 = (opt==COFF_OPTMAGIC_PE32);
00212                         s->add_staticmask_ptable(pe32header, h+4, pe_bigendian);
00213                         cs=new ht_collapsable_sub();
00214                         cs->init(file, s, 1, "optional header", 1);
00215                         v->insertsub(cs);
00216                         
00217                         s=new ht_mask_sub();
00218                         s->init(file, 3);
00219                         s->add_staticmask_ptable(pe32?pe32header_nt:pe64header_nt, h+4, pe_bigendian);
00220                         cs=new ht_collapsable_sub();
00221                         cs->init(file, s, 1, "optional header: NT fields", 1);
00222                         v->insertsub(cs);
00223                         
00224                         s=new ht_mask_sub();
00225                         s->init(file, 4);
00226                         s->add_staticmask_ptable(pe32header_nt_dirs, h+4+(pe32?0x74:0x84), pe_bigendian);
00227                         cs=new ht_collapsable_sub();
00228                         cs->init(file, s, 1, "optional header: directories", 1);
00229                         v->insertsub(cs);
00230                         break;
00231                 }
00232                 default: {
00233                         s->add_staticmask("optional magic                                   "STATICTAG_EDIT_WORD_LE("00000014")" "STATICTAG_DESC_WORD_LE("00000014", ATOM_PE_OPTIONAL_MAGICS_STR), h+4, pe_bigendian);
00234                         s->add_mask("-------------------------------------------------------------------------");
00235                         s->add_mask("Unsupported optional magic ! If you get this message in an original");
00236                         s->add_mask("(unmodified) file, please contact us (see help).");
00237                         cs=new ht_collapsable_sub();
00238                         cs->init(file, s, 1, "optional header", 1);
00239                         v->insertsub(cs);
00240                 }
00241         }
00242         
00243         /* section headers */
00244         
00245         for (UINT i=0; i<pe_shared->sections.section_count; i++) {
00246                 s=new ht_mask_sub();
00247                 s->init(file, 100+i);
00248 
00249                 s->add_staticmask_ptable(coff_section, h+24+pe_shared->coffheader.optional_header_size+i*COFF_SIZEOF_SECTION_HEADER, pe_bigendian);
00250 
00251                 char nm[9];
00252                 memmove(nm, pe_shared->sections.sections[i].name, 8);
00253                 nm[8]=0;
00254 
00255                 char t[256];
00256                 ht_snprintf(t, sizeof t, "section header %d: %-8s rva %08x vsize %08x", i, nm, pe_shared->sections.sections[i].data_address, pe_shared->sections.sections[i].data_vsize);
00257 
00258                 cs=new ht_collapsable_sub();
00259                 cs->init(file, s, 1, t, 1);
00260         
00261                 v->insertsub(cs);
00262         }
00263         return v;
00264 }
00265 
00266 format_viewer_if htpeheader_if = {
00267         htpeheader_init,
00268         0
00269 };
00270 
00271 /*
00272  *      CLASS ht_pe_header_viewer
00273  */
00274 
00275 void ht_pe_header_viewer::init(bounds *b, char *desc, int caps, ht_streamfile *file, ht_format_group *group)
00276 {
00277         ht_uformat_viewer::init(b, desc, caps, file, group);
00278         VIEW_DEBUG_NAME("ht_pe_header_viewer");
00279 }
00280 
00281 static ht_format_viewer *find_hex_viewer(ht_group *group)
00282 {
00283         // FIXME: God forgive us...
00284         ht_group *vr_group=group;
00285         while (strcmp(vr_group->desc, VIEWERGROUP_NAME)) vr_group=vr_group->group;
00286         ht_view *c=vr_group->getfirstchild();
00287         while (c) {
00288                 if (c->desc && (strcmp(c->desc, DESC_HEX)==0)) {
00289                         return (ht_format_viewer*)c;
00290                 }
00291                 c=c->next;
00292         }
00293         return NULL;
00294 }
00295 
00296 int ht_pe_header_viewer::ref_sel(LINE_ID *id)
00297 {
00298         ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)format_group->get_shared_data();
00299         switch (id->id1) {
00300                 case 0: {
00301                         ht_format_viewer *hexv = find_hex_viewer(group);
00302                         if (hexv) {
00303                                 UINT rva;
00304                                 UINT size;
00305                                 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE32) {
00306                                         rva = pe_shared->pe32.header_nt.directory[id->id2].address;
00307                                         size = pe_shared->pe32.header_nt.directory[id->id2].size;
00308                                 } else {
00309                                         rva = pe_shared->pe64.header_nt.directory[id->id2].address;
00310                                         size = pe_shared->pe64.header_nt.directory[id->id2].size;
00311                                 }
00312                                 FILEOFS ofs = 0;
00313                                 if (pe_rva_to_ofs(&pe_shared->sections, rva, &ofs)) {
00314                                         vstate_save();
00315                                         hexv->goto_offset(ofs, false);
00316                                         hexv->pselect_set(ofs, ofs+size);
00317                                         app->focus(hexv);
00318                                 } else errorbox("Can't follow: directory RVA %08x is not valid !", rva);
00319                         }
00320                         break;
00321                 }                       
00322                 case 1:
00323                         if (pe_shared->v_exports) {
00324                                 vstate_save();
00325                                 app->focus(pe_shared->v_exports);
00326                         }
00327                         break;
00328                 case 2:
00329                         if (pe_shared->v_imports) {
00330                                 vstate_save();
00331                                 app->focus(pe_shared->v_imports);
00332                         }
00333                         break;
00334                 case 3:
00335                         if (pe_shared->v_resources) {
00336                                 vstate_save();
00337                                 app->focus(pe_shared->v_resources);
00338                         }
00339                         break;
00340                 case 4: {
00341                         ht_format_viewer *hexv = find_hex_viewer(group);
00342                         if (hexv) {
00343                                 UINT ofs;
00344                                 UINT size;
00345                                 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE32) {
00346                                         ofs = pe_shared->pe32.header_nt.directory[id->id2].address;
00347                                         size = pe_shared->pe32.header_nt.directory[id->id2].size;
00348                                 } else {
00349                                         ofs = pe_shared->pe64.header_nt.directory[id->id2].address;
00350                                         size = pe_shared->pe64.header_nt.directory[id->id2].size;
00351                                 }
00352                                 if (size) {
00353                                         vstate_save();
00354                                         hexv->goto_offset(ofs, false);
00355                                         hexv->pselect_set(ofs, ofs+size);
00356                                         app->focus(hexv);
00357                                 } else errorbox("can't follow: No bound import directory!", ofs);
00358                         }
00359                         break;
00360                 }
00361                 case 15: {
00362                         if (pe_shared->v_il) {
00363                                 vstate_save();
00364                                 app->focus(pe_shared->v_il);
00365                         }
00366                         break;
00367                 }
00368         }
00369         return 1;
00370 }

Generated on Fri May 7 21:15:36 2004 by doxygen 1.3.5