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

htpeexp.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      htpeexp.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 "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 /* get export directory offset */
00074         /* 1. get export directory rva */
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         /* 2. transform it into an offset */
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 /* make a memfile out of this section */
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 /* read export directory header */
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 /* get export filename */
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 /* read in function entrypoint table */
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 /* read in name address table */
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 /* read in ordinal table */
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 /* exports by ordinal */
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 /* exports by name */
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 // sdgfdg
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 //      LOG("%s: PE: %d ticks (%d msec) to read exports", filename, get_timer_tick(h0), get_timer_msec(h0));
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  *      CLASS ht_pe_export_viewer
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  *      class ht_pe_export_function
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 }

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