Frida—HOOK 学习笔记1
JAVA層HOOK
在開始之前,依舊是熟悉的工具官方文檔。因本人英文水平不高,大佬們可通過官網(https://frida.re/docs/home/)或看雪(https://bbs.pediy.com/thread-222729.htm)自取準確說明文檔觀看。
1.JAVA方法基礎
Java方法是語句的集合,它們在一起執行一個功能。
- 方法是解決一類問題的步驟的有序組合
- 方法包含于類或對象中
- 方法在程序中被創建,在其他地方被引用
在Java中方法有一個的樣子;
修飾符:告訴編譯器如何調用該方法。定義了該方法的訪問類型。
返回值類型:就是功能結果的數據類型。當這個方法沒有返回值的時候,返回值的類型為void;當這個方法有返回值的時候,返回值的類型根據返回的數據來確定*(如果有返回值,必須使用return)**。*
方法名:符合命名規則即可。
參數:實際參數:就是實際參與運算的。形式參數;就是方法定義上的,用于接收實際參數的。
參數類型:就是參數的數據類型
參數名:就是變量名
方法體語句:就是完成功能的代碼。
return*:結束方法的。*
返回值:就是功能的結果,由return帶給調用者。
在知曉基本的Java方法結構后,開始本處的重點之一。
1) 普通方法
定義:簡單的說方法就是完成特定功能的代碼塊。
普通方法分為:有明確返回值的方法和沒有明確返回值的方法。
A.有明確返回值的方法的調用
可以單獨調用、輸出調用、賦值調用。
B.沒有明確返回值的方法調用(void類型方法的調用)
只能單獨使用。
舉個簡單的例子:
public class Fangfa {// 主方法public static void main(String args[]) {System.out.println(add(10,20));}//返回兩個整數相加public static int add(int a , int b){return a + b ;}}通過例子可以發現,普通方法就是我們寫的最常見、最大眾化的。滿足方法基本結構。
2) 構造方法
構造方法是類的一種特殊方法,用來初始化類的一個新的對象,在創建對象(new 運算符)之后自動調用。Java 中的每個類都有一個默認的構造方法,并且可以有一個以上的構造方法。
構造方法需滿足條件:
1、方法名與類名同名。
2、在方法中不能使用return 語句返回即為該方法沒有任何返回值,包括 void。
3、在方法名的前面沒有返回值的類型聲明
通過上述條件可發現,構造方法會在普通的方法結構上發生一些變化,舉個例子:
public class Constructor {// 給Constructor類定義了一個成員變量nameprivate String name;// 無參構造方法,方法名必須跟類名一致,即首字母需要大寫public Constructor() {System.out.println("調用無參數的構造方法。。");}// 帶一個參數的構造方法public Constructor(String name) {// 通過this()調用無參構造方法this();this.name = name;// 構造方法里可以調用普通方法commonMethod();}public void commonMethod() {System.out.println("調用普通方法");}// 寫個主函數測試一下public static void main(String[] args) {// 通過無參構造創建一個Constructor對象Constructor cons1 = new Constructor();cons1.name = "我是通過無參構造器創建的對象";System.out.println(cons1);System.out.println("=====================我是分隔線=====================");// 通過有參構造方法創建另一個對象Constructor cons2 = new Constructor("我是通過有參構造方法創建的對象");System.out.println(cons2);}public String toString() {return this.getClass().getSimpleName() + "[我的名字是:" + name + "]";}}運行結果如下:
3) 重載方法
重載方法(Overloading)的定義:如果有兩個方法的方法名相同,但參數不一致,哪么可以說一個方法是另一個方法的重載。 具體滿足條件包括:
- 方法名相同
- 方法的參數類型,參數個不一樣
- 方法的返回類型可以不相同
- 方法的修飾符可以不相同
- main 方法也可以被重載
舉個例子:
class MyClass {int height;MyClass() {System.out.println("無參數構造函數");height = 4;}MyClass(int i) {System.out.println("房子高度為 " + i + " 米");height = i;}void info() {System.out.println("房子高度為 " + height + " 米");}void info(String s) {System.out.println(s + ": 房子高度為 " + height + " 米");}}public class MainClass {public static void main(String[] args) {MyClass t = new MyClass(3);t.info();t.info("重載方法");//重載構造函數new MyClass();} }程序執行結果如下:
2.Frida安裝
對于安裝這部分,大家可在互聯網自行搜索安裝。個人建議是使用python2的舊版本,因為在burp中有一個brida工具來幫助使用Frida。Brida的使用可參考下述文章(https://blog.csdn.net/weixin_39190897/article/details/102691898),網絡上存在說python3也可使用該工具,不過本人嘗試后未成功。
在安裝Frida時要主要參考最新安裝教程所涉及的Frida及frida-tools的版本,直接使用pip進行安裝存在frida安裝最新版可以成功,但是安裝frida-tools時則會報錯。
3.普通方法HOOK
針對普通方法、構造方法、重載方法可使用APP安裝包:方法hook.app
安裝并啟動APP:
此處插入一個題外話,大佬們是不是看見一個可愛的群號呀,是不是想去搜一下呀。我替大家搜過了,知道了結果也就不打碼了。結果是這個樣子滴:
看到這個結果是不是可以放下手機了???
言歸正傳,發現APP在啟動后彈出3000,點擊普通方法彈出4000。
使用JADX等反編譯工具對APP進行反編譯操作,獲取到源碼。
在安卓源碼中存在文件AndroidManifest.xml,在這個文件內可尋找到中找到app的入口地址。訪問MainActivity,其代碼如下:
通過代碼可看出應用在運行后執行了一個onCreate方法,方法中包含一個方法為getCalc。這部分主要是寫了三個按鍵的事件和監聽,在方法最后一行出現了和按鍵無關的數字1000,2000。這個時候還記得應用運行時的彈出的3000嗎?
本節是使用Frida對普通函數進行hook,在app界面對應為按鈕1(button1),對于按鍵的響應事件被定義在onClick方法里,效果為點擊button1后彈出一個文本。在代碼中的關鍵方法為Utils.getCalc,這也是要hook的關鍵。在查看該方法的代碼:
發現該方法為簡單的加法運算。啟動firda對該函數進行hook。需要編寫一個腳本來進行操作,具體代碼這么寫呢?不要著急,frida官網給出了腳本的模版(https://frida.re/docs/examples/android/)通過本例寫出的腳本,告訴大家每部分是干嘛的。
frida的hook代碼如下:
import frida, sys //導入腳本所需的包jscode = """ //hook主要執行的代碼區域Java.perform(function () {//hook核心代碼包含在Java.perform函數之中。 var util = Java.use('com.xiaojianbang.app.Utils');//此處com.xiaojianbang.app.Utils為將要hook的方法所處的類的路徑。 util.getCalc.implementation = function (a, b) { // getCalc為在獲取類路徑后將要hook方法名。在這里更改類的方法的實現(implementation)console.log("Hook Start..."); send(a);send(b);send("Success!");return this.getCalc(a,b)//以上三行為hook代碼的執行代碼。} }); """ def message(message, data): if message["type"] == 'send': print("[] {0}".format(message['payload'])) else: print(message) process = frida.get_remote_device().attach('com.xiaojianbang.app') //利用Frida包中函數對要hook的app包名創建一個進程 script= process.create_script(jscode) script.on("message", message) script.load() sys.stdin.read()對代碼了解之后可發現只需對標紅處代碼進更改即可。編寫的重點在于執行代碼處。對于代碼標綠處有如圖兩種情況:
代碼正常執行后結果為:
將執行代碼進行如下修改:
執行結果如下:
通過以上執行結果發現傳入的100,300成功的進行了加運算。說明對該函數成功進行了hook。
本節所涉及代碼框架應用于全文,建議大家理解普通方法的hook腳本后繼續向下。后文代碼將以hook處理代碼為主。
4.構造方法HOOK
本節利用上節APP進行構造方法hook,對應功能為button2,點擊后效果如下:
按鍵代碼如下:
查看代碼中關鍵方法Utils.getMoney。
發現getMoney方法內存在一個new的實例化方法Money,查看該方法的代碼。根據最開始對Java方法的基礎學習發現這個方法符合構造方法的特征。
要hook這個函數,依據上節的經驗開始編寫:
正常的寫代碼到這個位置了,但是這時突然想起構造方法名是不是和類名一模一樣的。那就沒有必要在這個地方再寫方法名稱。這個時候拿出了一個固定寫法為$init。將上述代碼改為:
代碼執行結果如下:
出現上述結果說明hook成功了,但是要利用工具對我們輸入的值進行操作,可將代碼改寫為:
執行代碼之后,app的執行結果應為下圖所示,說明hook并成功利用了方法。
5.重載方法HOOK
本節進入重載的hook,事件綁定在button3。其按鍵監聽代碼為:
代碼中關鍵方法為Utils.test。查看其代碼:
發現有兩個方法都叫test,根據掌握的知識,這兩個方法互為重載。對該函數進行hook。根據上面兩節的經驗在進行更改類的實現的時候,會有一個疑惑:兩個方法名字一樣,代碼如何去選擇?這個地方引入一個overload(),該方法()填寫內容為hook方法的參數的類型,空參時該括號內容也為空。例如:overload(“int”)
hook的測試代碼為:
執行結果如下:
通過上述過程,腳本在hook同名方法時,只需在overload()中將參數的類型依次填入。在遇到string類型的參數時,應填寫為:Java.lang.String,因為string是Java提供用來來創建和操作字符串的類。
6. 函數參數類型表示
不同的參數類型都有自己的表示方法
對于基本類型,直接用它在Java中的表示方法就可以了,不用改變,例如:
· int
· short
· char
· byte
· boolean
· float
· double
· long
基本類型數組,用左中括號接上基本類型的縮寫
基本類型縮寫表示表:
| boolean | Z |
| byte | B |
| char | C |
| double | D |
| float | F |
| int | I |
| long | J |
| short | S |
例如:int[]類型,在重載時要寫成[I
任意類,直接寫完整類名即可
例如:java.lang.String
對象數組,用左中括號接上完整類名再接上分號
例如:[java.lang.String;
1) 帶參數的構造函數
修改參數為byte[]類型的構造函數的實現
ClassName.$init.overload('[B').implementation=function(param){//do something}注:ClassName是使用Java.use定義的類;param是可以在函數體中訪問的參數
修改多參數的構造函數的實現
ClassName.$init.overload('[B','int','int').implementation=function(param1,param2,param3){//do something}2) 無參數構造函數
ClassName.$init.overload().implementation=function(){//do something}調用原構造函數
ClassName.$init.overload().implementation=function(){//do somethingthis.$init();//do something}注意:當構造函數(函數)有多種重載形式,比如一個類中有兩個形式的func:void func()和void func(int),要加上overload來對函數進行重載,否則可以省略overload
3) 一般函數
修改函數名為func,參數為byte[]類型的函數的實現
ClassName.func.overload('[B').implementation=function(param){//do something//return ...}4) 無參數的函數
ClassName.func.overload().implementation=function(){//do something}注: 在修改函數實現時,如果原函數有返回值,那么我們在實現時也要返回合適的值
ClassName.func.overload().implementation=function(){//do somethingreturn this.func();}7. 構造對象參數HOOK
本節進入重載的hook,事件綁定在button4。執行效果為:
其按鍵監聽代碼為:
發現關鍵方法test中傳入了一個對象。查看關鍵函數代碼:
對比三個test方法,發現最后一個test的參數為一個對象還是一個重載。
按照重載方法hook的方式,我們可以編寫代碼:
var utils = Java.use('com.xiaojianbang.app.Utils');utils.test.overload().implementation = function (a) 但是因為本次傳入的內容是個人定義的內容。overload方法這里填寫內容這個時候可參考string的傳入。我們將overload內容要求變成傳入方法的全路徑。utils.test.overload('com.xiaojianbang.app.Money').implementation代碼整理后為:
運行結果如下:
這個時候在輸出中文時會出現如下報錯:
解決辦法是:
但是本節的結果是構造對象參數,將隨機輸入的參數利用hook函數進行處理。操作代碼如下;
jscode = """Java.perform(function () {var utils = Java.use('com.xiaojianbang.app.Utils');var money = Java.use('com.xiaojianbang.app.Money');//上述兩行是將hook方法中涉及的方法所在類導入utils.test.overload('com.xiaojianbang.app.Money').implementation = function (a) {send("Hook Start...");send(a.getInfo());//利用hook方法內方式進行輸出,簡單就是將money這個參數值標示變成了avar mon = money.$new(2000,'gangyuan');//因為test內輸入參數所利用的Money為構造函數,在使用時需利用$new進行實例化使用,可當一個通用方式來寫。send(mon.getInfo());return this.test(mon);}});"""執行結果如下,說明我們成功對目標方法進行了hook,并修改了傳入值。
8. 實例
在滲透測試過程中常會遇到數據包加密的情況。如下APP
用戶登陸數據如下:
針對數據包提示信息在源碼中進行搜索。
或者依據數據包提示接口位置進行搜索,在代碼附近找尋加密方式。各位大佬也可以用自己習慣的方式去找尋。
通過搜索關鍵字等方式,是為找到代碼中執行加密的部分:
我們發現傳輸的內容經過RequestUtil.encodeDesMap進行了處理。處理的數據內容為addMap,數據傳輸流程如下:
1.函數接受輸入參數發送,在login方法流程最后調用了requesNetwork方法。
2.requestNetwork方法中para2接受的參數一路傳遞至addRequestMap。
加密流程至加密處理時要加密內容進入到addMap。故獲取encodeDesMap相關信息。
RequestUtil.paraMap相關信息如下:
按上文獲取到加密代碼,目前可確定將要HOOK內容為paraMap:
在查看處理代碼時發現paraMap處理的內容為Map集合,直接HOOK該處內容為Map集合,涉及到字符串的拼接等不便于數據展示。在該方法的代碼中可發現Utils.md5方法,該方法對拼接后的數據進行了處理:
此處HOOK結果如下:
我們對encodeDesMap進行HOOK可獲取到加密后的結果。
9. 工具使用HOOK
這里用到的工具及環境有
BurpSuite,
HTTPDecrypt(https://github.com/lyxhh/lxhToolHTTPDecrypt),
Python3。
注意這個地方環境變成了python3,對應的Frida和frida-tools要重新安裝。
拿到一個新的app之后,總會有一段懵逼🤔尋找hook點的時候。HTTPDecrypt可以幫我較快的獲取到相應的內容。
將想要操作的APP的報名填入空格,點擊confirm。
這個時候可以將目標類進行HOOKS,會講類中存在的方法進行逐一HOOK。
進入HOOKS功能后,可看到上步選擇的類。點擊一下confirm。然后運行APP,進行正常的操作。
? 這時在該頁面會出現對HOOK函數結果的輸出:
? 在結果中尋找自己想要的結果,查看對應的方法。之后就可以自己寫腳本或者使用工具自帶的方法進行加密操作。
? 大佬們后可使用一下該工具與burp的結果使用,比brida較為方便。Brida涉及自己js腳本編寫,使用復雜度比較高,推薦使用該工具。
隱私合規涉及部分方法HOOK
HOOK腳本
//此腳本為基于Frida的安卓權限檢測腳本,HOOK函數因Android版本問題,存在誤差,可自行測試 //打印堆棧信息,需要手動在下面的函數里自己添加調用,也可以自己再寫一個輸出函數。 //function showStacks() { // var Exception = Java.use("java.lang.Exception"); // var ins = Exception.$new("Exception"); // var straces = ins.getStackTrace(); // if (undefined == straces || null == straces) { // return; // } // console.log("============================= Stack strat=======================\r\n"); // console.log(""); // for (var i = 0; i < straces.length; i++) { // var str = " " + straces[i].toString(); // console.log(str\r\n); // } // console.log(""); // console.log("============================= Stack end=======================\r\n");// Exception.$dispose(); //}// APP申請權限 function checkRequestPermission() {try {var ActivityCompat = Java.use("androidx.core.app.ActivityCompat")} catch (e) {console.log(e)return}ActivityCompat.requestPermissions.overload('android.app.Activity', '[Ljava.lang.String;', 'int').implementation = function(p1, p2, p3) {var temp = this.requestPermissions(p1, p2, p3);console.log("APP申請權限", "申請權限為: " + p2);return temp} } // APP獲取IMEI/IMSI function getPhoneState() {try {var TelephonyManager = Java.use("android.telephony.TelephonyManager");} catch (e) {console.log(e)return}// API level 26 獲取單個IMEI的方法TelephonyManager.getDeviceId.overload().implementation = function() {var temp = this.getDeviceId();console.log("獲取IMEI", "獲取的IMEI為: " + temp)return temp;};//API level 26 獲取多個IMEI的方法TelephonyManager.getDeviceId.overload('int').implementation = function(p) {var temp = this.getDeviceId(p);console.log("獲取IMEI", "獲取(" + p + ")的IMEI為: " + temp);return temp;};//API LEVEL26以上的獲取單個IMEI方法TelephonyManager.getImei.overload().implementation = function() {var temp = this.getImei();console.log("獲取IMEI", "獲取的IMEI為: " + temp)return temp;};// API LEVEL26以上的獲取多個IMEI方法TelephonyManager.getImei.overload('int').implementation = function(p) {var temp = this.getImei(p);console.log("獲取IMEI", "獲取(" + p + ")的IMEI為: " + temp);return temp;};//imsi/iccidTelephonyManager.getSimSerialNumber.overload().implementation = function() {var temp = this.getSimSerialNumber();console.log("獲取IMSI/iccid", "獲取IMSI/iccid為(String): " + temp);return temp;};//imsiTelephonyManager.getSubscriberId.overload().implementation = function() {var temp = this.getSubscriberId();console.log("獲取IMSI", "獲取IMSI為(int): " + temp);return temp;}//imsi/iccidTelephonyManager.getSimSerialNumber.overload('int').implementation = function(p) {var temp = this.getSimSerialNumber(p);console.log("獲取IMSI/iccid", "參數為:(" + p + "), 獲取IMSI/iccid為(int): " + temp);return temp;} } // 獲取系統屬性(記錄關鍵的)。意義不大,frida獲取不到。暫時留著 function getSystemProperties() {try {var SystemProperties = Java.use("android.os.SystemProperties");} catch (e) {console.log(e)return}SystemProperties.get.overload('java.lang.String').implementation = function(p1) {var temp = this.get(p1);if (p1 == "ro.serialno") {console.log("獲取設備序列號", "獲取(" + p1 + "),值為:" + temp);}if (p1 == "ro.build.display.id") {console.log("獲取版本號", "獲取(" + p1 + "),值為:" + temp);}//MEIDif (p1 == "ril.cdma.meid") {console.log("獲取MEID", "獲取(" + p1 + "),值為:" + temp);}//手機型號if (p1 == "ro.product.model") {console.log("獲取手機型號", "獲取(" + p1 + "),值為:" + temp);}//手機廠商if (p1 == "ro.product.manufacturer") {console.log("獲取手機廠商", "獲取(" + p1 + "),值為:" + temp);}return temp;}SystemProperties.get.overload('java.lang.String', 'java.lang.String').implementation = function(p1, p2) {var temp = this.get(p1, p2)if (p1 == "ro.serialno") {console.log("獲取設備序列號", "獲取(" + p1 + " 、 " + p2 + "),值為:" + temp);}if (p1 == "ro.build.display.id") {console.log("獲取版本號", "獲取(" + p1 + " 、 " + p2 + "),值為:" + temp);}//MEIDif (p1 == "ril.cdma.meid") {console.log("獲取MEID", "獲取(" + p1 + " 、 " + p2 + "),值為:" + temp);}//手機型號if (p1 == "ro.product.model") {console.log("獲取手機型號", "獲取(" + p1 + " 、 " + p2 + "),值為:" + temp);}//手機廠商if (p1 == "ro.product.manufacturer") {console.log("獲取手機廠商", "獲取(" + p1 + " 、 " + p2 + "),值為:" + temp);}return temp;}SystemProperties.getInt.overload('java.lang.String', 'int').implementation = function(p1, p2) {var temp = this.getInt(p1, p2)if (p1 == "ro.build.version.sdk") {console.log("獲取SDK版本號", "獲取(" + p1 + "),值為:" + temp);}return temp;} } //獲取content敏感信息 function getContentProvider() {try {// 通訊錄內容var ContactsContract = Java.use("android.provider.ContactsContract");var contact_authority = ContactsContract.class.getDeclaredField("AUTHORITY").get('java.lang.Object');} catch (e) {console.log(e)}try {// 日歷內容var CalendarContract = Java.use("android.provider.CalendarContract");var calendar_authority = CalendarContract.class.getDeclaredField("AUTHORITY").get('java.lang.Object');} catch (e) {console.log(e)}try {// 瀏覽器內容var BrowserContract = Java.use("android.provider.BrowserContract");var browser_authority = BrowserContract.class.getDeclaredField("AUTHORITY").get('java.lang.Object');} catch (e) {console.log(e)}try {var ContentResolver = Java.use("android.content.ContentResolver");ContentResolver.query.overload('android.net.Uri', '[Ljava.lang.String;', 'android.os.Bundle', 'android.os.CancellationSignal').implementation = function(p1, p2, p3, p4) {var temp = this.query(p1, p2, p3, p4);if (p1.toString().indexOf(contact_authority) != -1) {console.log("獲取content敏感信息", "獲取手機通信錄內容");} else if (p1.toString().indexOf(calendar_authority) != -1) {console.log("獲取content敏感信息", "獲取日歷內容");} else if (p1.toString().indexOf(browser_authority) != -1) {console.log("獲取content敏感信息", "獲取瀏覽器內容");}return temp;}} catch (e) {console.log(e)return} } // 獲取安卓ID function getAndroidId() {try {var SettingsSecure = Java.use("android.provider.Settings$Secure");} catch (e) {console.log(e)return}SettingsSecure.getString.implementation = function(p1, p2) {if (p2.indexOf("android_id") < 0) {return this.getString(p1, p2);}var temp = this.getString(p1, p2);console.log("獲取Android ID", "參數為:" + p2 + ",獲取到的ID為:" + temp.toString());return temp;} } //獲取其他app信息 function getPackageManager() {try {var PackageManager = Java.use("android.content.pm.PackageManager");PackageManager.getInstalledPackages.overload('int').implementation = function(p1) {var temp = this.getInstalledPackages(p1);console.log("獲取其他app信息", "1獲取的數據為:" + temp);return temp;};PackageManager.getInstalledApplications.overload('int').implementation = function(p1) {var temp = this.getInstalledApplications(p1);console.log("獲取其他app信息", "getInstalledApplications獲取的數據為:" + temp);return temp;};} catch (e) {console.log(e)}try {var ApplicationPackageManager = Java.use("android.app.ApplicationPackageManager");ApplicationPackageManager.getInstalledPackages.overload('int').implementation = function(p1) {var temp = this.getInstalledPackages(p1);console.log("獲取其他app信息", "getInstalledPackages獲取的數據為:" + temp);return temp;};ApplicationPackageManager.getInstalledApplications.overload('int').implementation = function(p1) {var temp = this.getInstalledApplications(p1);console.log("獲取其他app信息", "getInstalledApplications獲取的數據為:" + temp);return temp;};ApplicationPackageManager.queryIntentActivities.implementation = function(p1, p2) {var temp = this.queryIntentActivities(p1, p2);console.log("獲取其他app信息", "參數為:" + p1 + p2 + ",queryIntentActivities獲取的數據為:" + temp);return temp;};ApplicationPackageManager.getApplicationInfo.implementation = function(p1, p2) {var temp = this.getApplicationInfo(p1, p2);var string_to_recv;// 判斷是否為自身應用,是的話不記錄console.log("APP包名是:"+ p1);recv(function(received_json_object) {string_to_recv = received_json_object.my_data;}).wait();if (string_to_recv) {console.log("獲取其他app信息", "getApplicationInfo獲取的數據為:" + temp);}return temp;};} catch (e) {console.log(e)}try {var ActivityManager = Java.use("android.app.ActivityManager");ActivityManager.getRunningAppProcesses.implementation = function() {var temp = this.getRunningAppProcesses();console.log("獲取其他app信息", "獲取了正在運行的App"+temp);return temp;};} catch (e) {console.log(e)} } // 獲取位置信息 function getGSP() {try {var locationManager = Java.use("android.location.LocationManager");} catch (e) {console.log(e)return}locationManager.getLastKnownLocation.overload("java.lang.String").implementation = function(p1) {var temp = this.getLastKnownLocation(p1);console.log("獲取位置信息", "獲取位置信息,參數為:" + p1)return temp;}locationManager.requestLocationUpdates.overload("java.lang.String", "long", "float", "android.location.LocationListener").implementation = function(p1, p2, p3, p4) {var temp = this.requestLocationUpdates(p1, p2, p3, p4);console.log("獲取位置信息", "獲取位置信息");return temp;} } // 調用攝像頭(hook,防止靜默拍照) function getCamera() {try {var Camera = Java.use("android.hardware.Camera");} catch (e) {console.log(e)return}Camera.open.overload("int").implementation = function(p1) {var temp = this.open(p1);console.log("調用攝像頭", "調用攝像頭id:" + p1.toString());return temp;} } //獲取網絡信息 function getNetwork() {try {var WifiInfo = Java.use("android.net.wifi.WifiInfo");//獲取ipWifiInfo.getIpAddress.implementation = function() {var temp = this.getIpAddress();var _ip = new Array();_ip[0] = (temp >>> 24) >>> 0;_ip[1] = ((temp << 8) >>> 24) >>> 0;_ip[2] = (temp << 16) >>> 24;_ip[3] = (temp << 24) >>> 24;var _str = String(_ip[3]) + "." + String(_ip[2]) + "." + String(_ip[1]) + "." + String(_ip[0]);console.log("獲取網絡信息", "獲取IP地址:" + _str);return temp;}//獲取mac地址WifiInfo.getMacAddress.implementation = function() {var temp = this.getMacAddress();console.log("獲取Mac地址", "獲取到的Mac地址: " + temp);return temp;}WifiInfo.getSSID.implementation = function() {var temp = this.getSSID();console.log("獲取wifi SSID", "獲取到的SSID: " + temp);return temp;}WifiInfo.getBSSID.implementation = function() {var temp = this.getBSSID();console.log("獲取wifi BSSID", "獲取到的BSSID: " + temp);return temp;}} catch (e) {console.log(e)}try {var WifiManager = Java.use("android.net.wifi.WifiManager");// 獲取wifi信息WifiManager.getConnectionInfo.implementation = function() {var temp = this.getConnectionInfo();console.log("獲取wifi信息", "獲取wifi信息");return temp;};} catch (e) {console.log(e)}try {var InetAddress = Java.use("java.net.InetAddress");//獲取IPInetAddress.getHostAddress.implementation = function() {var temp = this.getHostAddress();console.log("獲取網絡信息", "獲取IP地址:" + temp.toString());return temp;}} catch (e) {console.log(e)}try {var NetworkInterface = Java.use("java.net.NetworkInterface");//獲取macNetworkInterface.getHardwareAddress.overload().implementation = function() {var temp = this.getHardwareAddress();console.log("獲取Mac地址", "獲取到的Mac地址: " + temp);return temp;}} catch (e) {console.log(e)}try {var NetworkInfo = Java.use("android.net.NetworkInfo");NetworkInfo.getType.implementation = function() {var temp = this.getType();console.log("獲取網絡信息", "獲取網絡類型:" + temp.toString());return temp;}NetworkInfo.getTypeName.implementation = function() {var temp = this.getTypeName();console.log("獲取網絡信息", "獲取網絡類型名稱:" + temp);return temp;}NetworkInfo.getExtraInfo.implementation = function() {var temp = this.getExtraInfo();console.log("獲取網絡信息", "獲取網絡名稱:" + temp);return temp;}NetworkInfo.isAvailable.implementation = function() {var temp = this.isAvailable();console.log("獲取網絡信息", "獲取網絡是否可用:" + temp.toString());return temp;}NetworkInfo.isConnected.implementation = function() {var temp = this.isConnected();console.log("獲取網絡信息", "獲取網絡是否連接:" + temp.toString());return temp;}} catch (e) {console.log(e)} } //獲取藍牙設備信息 function getBluetooth() {try {var BluetoothDevice = Java.use("android.bluetooth.BluetoothDevice");//獲取藍牙設備名稱BluetoothDevice.getName.overload().implementation = function() {var temp = this.getName();console.log("獲取藍牙信息", "獲取到的藍牙設備名稱: " + temp)return temp;}//獲取藍牙設備macBluetoothDevice.getAddress.implementation = function() {var temp = this.getAddress();console.log("獲取藍牙信息", "獲取到的藍牙設備mac: " + temp)return temp;}} catch (e) {console.log(e)}try {var BluetoothAdapter = Java.use("android.bluetooth.BluetoothAdapter");//獲取藍牙設備名稱BluetoothAdapter.getName.implementation = function() {var temp = this.getName();console.log("獲取藍牙信息", "獲取到的藍牙設備名稱: " + temp)return temp;};} catch (e) {console.log(e)} } //獲取基站信息 function getCidorLac() {try {// 電信卡cid lacvar CdmaCellLocation = Java.use("android.telephony.cdma.CdmaCellLocation");CdmaCellLocation.getBaseStationId.implementation = function() {var temp = this.getBaseStationId();console.log("獲取基站信息", "獲取到的cid: " + temp);return temp}CdmaCellLocation.getNetworkId.implementation = function() {var temp = this.getNetworkId();console.log("獲取基站信息", "獲取到的lac: " + temp);return temp}} catch (e) {console.log(e)}try {// 移動 聯通卡 cid/lacvar GsmCellLocation = Java.use("android.telephony.gsm.GsmCellLocation");GsmCellLocation.getCid.implementation = function() {var temp = this.getCid();console.log("獲取基站信息", "獲取到的cid: " + temp);return temp}GsmCellLocation.getLac.implementation = function() {var temp = this.getLac();console.log("獲取基站信息", "獲取到的lac: " + temp);return temp}} catch (e) {console.log(e)} }Java.perform(function() {console.log("合規檢測敏感接口開始監控...");checkRequestPermission();getPhoneState();getContentProvider();getAndroidId();getPackageManager();getGSP();getCamera();getNetwork();getBluetooth();getCidorLac();//getSystemProperties(); })腳本執行結果
不足
學習環境為Android 8.0版本,因后期安卓版本更新帶來的安全特性,使得腳本在高版本下使用效果不是很理想。
總結
以上是生活随笔為你收集整理的Frida—HOOK 学习笔记1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑死机的原因
- 下一篇: 自动驾驶基础-AEB