fix: 修复对指针的操作,导致修改了指针.

This commit is contained in:
asahi 2024-12-27 01:07:22 +08:00
parent aabbc73ee5
commit 989abab053
6 changed files with 132 additions and 35 deletions

View File

@ -1,10 +1,10 @@
use loadpe_rs::load_exe; use loadpe_rs::load_exe;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
const EXE_PATH: &str = r#"E:\work\逆向工程学习\PE学习\HelloWorld.exe"#; const EXE_PATH: &str = r#"E:\work\rust\loadpe-rs\tests\Testx64.exe"#;
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
const EXE_PATH: &str = r#"E:\work\rust\loadpe-rs\tests\Test.exe"#; const EXE_PATH: &str = r#"E:\work\rust\loadpe-rs\tests\Testx32.exe"#;
fn main() { fn main() {
match load_exe(EXE_PATH, None) { match load_exe(EXE_PATH, None) {

View File

@ -1,3 +1,5 @@
use std::alloc::LayoutError;
use thiserror::Error; use thiserror::Error;
use object::Error as ObjectError; use object::Error as ObjectError;
use windows::core::Error as WindowsError; use windows::core::Error as WindowsError;
@ -20,4 +22,9 @@ pub enum LoadPEError {
LoadLibraryError(#[from] WindowsError), LoadLibraryError(#[from] WindowsError),
#[error("GetProcAddress错误, {0}")] #[error("GetProcAddress错误, {0}")]
GetProcAddressError(String), GetProcAddressError(String),
#[error("没有重定位表!")]
NoRelocationTable,
#[error(transparent)]
LayoutError(#[from] LayoutError),
} }

View File

@ -2,7 +2,7 @@ use core::alloc;
use errors::LoadPEError; use errors::LoadPEError;
use object::{ use object::{
bytes_of, bytes_of_slice, endian, bytes_of, bytes_of_slice, endian,
pe::IMAGE_DIRECTORY_ENTRY_IMPORT, pe::{IMAGE_DIRECTORY_ENTRY_BASERELOC, IMAGE_DIRECTORY_ENTRY_IMPORT},
read::pe::{self, ImageOptionalHeader, PeFile32, PeFile64}, read::pe::{self, ImageOptionalHeader, PeFile32, PeFile64},
LittleEndian, Object, ObjectSection, Pod, LittleEndian, Object, ObjectSection, Pod,
}; };
@ -46,10 +46,14 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
// 3. 为镜像分配内存 // 3. 为镜像分配内存
// 分配的内存,后续需要修改内存属性 // 分配的内存,后续需要修改内存属性
// //
let buf = unsafe { alloc(Layout::for_value(&image_size)) }; let layout = Layout::from_size_align(image_size as usize, 1)?;
let buf = unsafe { alloc(layout) };
if buf.is_null() { if buf.is_null() {
return Err(LoadPEError::MemoryAllocFailed); return Err(LoadPEError::MemoryAllocFailed);
} }
dbg!("分配的内存地址: {:?}", buf);
// 进行数据的拷贝。 // 进行数据的拷贝。
{ {
// 拷贝整个头部 // 拷贝整个头部
@ -91,12 +95,17 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
// 从data[pointer_to_raw_data..pointer_to_raw_data + size_of_raw_data]中拷贝数据到buf[va..va + size_of_raw_data] // 从data[pointer_to_raw_data..pointer_to_raw_data + size_of_raw_data]中拷贝数据到buf[va..va + size_of_raw_data]
let section_data = &data let section_data = &data
[pointer_to_raw_data as usize..(pointer_to_raw_data + size_of_raw_data) as usize]; [pointer_to_raw_data as usize..(pointer_to_raw_data + size_of_raw_data) as usize];
unsafe {
std::ptr::copy_nonoverlapping( dbg!(
section_data.as_ptr(), "拷贝节区数据: va: {:?}, size_of_raw_data: {:?}, pointer_to_raw_data: {:?}, section_data.len: {:?}",
buf.add(va as usize), va, size_of_raw_data, pointer_to_raw_data, section_data.len()
size_of_raw_data as usize,
); );
unsafe {
let dst = (buf as usize + va as usize) as *mut u8;
dbg!("dst: {:p}", dst);
std::ptr::copy(section_data.as_ptr(), dst, size_of_raw_data as usize);
}; };
} }
// 修复IAT表 // 修复IAT表
@ -110,18 +119,17 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
let mut import_table_index = 0; let mut import_table_index = 0;
loop { loop {
let descriptor = unsafe { let descriptor = unsafe {
&*(buf.add(base_import_table_rva as usize) &*((buf as usize
+ base_import_table_rva as usize
+ import_table_index
* std::mem::size_of::<object::pe::ImageImportDescriptor>())
as *const object::pe::ImageImportDescriptor) as *const object::pe::ImageImportDescriptor)
.add(import_table_index)
}; };
if descriptor.original_first_thunk.get(LittleEndian) == 0 { if descriptor.original_first_thunk.get(LittleEndian) == 0 {
break; break;
} }
let module_name_rva = descriptor.name.get(LittleEndian); let module_name_rva = descriptor.name.get(LittleEndian);
let p_module_name = unsafe { let p_module_name = (buf as usize + module_name_rva as usize) as *const u8;
// buf[module_name_rva..]中读取一个c风格字符串
buf.add(module_name_rva as usize) as *const u8
};
// 使用LoadLibraryA加载模块 // 使用LoadLibraryA加载模块
let h_module = unsafe { let h_module = unsafe {
@ -151,13 +159,17 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
// 1. 从文件的数据中取出一个ImageThunkData // 1. 从文件的数据中取出一个ImageThunkData
let origin_thunk_data = unsafe { let origin_thunk_data = unsafe {
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
let thunk_data = &*(buf.add(base_original_first_thunk_va as usize) let thunk_data = &*((buf as usize
as *const object::pe::ImageThunkData32) + base_original_first_thunk_va as usize
.add(index); + index * std::mem::size_of::<object::pe::ImageThunkData32>())
as *const object::pe::ImageThunkData32);
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
let thunk_data = &*(buf.add(base_original_first_thunk_va as usize) let thunk_data = &*((buf as usize
as *const object::pe::ImageThunkData64) + base_original_first_thunk_va as usize
.add(index); + index * std::mem::size_of::<object::pe::ImageThunkData64>())
as *const object::pe::ImageThunkData64);
thunk_data thunk_data
}; };
// 2. 判断是否是最后一个ImageThunkData // 2. 判断是否是最后一个ImageThunkData
@ -190,7 +202,7 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
// 否则是名称表的RVA // 否则是名称表的RVA
let name_table_rva = origin_thunk_data_value; let name_table_rva = origin_thunk_data_value;
let p_function_name = let p_function_name =
unsafe { buf.add(name_table_rva as usize + 2) as *const u8 }; (buf as usize + name_table_rva as usize + 2) as *const u8;
// 构造一个PSTR // 构造一个PSTR
let p_function_name = PCSTR(p_function_name); let p_function_name = PCSTR(p_function_name);
// 使用GetProcAddress获取函数地址 // 使用GetProcAddress获取函数地址
@ -206,8 +218,11 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
} }
// 修复IAT表 // 修复IAT表
// 需要获取到IAT表的地址 // 需要获取到IAT表的地址
let iat_address = let iat_address = (buf as usize
unsafe { buf.add(base_import_address_table_va as usize + 4 * index) }; + base_import_address_table_va as usize
+ std::mem::size_of::<u32>() * index)
as *mut u8;
// 修复IAT表 // 修复IAT表
// 将函数地址写入IAT表 如果是x86_64需要写入8字节 // 将函数地址写入IAT表 如果是x86_64需要写入8字节
// 如果是x86需要写入4字节 // 如果是x86需要写入4字节
@ -224,25 +239,100 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
index += 1; index += 1;
} }
import_table_index += 1; import_table_index += 1;
} }
} }
// TODO: 修复重定向表 // TODO: 修复重定向表
{ {
// 1. 获取重定向表的数据目录
let relocation_table_directory = file.data_directory(IMAGE_DIRECTORY_ENTRY_BASERELOC);
if relocation_table_directory.is_none() {
// TODO: 如果没有重定位表,应该要把这个错误返回出去
return Err(LoadPEError::NoRelocationTable);
}
let base_relocation_table_rva = relocation_table_directory
.unwrap()
.virtual_address
.get(LittleEndian);
let mut relocation_offset = 0;
loop {
// 读取一个IMAGE_BASE_RELOCATION
let relocation = unsafe {
&*((buf as usize + base_relocation_table_rva as usize + relocation_offset)
as *const object::pe::ImageBaseRelocation)
};
// 如果SizeOfBlock为0表示已经到了最后一个IMAGE_BASE_RELOCATION
if relocation.size_of_block.get(LittleEndian) == 0 {
break;
}
// 获取重定位表的VirtualAddress和SizeOfBlock
let virtual_address = relocation.virtual_address.get(LittleEndian);
let size_of_block = relocation.size_of_block.get(LittleEndian);
let base_block = base_relocation_table_rva as usize + relocation_offset + 8;
let block_num = (size_of_block - 8) / 2;
for i in 0..block_num {
// 读取一个TypeOffset
let type_offset = unsafe {
&*((buf as usize
+ base_block as usize
+ i as usize * std::mem::size_of::<u16>())
as *mut u16)
};
// 高四位
let r_type = (type_offset >> 12) as u8;
// 剩余12位
let r_offset = type_offset & 0x0FFF;
// 需要修复的地址偏移
let offset_va = virtual_address + r_offset as u32;
dbg!(
"r_type: {:?}, r_offset: {:?}, offset_va: {:?}, virtual_address: {:?}",
r_type,
r_offset,
offset_va,
virtual_address
);
match r_type {
0 => {
// 如果r_type是0表示这个TypeOffset是一个IMAGE_REL_BASED_ABSOLUTE
// 这个时候不需要做任何操作
}
3 => {
// 如果r_type是3表示这个TypeOffset是一个IMAGE_REL_BASED_HIGHLOW
// 这个时候需要修复一个32位的地址
let p_address = (buf as usize + offset_va as usize) as *mut u32;
let address = unsafe { *p_address };
let new_address = address + buf as u32;
unsafe {
*p_address = new_address;
}
dbg!("修复一个32位地址: {:?} -> {:?}", address, new_address);
}
10 => {
// 需要实现64位的重定位
unimplemented!("未实现的重定位类型: {:?}", r_type);
}
_ => {
// 其他的类型,暂时不支持
unimplemented!("未实现的重定位类型: {:?}", r_type);
}
}
}
// 计算下一个IMAGE_BASE_RELOCATION的偏移
relocation_offset += size_of_block as usize;
}
} }
// TODO: 修复TLS表 // TODO: 修复TLS表
{ {}
}
// TODO: 修复资源表 // TODO: 修复资源表
{ {}
}
// TODO: 修复命令行参数 // TODO: 修复命令行参数
{ {}
// TODO: 设置节区属性
} {}
// TODO: 跳转到入口点
{}
} }
todo!("未实现") todo!("未实现")

Binary file not shown.

BIN
tests/Testx32.exe Normal file

Binary file not shown.

BIN
tests/Testx64.exe Normal file

Binary file not shown.