Skip to content

Instantly share code, notes, and snippets.

@h1code2
Last active December 27, 2023 20:20
Show Gist options
  • Save h1code2/5e12401de527b034945869e8ab614480 to your computer and use it in GitHub Desktop.
Save h1code2/5e12401de527b034945869e8ab614480 to your computer and use it in GitHub Desktop.
Objection/Fida常用功能一把梭Objection #frida #hook #spawn

Objection使用笔记及常用代码

1. Spawn方式Hook

从Objection的使用操作中我们可以发现,Obejction采用Attach附加模式进行Hook,这可能会让我们错过较早的Hook时机,可以通过如下的代码启动Objection,引号中的objection命令会在启动时就注入App

objection -g packageName explore --startup-command 'android hooking watch xxx' 

2. Hook加密库

11x256内容原文

console.log("Script loaded successfully 55");

Java.perform(function x() {
    var secret_key_spec = Java.use("javax.crypto.spec.SecretKeySpec");
    //SecretKeySpec is inistantiated with the bytes of the key, so we hook the constructor and get the bytes of the key from it
    //We will get the key but we won't know what data is decrypted/encrypted with it
    secret_key_spec.$init.overload("[B", "java.lang.String").implementation = function (x, y) {
        send('{"my_type" : "KEY"}', new Uint8Array(x));
        //console.log(xx.join(" "))
        return this.$init(x, y);
    }
    //hooking IvParameterSpec's constructor to get the IV as we got the key above.
    var iv_parameter_spec = Java.use("javax.crypto.spec.IvParameterSpec");
    iv_parameter_spec.$init.overload("[B").implementation = function (x) {
        send('{"my_type" : "IV"}', new Uint8Array(x));
        return this.$init(x);
    }
    //now we will hook init function in class Cipher, we will be able to tie keys,IVs with Cipher objects
    var cipher = Java.use("javax.crypto.Cipher");
    cipher.init.overload("int", "java.security.Key", "java.security.spec.AlgorithmParameterSpec").implementation = function (x, y, z) {
        //console.log(z.getClass()); 
        if (x == 1) // 1 means Cipher.MODE_ENCRYPT
            send('{"my_type" : "hashcode_enc", "hashcode" :"' + this.hashCode().toString() + '" }');
        else // In this android app it is either 1 (Cipher.MODE_ENCRYPT) or 2 (Cipher.MODE_DECRYPT)
            send('{"my_type" : "hashcode_dec", "hashcode" :"' + this.hashCode().toString() + '" }');
        //We will have two lists in the python code, which keep track of the Cipher objects and their modes.


        //Also we can obtain the key,iv from the args passed to init call
        send('{"my_type" : "Key from call to cipher init"}', new Uint8Array(y.getEncoded()));
        //arg z is of type AlgorithmParameterSpec, we need to cast it to IvParameterSpec first to be able to call getIV function
        send('{"my_type" : "IV from call to cipher init"}', new Uint8Array(Java.cast(z, iv_parameter_spec).getIV()));
        //init must be called this way to work properly
        return cipher.init.overload("int", "java.security.Key", "java.security.spec.AlgorithmParameterSpec").call(this, x, y, z);

    }
    //now hooking the doFinal method to intercept the enc/dec process
    //the mode specified in the previous init call specifies whether this Cipher object will decrypt or encrypt, there is no functions like cipher.getopmode() that we can use to get the operation mode of the object (enc or dec)
    //so we will send the data before and after the call to the python code, where we will decide which one of them is cleartext data
    //if the object will encrypt, so the cleartext data is availabe in the argument before the call, else if the object will decrypt, we need to send the data returned from the doFinal call and discard the data sent before the call
    cipher.doFinal.overload("[B").implementation = function (x) {
        send('{"my_type" : "before_doFinal" , "hashcode" :"' + this.hashCode().toString() + '" }', new Uint8Array(x));
        var ret = cipher.doFinal.overload("[B").call(this, x);
        send('{"my_type" : "after_doFinal" , "hashcode" :"' + this.hashCode().toString() + '" }', new Uint8Array(ret));

        return ret;
    }
});

3. Hook网络请求库

这样做用处有二,一是Hook网络请求+打印堆栈,从而找到加解密函数,二是代替Fiddler/Charles抓包。既然要做这些事,首先就需要了解Android会使用哪些网络库。

3.1. Android原生自带的网络通信库

HttpURLConnection

标准的Java接口(java.NET),HttpURLConnection基于http协议,支持get,post,put,delete等各种请求方式。。

HttpClient

Apache的HttpClient模块(org.apache.http),这个模块被放在Android的SDK(软件开发工具包)中,它旨在提供高效的、最新的、功能丰富的HTTP 服务。 这里需要讲一下这两大通信库的前世今生,在Android 2(2010年)的远古版本中,HttpURLConnection有个重大 Bug,所以那个时候推 荐使用HttpClient。时光荏苒,BUG被修复了,HttpURLConnection也不断得到优化和完善。从Android 5(2014年)开始,Android官方不再推荐使用Apache模块, Android 6.0的SDK中去掉了HttpCien,到了最新的Android 9版本中,Android更是彻底取消了对Apache HTTPClient的支持。因此原声库现在主要指HttpUrlConnection。

3.2. 封装好的网络通信工具/框架

在Android实际开发中,一般都会使用别人封装好的第三方网络请求框架,原因也很简单,网络操作涉及到很多东西,别人封装的东西好用。

  • Volley在2013年的Google I/O大会上,Google推出了这款异步网络请求框架和图片加载框架。它特别适合数据量小,通信频繁的网络操作。它基于HttpUrlConnection,目前也有一定的使用量。
  • Android-Async-Http基于Apache HttpClient库之上的一个异步网络请求处理库,现在已经不怎么用了。一是因为HttpClient被Android弃用,二是框架作者已停止维护,这个库知道即可。
  • OkHttpOkHttp是大名鼎鼎的Square公司的开源网络请求框架,需要注意的一点是,它并非是基于HttpURLConnection和HttpClient的封装或者补充,事实上,它们是平级的,三者构成竞争关系。从Android 4.4开始,HttpURLConnection的底层实现也已经基于OkHttp,由此可见OkHttp是时下当之无愧最热门的HTTP框架。OKhttp简单、快速、高效。
  • Retrofit同样出自于Square公司,Retrofit是对Okhttp的封装,网络请求的工作本质上是 OkHttp 完成。因此如果Hook网络请求的话,目前App的主要流量都来自Okhttp和Retrofit,Hook Okhttp即可,如果有余力,HttpURLConnection+Volley也可以Hook上,作者在文中提供了Volley的Demo。 Hook Okhttp已经有不少的资料,简单的只有几行代码,复杂的近千行,可是为什么要费这个劲去Hook网络请求库?Charles抓包不香吗?Postern不香吗?——还真是,有时候有些难言之隐。现在防抓包会做各种防范,双向验证啦,证书啦,禁止Proxy等等,分析代码后Hook或者装证书也是可以的,但比较麻烦,直接Hook Okhttp吐出请求有的时候还是挺有用的。 要想Hook Okhttp,操作中主要有几个问题。

3.2.1 App高度混淆后,Okhttp相关类的类名被混淆,找不到相关类。

3.2.2 Hook的方法和时机选择

yang大佬有Frida Hook 拦截器实现的OkHttp Hook,评论区有处理加固的版本 珍惜大佬关于Okhttp是三篇文章

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment