fix: 修复对指针的操作,导致修改了指针.
This commit is contained in:
parent
aabbc73ee5
commit
989abab053
@ -1,10 +1,10 @@
|
||||
use loadpe_rs::load_exe;
|
||||
|
||||
#[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")]
|
||||
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() {
|
||||
match load_exe(EXE_PATH, None) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
use std::alloc::LayoutError;
|
||||
|
||||
use thiserror::Error;
|
||||
use object::Error as ObjectError;
|
||||
use windows::core::Error as WindowsError;
|
||||
@ -20,4 +22,9 @@ pub enum LoadPEError {
|
||||
LoadLibraryError(#[from] WindowsError),
|
||||
#[error("GetProcAddress错误!, {0}")]
|
||||
GetProcAddressError(String),
|
||||
#[error("没有重定位表!")]
|
||||
NoRelocationTable,
|
||||
#[error(transparent)]
|
||||
LayoutError(#[from] LayoutError),
|
||||
|
||||
}
|
156
src/lib.rs
156
src/lib.rs
@ -2,7 +2,7 @@ use core::alloc;
|
||||
use errors::LoadPEError;
|
||||
use object::{
|
||||
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},
|
||||
LittleEndian, Object, ObjectSection, Pod,
|
||||
};
|
||||
@ -46,10 +46,14 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
|
||||
// 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() {
|
||||
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]
|
||||
let section_data = &data
|
||||
[pointer_to_raw_data as usize..(pointer_to_raw_data + size_of_raw_data) as usize];
|
||||
|
||||
dbg!(
|
||||
"拷贝节区数据: va: {:?}, size_of_raw_data: {:?}, pointer_to_raw_data: {:?}, section_data.len: {:?}",
|
||||
va, size_of_raw_data, pointer_to_raw_data, section_data.len()
|
||||
);
|
||||
|
||||
unsafe {
|
||||
std::ptr::copy_nonoverlapping(
|
||||
section_data.as_ptr(),
|
||||
buf.add(va as usize),
|
||||
size_of_raw_data as usize,
|
||||
);
|
||||
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表
|
||||
@ -110,18 +119,17 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
|
||||
let mut import_table_index = 0;
|
||||
loop {
|
||||
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)
|
||||
.add(import_table_index)
|
||||
};
|
||||
if descriptor.original_first_thunk.get(LittleEndian) == 0 {
|
||||
break;
|
||||
}
|
||||
let module_name_rva = descriptor.name.get(LittleEndian);
|
||||
let p_module_name = unsafe {
|
||||
// buf[module_name_rva..]中读取一个c风格字符串
|
||||
buf.add(module_name_rva as usize) as *const u8
|
||||
};
|
||||
let p_module_name = (buf as usize + module_name_rva as usize) as *const u8;
|
||||
|
||||
// 使用LoadLibraryA加载模块
|
||||
let h_module = unsafe {
|
||||
@ -151,13 +159,17 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
|
||||
// 1. 从文件的数据中取出一个ImageThunkData
|
||||
let origin_thunk_data = unsafe {
|
||||
#[cfg(target_arch = "x86")]
|
||||
let thunk_data = &*(buf.add(base_original_first_thunk_va as usize)
|
||||
as *const object::pe::ImageThunkData32)
|
||||
.add(index);
|
||||
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.add(base_original_first_thunk_va as usize)
|
||||
as *const object::pe::ImageThunkData64)
|
||||
.add(index);
|
||||
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);
|
||||
|
||||
thunk_data
|
||||
};
|
||||
// 2. 判断是否是最后一个ImageThunkData
|
||||
@ -190,7 +202,7 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
|
||||
// 否则是名称表的RVA
|
||||
let name_table_rva = origin_thunk_data_value;
|
||||
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
|
||||
let p_function_name = PCSTR(p_function_name);
|
||||
// 使用GetProcAddress获取函数地址
|
||||
@ -206,8 +218,11 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
|
||||
}
|
||||
// 修复IAT表
|
||||
// 需要获取到IAT表的地址
|
||||
let iat_address =
|
||||
unsafe { buf.add(base_import_address_table_va as usize + 4 * index) };
|
||||
let iat_address = (buf as usize
|
||||
+ base_import_address_table_va as usize
|
||||
+ std::mem::size_of::<u32>() * index)
|
||||
as *mut u8;
|
||||
|
||||
// 修复IAT表
|
||||
// 将函数地址写入IAT表 如果是x86_64,需要写入8字节
|
||||
// 如果是x86,需要写入4字节
|
||||
@ -223,26 +238,101 @@ pub fn load_exe(exe_path: &str, args: Option<Vec<&str>>) -> Result<(), LoadPEErr
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
import_table_index += 1;
|
||||
|
||||
import_table_index += 1;
|
||||
}
|
||||
}
|
||||
// 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: 修复资源表
|
||||
{
|
||||
|
||||
}
|
||||
{}
|
||||
// TODO: 修复命令行参数
|
||||
{
|
||||
|
||||
}
|
||||
{}
|
||||
// TODO: 设置节区属性
|
||||
{}
|
||||
// TODO: 跳转到入口点
|
||||
{}
|
||||
}
|
||||
|
||||
todo!("未实现")
|
||||
|
BIN
tests/Test.exe
BIN
tests/Test.exe
Binary file not shown.
BIN
tests/Testx32.exe
Normal file
BIN
tests/Testx32.exe
Normal file
Binary file not shown.
BIN
tests/Testx64.exe
Normal file
BIN
tests/Testx64.exe
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user