在内存中已 Load 的程序如何快速找到其具有执行权限的段

方法一:利用操作系统 API

这是最常用、最稳定的方法。Windows 提供了强大的内存查询 API,可以快速遍历和检查一个进程的内存空间

  1. VirtualQueryEx 函数: 这是最核心的 API。通过循环调用 VirtualQueryEx,你可以遍历整个进程的虚拟地址空间。这个函数会填充一个 MEMORY_BASIC_INFORMATION 结构体,其中包含了每个内存页面的信息,例如:
    • BaseAddress:内存区域的起始地址
    • RegionSize:内存区域的大小
    • State:内存区域的状态(如已提交 MEM_COMMIT
    • Protect:最重要的字段,描述内存区域的保护权限
  2. 检查 Protect 字段: Protect 字段是一个位掩码,你需要检查它是否包含代表可执行的标志。常见的可执行权限标志有:
    • PAGE_EXECUTE
    • PAGE_EXECUTE_READ
    • PAGE_EXECUTE_READWRITE
    • PAGE_EXECUTE_WRITECOPY

示例代码(伪C++):

#include <windows.h>
#include <iostream>

void FindExecutableRegions(HANDLE hProcess) {
    MEMORY_BASIC_INFORMATION mbi;
    LPVOID pBaseAddress = nullptr;

    while (VirtualQueryEx(hProcess, pBaseAddress, &mbi, sizeof(mbi)) == sizeof(mbi)) {
        // 检查内存状态,确保它已提交并有可执行权限
        if (mbi.State == MEM_COMMIT && 
            (mbi.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY))) {

            // 找到了一个可执行的区域
            std::cout << "Executable region found at: " << std::hex << mbi.BaseAddress 
                      << ", Size: " << mbi.RegionSize << " bytes" << std::endl;
        }

        // 移动到下一个内存区域
        pBaseAddress = (LPVOID)((DWORD_PTR)mbi.BaseAddress + mbi.RegionSize);
    }
}

int main() {
    // 假设你已经获取了目标进程的句柄
    // HANDLE hTargetProcess = OpenProcess(...);
    // FindExecutableRegions(hTargetProcess);
    return 0;
}

方法二:利用 PEB(进程环境块)和 PE 结构

对于已加载的 PE 文件,你可以直接解析其在内存中的结构来找到可执行段。这通常比遍历所有内存区域更快,但只适用于目标是主模块或已知的 DLL

  1. 定位 PEB:
    • 32 位:通过 FS:[0x30] 寄存器获取
    • 64 位:通过 GS:[0x60] 寄存器获取
  2. 获取 ImageBase: 从 PEB 中找到 ImageBase 字段,它存储了主模块在内存中的基址
  3. 解析 PE 头部:
    • ImageBase 开始,找到 e_lfanew 字段,它指向 NT 头部(NT Header)
    • 在 NT 头部中,找到可选头部(Optional Header)
    • 在可选头部中,找到节表(Section Table)的偏移
  4. 遍历节表:
    • 节表是一个 IMAGE_SECTION_HEADER 结构体数组
    • 遍历这个数组,检查每个节的特征(Characteristics)字段
    • 寻找 IMAGE_SCN_MEM_EXECUTE 标志。如果这个标志被设置,那么这个节就是可执行的
  5. 计算地址: 找到可执行的节后,其在内存中的实际地址是 ImageBase + VirtualAddress

方法三:利用调试器或反汇编器

如果你在使用调试器(如 x64dbg 或 IDA Pro)或反汇编器(如 Ghidra),这个过程会变得非常直观

  • x64dbg:
    • 打开内存视图(Memory Map),通常是快捷键 Alt+M
    • 在这里,你会看到所有已加载的模块和内存区域的列表
    • 列表会清楚地显示每个区域的权限(RWX),你可以直接找到所有带有 X 标志的区域
  • IDA Pro / Ghidra:
    • 这些工具会自动解析 PE 文件并显示其所有节
    • 你可以进入“段”(Segments)或“内存区域”(Memory Regions)视图
    • 视图中会明确标记每个段的权限,通常.text 段会显示为 EXECUTE 权限
方法 优点 缺点 适用场景
API调用 最通用、最稳定。能找到所有可执行内存区域,包括非PE结构(如JIT编译的代码) 需要编写代码。性能相对较低,需要遍历整个虚拟内存空间 动态分析、恶意软件分析、注入器等
PE结构解析 速度快,精确。能快速定位.text段和其它可执行的PE节 只能用于已加载的PE文件。如果程序有自解压或自修改行为,可能会失效 静态分析,当你知道目标是合法的PE文件时
调试器/反汇编器 最直观、最简单。提供可视化的界面,无需编写代码 依赖于外部工具。无法自动化(除非通过脚本) 交互式调试、快速逆向工程
Copyright © 版权信息 all right reserved,powered by Gitbook该文件修订时间: 2025-09-25 03:13:05

results matching ""

    No results matching ""