手动添加PE节区时切片引用错误的问题排查
问题分析与修复方案
核心问题出在PE节区数据对齐、Slice内存布局验证以及PE加载地址一致性这几个环节,以下是具体修复点:
1. 补全新节区的文件对齐填充
PE文件要求节区的SizeOfRawData必须对齐到FileAlignment,你当前只把压缩PE追加到打包器中,没有填充剩余字节到对齐长度,导致加载器读取节区数据时出错。
在packer.extend(&packed_pe);后添加填充代码:
// 计算对齐后的节区文件大小 let aligned_file_size = (packed_pe.len() as f32 / file_alignment as f32).ceil() as u32 * file_alignment; // 生成填充的0字节 let padding = vec![0; aligned_file_size as usize - packed_pe.len()]; packer.extend(padding);
2. 显式构造Slice的内存表示
虽然你当前的拼接逻辑看似正确,但显式构造Slice的16字节结构(x86_64下为8字节指针+8字节长度)可以避免拼接时的潜在错误:
// 替换原有的slice写入代码 let slice_ptr = ((*nt_header).OptionalHeader.ImageBase + size_of_image as u64).to_le_bytes(); let slice_len = packed_pe.len().to_le_bytes(); let mut slice_data = [0u8; 16]; slice_data[0..8].copy_from_slice(&slice_ptr); slice_data[8..16].copy_from_slice(&slice_len); // 确保写入的长度准确,避免越界 packer[offset as usize..offset as usize + 16].copy_from_slice(&slice_data);
3. 固定PE加载地址(禁用ASLR)
如果打包器Stub没有处理重定位,ASLR会导致实际加载地址与你写入的默认ImageBase不符,导致Slice引用无效。在打包器Stub的Cargo.toml中添加编译参数:
[profile.release] rustflags = [ "-C", "link-args=-Wl,--disable-auto-image-base", "-C", "link-args=-subsystem:console" # 确保是控制台程序,方便调试输出 ]
4. 添加调试验证代码
在打包器Stub的main函数中添加调试输出,确认Slice的地址和长度是否正确:
fn main() { unsafe { println!("PE 指针: {:p}, 长度: {}", PE.as_ptr(), PE.len()); let unpacked_data = common::unpack_to_vec(PE); println!("解包后长度: {}", unpacked_data.len()); rspe::reflective_loader(unpacked_data); } }
运行打包后的packed.exe,如果能看到输出且长度符合预期,说明Slice引用已正确设置;如果无输出,检查是否为GUI程序(需调整子系统为console)。
5. 确认节区属性正确性
你设置的节区属性0x40000040是IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA,符合只读数据节区的要求,无需修改。
内容的提问来源于stack exchange,提问作者Xobtah
相关产品推荐
相关产品推荐

