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

如何通过路径加载Mach-O头替换dyld_get_image_header返回值?

问题描述

已成功Hook const mach_header* dyld_get_image_header(uint32_t image_index) 函数,当前运行的可执行文件"Fake"在dyld_image_count()返回的镜像列表中索引为1,调用原函数会返回Fake的mach_header指针。现在需要当image_index == 1时,将返回值替换为指定路径下"Original"可执行文件的mach_header指针,伪代码如下:

const mach_header* dyld_get_image_header_hook(uint32_t image_index){
    const mach_header* fake_ret = dyld_get_image_header_org(image_index);
    if(image_index == 1){
        fake_ret = original; // 此处需加载指定路径的Original文件
        return fake_ret;
    }
    return fake_ret;
}

其中dyld_get_image_header_org是原函数指针,需实现加载"Original"并转换为const mach_header*的逻辑。

解决方案

你可以借助macOS动态链接器API完成目标文件加载与mach_header指针获取,具体实现如下:

1. 缓存加载结果(避免重复加载)

声明全局静态变量缓存Original的mach_header指针,防止每次调用Hook函数重复加载文件:

static const mach_header* s_original_mh = NULL;
static const char* s_original_path = "/path/to/Original"; // 替换为你的绝对路径

2. 完整Hook函数实现

在Hook逻辑中,仅当缓存未初始化时执行加载操作,通过dlopen加载目标文件,再用dlinfo直接提取mach_header指针:

#include <dlfcn.h>
#include <mach-o/dyld.h>

static const mach_header* s_original_mh = NULL;
static const char* s_original_path = "/path/to/Original"; // 替换为实际绝对路径

const mach_header* dyld_get_image_header_hook(uint32_t image_index){
    const mach_header* fake_ret = dyld_get_image_header_org(image_index);
    
    if(image_index == 1){
        if (!s_original_mh) {
            // 加载Original可执行文件
            void* handle = dlopen(s_original_path, RTLD_LAZY | RTLD_LOCAL);
            if (handle) {
                // 通过dlinfo获取mach_header指针
                if (dlinfo(handle, RTLD_DI_MH, &s_original_mh) == 0) {
                    // 成功获取后关闭句柄
                    dlclose(handle);
                } else {
                    // 获取失败,关闭句柄并 fallback 到原返回值
                    dlclose(handle);
                    s_original_mh = fake_ret;
                }
            } else {
                // 加载失败,fallback 到原返回值
                s_original_mh = fake_ret;
            }
        }
        fake_ret = s_original_mh;
    }
    return fake_ret;
}

注意事项

  • 必须使用绝对路径加载Original,相对路径可能因进程当前工作目录变化导致加载失败
  • dlopen加载可执行文件时会触发其初始化代码(如__main、构造函数),若无需执行初始化,可考虑用mmap手动映射文件并解析mach-o结构,但实现复杂度更高
  • 需确保Original与Fake的CPU架构一致(如均为arm64或x86_64),否则加载会失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:30:51