1use alloc::vec::Vec;
2use scroll::{Pread, Pwrite};
3
4use log::debug;
5
6use crate::error;
7
8use crate::pe::data_directories;
9use crate::pe::options;
10use crate::pe::section_table;
11use crate::pe::utils;
12
13#[repr(C)]
14#[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite)]
15pub struct ExportDirectoryTable {
16 pub export_flags: u32,
17 pub time_date_stamp: u32,
18 pub major_version: u16,
19 pub minor_version: u16,
20 pub name_rva: u32,
21 pub ordinal_base: u32,
22 pub address_table_entries: u32,
23 pub number_of_name_pointers: u32,
24 pub export_address_table_rva: u32,
25 pub name_pointer_rva: u32,
26 pub ordinal_table_rva: u32,
27}
28
29pub const SIZEOF_EXPORT_DIRECTORY_TABLE: usize = 40;
30
31impl ExportDirectoryTable {
32 pub fn parse(bytes: &[u8], offset: usize) -> error::Result<Self> {
33 let res = bytes.pread_with(offset, scroll::LE)?;
34 Ok(res)
35 }
36}
37
38#[derive(Debug)]
39pub enum ExportAddressTableEntry {
40 ExportRVA(u32),
41 ForwarderRVA(u32),
42}
43
44pub const SIZEOF_EXPORT_ADDRESS_TABLE_ENTRY: usize = 4;
45
46pub type ExportAddressTable = Vec<ExportAddressTableEntry>;
47
48pub type ExportNamePointerTable = Vec<u32>;
52
53pub type ExportOrdinalTable = Vec<u16>;
57
58#[derive(Debug, Default)]
59pub struct ExportData<'a> {
61 pub name: Option<&'a str>,
62 pub export_directory_table: ExportDirectoryTable,
63 pub export_name_pointer_table: ExportNamePointerTable,
64 pub export_ordinal_table: ExportOrdinalTable,
65 pub export_address_table: ExportAddressTable,
66}
67
68impl<'a> ExportData<'a> {
69 pub fn parse(
70 bytes: &'a [u8],
71 dd: data_directories::DataDirectory,
72 sections: &[section_table::SectionTable],
73 file_alignment: u32,
74 ) -> error::Result<ExportData<'a>> {
75 Self::parse_with_opts(
76 bytes,
77 dd,
78 sections,
79 file_alignment,
80 &options::ParseOptions::default(),
81 )
82 }
83
84 pub fn parse_with_opts(
85 bytes: &'a [u8],
86 dd: data_directories::DataDirectory,
87 sections: &[section_table::SectionTable],
88 file_alignment: u32,
89 opts: &options::ParseOptions,
90 ) -> error::Result<ExportData<'a>> {
91 let export_rva = dd.virtual_address as usize;
92 let size = dd.size as usize;
93 debug!("export_rva {:#x} size {:#}", export_rva, size);
94 let export_offset = utils::find_offset_or(
95 export_rva,
96 sections,
97 file_alignment,
98 opts,
99 &format!("cannot map export_rva ({:#x}) into offset", export_rva),
100 )?;
101 let export_directory_table =
102 ExportDirectoryTable::parse(bytes, export_offset).map_err(|_| {
103 error::Error::Malformed(format!(
104 "cannot parse export_directory_table (offset {:#x})",
105 export_offset
106 ))
107 })?;
108 let number_of_name_pointers = export_directory_table.number_of_name_pointers as usize;
109 let address_table_entries = export_directory_table.address_table_entries as usize;
110
111 if number_of_name_pointers > bytes.len() {
112 return Err(error::Error::BufferTooShort(
113 number_of_name_pointers,
114 "name pointers",
115 ));
116 }
117 if address_table_entries > bytes.len() {
118 return Err(error::Error::BufferTooShort(
119 address_table_entries,
120 "address table entries",
121 ));
122 }
123
124 let export_name_pointer_table = utils::find_offset(
125 export_directory_table.name_pointer_rva as usize,
126 sections,
127 file_alignment,
128 opts,
129 )
130 .map_or(vec![], |table_offset| {
131 let mut offset = table_offset;
132 let mut table: ExportNamePointerTable = Vec::with_capacity(number_of_name_pointers);
133
134 for _ in 0..number_of_name_pointers {
135 if let Ok(name_rva) = bytes.gread_with(&mut offset, scroll::LE) {
136 table.push(name_rva);
137 } else {
138 break;
139 }
140 }
141
142 table
143 });
144
145 let export_ordinal_table = utils::find_offset(
146 export_directory_table.ordinal_table_rva as usize,
147 sections,
148 file_alignment,
149 opts,
150 )
151 .map_or(vec![], |table_offset| {
152 let mut offset = table_offset;
153 let mut table: ExportOrdinalTable = Vec::with_capacity(number_of_name_pointers);
154
155 for _ in 0..number_of_name_pointers {
156 if let Ok(name_ordinal) = bytes.gread_with(&mut offset, scroll::LE) {
157 table.push(name_ordinal);
158 } else {
159 break;
160 }
161 }
162
163 table
164 });
165
166 let export_address_table = utils::find_offset(
167 export_directory_table.export_address_table_rva as usize,
168 sections,
169 file_alignment,
170 opts,
171 )
172 .map_or(vec![], |table_offset| {
173 let mut offset = table_offset;
174 let mut table: ExportAddressTable = Vec::with_capacity(address_table_entries);
175 let export_end = export_rva + size;
176
177 for _ in 0..address_table_entries {
178 if let Ok(func_rva) = bytes.gread_with::<u32>(&mut offset, scroll::LE) {
179 if utils::is_in_range(func_rva as usize, export_rva, export_end) {
180 table.push(ExportAddressTableEntry::ForwarderRVA(func_rva));
181 } else {
182 table.push(ExportAddressTableEntry::ExportRVA(func_rva));
183 }
184 } else {
185 break;
186 }
187 }
188
189 table
190 });
191
192 let name = utils::find_offset(
193 export_directory_table.name_rva as usize,
194 sections,
195 file_alignment,
196 opts,
197 )
198 .and_then(|offset| bytes.pread(offset).ok());
199
200 Ok(ExportData {
201 name,
202 export_directory_table,
203 export_name_pointer_table,
204 export_ordinal_table,
205 export_address_table,
206 })
207 }
208}
209
210#[derive(Debug)]
211pub enum Reexport<'a> {
213 DLLName { export: &'a str, lib: &'a str },
214 DLLOrdinal { ordinal: usize, lib: &'a str },
215}
216
217impl<'a> scroll::ctx::TryFromCtx<'a, scroll::Endian> for Reexport<'a> {
218 type Error = crate::error::Error;
219 #[inline]
220 fn try_from_ctx(bytes: &'a [u8], _ctx: scroll::Endian) -> Result<(Self, usize), Self::Error> {
221 let reexport = bytes.pread::<&str>(0)?;
222 let reexport_len = reexport.len();
223 debug!("reexport: {}", &reexport);
224 for o in 0..reexport_len {
225 let c: u8 = bytes.pread(o)?;
226 debug!("reexport offset: {:#x} char: {:#x}", o, c);
227 if c == b'.' {
228 let dll: &'a str = bytes.pread_with(0, scroll::ctx::StrCtx::Length(o))?;
229 debug!("dll: {:?}", &dll);
230 if o + 1 == reexport_len {
231 break;
232 }
233 let len = reexport_len - o - 1;
234 let rest: &'a [u8] = bytes.pread_with(o + 1, len)?;
235 debug!("rest: {:?}", &rest);
236 if rest[0] == b'#' {
237 let ordinal =
238 rest.pread_with::<&str>(1, scroll::ctx::StrCtx::Length(len - 1))?;
239 let ordinal = ordinal.parse::<u32>().map_err(|_e| {
240 error::Error::Malformed(format!(
241 "Cannot parse reexport ordinal from {} bytes",
242 bytes.len()
243 ))
244 })?;
245 return Ok((
246 Reexport::DLLOrdinal {
247 ordinal: ordinal as usize,
248 lib: dll,
249 },
250 reexport_len + 1,
251 ));
252 } else {
253 let export = rest.pread_with::<&str>(0, scroll::ctx::StrCtx::Length(len))?;
254 return Ok((Reexport::DLLName { export, lib: dll }, reexport_len + 1));
255 }
256 }
257 }
258 Err(error::Error::Malformed(format!(
259 "Reexport {:#} is malformed",
260 reexport
261 )))
262 }
263}
264
265impl<'a> Reexport<'a> {
266 pub fn parse(bytes: &'a [u8], offset: usize) -> crate::error::Result<Reexport<'a>> {
267 bytes.pread(offset)
268 }
269}
270
271#[derive(Debug, Default)]
272pub struct Export<'a> {
274 pub name: Option<&'a str>,
275 pub offset: Option<usize>,
276 pub rva: usize,
277 pub size: usize,
278 pub reexport: Option<Reexport<'a>>,
279}
280
281#[derive(Debug, Copy, Clone)]
282struct ExportCtx<'a> {
283 pub ptr: u32,
284 pub idx: usize,
285 pub sections: &'a [section_table::SectionTable],
286 pub file_alignment: u32,
287 pub addresses: &'a ExportAddressTable,
288 pub ordinals: &'a ExportOrdinalTable,
289 pub opts: options::ParseOptions,
290}
291
292impl<'a, 'b> scroll::ctx::TryFromCtx<'a, ExportCtx<'b>> for Export<'a> {
293 type Error = error::Error;
294 #[inline]
295 fn try_from_ctx(
296 bytes: &'a [u8],
297 ExportCtx {
298 ptr,
299 idx,
300 sections,
301 file_alignment,
302 addresses,
303 ordinals,
304 opts,
305 }: ExportCtx<'b>,
306 ) -> Result<(Self, usize), Self::Error> {
307 use self::ExportAddressTableEntry::*;
308
309 let name = utils::find_offset(ptr as usize, sections, file_alignment, &opts)
310 .and_then(|offset| bytes.pread::<&str>(offset).ok());
311
312 if let Some(ordinal) = ordinals.get(idx) {
313 if let Some(rva) = addresses.get(*ordinal as usize) {
314 match *rva {
315 ExportRVA(rva) => {
316 let rva = rva as usize;
317 let offset = utils::find_offset(rva, sections, file_alignment, &opts);
318 Ok((
319 Export {
320 name,
321 offset,
322 rva,
323 reexport: None,
324 size: 0,
325 },
326 0,
327 ))
328 }
329
330 ForwarderRVA(rva) => {
331 let rva = rva as usize;
332 let offset = utils::find_offset_or(
333 rva,
334 sections,
335 file_alignment,
336 &opts,
337 &format!(
338 "cannot map RVA ({:#x}) of export ordinal {} into offset",
339 rva, ordinal
340 ),
341 )?;
342 let reexport = Reexport::parse(bytes, offset)?;
343 Ok((
344 Export {
345 name,
346 offset: Some(offset),
347 rva,
348 reexport: Some(reexport),
349 size: 0,
350 },
351 0,
352 ))
353 }
354 }
355 } else {
356 Err(error::Error::Malformed(format!(
357 "cannot get RVA of export ordinal {}",
358 ordinal
359 )))
360 }
361 } else {
362 Err(error::Error::Malformed(format!(
363 "cannot get ordinal of export name entry {}",
364 idx
365 )))
366 }
367 }
368}
369
370impl<'a> Export<'a> {
371 pub fn parse(
372 bytes: &'a [u8],
373 export_data: &ExportData,
374 sections: &[section_table::SectionTable],
375 file_alignment: u32,
376 ) -> error::Result<Vec<Export<'a>>> {
377 Self::parse_with_opts(
378 bytes,
379 export_data,
380 sections,
381 file_alignment,
382 &options::ParseOptions::default(),
383 )
384 }
385
386 pub fn parse_with_opts(
387 bytes: &'a [u8],
388 export_data: &ExportData,
389 sections: &[section_table::SectionTable],
390 file_alignment: u32,
391 opts: &options::ParseOptions,
392 ) -> error::Result<Vec<Export<'a>>> {
393 let pointers = &export_data.export_name_pointer_table;
394 let addresses = &export_data.export_address_table;
395 let ordinals = &export_data.export_ordinal_table;
396
397 let mut exports = Vec::with_capacity(pointers.len());
398 for (idx, &ptr) in pointers.iter().enumerate() {
399 if let Ok(export) = bytes.pread_with(
400 0,
401 ExportCtx {
402 ptr,
403 idx,
404 sections,
405 file_alignment,
406 addresses,
407 ordinals,
408 opts: *opts,
409 },
410 ) {
411 exports.push(export);
412 }
413 }
414
415 Ok(exports)
417 }
418}
419
420#[cfg(test)]
421mod tests {
422 use self::data_directories::*;
423 use super::*;
424
425 static CORKAMI_POCS_PE_EXPORTSDATA_EXE: [u8; 0x400] = [
426 0x4d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x40, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x02, 0x01, 0x0b, 0x01,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
434 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x01,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x10, 0x00, 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x10, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02,
448 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x80, 0x03,
461 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2a, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20,
462 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x66, 0x61, 0x6b, 0x65, 0x20,
463 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84,
465 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x10, 0x00, 0x00,
466 0x40, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0x00, 0xa0, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c,
469 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66,
470 0x00, 0x6d, 0x73, 0x76, 0x63, 0x72, 0x74, 0x2e, 0x64, 0x6c, 0x6c, 0x00, 0x65, 0x78, 0x70,
471 0x6f, 0x72, 0x74, 0x73, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x68, 0x14, 0x10, 0xf0, 0x10, 0xff, 0x15, 0x30, 0x10, 0x00, 0x10, 0x73, 0xc4, 0x04,
476 0xc3, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00,
495 ];
496
497 #[test]
498 fn size_export_directory_table() {
499 assert_eq!(
500 ::std::mem::size_of::<ExportDirectoryTable>(),
501 SIZEOF_EXPORT_DIRECTORY_TABLE
502 );
503 }
504
505 #[test]
506 fn parse_export_table() {
507 let data_dirs =
508 DataDirectories::parse(&CORKAMI_POCS_PE_EXPORTSDATA_EXE[..], 16, &mut 0xb8).unwrap();
509 let export_table = data_dirs.get_export_table().unwrap();
510
511 assert_eq!(export_table.virtual_address, 0x10b0);
512 assert_eq!(export_table.size, 0x0);
513 }
514
515 #[test]
516 fn parse_export_directory() {
517 let data_dir = ExportDirectoryTable::parse(&CORKAMI_POCS_PE_EXPORTSDATA_EXE[..], 0x2b0);
518 assert!(data_dir.is_ok());
519
520 let data_dir = data_dir.unwrap();
521 assert_eq!(data_dir.export_flags, 0x0);
522 assert_eq!(data_dir.time_date_stamp, 0x0);
523 assert_eq!(data_dir.major_version, 0x0);
524 assert_eq!(data_dir.minor_version, 0x0);
525 assert_eq!(data_dir.name_rva, 0x0);
526 assert_eq!(data_dir.ordinal_base, 0x0);
527 assert_eq!(data_dir.address_table_entries, 0x4);
528 assert_eq!(data_dir.number_of_name_pointers, 0x0);
529 assert_eq!(data_dir.export_address_table_rva, 0x10e0);
530 assert_eq!(data_dir.name_pointer_rva, 0x0);
531 assert_eq!(data_dir.ordinal_table_rva, 0x1100);
532 }
533}