主要內容:
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.te systemsepolicyprebuiltsapi29.0publicfile.te
在以上文件中添加如下內容,需要保證兩個文件添加的內容一致。不然要編譯錯誤。
#/data/system/xsettings/ typefrdinject_data_file,file_type,data_file_type,core_data_file_type,mlstrustedobject;
(2).為文件目錄關聯frdinject_data_file標簽
在如下文件中添加關聯/data/system/xsettings目錄selinux標簽,文件列表:
systemsepolicyprebuiltsapi29.0privatefile_contexts systemsepolicyprivatefile_contexts
在以上文件中添加如下內容,需要保證兩個文件添加的內容一致。不然要編譯錯誤。
/data/system/xsettings(/.*)?ufrdinject_data_file:s0
(3).配置App訪問frdinject_data_file標簽的權限
這個地方主要配置兩種App。一種是system權限的配置端App。第二種是第三方App。
具有系統權限的配置端App selinux配置如下:
在如下文件中:
systemsepolicyprivatesystem_app.te systemsepolicyprebuiltsapi29.0privatesystem_app.te
添加如下訪問權限,添加之后請保持兩個文件內容一致:
#addforaccessingfrdinject_data_file allowsystem_appfrdinject_data_file:dir{getattrsetattropenreadwriteremove_namecreateadd_namesearchrmdir}; allowsystem_appfrdinject_data_file:file{getattrsetattropenreadwritecreateunlink};
第三方App配置selinux如下:
在以下文件中添加app訪問文件夾的selinux策略。確保相對應的文件內容一致。
在以下untrusted_app_all.te文件:
systemsepolicyprivateuntrusted_app_all.te systemsepolicyprebuiltsapi29.0privateuntrusted_app_all.te
添加內容如下:
#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中配置開機的時候就創建對應的目錄
該持久化實現中,使用了如下目錄。
/data/system/xsettings/frdinject/persist /data/system/xsettings/frdinject/jscfg
所以可以將該目錄放在init進程啟動的時候進行創建。由于init進程會解析init.rc文件執行配置的命令,所以可以根據init.rc創建文件夾的規則加入創建以上兩個目錄的操作。在systemcore ootdirinit.rc文件中添加內容如下:
#/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.系統源碼中相關Java接口封裝
3.1 封裝和超級Root權限通信的MgskSu模塊
在源碼根目錄中創建如下對應的目錄:
frameworksasecorejavaandroidxfrd
在目錄xfrd中將存放MgskSu模塊的接口實現。具體實現如下:
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{ //創建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 封裝針對App需要持久化判斷和獲取對應js文件路徑的接口
在該方案中通過對應App的包名組裝文件路徑來識別是否存在來判斷App是否需要啟動就加載js文件。在MagiskSu.java同目錄中創建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(); } /**********************判斷是否開啟持久化***************************/ //設置對應的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是否打開自動注入腳本功能 publicstaticbooleanisEnablePersistFrida(StringpkgName,StringmethodType){ FileenableFile=newFile(SETTINGS_DIR,pkgName+"/"+methodType); returnenableFile.exists(); } }
4.源碼中在App啟動入口ActivityThread.java中添加加載js邏輯
在之前方案分析中已經找到了在frameworksasecorejavaandroidappActivityThread.java中的handleBindApplication方法中加入加載js的邏輯是一個比較不錯的選擇。在handleBindApplication中加入如下關鍵調用代碼,實現App啟動的時候就去加載執行js。核心關鍵代碼如下:
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) { //這個地方比較重要,不然App運行會奔潰。 //App中主線程中調用網絡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開發實現對第三方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
審核編輯:劉清
-
JAVA
+關注
關注
19文章
2974瀏覽量
104968 -
API接口
+關注
關注
1文章
84瀏覽量
10478
原文標題:基于frida-inject腳本持久化開發實戰
文章出處:【微信號:哆啦安全,微信公眾號:哆啦安全】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論