基于frida-inject脚本持久化开发实战分享

主要内容:
frida-inject脚本持久化的方案
app开关文件目录以及脚本存储文件目录selinux配置
封装和超级root权限后台进程通信的java api接口以及封装访问脚本相关目录文件的java接口
系统源码中添加app启动的时候执行frida-inject命令的逻辑代码
开发控制app实现对第三方app 持久化的配置
1.frida-inject脚本持久化方案原理
方案原理:
在系统源码app启动入口的地方,找一个合适的时机。将frida-inject组装执行附加的命令通过socket连接发送到超级root权限后台进程中执行,达到实现app启动就加载js脚本的功能。app启动入口加载时机我们选择activitythread.java中的handlebindapplication方法。以下是该方案的一个图示:
2.持久化相关目录文件创建及selinux配置
2.1 文件及目录设计
在该方案中,设计以下的文件目录用来判断app是否需要开启frida inject持久化以及加载的js文件路径。设计如下:
# 配置某一个app是否开启持久化功能,$pkg_name表示app的包名#比如一个参考:/data/system/xsettings/frdinject/persist/com.android.jnidemo01/persist_fridainject/data/system/xsettings/frdinject/persist/$pkg_name/persist_fridainject#配置某一个app加载的js文件路径,$pkg_name表示app的包名# /data/system/xsettings/frdinject/jscfg/com.android.jnidemo01/config.js/data/system/xsettings/frdinject/jscfg/$pkg_name/config.js  
在涉及以上的文件或者目录中,管控端app具有system权限,需要配置系统权限的app对以上文件或者目录读写的selinux权限。普通app需要对以上文件有读的权限,所以需要配置第三方app具有读以上文件的selinux权限。
2.2  配置selinux操作
(1).创建文件类型selinux标签
在如下文件中创建文件标签frdinject_data_file,文件列表:
systemsepolicypublicfile.tesystemsepolicyprebuiltsapi29.0publicfile.te  
在以上文件中添加如下内容,需要保证两个文件添加的内容一致。不然要编译错误。
# /data/system/xsettings/type frdinject_data_file, file_type, data_file_type, core_data_file_type,mlstrustedobject;  
(2).为文件目录关联frdinject_data_file标签
在如下文件中添加关联/data/system/xsettings目录selinux标签,文件列表:
systemsepolicyprebuiltsapi29.0privatefile_contextssystemsepolicyprivatefile_contexts  
在以上文件中添加如下内容,需要保证两个文件添加的内容一致。不然要编译错误。
/data/system/xsettings(/.*)?    ufrdinject_data_file:s0  
(3).配置app访问frdinject_data_file标签的权限
这个地方主要配置两种app。一种是system权限的配置端app。第二种是第三方app。
具有系统权限的配置端app selinux配置如下:
在如下文件中:
systemsepolicyprivatesystem_app.tesystemsepolicyprebuiltsapi29.0privatesystem_app.te  
添加如下访问权限,添加之后请保持两个文件内容一致:
# add for accessing frdinject_data_fileallow system_app  frdinject_data_file:dir  { getattr setattr open read write remove_name create add_name search rmdir };allow system_app  frdinject_data_file:file { getattr setattr open read write  create  unlink };  
第三方app配置selinux如下:
在以下文件中添加app访问文件夹的selinux策略。确保相对应的文件内容一致。
在以下untrusted_app_all.te文件:
systemsepolicyprivateuntrusted_app_all.tesystemsepolicyprebuiltsapi29.0privateuntrusted_app_all.te  
添加内容如下:
# add for accessing frdinject_data_fileallow untrusted_app_all  frdinject_data_file:dir  { getattr  open read  search };allow untrusted_app_all  frdinject_data_file:file { getattr  open read };  
在以下untrusted_app_27.te文件:
systemsepolicyprivateuntrusted_app_27.tesystemsepolicyprebuiltsapi29.0privateuntrusted_app_27.te  
在以下文件:
# add for accessing frdinject_data_fileallow untrusted_app_27  frdinject_data_file:dir  { getattr  open read  search };allow untrusted_app_27  frdinject_data_file:file { getattr  open read };  
在以下untrusted_app_25.te文件:
systemsepolicyprivateuntrusted_app_25.tesystemsepolicyprebuiltsapi29.0privateuntrusted_app_25.te# add for accessing frdinject_data_fileallow untrusted_app_25  frdinject_data_file:dir  { getattr  open read  search };allow untrusted_app_25  frdinject_data_file:file { getattr  open read };  
在以下untrusted_app.te文件:
systemsepolicyprivateuntrusted_app.tesystemsepolicyprebuiltsapi29.0privateuntrusted_app.te# add for accessing frdinject_data_fileallow untrusted_app  frdinject_data_file:dir  { getattr  open read  search };allow untrusted_app  frdinject_data_file:file { getattr  open read };  
2.3  init.rc中配置开机的时候就创建对应的目录
该持久化实现中,使用了如下目录。
/data/system/xsettings/frdinject/persist/data/system/xsettings/frdinject/jscfg  
所以可以将该目录放在init进程启动的时候进行创建。由于init进程会解析init.rc文件执行配置的命令,所以可以根据init.rc创建文件夹的规则加入创建以上两个目录的操作。在systemcore ootdirinit.rc文件中添加内容如下:
# /data/system/xsettings/frdinject/persistmkdir /data/system/xsettings 0775 system systemmkdir /data/system/xsettings/frdinject 0775 system systemmkdir /data/system/xsettings/frdinject/persist 0775 system systemmkdir /data/system/xsettings/frdinject/jscfg 0775 system system  
3.系统源码中相关java接口封装
3.1 封装和超级root权限通信的mgsksu模块
在源码根目录中创建如下对应的目录:
frameworksasecorejavaandroidxfrd  
在目录xfrd中将存放mgsksu模块的接口实现。具体实现如下:
package android.xfrd;import java.io.bufferedreader;import java.io.bufferedwriter;import java.io.inputstreamreader;import java.io.outputstreamwriter;import java.net.inetsocketaddress;import java.net.socket;public class mgsksu {    public static  string  magisksu(string cmd)    {        string retstring=;        try {            //创建socket            string mycmd=do_cmd|+cmd;            socket msocket = new socket();            inetsocketaddress inetsocketaddress=new inetsocketaddress(127.0.0.1,11111);            msocket.connect(inetsocketaddress);            bufferedwriter bufferedwriter=new bufferedwriter(new outputstreamwriter(msocket.getoutputstream()));            bufferedreader bufferedreader=new bufferedreader(new inputstreamreader(msocket.getinputstream()));            bufferedwriter.write(mycmd+);            bufferedwriter.flush();            retstring=bufferedreader.readline();            bufferedreader.close();            bufferedwriter.close();        }catch (exception eeeee)        {            eeeee.printstacktrace();        }        return  retstring;    }}  
3.2 封装针对app需要持久化判断和获取对应js文件路径的接口
在该方案中通过对应app的包名组装文件路径来识别是否存在来判断app是否需要启动就加载js文件。在magisksu.java同目录中创建frdsettings.java模块文件。核心代码如下:
package android.xfrd;import android.system.os;import java.io.file;public class frdsettings {    static final string tag=frdsettings.class.getsimplename();    private static final string settings_dir=/data/system/xsettings/frdinject/persist;    private  static final string config_js_dir=/data/system/xsettings/frdinject/jscfg;    public static  final string persist_frida_inject=persist_fridainject;    public static final  string persist_frida_gadget=persist_fridagadget;    public static  final string persist_frida_gumjs=persist_fridagumjs;    //    public static boolean  isappjspathexists(string pkgname){           file file=new file(config_js_dir+/+pkgname+/config.js);           return file.exists();       }    public static  string  getappjspath(string pkgname)       {           file file=new file(config_js_dir+/+pkgname+/config.js);           return file.getabsolutepath();    }     /**********************判断是否开启持久化***************************/    //设置对应的app是否开启持久化    public static void setenablepersistfridainject(string pkgname,string methodtype, boolean isenable) {        file file = new file(settings_dir);        if (!file.exists()) {            file.mkdirs();            try {                os.chmod(file.getabsolutepath(), 0775);            } catch (exception eeee) {            }        }        file pkgfile = new file(file, pkgname);        if (!pkgfile.exists()) {            pkgfile.mkdirs();            try {                os.chmod(pkgfile.getabsolutepath(), 0775);            } catch (exception eeee) {                eeee.printstacktrace();            }        }        file enablefile = new file(pkgfile, methodtype);        if (isenable) {            if (!enablefile.exists()) {                try {                    enablefile.createnewfile();                    //mylog.d(tag, create file success);                    os.chmod(enablefile.getabsolutepath(), 0775);                } catch (exception eeee) {                    //mylog.d(tag, file create errror: + enablefile.getabsolutepath());                    eeee.printstacktrace();                }            } else {                //mylog.d(tag, file exists: + enablefile.getabsolutepath());            }        } else {            if (enablefile.exists()) {                enablefile.delete();            }        }    }    //判断app是否打开自动注入脚本功能    public static boolean isenablepersistfrida(string pkgname,string methodtype) {        file enablefile = new file(settings_dir, pkgname + /+methodtype);        return enablefile.exists();    }}  
4.源码中在app启动入口activitythread.java中添加加载js逻辑
在之前方案分析中已经找到了在frameworksasecorejavaandroidappactivitythread.java中的handlebindapplication方法中加入加载js的逻辑是一个比较不错的选择。在handlebindapplication中加入如下关键调用代码,实现app启动的时候就去加载执行js。核心关键代码如下:
string curpkgname = data.appinfo.packagename;        int mypid=process.mypid();        int mytempuid=process.myuid();        if(mytempuid>10000)        {           boolean isb=frdsettings.isenablepersistfrida(curpkgname,frdsettings.persist_frida_inject);           log.d(fridainject,curpkgname  isenablefridainject:+isb);           if(isb)           {              string  jspath=frdsettings.getappjspath(curpkgname);              if(jspath!=null)              {                  //这个地方比较重要,不然app运行会奔溃。                  //app中主线程中调用网络socket操作配置                  android.os.strictmode.threadpolicy policy = new android.os.strictmode.threadpolicy.builder().permitall().build();                  android.os.strictmode.setthreadpolicy(policy);                  string  cmdstring=myfridainjectarm64  -p +mypid+  -s +jspath+  -e;                  string retstring=mgsksu.magisksu(cmdstring);                  try{                     thread.sleep(50);                  }catch(exception eee)                  {                  }                  log.d(fridainject,retstring is +retstring);              }else{                  log.d(fridainject,jspath is null);              }          }else{          }        }  
5.控制端app开发实现对第三方app持久化配置
控制端app中对app是否持久化开关配置以及js路径配置使用的封装接口和以上系统源码中封装的frdsettings.java是一样的封装。这个地方就不讲接口的封装了。只说一下几个关键的地方使用。
配置界面参考:
主要涉及的几个接口调用如下:
(1).打开/关闭第三方app加载js功能
调用了封装的接口:setenablepersistfridainject
(2).将选择的js文件复制到对应app的配置js目录
调用了封装的接口:copyjsfiletoappjspath
(3).判断app当前是否配置了加载js功能
调用了封装的接口:isenablepersistfrida
(4).获取app配置的js文件路径
置以及js路径配置使用的封装接口和以上系统源码中封装的frdsettings.java是一样的封装。这个地方就不讲接口的封装了。只说一下几个关键的地方使用。
配置界面参考:
[外链图片转存中…(img-l6ihssd7-1667868558625)]
主要涉及的几个接口调用如下:
(1).打开/关闭第三方app加载js功能
调用了封装的接口:setenablepersistfridainject
(2).将选择的js文件复制到对应app的配置js目录
调用了封装的接口:copyjsfiletoappjspath
(3).判断app当前是否配置了加载js功能
调用了封装的接口:isenablepersistfrida
(4).获取app配置的js文件路径
调用了封装接口:getappjspath


传感器超详细分类大汇总
旷视科技产品总经理对手机端的几点思考
OPPO不止定制IMX766,IMX789正在测试中
oracle创建表空间的sql语句
公网访问虹科工业树莓派的快捷工具--Teamviewer
基于frida-inject脚本持久化开发实战分享
苹果或先推出支持6GHz以下频段的5G iPhone
PathWave制造业分析软体开启工业4.0数字转型之旅
忆阻器,你了解吗?全球首颗清华忆阻器存算一体芯片究竟是个啥?
大小电容并联做电源滤波原因
虹科分享|终端安全防护|网络安全术语列表(二)
折叠屏是真的准备好了吗?可折叠AMOLED屏其实并没成熟
云计算会带来哪些变化 云计算有哪些应用
华为平板M5 10.8英寸与iPad争雌雄
汽车制动系统组成和原理
索尼发布两款旗舰OLED电视机,搭载新一代图像处理芯片,重新定义全新“画谛系列”
AIGC技术的采用是是否代表人工智能创意生产时代已来临?
大批量插入数据,却不会优化怎么办
强大蒸水洗,华帝飓拢吸油烟机常用常新
印制电路板之前需要做什么准备