如何在Frida注入的JavaScript脚本中执行cp等控制台命令
Frida 注入脚本内执行cp等系统命令的实现
核心前提
代码运行在目标应用的进程上下文,执行前先确认:
- 目标应用对源文件、目标路径有读写权限
- 目标应用有执行shell命令的权限,Android高版本的SELinux规则、存储权限限制会直接拦截命令执行,初期测试建议先把目标路径设为应用私有缓存目录
/data/data/对应应用包名/cache/
方案1:直接调用libc的system接口执行命令(最稳定,兼容所有Frida版本)
不要在回调里重复查找函数指针,提前初始化NativeFunction,示例代码如下:
// 提前加载libc的system函数,Android平台libc库名为libc.so const systemFunc = new NativeFunction( Module.findExportByName("libc.so", "system"), 'int', ['pointer'] ); const createPtr = Module.findExportByName(null, 'create'); Interceptor.replace(createPtr, new NativeCallback(function (a) { // 注意:以下逻辑默认参数a是const char*类型的源文件路径指针 // 如果a是文件描述符/内存指针,不能直接拼cp命令,需要先处理成文件路径再操作 const sourcePath = a.readCString(); const targetPath = "/out/path"; // 拼接命令,路径加引号规避空格、特殊字符导致的命令解析错误 const cmdStr = `cp "${sourcePath}" "${targetPath}"`; // 分配内存转成C风格字符串传入system const cmdCStr = Memory.allocUtf8String(cmdStr); const exitCode = systemFunc(cmdCStr); if (exitCode !== 0) { console.log(`cp执行失败,退出码:${exitCode},请检查权限、路径是否存在`); } return 1; }, 'int', ['pointer']));
方案2:使用Frida内置API执行(写法更简洁,Frida 14.0+版本支持)
不需要手动找libc导出函数,直接用Frida封装的Process.popen接口:
Interceptor.replace(createPtr, new NativeCallback(function (a) { const sourcePath = a.readCString(); const targetPath = "/out/path"; const cmd = `cp "${sourcePath}" "${targetPath}"`; // 执行命令,wait()等待执行完成返回退出码 const exitCode = Process.popen(`sh -c "${cmd}"`).wait(); if (exitCode !== 0) console.log(`cp执行失败,退出码:${exitCode}`); return 1; }, 'int', ['pointer']));
常见踩坑
- 如果参数
a不是文件路径指针,是内存中的文件内容、或者已打开的文件描述符,不要硬套cp命令,直接调用libc的open/read/write/close接口实现内存/FD到目标文件的写入,比走shell兼容性好很多。 - 不要在Interceptor的回调里执行大文件复制这类耗时操作,会阻塞原线程触发目标应用ANR,大文件操作建议放到独立线程执行,不要阻塞hook点的原执行流程。
- 部分定制ROM会通过SELinux拦截普通应用执行shell命令、访问公共存储路径,这种场景下调shell命令会返回非0退出码,优先用Native文件API实现复制逻辑。
- 拼接shell命令时记得给路径加引号,避免路径带空格、特殊字符导致命令解析错误。
内容的提问来源于stack exchange,提问作者Nederealm
相关产品推荐
相关产品推荐

