1 /*
2 * HT Editor
3 * htpedimp.cc
4 *
5 * Copyright (C) 1999-2002 Stefan Weyergraf
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "formats.h"
22 #include "htanaly.h"
23 #include "htctrl.h"
24 #include "endianess.h"
25 #include "htiobox.h"
26 #include "htnewexe.h"
27 #include "htpal.h"
28 #include "htpe.h"
29 #include "htpeimp.h"
30 #include "htpedimp.h"
31 #include "httag.h"
32 #include "strtools.h"
33 #include "log.h"
34 #include "pe_analy.h"
35 #include "snprintf.h"
36 #include "stream.h"
37
38 #include <stdlib.h>
39
htpedelayimports_init(Bounds * b,File * file,ht_format_group * group)40 static ht_view *htpedelayimports_init(Bounds *b, File *file, ht_format_group *group)
41 {
42 ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)group->get_shared_data();
43 String fn;
44
45 if (pe_shared->opt_magic!=COFF_OPTMAGIC_PE32) return NULL;
46
47 RVA sec_rva = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_DELAY_IMPORT].address;
48 uint sec_size = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_DELAY_IMPORT].size;
49 if (!sec_rva || !sec_size) return NULL;
50
51 int h0=new_timer();
52 start_timer(h0);
53
54 uint dll_count=0;
55 uint function_count=0;
56
57 ht_group *g;
58 Bounds c;
59 ht_statictext *head;
60
61 c=*b;
62 g=new ht_group();
63 g->init(&c, VO_RESIZE, DESC_PE_DIMPORTS"-g");
64
65 c.y++;
66 c.h--;
67 ht_pe_dimport_viewer *v=new ht_pe_dimport_viewer();
68 v->init(&c, DESC_PE_DIMPORTS, group);
69
70 PE_DELAY_IMPORT_DESCRIPTOR dimport;
71 uint dll_index;
72 char iline[256];
73
74 c.y--;
75 c.h=1;
76 /* get delay import directory offset */
77 /* 1. get import directory rva */
78 FileOfs iofs;
79 RVA irva=pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_DELAY_IMPORT].address;
80 // uint isize=pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_DELAY_IMPORT].size;
81 /* 2. transform it into an offset */
82 if (!pe_rva_to_ofs(&pe_shared->sections, irva, &iofs)) goto pe_read_error;
83 LOG("%y: PE: reading delay-import directory at offset 0x%08qx, rva 0x%08x, size 0x%08x...", &file->getFilename(fn), iofs, irva, pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_DELAY_IMPORT].size);
84
85 /*** read delay import directory ***/
86 dll_index=0;
87
88 while (1) {
89 file->seek(iofs);
90 file->read(&dimport, sizeof dimport);
91 createHostStruct(&dimport, PE_DELAY_IMPORT_DESCRIPTOR_struct, little_endian);
92 if (!dimport.name) break;
93 uint32 base = dimport.attributes & 1 ? 0 : pe_shared->pe32.header_nt.image_base;
94
95 FileOfs dllname_ofs;
96 if (!pe_rva_to_ofs(&pe_shared->sections, dimport.name-base, &dllname_ofs)) goto pe_read_error;
97 file->seek(dllname_ofs);
98 char *dllname = file->fgetstrz();
99 ht_pe_import_library *lib=new ht_pe_import_library(dllname);
100 pe_shared->dimports.libs->insert(lib);
101 dll_count++;
102
103 FileOfs ntofs, atofs;
104 uint nva, ava;
105 if (!pe_rva_to_ofs(&pe_shared->sections, dimport.delay_int-base, &ntofs)) goto pe_read_error;
106 if (!pe_rva_to_ofs(&pe_shared->sections, dimport.delay_iat-base, &atofs)) goto pe_read_error;
107 while (1) {
108 ht_pe_import_function *func;
109 file->seek(ntofs);
110 file->read(&nva, 4);
111 nva = createHostInt(&nva, 4, little_endian);
112 if (!nva) break;
113 function_count++;
114 file->seek(atofs);
115 file->read(&ava, 4);
116 ava = createHostInt(&ava, 4, little_endian);
117 if (nva & 0x80000000) {
118 /* import by ordinal */
119 func=new ht_pe_import_function(dll_index, ava, nva&0xffff);
120 } else {
121 FileOfs nofs;
122 /* import by name */
123 if (!pe_rva_to_ofs(&pe_shared->sections, nva-base, &nofs)) goto pe_read_error;
124 uint16 hint=0;
125 file->seek(nofs);
126 file->read(&hint, 2);
127 hint = createHostInt(&hint, 2, little_endian);
128 char *name = file->fgetstrz();
129 func=new ht_pe_import_function(dll_index, ava, name, hint);
130 free(name);
131 }
132 pe_shared->dimports.funcs->insert(func);
133 ntofs+=4;
134 atofs+=4;
135 }
136
137 free(dllname);
138 iofs+=sizeof dimport;
139 dll_index++;
140 }
141
142 stop_timer(h0);
143 // LOG("%y: PE: %d ticks (%d msec) to read delay-imports", file->get_name(), get_timer_tick(h0), get_timer_msec(h0));
144 delete_timer(h0);
145
146 ht_snprintf(iline, sizeof iline, "* PE delay-import directory at offset %08x (%d delay-imports from %d libraries)", iofs, function_count, dll_count);
147
148 head=new ht_statictext();
149 head->init(&c, iline, align_left);
150
151 g->insert(head);
152 g->insert(v);
153 //
154 for (uint i=0; i < pe_shared->dimports.funcs->count(); i++) {
155
156 ht_pe_import_function *func = (ht_pe_import_function*)(*pe_shared->dimports.funcs)[i];
157 assert(func);
158 ht_pe_import_library *lib = (ht_pe_import_library*)(*pe_shared->dimports.libs)[func->libidx];
159 assert(lib);
160 char addr[32], name[256];
161 ht_snprintf(addr, sizeof addr, "%08x", func->address);
162 if (func->byname) {
163 ht_snprintf(name, sizeof name, "%s", func->name.name);
164 } else {
165 ht_snprintf(name, sizeof name, "%04x (by ordinal)", func->ordinal);
166 }
167 v->insert_str(i, lib->name, addr, name);
168 }
169 //
170 v->update();
171
172 g->setpalette(palkey_generic_window_default);
173
174 pe_shared->v_dimports=v;
175
176 return g;
177 pe_read_error:
178 delete_timer(h0);
179 errorbox("%y: PE delay-import directory seems to be corrupted.", &file->getFilename(fn));
180 v->done();
181 delete v;
182 g->done();
183 delete g;
184 return NULL;
185 }
186
187 format_viewer_if htpedelayimports_if = {
188 htpedelayimports_init,
189 NULL
190 };
191
192 /*
193 * CLASS ht_pe_dimport_viewer
194 */
195
select_entry(void * entry)196 bool ht_pe_dimport_viewer::select_entry(void *entry)
197 {
198 ht_text_listbox_item *i = (ht_text_listbox_item *)entry;
199
200 ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)format_group->get_shared_data();
201
202 ht_pe_import_function *e = (ht_pe_import_function*)(*pe_shared->dimports.funcs)[i->id];
203 if (!e) return true;
204 if (pe_shared->v_image) {
205 ht_aviewer *av = (ht_aviewer*)pe_shared->v_image;
206 PEAnalyser *a = (PEAnalyser*)av->analy;
207 Address *addr;
208 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE32) {
209 addr = a->createAddress32(e->address/*+pe_shared->pe32.header_nt.image_base*/);
210 } else {
211 addr = a->createAddress64(e->address/*+pe_shared->pe64.header_nt.image_base*/);
212 }
213 if (av->gotoAddress(addr, NULL)) {
214 app->focus(av);
215 vstate_save();
216 } else {
217 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT | ADDRESS_STRING_FORMAT_ADD_0X;
218 errorbox("can't follow: %s %y is not valid!", "delay-import address", addr);
219 }
220 delete addr;
221 } else errorbox("can't follow: no image viewer");
222 return true;
223 }
224
225