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 "htendian.h"
00025 #include "htiobox.h"
00026 #include "htnewexe.h"
00027 #include "htpal.h"
00028 #include "htpe.h"
00029 #include "htpeimp.h"
00030 #include "htpedimp.h"
00031 #include "httag.h"
00032 #include "htstring.h"
00033 #include "log.h"
00034 #include "pe_analy.h"
00035 #include "snprintf.h"
00036 #include "stream.h"
00037
00038 #include <stdlib.h>
00039
00040 static ht_view *htpedelayimports_init(bounds *b, ht_streamfile *file, ht_format_group *group)
00041 {
00042 ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)group->get_shared_data();
00043
00044 if (pe_shared->opt_magic!=COFF_OPTMAGIC_PE32) return NULL;
00045
00046 RVA sec_rva = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_DELAY_IMPORT].address;
00047 UINT sec_size = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_DELAY_IMPORT].size;
00048 if (!sec_rva || !sec_size) return NULL;
00049
00050 int h0=new_timer();
00051 start_timer(h0);
00052
00053 UINT dll_count=0;
00054 UINT function_count=0;
00055
00056 ht_group *g;
00057 bounds c;
00058 ht_statictext *head;
00059
00060 c=*b;
00061 g=new ht_group();
00062 g->init(&c, VO_RESIZE, DESC_PE_DIMPORTS"-g");
00063
00064 c.y++;
00065 c.h--;
00066 ht_pe_dimport_viewer *v=new ht_pe_dimport_viewer();
00067 v->init(&c, DESC_PE_DIMPORTS, group);
00068
00069 PE_DELAY_IMPORT_DESCRIPTOR dimport;
00070 UINT dll_index;
00071 char iline[256];
00072
00073 c.y--;
00074 c.h=1;
00075
00076
00077 FILEOFS iofs;
00078 RVA irva=pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_DELAY_IMPORT].address;
00079
00080
00081 if (!pe_rva_to_ofs(&pe_shared->sections, irva, &iofs)) goto pe_read_error;
00082 LOG("%s: PE: reading delay-import directory at offset %08x, rva %08x, size %08x...", file->get_filename(), iofs, irva, pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_DELAY_IMPORT].size);
00083
00084
00085 dll_index=0;
00086
00087 while (1) {
00088 file->seek(iofs);
00089 file->read(&dimport, sizeof dimport);
00090 create_host_struct(&dimport, PE_DELAY_IMPORT_DESCRIPTOR_struct, little_endian);
00091 if (!dimport.name) break;
00092 dword base = dimport.attributes & 1 ? 0 : pe_shared->pe32.header_nt.image_base;
00093
00094 FILEOFS dllname_ofs;
00095 if (!pe_rva_to_ofs(&pe_shared->sections, dimport.name-base, &dllname_ofs)) goto pe_read_error;
00096 file->seek(dllname_ofs);
00097 char *dllname=fgetstrz(file);
00098 ht_pe_import_library *lib=new ht_pe_import_library(dllname);
00099 pe_shared->dimports.libs->insert(lib);
00100 dll_count++;
00101
00102 FILEOFS ntofs, atofs;
00103 UINT nva, ava;
00104 if (!pe_rva_to_ofs(&pe_shared->sections, dimport.delay_int-base, &ntofs)) goto pe_read_error;
00105 if (!pe_rva_to_ofs(&pe_shared->sections, dimport.delay_iat-base, &atofs)) goto pe_read_error;
00106 while (1) {
00107 ht_pe_import_function *func;
00108 file->seek(ntofs);
00109 file->read(&nva, 4);
00110 nva = create_host_int(&nva, 4, little_endian);
00111 if (!nva) break;
00112 function_count++;
00113 file->seek(atofs);
00114 file->read(&ava, 4);
00115 ava = create_host_int(&ava, 4, little_endian);
00116 if (nva & 0x80000000) {
00117
00118 func=new ht_pe_import_function(dll_index, ava, nva&0xffff);
00119 } else {
00120 FILEOFS nofs;
00121
00122 if (!pe_rva_to_ofs(&pe_shared->sections, nva-base, &nofs)) goto pe_read_error;
00123 word hint=0;
00124 file->seek(nofs);
00125 file->read(&hint, 2);
00126 hint = create_host_int(&hint, 2, little_endian);
00127 char *name=fgetstrz(file);
00128 func=new ht_pe_import_function(dll_index, ava, name, hint);
00129 free(name);
00130 }
00131 pe_shared->dimports.funcs->insert(func);
00132 ntofs+=4;
00133 atofs+=4;
00134 }
00135
00136 free(dllname);
00137 iofs+=sizeof dimport;
00138 dll_index++;
00139 }
00140
00141 stop_timer(h0);
00142
00143 delete_timer(h0);
00144
00145 ht_snprintf(iline, sizeof iline, "* PE delay-import directory at offset %08x (%d delay-imports from %d libraries)", iofs, function_count, dll_count);
00146
00147 head=new ht_statictext();
00148 head->init(&c, iline, align_left);
00149
00150 g->insert(head);
00151 g->insert(v);
00152
00153 for (UINT i=0; i<pe_shared->dimports.funcs->count(); i++) {
00154 ht_pe_import_function *func = (ht_pe_import_function*)pe_shared->dimports.funcs->get(i);
00155 assert(func);
00156 ht_pe_import_library *lib = (ht_pe_import_library*)pe_shared->dimports.libs->get(func->libidx);
00157 assert(lib);
00158 char addr[32], name[256];
00159 ht_snprintf(addr, sizeof addr, "%08x", func->address);
00160 if (func->byname) {
00161 ht_snprintf(name, sizeof name, "%s", func->name.name);
00162 } else {
00163 ht_snprintf(name, sizeof name, "%04x (by ordinal)", func->ordinal);
00164 }
00165 v->insert_str(i, lib->name, addr, name);
00166 }
00167
00168 v->update();
00169
00170 g->setpalette(palkey_generic_window_default);
00171
00172 pe_shared->v_dimports=v;
00173
00174 return g;
00175 pe_read_error:
00176 delete_timer(h0);
00177 errorbox("%s: PE delay-import directory seems to be corrupted.", file->get_filename());
00178 v->done();
00179 delete v;
00180 g->done();
00181 delete g;
00182 return NULL;
00183 }
00184
00185 format_viewer_if htpedelayimports_if = {
00186 htpedelayimports_init,
00187 NULL
00188 };
00189
00190
00191
00192
00193
00194 bool ht_pe_dimport_viewer::select_entry(void *entry)
00195 {
00196 ht_text_listbox_item *i = (ht_text_listbox_item *)entry;
00197
00198 ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)format_group->get_shared_data();
00199
00200 ht_pe_import_function *e = (ht_pe_import_function*)pe_shared->dimports.funcs->get(i->id);
00201 if (!e) return true;
00202 if (pe_shared->v_image) {
00203 ht_aviewer *av = (ht_aviewer*)pe_shared->v_image;
00204 PEAnalyser *a = (PEAnalyser*)av->analy;
00205 Address *addr;
00206 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE32) {
00207 addr = a->createAddress32(e->address);
00208 } else {
00209 addr = a->createAddress64(to_qword(e->address));
00210 }
00211 if (av->gotoAddress(addr, NULL)) {
00212 app->focus(av);
00213 vstate_save();
00214 } else {
00215 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT | ADDRESS_STRING_FORMAT_ADD_0X;
00216 errorbox("can't follow: %s %y is not valid !", "delay-import address", addr);
00217 }
00218 delete addr;
00219 } else errorbox("can't follow: no image viewer");
00220 return true;
00221 }
00222