You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Free Pascal中执行字节数组作为函数触发访问冲突的技术问询

问题分析与解决方案

这种场景完全可行!你触发Access Violation的核心原因是内存页的执行权限限制:你从内存转储得到的字节数组,默认存储在普通的读写内存区域(比如全局数组或栈上),而现代操作系统的DEP(数据执行保护)机制会禁止CPU执行这类非可执行区域的代码,所以你赋值指针没问题,但调用时就会触发异常。

下面分平台给你具体的解决步骤:

Windows平台实现步骤

  • 首先需要用VirtualAlloc分配一块带有执行权限的内存区域,这是关键:
    #include <Windows.h>
    
    // 假设这是你转储得到的函数字节数组(示例为x86架构的int add(int a, int b)函数指令)
    unsigned char calcFuncBytes[] = { 0x55, 0x8B, 0xEC, 0x8B, 0x45, 0x08, 0x03, 0x45, 0x0C, 0x5D, 0xC3 };
    
    int main() {
        size_t funcSize = sizeof(calcFuncBytes);
    
        // 分配可执行内存:MEM_COMMIT | MEM_RESERVE 标记,权限设为PAGE_EXECUTE_READWRITE
        void* execMemory = VirtualAlloc(NULL, funcSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (execMemory == NULL) {
            // 处理内存分配失败,比如打印GetLastError()排查问题
            return 1;
        }
    
  • 把字节数组复制到这块可执行内存中:
    memcpy(execMemory, calcFuncBytes, funcSize);
    
  • 将内存指针转换为对应的函数指针类型,然后就可以正常调用了:
    // 定义函数指针类型,必须和原函数的签名完全匹配
        typedef int(*CalcFunction)(int, int);
        CalcFunction callableCalc = (CalcFunction)execMemory;
    
        // 调用测试,这里应该返回30
        int result = callableCalc(10, 20);
    
  • 使用完毕后记得释放内存:
    VirtualFree(execMemory, 0, MEM_RELEASE);
        return 0;
    }
    

Linux/macOS平台实现步骤

  • 用mmap分配带执行权限的匿名内存:
    #include <sys/mman.h>
    #include <string.h>
    #include <stdio.h>
    
    // 示例为x86_64架构的int add(int a, int b)函数指令
    unsigned char calcFuncBytes[] = { 0x55, 0x48, 0x89, 0xE5, 0x8B, 0x45, 0x10, 0x03, 0x45, 0x08, 0x5D, 0xC3 };
    
    int main() {
        size_t funcSize = sizeof(calcFuncBytes);
    
        // 分配可执行内存:权限设为PROT_READ | PROT_WRITE | PROT_EXEC,使用MAP_PRIVATE | MAP_ANONYMOUS创建匿名映射
        void* execMemory = mmap(NULL, funcSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        if (execMemory == MAP_FAILED) {
            perror("mmap failed");
            return 1;
        }
    
  • 复制字节数组到可执行内存:
    memcpy(execMemory, calcFuncBytes, funcSize);
    
  • 转换指针并调用:
    typedef int(*CalcFunction)(int, int);
        CalcFunction callableCalc = (CalcFunction)execMemory;
    
        // 调用测试,这里应该返回40
        int result = callableCalc(15, 25);
        printf("Result: %d\n", result);
    
  • 释放内存:
    munmap(execMemory, funcSize);
        return 0;
    }
    

额外注意事项

  • 确保你转储的字节数组和当前运行平台的指令集完全匹配:比如原函数是x64的,就不能在x86进程里执行这些字节,否则会触发非法指令异常。
  • 如果你在更严格的安全环境下运行,建议先分配读写内存,写入字节后再修改权限为只读+执行(Windows用VirtualProtect,Linux用mprotect),这样能避免内存被意外篡改,更安全。
  • 因为你的函数是简单计算(无外部调用、无字符串操作),所以不需要处理重定位、导入表这些复杂问题,直接复制执行即可。

内容的提问来源于stack exchange,提问作者GrowingBrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:59:53