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 "htpeil.h"
00033 #include "httag.h"
00034 #include "htstring.h"
00035 #include "snprintf.h"
00036
00037 #include "pestruct.h"
00038 #include "ilopc.h"
00039 #include "ilstruct.h"
00040
00041 #include <string.h>
00042
00043 static ht_mask_ptable il_directory[] = {
00044 {"size", STATICTAG_EDIT_DWORD_LE("00000000")},
00045 {"major version", STATICTAG_EDIT_WORD_LE("00000004")},
00046 {"minor version", STATICTAG_EDIT_WORD_LE("00000006")},
00047 {"metadata rva", STATICTAG_EDIT_DWORD_LE("00000008")},
00048 {"metadata size", STATICTAG_EDIT_DWORD_LE("0000000c")},
00049 {"attributes", STATICTAG_EDIT_DWORD_LE("00000010")},
00050 {0, 0}
00051 };
00052
00053 static ht_mask_ptable metadata_section[] = {
00054 {"magic", STATICTAG_EDIT_DWORD_LE("00000000")},
00055 {"major_version", STATICTAG_EDIT_WORD_LE("00000004")},
00056 {"minor_version", STATICTAG_EDIT_WORD_LE("00000006")},
00057 {"unknown", STATICTAG_EDIT_DWORD_LE("00000008")},
00058 {"version_string_length", STATICTAG_EDIT_DWORD_LE("00000010")},
00059 {0, 0}
00060 };
00061
00062 static ht_view *htpeil_init(bounds *b, ht_streamfile *file, ht_format_group *group)
00063 {
00064 ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)group->get_shared_data();
00065
00066 if (pe_shared->opt_magic!=COFF_OPTMAGIC_PE32) return NULL;
00067
00068 dword sec_rva, sec_size;
00069 FILEOFS sec_ofs;
00070 sec_rva = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_IL].address;
00071 sec_size = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_IL].size;
00072 if (!sec_rva || !sec_size) return NULL;
00073
00074 PE_IL_DIRECTORY dir;
00075 bool pe_bigendian = false;
00076 ht_pe_il_viewer *v;
00077
00078 if (!pe_rva_to_ofs(&pe_shared->sections, sec_rva, &sec_ofs)) goto read_error;
00079
00080 file->seek(sec_ofs);
00081 if (file->read(&dir, sizeof dir) != sizeof dir) goto read_error;
00082
00083 create_host_struct(&dir, PE_IL_DIRECTORY_struct, little_endian);
00084
00085 if (sec_size != dir.size) goto read_error;
00086
00087 pe_shared->il = new ht_pe_il();
00088 pe_shared->il->dir = dir;
00089
00090 v=new ht_pe_il_viewer();
00091 v->init(b, DESC_PE_IL, VC_EDIT | VC_SEARCH, file, group);
00092 pe_shared->v_il = v;
00093 ht_mask_sub *s;
00094
00095
00096 s=new ht_mask_sub();
00097 s->init(file, 0);
00098 char info[128];
00099 ht_snprintf(info, sizeof info, "* COM+ directory at offset %08x", sec_ofs);
00100 s->add_mask(info);
00101 v->insertsub(s);
00102
00103
00104
00105 s=new ht_mask_sub();
00106 s->init(file, 1);
00107 s->add_staticmask_ptable(il_directory, sec_ofs, pe_bigendian);
00108 v->insertsub(s);
00109
00110 FILEOFS metadata_ofs;
00111 if (pe_rva_to_ofs(&pe_shared->sections, dir.metadata_section_rva, &metadata_ofs)) {
00112
00113 IL_METADATA_SECTION metadata;
00114 file->seek(metadata_ofs);
00115 if (file->read(&metadata, sizeof metadata) == sizeof metadata) {
00116 create_host_struct(&metadata, IL_METADATA_SECTION_struct, little_endian);
00117 pe_shared->il->metadata = metadata;
00118 dword add = 2;
00119 if (metadata.minor_version == 1) {
00120
00121 dword version_string_length;
00122 file->read(&version_string_length, 4);
00123 file->read(&version_string_length, 4);
00124 version_string_length = create_host_int(&version_string_length, 4, little_endian);
00125 add += version_string_length + 8;
00126 }
00127 FILEOFS ofs = metadata_ofs + sizeof metadata + add;
00128 file->seek(ofs);
00129 word count;
00130 file->read(&count, 2);
00131 count = create_host_int(&count, 2, little_endian);
00132 pe_shared->il->entries = new ht_clist();
00133 pe_shared->il->entries->init();
00134 for (UINT i=0; i<count; i++) {
00135 IL_METADATA_SECTION_ENTRY sec_entry;
00136 ht_il_metadata_entry *entry;
00137
00138 file->read(&sec_entry, sizeof sec_entry);
00139 create_host_struct(&sec_entry, IL_METADATA_SECTION_ENTRY_struct, little_endian);
00140 char *name = fgetstrz(file);
00141 int nlen = strlen(name)+1;
00142 dword dummy;
00143 if (nlen % 4) {
00144
00145 file->read(&dummy, 4 - nlen % 4);
00146 }
00147 entry = new ht_il_metadata_entry(name, metadata_ofs+sec_entry.offset, sec_entry.size);
00148
00149 pe_shared->il->entries->insert(entry);
00150
00151 free(name);
00152 }
00153 for (UINT i=0; i<count; i++) {
00154 ht_il_metadata_entry *entry = (ht_il_metadata_entry *)pe_shared->il->entries->get(i);
00155 if (strcmp(entry->name, "#~") == 0) {
00156
00157 char dummy[8];
00158 qword types;
00159 file->seek(entry->offset);
00160 file->read(&dummy, 8);
00161 file->read(&types, 8);
00162
00163 } else if (strcmp(entry->name, "#US")==0) {
00164
00165 pe_shared->il->string_pool = (char*)malloc(entry->size);
00166 file->seek(entry->offset);
00167 pe_shared->il->string_pool_size = file->read(pe_shared->il->string_pool, entry->size);
00168 }
00169 }
00170 }
00171 }
00172
00173 return v;
00174
00175 read_error:
00176 return NULL;
00177 }
00178
00179 format_viewer_if htpeil_if = {
00180 htpeil_init,
00181 0
00182 };
00183
00184
00185
00186
00187
00188 void ht_pe_il_viewer::init(bounds *b, char *desc, int caps, ht_streamfile *file, ht_format_group *group)
00189 {
00190 ht_uformat_viewer::init(b, desc, caps, file, group);
00191 VIEW_DEBUG_NAME("ht_pe_il_viewer");
00192 }
00193
00194 void ht_pe_il_viewer::done()
00195 {
00196 ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)format_group->get_shared_data();
00197 if (pe_shared && pe_shared->il) {
00198 if (pe_shared->il->string_pool) free(pe_shared->il->string_pool);
00199 if (pe_shared->il->entries) {
00200 pe_shared->il->entries->destroy();
00201 delete pe_shared->il->entries;
00202 }
00203 delete pe_shared->il;
00204 }
00205 ht_uformat_viewer::done();
00206 }
00207
00208 ht_il_metadata_entry::ht_il_metadata_entry(char *n, dword o, dword s)
00209 {
00210 name = ht_strdup(n);
00211 offset = o;
00212 size = s;
00213 }
00214
00215 ht_il_metadata_entry::~ht_il_metadata_entry()
00216 {
00217 free(name);
00218 }
00219
00220
00221
00222
00223 int ILunpackDword(dword &result, const byte *buf, int len)
00224 {
00225 if (len) {
00226 result = *(buf++);
00227 len--;
00228 if (result < 0x80) return 1;
00229 if (!len) return 0;
00230 if ((result & 0xc0) == 0x80) {
00231
00232 result = ((result & 0x3f) << 8) | buf[0];
00233 return 2;
00234 } else if ((result & 0xe0) == 0xc0) {
00235
00236 if (len < 2) return 0;
00237 result = ((result & 0x1F) << 24) |
00238 (((dword)buf[0]) << 16) |
00239 (((dword)buf[1]) << 8) |
00240 (dword)buf[2];
00241 return 4;
00242 } else if ((result & 0xf0) == 0xe0) {
00243
00244 if (len < 3) return 0;
00245 result = (((dword)buf[0]) << 24) |
00246 (((dword)buf[1]) << 16) |
00247 (((dword)buf[2]) << 8) |
00248 (dword)buf[3];
00249 return 5;
00250 }
00251 }
00252 return 0;
00253 }
00254
00255 int ILunpackToken(dword &result, const byte *buf, int len)
00256 {
00257 int read = ILunpackDword(result, buf, len);
00258 if (!read) return 0;
00259 dword type;
00260 switch (result & 0x03) {
00261 case 0x00:
00262 type = IL_META_TOKEN_TYPE_DEF;
00263 break;
00264 case 0x01:
00265 type = IL_META_TOKEN_TYPE_REF;
00266 break;
00267 case 0x02:
00268 type = IL_META_TOKEN_TYPE_SPEC;
00269 break;
00270 default:
00271 type = IL_META_TOKEN_BASE_TYPE;
00272 }
00273 result = (result >> 2) | type;
00274 return read;
00275 }