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 "htanaly.h"
00023 #include "htctrl.h"
00024 #include "htdata.h"
00025 #include "htdebug.h"
00026 #include "htendian.h"
00027 #include "htiobox.h"
00028 #include "htnewexe.h"
00029 #include "htpal.h"
00030 #include "htpe.h"
00031 #include "htpeexp.h"
00032 #include "htstring.h"
00033 #include "httag.h"
00034 #include "log.h"
00035 #include "pe_analy.h"
00036 #include "snprintf.h"
00037 #include "stream.h"
00038 #include "tools.h"
00039
00040 #include <stdlib.h>
00041 #include <string.h>
00042
00043 static ht_view *htpeexports_init(bounds *b, ht_streamfile *file, ht_format_group *group)
00044 {
00045 ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)group->get_shared_data();
00046
00047 if (pe_shared->opt_magic!=COFF_OPTMAGIC_PE32) return NULL;
00048
00049 dword sec_rva, sec_size;
00050 sec_rva = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_EXPORT].address;
00051 sec_size = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_EXPORT].size;
00052 if (!sec_rva || !sec_size) return NULL;
00053
00054 int h0=new_timer();
00055 start_timer(h0);
00056
00057 dword *efunct=NULL, *enamet=NULL;
00058 word *eordt=NULL;
00059 ht_mem_file *efile;
00060 ht_streamfile *origfile = file;
00061 const char *filename = file->get_filename();
00062 char *esectionbuf;
00063 char eline[256];
00064 FILEOFS ename_ofs;
00065 char *ename;
00066 bool *lord;
00067
00068 ht_group *g = NULL;
00069 bounds c;
00070 ht_statictext *head;
00071 ht_pe_export_viewer *v = NULL;
00072
00073
00074
00075 FILEOFS eofs;
00076 dword erva=pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_EXPORT].address;
00077 dword esize=pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_EXPORT].size;
00078
00079 if (!pe_rva_to_ofs(&pe_shared->sections, erva, &eofs)) goto pe_read_error;
00080 LOG("%s: PE: reading export directory at offset %08x, rva %08x, size %08x...", filename, eofs, erva, esize);
00081
00082
00083 efile=new ht_mem_file();
00084 efile->init(eofs, esize, FAM_READ | FAM_WRITE);
00085 esectionbuf=(char*)malloc(esize);
00086 file->seek(eofs);
00087 file->read(esectionbuf, esize);
00088 efile->write(esectionbuf, esize);
00089 file=efile;
00090 free(esectionbuf);
00091
00092 PE_EXPORT_DIRECTORY edir;
00093 file->seek(eofs);
00094 file->read(&edir, sizeof edir);
00095 create_host_struct(&edir, PE_EXPORT_DIRECTORY_struct, little_endian);
00096
00097 if (!pe_rva_to_ofs(&pe_shared->sections, edir.name_address, &ename_ofs)) goto pe_read_error;
00098 file->seek(ename_ofs);
00099 ename=fgetstrz(file);
00100
00101 FILEOFS efunct_ofs;
00102 efunct=(dword*)malloc(edir.function_count*sizeof *efunct);
00103 if (!pe_rva_to_ofs(&pe_shared->sections, edir.function_table_address, &efunct_ofs)) goto pe_read_error;
00104 file->seek(efunct_ofs);
00105 file->read(efunct, edir.function_count*sizeof *efunct);
00106 for (UINT i=0; i<edir.function_count;i++) {
00107 efunct[i] = create_host_int(efunct+i, sizeof *efunct, little_endian);
00108 }
00109
00110 FILEOFS enamet_ofs;
00111 enamet=(dword*)malloc(edir.name_count*sizeof *enamet);
00112 if (!pe_rva_to_ofs(&pe_shared->sections, edir.name_table_address, &enamet_ofs)) goto pe_read_error;
00113 file->seek(enamet_ofs);
00114 file->read(enamet, edir.name_count*sizeof *enamet);
00115 for (UINT i=0; i<edir.name_count; i++) {
00116 enamet[i] = create_host_int(enamet+i, sizeof *enamet, little_endian);
00117 }
00118
00119 FILEOFS eordt_ofs;
00120 eordt=(word*)malloc(edir.name_count*sizeof *eordt);
00121 if (!pe_rva_to_ofs(&pe_shared->sections, edir.ordinal_table_address, &eordt_ofs)) goto pe_read_error;
00122 file->seek(eordt_ofs);
00123 file->read(eordt, edir.name_count*sizeof *eordt);
00124 for (UINT i=0; i<edir.name_count; i++) {
00125 eordt[i] = create_host_int(eordt+i, sizeof *eordt, little_endian);
00126 }
00127
00128 lord=(bool*)malloc(sizeof *lord*edir.function_count);
00129 memset(lord, 0, sizeof *lord*edir.function_count);
00130 for (UINT i=0; i < edir.name_count; i++) {
00131 if (eordt[i] < edir.function_count) {
00132 lord[eordt[i]]=true;
00133 }
00134 }
00135
00136
00137 for (UINT i=0; i<edir.function_count; i++) {
00138 if (lord[i]) continue;
00139
00140 RVA f = efunct[i];
00141
00142 ht_pe_export_function *efd = new ht_pe_export_function(f, i+edir.ordinal_base);
00143 pe_shared->exports.funcs->insert(efd);
00144 }
00145 free(lord);
00146
00147 for (UINT i=0; i < edir.name_count; i++) {
00148 UINT o = eordt[i];
00149 RVA f = efunct[o];
00150 FILEOFS en;
00151 if (!pe_rva_to_ofs(&pe_shared->sections, *(enamet+i), &en)) goto pe_read_error;
00152 file->seek(en);
00153 char *s = fgetstrz(file);
00154
00155 ht_pe_export_function *efd = new ht_pe_export_function(f, o+edir.ordinal_base, s);
00156 pe_shared->exports.funcs->insert(efd);
00157 free(s);
00158 }
00159
00160
00161 c = *b;
00162 c.x = 0;
00163 c.y = 0;
00164 g = new ht_group();
00165 g->init(&c, VO_RESIZE, DESC_PE_EXPORTS"-g");
00166
00167 c.y = 1;
00168 c.h--;
00169 v = new ht_pe_export_viewer();
00170 v->init(&c, group);
00171
00172 c.y = 0;
00173 c.h = 1;
00174 ht_snprintf(eline, sizeof eline, "* PE export directory at offset %08x (dllname = %s)", eofs, ename);
00175 head = new ht_statictext();
00176 head->init(&c, eline, align_left);
00177
00178 g->insert(head);
00179 g->insert(v);
00180
00181 for (UINT i=0; i<pe_shared->exports.funcs->count(); i++) {
00182 ht_pe_export_function *e = (ht_pe_export_function *)pe_shared->exports.funcs->get(i);
00183 char ord[32], addr[32];
00184 ht_snprintf(ord, sizeof ord, "%04x", e->ordinal);
00185 ht_snprintf(addr, sizeof addr, "%08x", e->address);
00186 v->insert_str(i, ord, addr, e->byname ? e->name : "<by ordinal>");
00187 }
00188
00189 v->update();
00190
00191 g->setpalette(palkey_generic_window_default);
00192
00193 stop_timer(h0);
00194
00195 delete_timer(h0);
00196
00197 if (ename) free(ename);
00198
00199 efile->done();
00200 delete efile;
00201
00202 if (efunct) free(efunct);
00203 if (enamet) free(enamet);
00204 if (eordt) free(eordt);
00205 pe_shared->v_exports=v;
00206 return g;
00207 pe_read_error:
00208 delete_timer(h0);
00209 errorbox("%s: PE export directory seems to be corrupted.", origfile->get_filename());
00210 if (efunct) free(efunct);
00211 if (enamet) free(enamet);
00212 if (eordt) free(eordt);
00213 if (g) {
00214 g->done();
00215 delete g;
00216 }
00217 if (v) {
00218 v->done();
00219 delete v;
00220 }
00221 return NULL;
00222 }
00223
00224 format_viewer_if htpeexports_if = {
00225 htpeexports_init,
00226 NULL
00227 };
00228
00229
00230
00231
00232
00233 void ht_pe_export_viewer::init(bounds *b, ht_format_group *fg)
00234 {
00235 ht_text_listbox::init(b, 3, 2, LISTBOX_QUICKFIND);
00236 options |= VO_BROWSABLE;
00237 desc = strdup(DESC_PE_EXPORTS);
00238 format_group = fg;
00239 }
00240
00241 void ht_pe_export_viewer::done()
00242 {
00243 ht_text_listbox::done();
00244 }
00245
00246 char *ht_pe_export_viewer::func(UINT i, bool execute)
00247 {
00248 ht_text_listbox_sort_order sortord;
00249 switch (i) {
00250 case 2:
00251 if (execute) {
00252 sortord.col = 0;
00253 sortord.compare_func = strcmp;
00254 sort(1, &sortord);
00255 }
00256 return "sortord";
00257 case 4:
00258 if (execute) {
00259 sortord.col = 1;
00260 sortord.compare_func = strcmp;
00261 sort(1, &sortord);
00262 }
00263 return "sortva";
00264 case 5:
00265 if (execute) {
00266 sortord.col = 2;
00267 sortord.compare_func = strcmp;
00268 sort(1, &sortord);
00269 }
00270 return "sortname";
00271 }
00272 return NULL;
00273 }
00274
00275 void ht_pe_export_viewer::handlemsg(htmsg *msg)
00276 {
00277 switch (msg->msg) {
00278 case msg_funcexec:
00279 if (func(msg->data1.integer, 1)) {
00280 clearmsg(msg);
00281 return;
00282 }
00283 break;
00284 case msg_funcquery: {
00285 char *s=func(msg->data1.integer, 0);
00286 if (s) {
00287 msg->msg=msg_retval;
00288 msg->data1.str=s;
00289 }
00290 break;
00291 }
00292 case msg_keypressed: {
00293 if (msg->data1.integer == K_Return) {
00294 select_entry(e_cursor);
00295 clearmsg(msg);
00296 }
00297 break;
00298 }
00299 }
00300 ht_text_listbox::handlemsg(msg);
00301 }
00302
00303 bool ht_pe_export_viewer::select_entry(void *entry)
00304 {
00305 ht_text_listbox_item *i = (ht_text_listbox_item *)entry;
00306
00307 ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)format_group->get_shared_data();
00308
00309 ht_pe_export_function *e = (ht_pe_export_function*)pe_shared->exports.funcs->get(i->id);
00310 if (!e) return true;
00311 if (pe_shared->v_image) {
00312 ht_aviewer *av = (ht_aviewer*)pe_shared->v_image;
00313 PEAnalyser *a = (PEAnalyser*)av->analy;
00314 Address *addr;
00315 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE32) {
00316 addr = a->createAddress32(e->address+pe_shared->pe32.header_nt.image_base);
00317 } else {
00318 addr = a->createAddress64(to_qword(e->address)+pe_shared->pe64.header_nt.image_base);
00319 }
00320 if (av->gotoAddress(addr, NULL)) {
00321 app->focus(av);
00322 vstate_save();
00323 } else {
00324 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT | ADDRESS_STRING_FORMAT_ADD_0X;
00325 errorbox("can't follow: %s %y is not valid !", "export address", addr);
00326 }
00327 delete addr;
00328 } else errorbox("can't follow: no image viewer");
00329 return true;
00330 }
00331
00332
00333
00334
00335
00336 ht_pe_export_function::ht_pe_export_function(RVA addr, UINT ord)
00337 {
00338 ordinal = ord;
00339 address = addr;
00340 byname = false;
00341 }
00342
00343 ht_pe_export_function::ht_pe_export_function(RVA addr, UINT ord, char *n)
00344 {
00345 ordinal = ord;
00346 name = ht_strdup(n);
00347 address = addr;
00348 byname = true;
00349 }
00350
00351 ht_pe_export_function::~ht_pe_export_function()
00352 {
00353 if ((byname) && (name)) free(name);
00354 }