00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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
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
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
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 }