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

Frida内存分配使用是否正确?文件替换场景遇权限异常

问题

我需要在运行时给类文本编辑器打补丁:当用户打开任意文件时,自动替换为打开预定义文件/tmp/predefined。我用Frida的JavaScript API拦截所有open()系统调用,判断后替换第一个参数(文件路径)。

脚本patcher.js如下:

function main()
{

Interceptor.attach(Module.getExportByName(null, 'open'), {
    onEnter(args) {
        const originalPath = args[0].readCString();
        if (shouldReplace(originalPath)){
            args[0].writeUtf8String('/tmp/predefined'); // (1)
            //args[0] = Memory.allocUtf8String("/tmp/predefined"); (2)
        }
    },
  });
}

function shouldReplace(path) {
if (!path) return false;
// Do not replace essential system or config files:
if (path.startsWith("/usr/") || path.startsWith("/etc/") || path.startsWith("/lib") || 
    path.startsWith("/var/") || path.startsWith("/proc/") || path.startsWith("/sys/") || 
    path.startsWith("/dev/") || path.startsWith("/run/") || path.startsWith("/home/user/.config/")
||  path.startsWith("/home/user/.cache") || path.startsWith("/home/user/.local") ) {
    return false;
}
// Avoid replacing if it's already the predefined file (prevent infinite loop)
if (path === "/tmp/predefined") {
    return false;
}
// Otherwise, assume it's a user-requested file and should be replaced
return true;
}

main()

测试时使用gnome-text-editor,运行命令:

./frida -l patcher.js -f /usr/bin/gnome-text-editor /tmp/originalFile

启用(1)直接改写args[0]指向的内存时功能正常,能成功打开/tmp/predefined。但启用(2),用Memory.allocUtf8String分配新内存并让args[0]指向它时,出现两个异常:

  1. 编辑器提示Could Not Open File You do not have permissions to open the file,无法打开/tmp/predefined
  2. 终端输出警告:(gnome-text-editor:9036): editor-document-WARNING **: 11:11:33.542: Failed to load file: Error opening file /tmp/originalFile: No such file or directory,但/tmp/originalFile实际存在。

我想知道是不是Memory.allocUtf8String的用法有误?

原因分析与解决方法

问题根源

Memory.allocUtf8String()默认在Frida自身的内存区域分配内存,这块内存对目标进程来说是不可访问的。当你把args[0]指向该区域后,目标进程调用open()时会尝试读取不可访问的地址,导致实际传递给系统调用的路径无效,进而触发权限错误和文件不存在的警告。

而直接用args[0].writeUtf8String()是修改目标进程自己分配的、可正常访问的内存区域,系统调用能正确读取到新路径,因此功能正常。

正确的内存分配方式

要在目标进程的可访问内存中分配空间,需要确保内存属于目标进程的地址空间。可以用Memory.alloc()配合writeUtf8String()来实现:

修改后的onEnter代码片段:

onEnter(args) {
    const originalPath = args[0].readCString();
    if (shouldReplace(originalPath)){
        // 在目标进程的可访问内存中分配足够空间存储路径
        const newPathLen = '/tmp/predefined'.length + 1; // +1 用于字符串结束符
        const newPathPtr = Memory.alloc(newPathLen);
        newPathPtr.writeUtf8String('/tmp/predefined');
        args[0] = newPathPtr;
    }
}

额外说明

  • 也可以用Process.pageSize直接分配一整页内存,避免计算路径长度的麻烦,比如Memory.alloc(Process.pageSize)
  • 所有传递给目标进程函数或系统调用的内存,必须属于目标进程的地址空间,不能用Frida自身的内存区域

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:13:16