手动实现Windows Dll加载与内存数据修复
手动实现Windows Dll加载与内存数据修复
加载dll文件到内存中 (std.heap.GeneralPurposeAllocator)
解析Dos头和Nt头, 获取
ntHeaders.OptionalHeader.SizeOfImage大小, 并分配内存 (std.heap.page_allocator)复制PE头 (Dos头 + Nt头), 大小
ntHeaders.OptionalHeader.SizeOfHeaders复制节表到对应内存中, 并配置对应内存属性
处理基址重定位表
处理导入表
调用Dll入口函数 (DllMain)
返回模块基地址
1. 复制PE头和节表数据到指定内存
// 复制dos头与nt头
const headerSize = ntHeaders.OptionalHeader.SizeOfHeaders;
@memcpy(peMemory[0..headerSize], peFile[0..headerSize]);
// 复制节区数据
const sectionHeaders: [*]const windows.IMAGE_SECTION_HEADER = @ptrCast(@alignCast(peFile.ptr + ntHeadersOffset + @sizeOf(windows.IMAGE_NT_HEADERS)));
const sectionHeadersSlice: []const windows.IMAGE_SECTION_HEADER = @ptrCast(sectionHeaders[0..ntHeaders.FileHeader.NumberOfSections]);
for (sectionHeadersSlice) |section| {
const fileOffset = section.PointerToRawData;
const memoryOffset = section.VirtualAddress;
const dataSize = section.SizeOfRawData;
const memSize = section.Misc.VirtualSize;
const characteristics = section.Characteristics;
// 拷贝节数据到内存
if (characteristics & (windows.IMAGE_SCN_CNT_CODE | windows.IMAGE_SCN_CNT_INITIALIZED_DATA) != 0) {
@memcpy(peMemory[memoryOffset..(memoryOffset + dataSize)], peFile[fileOffset..(fileOffset + dataSize)]);
if (memSize > dataSize) {
@memset(peMemory[memoryOffset + dataSize .. (memoryOffset + memSize)], 0);
}
} else if (characteristics & windows.IMAGE_SCN_CNT_UNINITIALIZED_DATA != 0) {
@memset(peMemory[memoryOffset..(memoryOffset + memSize)], 0);
} else {
continue;
}
// 设置页保护
const protect = getPageProtectFlags(characteristics);
const result = windows.VirtualProtect(peMemory.ptr + memoryOffset, memSize, protect, null)
if (result != windows.TRUE) {
return LoadDllError.VirtualProtectFailed;
}
}2. 配置页保护
fn getPageProtectFlags(characteristics: windows.DWORD) windows.DWORD {
const exec = characteristics & windows.IMAGE_SCN_MEM_EXECUTE != 0;
const read = characteristics & windows.IMAGE_SCN_MEM_READ != 0;
const write = characteristics & windows.IMAGE_SCN_MEM_WRITE != 0;
var flags: u3 = 0;
if (exec) flags |= 0b100;
if (read) flags |= 0b010;
if (write) flags |= 0b001;
var protect: windows.DWORD = switch (flags) {
0b111 => windows.PAGE_EXECUTE_READWRITE,
0b110 => windows.PAGE_EXECUTE_READ,
0b101 => windows.PAGE_EXECUTE_WRITECOPY,
0b100 => windows.PAGE_EXECUTE,
0b011 => windows.PAGE_READWRITE,
0b010 => windows.PAGE_READONLY,
0b001 => windows.PAGE_WRITECOPY,
0b000 => windows.PAGE_NOACCESS,
};
if (characteristics & windows.IMAGE_SCN_MEM_NOT_CACHED != 0) {
protect |= windows.PAGE_NOCACHE;
}
return protect;
}手动实现Windows Dll加载与内存数据修复
https://simonkimi.githubio.io/2026/03/05/手动实现Windows-Dll加载与内存数据修复/