let import_directory = file.data_directory(IMAGE_DIRECTORY_ENTRY_IMPORT);
if import_directory.is_none() {
return Err(LoadPEError::ExecutableWithoutImportTable);
let base_import_table_rva = import_directory.unwrap().virtual_address.get(LittleEndian);
let mut import_table_index = 0;
let descriptor = unsafe {
+ base_import_table_rva as usize
+ import_table_index * std::mem::size_of::<object::pe::ImageImportDescriptor>())
as *const object::pe::ImageImportDescriptor)
if descriptor.original_first_thunk.get(LittleEndian) == 0 {
let module_name_rva = descriptor.name.get(LittleEndian);
let p_module_name = (buf as usize + module_name_rva as usize) as *const u8;
LoadLibraryA(PCSTR::from_raw(p_module_name))
.map_err(|err| LoadPEError::LoadLibraryError(err))?
if h_module.is_invalid() {
unimplemented!("LoadLibraryA failed");
// 加载每一个方法。使用GetProcAddress,获取地址。
// 然后修复IAT表。如果其中一个环节出现问题,我们应该:释放所有加载的Module,然后返回错误
// 获取Image_thunk_data数组的首地址
let base_original_first_thunk_va =
if descriptor.original_first_thunk.get(LittleEndian) != 0 {
descriptor.original_first_thunk.get(LittleEndian)
// 如果OriginalFirstThunk不存在,则使用FirstThunk 的值
descriptor.first_thunk.get(LittleEndian)
let base_import_address_table_va = descriptor.first_thunk.get(LittleEndian);
// 1. 从文件的数据中取出一个ImageThunkData
let origin_thunk_data = unsafe {
#[cfg(target_arch = "x86")]
let thunk_data = &*((buf as usize
+ base_original_first_thunk_va as usize
+ index * std::mem::size_of::<object::pe::ImageThunkData32>())
as *const object::pe::ImageThunkData32);
#[cfg(target_arch = "x86_64")]
let thunk_data = &*((buf as usize
+ base_original_first_thunk_va as usize
+ index * std::mem::size_of::<object::pe::ImageThunkData64>())
as *const object::pe::ImageThunkData64);
// 2. 判断是否是最后一个ImageThunkData
let origin_thunk_data_value = origin_thunk_data.0.get(LittleEndian) as u64;
if origin_thunk_data_value == 0 {
#[cfg(target_arch = "x86")]
let is_ordinal = origin_thunk_data_value & 0x80000000 != 0;
#[cfg(target_arch = "x86_64")]
let is_ordinal = origin_thunk_data_value & 0x8000000000000000 != 0;
let ordinal = origin_thunk_data_value as u16;
let pstr = PCSTR(ordinal as *const u8);
// 使用GetProcAddress获取函数地址
let p_function = unsafe { GetProcAddress(h_module, pstr) };
if p_function.is_none() {
return Err(LoadPEError::GetProcAddressError(format!(
"GetProcAddress failed, ordinal: {:?}",
function_address = p_function.unwrap() as *const u8;
let name_table_rva = origin_thunk_data_value;
let p_function_name = (buf as usize + name_table_rva as usize + 2) as *const u8;
let p_function_name = PCSTR(p_function_name);
// 使用GetProcAddress获取函数地址
let p_function = unsafe { GetProcAddress(h_module, p_function_name) };
if p_function.is_none() {
return Err(LoadPEError::GetProcAddressError(format!(
"GetProcAddress failed, function name: {:?}",
function_address = p_function.unwrap() as *const u8;
let iat_address = (buf as usize
+ base_import_address_table_va as usize
+ std::mem::size_of::<u32>() * index)
// 将函数地址写入IAT表 如果是x86_64,需要写入8字节
#[cfg(target_arch = "x86")]
*(iat_address as *mut u32) = function_address as u32;
#[cfg(target_arch = "x86_64")]
*(iat_address as *mut u64) = function_address as u64;