主要內(nèi)容:
frida-inject腳本持久化的方案
App開關(guān)文件目錄以及腳本存儲(chǔ)文件目錄selinux配置
封裝和超級(jí)Root權(quán)限后臺(tái)進(jìn)程通信的java Api接口以及封裝訪問(wèn)腳本相關(guān)目錄文件的Java接口
系統(tǒng)源碼中添加App啟動(dòng)的時(shí)候執(zhí)行frida-inject命令的邏輯代碼
開發(fā)控制App實(shí)現(xiàn)對(duì)第三方App 持久化的配置
1.frida-inject腳本持久化方案原理
方案原理:
在系統(tǒng)源碼App啟動(dòng)入口的地方,找一個(gè)合適的時(shí)機(jī)。將frida-inject組裝執(zhí)行附加的命令通過(guò)Socket連接發(fā)送到超級(jí)Root權(quán)限后臺(tái)進(jìn)程中執(zhí)行,達(dá)到實(shí)現(xiàn)App啟動(dòng)就加載js腳本的功能。App啟動(dòng)入口加載時(shí)機(jī)我們選擇ActivityThread.java中的handleBindApplication方法。以下是該方案的一個(gè)圖示:

2.持久化相關(guān)目錄文件創(chuàng)建及selinux配置
2.1 文件及目錄設(shè)計(jì)
在該方案中,設(shè)計(jì)以下的文件目錄用來(lái)判斷App是否需要開啟frida inject持久化以及加載的js文件路徑。設(shè)計(jì)如下:
#配置某一個(gè)App是否開啟持久化功能,$PKG_NAME表示App的包名 #比如一個(gè)參考:/data/system/xsettings/frdinject/persist/com.android.jnidemo01/persist_fridainject /data/system/xsettings/frdinject/persist/$PKG_NAME/persist_fridainject #配置某一個(gè)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權(quán)限,需要配置系統(tǒng)權(quán)限的App對(duì)以上文件或者目錄讀寫的selinux權(quán)限。普通App需要對(duì)以上文件有讀的權(quán)限,所以需要配置第三方App具有讀以上文件的selinux權(quán)限。
2.2 配置selinux操作
(1).創(chuàng)建文件類型selinux標(biāo)簽
在如下文件中創(chuàng)建文件標(biāo)簽frdinject_data_file,文件列表:
systemsepolicypublicfile.te systemsepolicyprebuiltsapi29.0publicfile.te
在以上文件中添加如下內(nèi)容,需要保證兩個(gè)文件添加的內(nèi)容一致。不然要編譯錯(cuò)誤。
#/data/system/xsettings/ typefrdinject_data_file,file_type,data_file_type,core_data_file_type,mlstrustedobject;
(2).為文件目錄關(guān)聯(lián)frdinject_data_file標(biāo)簽
在如下文件中添加關(guān)聯(lián)/data/system/xsettings目錄selinux標(biāo)簽,文件列表:
systemsepolicyprebuiltsapi29.0privatefile_contexts systemsepolicyprivatefile_contexts
在以上文件中添加如下內(nèi)容,需要保證兩個(gè)文件添加的內(nèi)容一致。不然要編譯錯(cuò)誤。
/data/system/xsettings(/.*)?ufrdinject_data_file:s0
(3).配置App訪問(wèn)frdinject_data_file標(biāo)簽的權(quán)限
這個(gè)地方主要配置兩種App。一種是system權(quán)限的配置端App。第二種是第三方App。
具有系統(tǒng)權(quán)限的配置端App selinux配置如下:
在如下文件中:
systemsepolicyprivatesystem_app.te systemsepolicyprebuiltsapi29.0privatesystem_app.te
添加如下訪問(wèn)權(quán)限,添加之后請(qǐng)保持兩個(gè)文件內(nèi)容一致:
#addforaccessingfrdinject_data_file
allowsystem_appfrdinject_data_file:dir{getattrsetattropenreadwriteremove_namecreateadd_namesearchrmdir};
allowsystem_appfrdinject_data_file:file{getattrsetattropenreadwritecreateunlink};
第三方App配置selinux如下:
在以下文件中添加app訪問(wèn)文件夾的selinux策略。確保相對(duì)應(yīng)的文件內(nèi)容一致。
在以下untrusted_app_all.te文件:
systemsepolicyprivateuntrusted_app_all.te systemsepolicyprebuiltsapi29.0privateuntrusted_app_all.te
添加內(nèi)容如下:
#addforaccessingfrdinject_data_file
allowuntrusted_app_allfrdinject_data_file:dir{getattropenreadsearch};
allowuntrusted_app_allfrdinject_data_file:file{getattropenread};
在以下untrusted_app_27.te文件:
systemsepolicyprivateuntrusted_app_27.te systemsepolicyprebuiltsapi29.0privateuntrusted_app_27.te
在以下文件:
#addforaccessingfrdinject_data_file
allowuntrusted_app_27frdinject_data_file:dir{getattropenreadsearch};
allowuntrusted_app_27frdinject_data_file:file{getattropenread};
在以下untrusted_app_25.te文件:
systemsepolicyprivateuntrusted_app_25.te systemsepolicyprebuiltsapi29.0privateuntrusted_app_25.te
#addforaccessingfrdinject_data_file
allowuntrusted_app_25frdinject_data_file:dir{getattropenreadsearch};
allowuntrusted_app_25frdinject_data_file:file{getattropenread};
在以下untrusted_app.te文件:
systemsepolicyprivateuntrusted_app.te systemsepolicyprebuiltsapi29.0privateuntrusted_app.te
#addforaccessingfrdinject_data_file
allowuntrusted_appfrdinject_data_file:dir{getattropenreadsearch};
allowuntrusted_appfrdinject_data_file:file{getattropenread};
2.3 init.rc中配置開機(jī)的時(shí)候就創(chuàng)建對(duì)應(yīng)的目錄
該持久化實(shí)現(xiàn)中,使用了如下目錄。
/data/system/xsettings/frdinject/persist /data/system/xsettings/frdinject/jscfg
所以可以將該目錄放在init進(jìn)程啟動(dòng)的時(shí)候進(jìn)行創(chuàng)建。由于init進(jìn)程會(huì)解析init.rc文件執(zhí)行配置的命令,所以可以根據(jù)init.rc創(chuàng)建文件夾的規(guī)則加入創(chuàng)建以上兩個(gè)目錄的操作。在systemcore ootdirinit.rc文件中添加內(nèi)容如下:
#/data/system/xsettings/frdinject/persist mkdir/data/system/xsettings0775systemsystem mkdir/data/system/xsettings/frdinject0775systemsystem mkdir/data/system/xsettings/frdinject/persist0775systemsystem mkdir/data/system/xsettings/frdinject/jscfg0775systemsystem
3.系統(tǒng)源碼中相關(guān)Java接口封裝
3.1 封裝和超級(jí)Root權(quán)限通信的MgskSu模塊
在源碼根目錄中創(chuàng)建如下對(duì)應(yīng)的目錄:
frameworksasecorejavaandroidxfrd
在目錄xfrd中將存放MgskSu模塊的接口實(shí)現(xiàn)。具體實(shí)現(xiàn)如下:
packageandroid.xfrd;
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
importjava.net.InetSocketAddress;
importjava.net.Socket;
publicclassMgskSu{
publicstaticStringmagiskSu(Stringcmd)
{
StringretString="";
try{
//創(chuàng)建socket
StringmyCmd="do_cmd|"+cmd;
SocketmSocket=newSocket();
InetSocketAddressinetSocketAddress=newInetSocketAddress("127.0.0.1",11111);
mSocket.connect(inetSocketAddress);
BufferedWriterbufferedWriter=newBufferedWriter(newOutputStreamWriter(mSocket.getOutputStream()));
BufferedReaderbufferedReader=newBufferedReader(newInputStreamReader(mSocket.getInputStream()));
bufferedWriter.write(myCmd+"
");
bufferedWriter.flush();
retString=bufferedReader.readLine();
bufferedReader.close();
bufferedWriter.close();
}catch(Exceptioneeeee)
{
eeeee.printStackTrace();
}
returnretString;
}
}
3.2 封裝針對(duì)App需要持久化判斷和獲取對(duì)應(yīng)js文件路徑的接口
在該方案中通過(guò)對(duì)應(yīng)App的包名組裝文件路徑來(lái)識(shí)別是否存在來(lái)判斷App是否需要啟動(dòng)就加載js文件。在MagiskSu.java同目錄中創(chuàng)建FrdSettings.java模塊文件。核心代碼如下:
packageandroid.xfrd;
importandroid.system.Os;
importjava.io.File;
publicclassFrdSettings{
staticfinalStringTAG=FrdSettings.class.getSimpleName();
privatestaticfinalStringSETTINGS_DIR="/data/system/xsettings/frdinject/persist";
privatestaticfinalStringCONFIG_JS_DIR="/data/system/xsettings/frdinject/jscfg";
publicstaticfinalStringPERSIST_FRIDA_INJECT="persist_fridainject";
publicstaticfinalStringPERSIST_FRIDA_GADGET="persist_fridagadget";
publicstaticfinalStringPERSIST_FRIDA_GUMJS="persist_fridagumjs";
//
publicstaticbooleanisAppJsPathExists(StringpkgName){
Filefile=newFile(CONFIG_JS_DIR+"/"+pkgName+"/config.js");
returnfile.exists();
}
publicstaticStringgetAppJsPath(StringpkgName)
{
Filefile=newFile(CONFIG_JS_DIR+"/"+pkgName+"/config.js");
returnfile.getAbsolutePath();
}
/**********************判斷是否開啟持久化***************************/
//設(shè)置對(duì)應(yīng)的App是否開啟持久化
publicstaticvoidsetEnablePersistFridaInject(StringpkgName,StringmethodType,booleanisEnable){
Filefile=newFile(SETTINGS_DIR);
if(!file.exists()){
file.mkdirs();
try{
Os.chmod(file.getAbsolutePath(),0775);
}catch(Exceptioneeee){
}
}
FilepkgFile=newFile(file,pkgName);
if(!pkgFile.exists()){
pkgFile.mkdirs();
try{
Os.chmod(pkgFile.getAbsolutePath(),0775);
}catch(Exceptioneeee){
eeee.printStackTrace();
}
}
FileenableFile=newFile(pkgFile,methodType);
if(isEnable){
if(!enableFile.exists()){
try{
enableFile.createNewFile();
//MyLog.d(TAG,"createfilesuccess");
Os.chmod(enableFile.getAbsolutePath(),0775);
}catch(Exceptioneeee){
//MyLog.d(TAG,"filecreateerrror:"+enableFile.getAbsolutePath());
eeee.printStackTrace();
}
}else{
//MyLog.d(TAG,"fileexists:"+enableFile.getAbsolutePath());
}
}else{
if(enableFile.exists()){
enableFile.delete();
}
}
}
//判斷app是否打開自動(dòng)注入腳本功能
publicstaticbooleanisEnablePersistFrida(StringpkgName,StringmethodType){
FileenableFile=newFile(SETTINGS_DIR,pkgName+"/"+methodType);
returnenableFile.exists();
}
}
4.源碼中在App啟動(dòng)入口ActivityThread.java中添加加載js邏輯
在之前方案分析中已經(jīng)找到了在frameworksasecorejavaandroidappActivityThread.java中的handleBindApplication方法中加入加載js的邏輯是一個(gè)比較不錯(cuò)的選擇。在handleBindApplication中加入如下關(guān)鍵調(diào)用代碼,實(shí)現(xiàn)App啟動(dòng)的時(shí)候就去加載執(zhí)行js。核心關(guān)鍵代碼如下:
StringcurPkgName=data.appInfo.packageName;
intmypid=Process.myPid();
intmytempUid=Process.myUid();
if(mytempUid>10000)
{
BooleanisB=FrdSettings.isEnablePersistFrida(curPkgName,FrdSettings.PERSIST_FRIDA_INJECT);
Log.d("FridaInject","curPkgNameisEnableFridaInject:"+isB);
if(isB)
{
StringjsPath=FrdSettings.getAppJsPath(curPkgName);
if(jsPath!=null)
{
//這個(gè)地方比較重要,不然App運(yùn)行會(huì)奔潰。
//App中主線程中調(diào)用網(wǎng)絡(luò)socket操作配置
android.os.StrictMode.ThreadPolicypolicy=newandroid.os.StrictMode.ThreadPolicy.Builder().permitAll().build();
android.os.StrictMode.setThreadPolicy(policy);
StringcmdString="myfridainjectarm64-p"+mypid+"-s"+jsPath+"-e";
StringretString=MgskSu.magiskSu(cmdString);
try{
Thread.sleep(50);
}catch(Exceptioneee)
{
}
Log.d("FridaInject","retStringis"+retString);
}else{
Log.d("FridaInject","jsPathisnull");
}
}else{
}
}
5.控制端App開發(fā)實(shí)現(xiàn)對(duì)第三方App持久化配置
控制端App中對(duì)App是否持久化開關(guān)配置以及js路徑配置使用的封裝接口和以上系統(tǒng)源碼中封裝的FrdSettings.java是一樣的封裝。這個(gè)地方就不講接口的封裝了。只說(shuō)一下幾個(gè)關(guān)鍵的地方使用。
配置界面參考:

主要涉及的幾個(gè)接口調(diào)用如下:
(1).打開/關(guān)閉第三方App加載js功能
調(diào)用了封裝的接口:setEnablePersistFridaInject
(2).將選擇的js文件復(fù)制到對(duì)應(yīng)App的配置js目錄
調(diào)用了封裝的接口:copyJsFileToAppJsPath
(3).判斷App當(dāng)前是否配置了加載js功能
調(diào)用了封裝的接口:isEnablePersistFrida
(4).獲取App配置的js文件路徑
置以及js路徑配置使用的封裝接口和以上系統(tǒng)源碼中封裝的FrdSettings.java是一樣的封裝。這個(gè)地方就不講接口的封裝了。只說(shuō)一下幾個(gè)關(guān)鍵的地方使用。
配置界面參考:
[外鏈圖片轉(zhuǎn)存中…(img-L6IhssD7-1667868558625)]
主要涉及的幾個(gè)接口調(diào)用如下:
(1).打開/關(guān)閉第三方App加載js功能
調(diào)用了封裝的接口:setEnablePersistFridaInject
(2).將選擇的js文件復(fù)制到對(duì)應(yīng)App的配置js目錄
調(diào)用了封裝的接口:copyJsFileToAppJsPath
(3).判斷App當(dāng)前是否配置了加載js功能
調(diào)用了封裝的接口:isEnablePersistFrida
(4).獲取App配置的js文件路徑
調(diào)用了封裝接口:getAppJsPath
審核編輯:劉清
-
JAVA
+關(guān)注
關(guān)注
20文章
3001瀏覽量
116426 -
API接口
+關(guān)注
關(guān)注
1文章
114瀏覽量
11247
原文標(biāo)題:基于frida-inject腳本持久化開發(fā)實(shí)戰(zhàn)
文章出處:【微信號(hào):哆啦安全,微信公眾號(hào):哆啦安全】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
Windows/Ubuntu安裝frida和objection
frida-inject工具使用及說(shuō)明 內(nèi)置frida-inject工具到手機(jī)系統(tǒng)
自動(dòng)化測(cè)試腳本開發(fā)技巧
LabVIEW入門與實(shí)戰(zhàn)開發(fā)100例
如何使用Myeclipse進(jìn)行java可視化開發(fā)
數(shù)據(jù)可視化開發(fā)平臺(tái)PageNow上線了
JavaScript模塊化開發(fā)實(shí)驗(yàn)---webpack入門
基于frida-inject腳本持久化開發(fā)實(shí)戰(zhàn)分享
評(píng)論