手动实现Windows Dll加载与内存数据修复

手动实现Windows Dll加载与内存数据修复

  1. 加载dll文件到内存中 (std.heap.GeneralPurposeAllocator)

  2. 解析Dos头和Nt头, 获取 ntHeaders.OptionalHeader.SizeOfImage 大小, 并分配内存 (std.heap.page_allocator)

  3. 复制PE头 (Dos头 + Nt头), 大小 ntHeaders.OptionalHeader.SizeOfHeaders

  4. 复制节表到对应内存中, 并配置对应内存属性

  5. 处理基址重定位表

  6. 处理导入表

  7. 调用Dll入口函数 (DllMain)

  8. 返回模块基地址

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加载与内存数据修复/
作者
simonkimi
发布于
2026年3月5日
许可协议