一、Frida简介
网站建设哪家好,找创新互联!专注于网页设计、网站建设、微信开发、成都小程序开发、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了黄冈免费建站欢迎大家使用!
1. 基础介绍
Frida是适用于开发人员、逆向工程师和安全研究人员的轻量级Hook工具,它允许将JavaScript代码或库注入Windows、macOS、GNU / Linux、iOS、Android和QNX上的本机应用程序。此外, Frida还提供了一些基于Frida API构建的简单工具。
Frida的四大特点:
Frida访问地址:https://github.com/frida/frida。
2. 与其他Hook工具的对比
(1) Xposed的优缺点
(2) Frida的优缺点
(3) SubstrateCydia的优缺点
以上3个工具可以说是现在用得最多的hook工具了,总结一句话就是,写Java层hook还是Xposed方便,写Native层hook适合用SubstrateCydia,而对于处在开发阶段的破解者来说,则还是Frida最靠谱。
二、Frida Hook示例
1. 连接Android设备
(1)需要一台已经root的Android设备(可以使用Android模拟器),支持4.2~6.0版本。
(2)需要使用来自Android SDK中的adb工具连接Android设备。
(3)在https://github.com/frida/frida/releases中下载相应的frida-server应用,示例使用夜神Android模拟器4.4版本,下载的frida服务端是frida-server-12.2.16-android-x86.xz。
(4)启动夜神Android模拟器4.4版本,运行adb devices命令,即可成功连接Android设备,如图2.1所示。
图2.1连接 Android 设备
(5)运行如下命令,将frida-server复制到Android设备上,提升权限并运行。
- $ adb push frida-server /data/local/tmp/
- $ adb shell "chmod 777 /data/local/tmp/frida-server"
- $ adb shell "/data/local/tmp/frida-server &"
(6)运行adb shell ps命令,查看frida-server已成功运行,如图2.2所示。
图2.2 Frida-Server 成功运行
(7)运行adb shell netstat命令,检查frida-server监听端口,默认为27042,如图2.3所示。
图2.3 端口监听成功
(8)运行adb forward tcp:27042 tcp:27042命令,把Android设备端口转发到PC端。
(9)运行frida-ps –R命令,即可查询Android设备当前运行进程,至此连接Android设备成功(见图2.4)。另外,也可以直接通过USB将Android设备与PC端连接,运行frida-ps –U即可测试是否连接成功。
图2.4 Android 设备连接成功检测
2. HTTPS单向认证强校验Hook示例
本次示例通过在本地搭建Tomcat + SSL自签名证书环境,使用一个开源的Android HTTPS双向认证项目:
https://github.com/Frank-Zhu/AndroidHttpsDemo ,对其中部分代码进行修改后重新编译,构建本次测试的 APP应用。
(1) 基本原理
想要绕过证书锁定抓明文包就需要先知道APP是如何进行锁定操作的,然后再针对其操作进行注入解锁。
Android客户端关于证书处理的逻辑按照安全等级分类,如表2.1所示。
表2.1 Android客户端证书处理的安全等级分类
Apache http client 因为从api23起被Android抛弃,因此使用率较低。目前更多使用的是HttpURLConnection类或第三方库OKhttp3.0进行HTTPS通信。其中OKhttp3.0的部分运用与HttpURLConnection相同,客户端都可以通过实现X509TrustManager接口的checkServerTrusted方法,将服务器证书与APP预埋证书做对比,来完成强校验。此外,也可以再通过实现HostnameVerifier接口的verify方法,校验服务器证书中的一般名称(CN)是否与域名相符。通过使用上述方法,完成客户端对服务端的证书强校验。
(2) 应用分析
由于这次是自编译的文件,就不通过APK反编译等方法查看代码了,直接看主要通信类HttpClientSslHelper的源码。
- public class HttpClientSslHelper {
- public static boolean isServerTrusted1 = true; //强校验关键参数
- private static SSLContext sslContext = null;
- public static OkHttpClient getSslOkHttpClient(Context context) {
- OkHttpClient.Builder builder = new OkHttpClient.Builder();
- builder.sslSocketFactory(getSslContextByCustomTrustManager(context).getSocketFactory())
- .hostnameVerifier(new HostnameVerifier() {
- @Override //实现自定义的HostnameVerifier 对象的verify校验方法
- public boolean verify(String hostname, SSLSession session) {
- Log.d("HttpClientSslHelper", "hostname = " + hostname);
- if ("192.168.96.1".equals(hostname)) {
- //根据isServerTrusted1的值进行校验,若为True,则校验成功,执行后续连接
- return isServerTrusted1;
- } else {
- //由于是实验环境,if语句总为真,不会执行else语句
- HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
- return hv.verify("localhost", session);
- }
- }
- });
- return builder.build();
- }
- public static SSLContext getSslContextByCustomTrustManager(Context context) {
- if (sslContext == null) {
- try {
- CertificateFactory cf = CertificateFactory.getInstance("X.509","BC");
- InputStream caInput = new BufferedInputStream(context.getResources().getAssets().open("server.cer"));
- final Certificate ca;
- try {
- ca = cf.generateCertificate(caInput);
- } finally {
- caInput.close();
- }
- sslContext = SSLContext.getInstance("TLS");
- //自定义X509TrustManager接口的checkClientTrusted、checkServerTrusted和getAcceptedIssuers方法
- sslContext.init(null, new X509TrustManager[]{new X509TrustManager() {
- public void checkClientTrusted(X509Certificate[] chain,
- String authType) throws CertificateException {
- Log.d("HttpClientSslHelper", "checkClientTrusted --> authType = " + authType);
- //校验客户端证书
- }
- public void checkServerTrusted(X509Certificate[] chain,
- String authType) throws CertificateException {
- Log.d("HttpClientSslHelper", "checkServerTrusted --> authType = " + authType);
- //校验服务器证书
- for (X509Certificate cert : chain) {
- cert.checkValidity();
- try {
- //关键点,用APP中内置的服务端证书server.cer来校验网络连接中服务器颁发的证书
- cert.verify(ca.getPublicKey());
- } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException | SignatureException e) {
- e.printStackTrace();
- //校验失败,则更改isServerTrusted1值为false
- isServerTrusted1 = false;
- }
- }
- }
- public X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
- }}, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return sslContext;
- }
- }
由上可知,将HttpClientSslHelper类的getSslContextByCustomTrustManager方法重写,重新实现checkServerTrusted方法,让其不修改isServerTrusted1的值,即可绕过证书强校验。
(3) 开始Hook
重新实现checkServerTrusted方法
构造完整脚本如下:
- import frida, sys
- def on_message(message, data):
- if message['type'] == 'send':
- print("[*] {0}".format(message['payload']))
- else:
- print(message)
- jscode = """
- Java.perform(function () {
- var HttpClientSslHelper = Java.use('com.frankzhu.androidhttpsdemo.HttpClientSslHelper');
- var Log = Java.use('android.util.Log');
- HttpClientSslHelper.getSslContextByCustomTrustManager.implementation = function () {
- var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
- var SSLContext = Java.use('javax.net.ssl.SSLContext');
- var TrustManager = Java.registerClass({
- name: 'com.frankzhu.androidhttpsdemo.test',
- implements: [X509TrustManager],
- methods: {
- checkClientTrusted: function (chain, authType) {
- },
- checkServerTrusted: function (chain, authType) {
- Log.d("Frida Hook checkServerTrusted()", "Success!!!");
- send("Frida Hook checkServerTrusted() Success!!!");
- },
- getAcceptedIssuers: function () {
- return [];
- }
- }
- });
- // Prepare the TrustManagers array to pass to HttpClientSslHelper.sslContext.init()
- var TrustManagers = [TrustManager.$new()];
- send("Custom, Empty TrustManager ready");
- // Override the init method, specifying our new TrustManager
- var sslContext = SSLContext.getInstance("TLS");
- sslContext.init(null, TrustManagers, null);
- //return的值类型必须与原来的相同,否则会出现Error: Implementation for getSslContextByCustomTrustManager expected return value compatible with 'javax.net.ssl.SSLContext',同时导致应用崩溃
- //源码里有private static SSLContext sslContext = null;如果想通过this.sslContext使用该变量,一定要注意Hook的时机,要在sslContext变为对象后再Hook,这样就不会出现应用异常崩溃
- return sslContext;
- }
- });
- """
- process = frida.get_remote_device().attach('com.frankzhu.androidhttpsdemo')
- script = process.create_script(jscode)
- script.on('message', on_message)
- script.load()
- sys.stdin.read()
测试步骤:
未用Frida Hook的结果如图2.5、图2.6所示。
图2.5 连接报错
图2.6 HTTPS 抓包失败
使用Frida Hook后的结果如图2.7~图2.9所示。
图2.7 脚本运行成功
图2.8 运行日志
图2.9 HTTPS 证书验证破解成功
网页标题:Frida应用基础及APP https证书验证破解
本文URL:http://www.stwzsj.com/qtweb/news17/6417.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联