MCPcopy Create free account
hub / github.com/Nariod/RustPacker / parse_exports

Function parse_exports

src/pe_parser.rs:48–129  ·  view source on GitHub ↗
(dll_path: &Path)

Source from the content-addressed store, hash-verified

46}
47
48pub fn parse_exports(dll_path: &Path) -> Result<Vec<DllExport>, String> {
49 let data = fs::read(dll_path).map_err(|e| format!("Failed to read DLL: {}", e))?;
50
51 if data.len() < 64 || read_u16(&data, 0) != 0x5A4D {
52 return Err("Not a valid PE file (bad MZ signature)".into());
53 }
54
55 let pe_offset = read_u32(&data, 0x3C) as usize;
56 if data.len() < pe_offset + 4 || read_u32(&data, pe_offset) != 0x00004550 {
57 return Err("Not a valid PE file (bad PE signature)".into());
58 }
59
60 let magic = read_u16(&data, pe_offset + 24);
61 let export_dir_rva_offset = match magic {
62 0x10b => pe_offset + 24 + 96, // PE32
63 0x20b => pe_offset + 24 + 112, // PE32+
64 _ => return Err(format!("Unknown PE optional header magic: 0x{:04x}", magic)),
65 };
66
67 let num_sections = read_u16(&data, pe_offset + 6);
68 let sections = parse_sections(&data, pe_offset, num_sections);
69
70 let export_rva = read_u32(&data, export_dir_rva_offset);
71 let export_size = read_u32(&data, export_dir_rva_offset + 4);
72
73 if export_rva == 0 || export_size == 0 {
74 return Ok(vec![]);
75 }
76
77 let export_offset =
78 rva_to_offset(&sections, export_rva).ok_or("Cannot resolve export directory RVA")?;
79
80 let num_functions = read_u32(&data, export_offset + 20) as usize;
81 let num_names = read_u32(&data, export_offset + 24) as usize;
82 let ordinal_base = read_u32(&data, export_offset + 16) as u16;
83
84 let addr_table_rva = read_u32(&data, export_offset + 28);
85 let name_ptr_rva = read_u32(&data, export_offset + 32);
86 let ordinal_table_rva = read_u32(&data, export_offset + 36);
87
88 let addr_table_off =
89 rva_to_offset(&sections, addr_table_rva).ok_or("Cannot resolve address table RVA")?;
90 let name_ptr_off =
91 rva_to_offset(&sections, name_ptr_rva).ok_or("Cannot resolve name pointer RVA")?;
92 let ordinal_off =
93 rva_to_offset(&sections, ordinal_table_rva).ok_or("Cannot resolve ordinal table RVA")?;
94
95 let mut name_for_index: Vec<Option<String>> = vec![None; num_functions];
96 for i in 0..num_names {
97 let name_rva = read_u32(&data, name_ptr_off + i * 4);
98 let ord_index = read_u16(&data, ordinal_off + i * 2) as usize;
99 if let Some(off) = rva_to_offset(&sections, name_rva) {
100 if let Some(name) = read_cstring(&data, off) {
101 if ord_index < num_functions {
102 name_for_index[ord_index] = Some(name);
103 }
104 }
105 }

Callers 5

test_parse_named_exportsFunction · 0.85
test_parse_no_exportsFunction · 0.85
test_parse_invalid_fileFunction · 0.85
test_parse_single_exportFunction · 0.85
apply_proxyFunction · 0.85

Calls 5

read_u16Function · 0.85
read_u32Function · 0.85
parse_sectionsFunction · 0.85
rva_to_offsetFunction · 0.85
read_cstringFunction · 0.85

Tested by 4

test_parse_named_exportsFunction · 0.68
test_parse_no_exportsFunction · 0.68
test_parse_invalid_fileFunction · 0.68
test_parse_single_exportFunction · 0.68