diff options
Diffstat (limited to 'third_party/rust/goblin/src/pe/export.rs')
-rw-r--r-- | third_party/rust/goblin/src/pe/export.rs | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/third_party/rust/goblin/src/pe/export.rs b/third_party/rust/goblin/src/pe/export.rs new file mode 100644 index 0000000000..f892c75276 --- /dev/null +++ b/third_party/rust/goblin/src/pe/export.rs @@ -0,0 +1,533 @@ +use alloc::vec::Vec; +use scroll::{Pread, Pwrite}; + +use log::debug; + +use crate::error; + +use crate::pe::data_directories; +use crate::pe::options; +use crate::pe::section_table; +use crate::pe::utils; + +#[repr(C)] +#[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite)] +pub struct ExportDirectoryTable { + pub export_flags: u32, + pub time_date_stamp: u32, + pub major_version: u16, + pub minor_version: u16, + pub name_rva: u32, + pub ordinal_base: u32, + pub address_table_entries: u32, + pub number_of_name_pointers: u32, + pub export_address_table_rva: u32, + pub name_pointer_rva: u32, + pub ordinal_table_rva: u32, +} + +pub const SIZEOF_EXPORT_DIRECTORY_TABLE: usize = 40; + +impl ExportDirectoryTable { + pub fn parse(bytes: &[u8], offset: usize) -> error::Result<Self> { + let res = bytes.pread_with(offset, scroll::LE)?; + Ok(res) + } +} + +#[derive(Debug)] +pub enum ExportAddressTableEntry { + ExportRVA(u32), + ForwarderRVA(u32), +} + +pub const SIZEOF_EXPORT_ADDRESS_TABLE_ENTRY: usize = 4; + +pub type ExportAddressTable = Vec<ExportAddressTableEntry>; + +/// Array of rvas into the export name table +/// +/// Export name is defined iff pointer table has pointer to the name +pub type ExportNamePointerTable = Vec<u32>; + +/// Array of indexes into the export address table. +/// +/// Should obey the formula `idx = ordinal - ordinalbase` +pub type ExportOrdinalTable = Vec<u16>; + +#[derive(Debug, Default)] +/// Export data contains the `dll` name which other libraries can import symbols by (two-level namespace), as well as other important indexing data allowing symbol lookups +pub struct ExportData<'a> { + pub name: Option<&'a str>, + pub export_directory_table: ExportDirectoryTable, + pub export_name_pointer_table: ExportNamePointerTable, + pub export_ordinal_table: ExportOrdinalTable, + pub export_address_table: ExportAddressTable, +} + +impl<'a> ExportData<'a> { + pub fn parse( + bytes: &'a [u8], + dd: data_directories::DataDirectory, + sections: &[section_table::SectionTable], + file_alignment: u32, + ) -> error::Result<ExportData<'a>> { + Self::parse_with_opts( + bytes, + dd, + sections, + file_alignment, + &options::ParseOptions::default(), + ) + } + + pub fn parse_with_opts( + bytes: &'a [u8], + dd: data_directories::DataDirectory, + sections: &[section_table::SectionTable], + file_alignment: u32, + opts: &options::ParseOptions, + ) -> error::Result<ExportData<'a>> { + let export_rva = dd.virtual_address as usize; + let size = dd.size as usize; + debug!("export_rva {:#x} size {:#}", export_rva, size); + let export_offset = utils::find_offset_or( + export_rva, + sections, + file_alignment, + opts, + &format!("cannot map export_rva ({:#x}) into offset", export_rva), + )?; + let export_directory_table = + ExportDirectoryTable::parse(bytes, export_offset).map_err(|_| { + error::Error::Malformed(format!( + "cannot parse export_directory_table (offset {:#x})", + export_offset + )) + })?; + let number_of_name_pointers = export_directory_table.number_of_name_pointers as usize; + let address_table_entries = export_directory_table.address_table_entries as usize; + + if number_of_name_pointers > bytes.len() { + return Err(error::Error::BufferTooShort( + number_of_name_pointers, + "name pointers", + )); + } + if address_table_entries > bytes.len() { + return Err(error::Error::BufferTooShort( + address_table_entries, + "address table entries", + )); + } + + let export_name_pointer_table = utils::find_offset( + export_directory_table.name_pointer_rva as usize, + sections, + file_alignment, + opts, + ) + .map_or(vec![], |table_offset| { + let mut offset = table_offset; + let mut table: ExportNamePointerTable = Vec::with_capacity(number_of_name_pointers); + + for _ in 0..number_of_name_pointers { + if let Ok(name_rva) = bytes.gread_with(&mut offset, scroll::LE) { + table.push(name_rva); + } else { + break; + } + } + + table + }); + + let export_ordinal_table = utils::find_offset( + export_directory_table.ordinal_table_rva as usize, + sections, + file_alignment, + opts, + ) + .map_or(vec![], |table_offset| { + let mut offset = table_offset; + let mut table: ExportOrdinalTable = Vec::with_capacity(number_of_name_pointers); + + for _ in 0..number_of_name_pointers { + if let Ok(name_ordinal) = bytes.gread_with(&mut offset, scroll::LE) { + table.push(name_ordinal); + } else { + break; + } + } + + table + }); + + let export_address_table = utils::find_offset( + export_directory_table.export_address_table_rva as usize, + sections, + file_alignment, + opts, + ) + .map_or(vec![], |table_offset| { + let mut offset = table_offset; + let mut table: ExportAddressTable = Vec::with_capacity(address_table_entries); + let export_end = export_rva + size; + + for _ in 0..address_table_entries { + if let Ok(func_rva) = bytes.gread_with::<u32>(&mut offset, scroll::LE) { + if utils::is_in_range(func_rva as usize, export_rva, export_end) { + table.push(ExportAddressTableEntry::ForwarderRVA(func_rva)); + } else { + table.push(ExportAddressTableEntry::ExportRVA(func_rva)); + } + } else { + break; + } + } + + table + }); + + let name = utils::find_offset( + export_directory_table.name_rva as usize, + sections, + file_alignment, + opts, + ) + .and_then(|offset| bytes.pread(offset).ok()); + + Ok(ExportData { + name, + export_directory_table, + export_name_pointer_table, + export_ordinal_table, + export_address_table, + }) + } +} + +#[derive(Debug)] +/// PE binaries have two kinds of reexports, either specifying the dll's name, or the ordinal value of the dll +pub enum Reexport<'a> { + DLLName { export: &'a str, lib: &'a str }, + DLLOrdinal { ordinal: usize, lib: &'a str }, +} + +impl<'a> scroll::ctx::TryFromCtx<'a, scroll::Endian> for Reexport<'a> { + type Error = crate::error::Error; + #[inline] + fn try_from_ctx(bytes: &'a [u8], _ctx: scroll::Endian) -> Result<(Self, usize), Self::Error> { + let reexport = bytes.pread::<&str>(0)?; + let reexport_len = reexport.len(); + debug!("reexport: {}", &reexport); + for o in 0..reexport_len { + let c: u8 = bytes.pread(o)?; + debug!("reexport offset: {:#x} char: {:#x}", o, c); + if c == b'.' { + let dll: &'a str = bytes.pread_with(0, scroll::ctx::StrCtx::Length(o))?; + debug!("dll: {:?}", &dll); + if o + 1 == reexport_len { + break; + } + let len = reexport_len - o - 1; + let rest: &'a [u8] = bytes.pread_with(o + 1, len)?; + debug!("rest: {:?}", &rest); + if rest[0] == b'#' { + let ordinal = + rest.pread_with::<&str>(1, scroll::ctx::StrCtx::Length(len - 1))?; + let ordinal = ordinal.parse::<u32>().map_err(|_e| { + error::Error::Malformed(format!( + "Cannot parse reexport ordinal from {} bytes", + bytes.len() + )) + })?; + return Ok(( + Reexport::DLLOrdinal { + ordinal: ordinal as usize, + lib: dll, + }, + reexport_len + 1, + )); + } else { + let export = rest.pread_with::<&str>(0, scroll::ctx::StrCtx::Length(len))?; + return Ok((Reexport::DLLName { export, lib: dll }, reexport_len + 1)); + } + } + } + Err(error::Error::Malformed(format!( + "Reexport {:#} is malformed", + reexport + ))) + } +} + +impl<'a> Reexport<'a> { + pub fn parse(bytes: &'a [u8], offset: usize) -> crate::error::Result<Reexport<'a>> { + bytes.pread(offset) + } +} + +#[derive(Debug, Default)] +/// An exported symbol in this binary, contains synthetic data (name offset, etc., are computed) +pub struct Export<'a> { + pub name: Option<&'a str>, + pub offset: Option<usize>, + pub rva: usize, + pub size: usize, + pub reexport: Option<Reexport<'a>>, +} + +#[derive(Debug, Copy, Clone)] +struct ExportCtx<'a> { + pub ptr: u32, + pub idx: usize, + pub sections: &'a [section_table::SectionTable], + pub file_alignment: u32, + pub addresses: &'a ExportAddressTable, + pub ordinals: &'a ExportOrdinalTable, + pub opts: options::ParseOptions, +} + +impl<'a, 'b> scroll::ctx::TryFromCtx<'a, ExportCtx<'b>> for Export<'a> { + type Error = error::Error; + #[inline] + fn try_from_ctx( + bytes: &'a [u8], + ExportCtx { + ptr, + idx, + sections, + file_alignment, + addresses, + ordinals, + opts, + }: ExportCtx<'b>, + ) -> Result<(Self, usize), Self::Error> { + use self::ExportAddressTableEntry::*; + + let name = utils::find_offset(ptr as usize, sections, file_alignment, &opts) + .and_then(|offset| bytes.pread::<&str>(offset).ok()); + + if let Some(ordinal) = ordinals.get(idx) { + if let Some(rva) = addresses.get(*ordinal as usize) { + match *rva { + ExportRVA(rva) => { + let rva = rva as usize; + let offset = utils::find_offset(rva, sections, file_alignment, &opts); + Ok(( + Export { + name, + offset, + rva, + reexport: None, + size: 0, + }, + 0, + )) + } + + ForwarderRVA(rva) => { + let rva = rva as usize; + let offset = utils::find_offset_or( + rva, + sections, + file_alignment, + &opts, + &format!( + "cannot map RVA ({:#x}) of export ordinal {} into offset", + rva, ordinal + ), + )?; + let reexport = Reexport::parse(bytes, offset)?; + Ok(( + Export { + name, + offset: Some(offset), + rva, + reexport: Some(reexport), + size: 0, + }, + 0, + )) + } + } + } else { + Err(error::Error::Malformed(format!( + "cannot get RVA of export ordinal {}", + ordinal + ))) + } + } else { + Err(error::Error::Malformed(format!( + "cannot get ordinal of export name entry {}", + idx + ))) + } + } +} + +impl<'a> Export<'a> { + pub fn parse( + bytes: &'a [u8], + export_data: &ExportData, + sections: &[section_table::SectionTable], + file_alignment: u32, + ) -> error::Result<Vec<Export<'a>>> { + Self::parse_with_opts( + bytes, + export_data, + sections, + file_alignment, + &options::ParseOptions::default(), + ) + } + + pub fn parse_with_opts( + bytes: &'a [u8], + export_data: &ExportData, + sections: &[section_table::SectionTable], + file_alignment: u32, + opts: &options::ParseOptions, + ) -> error::Result<Vec<Export<'a>>> { + let pointers = &export_data.export_name_pointer_table; + let addresses = &export_data.export_address_table; + let ordinals = &export_data.export_ordinal_table; + + let mut exports = Vec::with_capacity(pointers.len()); + for (idx, &ptr) in pointers.iter().enumerate() { + if let Ok(export) = bytes.pread_with( + 0, + ExportCtx { + ptr, + idx, + sections, + file_alignment, + addresses, + ordinals, + opts: *opts, + }, + ) { + exports.push(export); + } + } + + // TODO: sort + compute size + Ok(exports) + } +} + +#[cfg(test)] +mod tests { + use self::data_directories::*; + use super::*; + + static CORKAMI_POCS_PE_EXPORTSDATA_EXE: [u8; 0x400] = [ + 0x4d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x02, 0x01, 0x0b, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x80, 0x03, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2a, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x66, 0x61, 0x6b, 0x65, 0x20, + 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x10, 0x00, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xa0, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, + 0x00, 0x6d, 0x73, 0x76, 0x63, 0x72, 0x74, 0x2e, 0x64, 0x6c, 0x6c, 0x00, 0x65, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x73, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x68, 0x14, 0x10, 0xf0, 0x10, 0xff, 0x15, 0x30, 0x10, 0x00, 0x10, 0x73, 0xc4, 0x04, + 0xc3, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + #[test] + fn size_export_directory_table() { + assert_eq!( + ::std::mem::size_of::<ExportDirectoryTable>(), + SIZEOF_EXPORT_DIRECTORY_TABLE + ); + } + + #[test] + fn parse_export_table() { + let data_dirs = + DataDirectories::parse(&CORKAMI_POCS_PE_EXPORTSDATA_EXE[..], 16, &mut 0xb8).unwrap(); + let export_table = data_dirs.get_export_table().unwrap(); + + assert_eq!(export_table.virtual_address, 0x10b0); + assert_eq!(export_table.size, 0x0); + } + + #[test] + fn parse_export_directory() { + let data_dir = ExportDirectoryTable::parse(&CORKAMI_POCS_PE_EXPORTSDATA_EXE[..], 0x2b0); + assert!(data_dir.is_ok()); + + let data_dir = data_dir.unwrap(); + assert_eq!(data_dir.export_flags, 0x0); + assert_eq!(data_dir.time_date_stamp, 0x0); + assert_eq!(data_dir.major_version, 0x0); + assert_eq!(data_dir.minor_version, 0x0); + assert_eq!(data_dir.name_rva, 0x0); + assert_eq!(data_dir.ordinal_base, 0x0); + assert_eq!(data_dir.address_table_entries, 0x4); + assert_eq!(data_dir.number_of_name_pointers, 0x0); + assert_eq!(data_dir.export_address_table_rva, 0x10e0); + assert_eq!(data_dir.name_pointer_rva, 0x0); + assert_eq!(data_dir.ordinal_table_rva, 0x1100); + } +} |