从Objection的使用操作中我们可以发现,Obejction采用Attach附加模式进行Hook,这可能会让我们错过较早的Hook时机,可以通过如下的代码启动Objection,引号中的objection命令会在启动时就注入App
objection -g packageName explore --startup-command 'android hooking watch xxx'
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;
}
});
这样做用处有二,一是Hook网络请求+打印堆栈,从而找到加解密函数,二是代替Fiddler/Charles抓包。既然要做这些事,首先就需要了解Android会使用哪些网络库。
标准的Java接口(java.NET),HttpURLConnection基于http协议,支持get,post,put,delete等各种请求方式。。
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。
在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,操作中主要有几个问题。
yang大佬有Frida Hook 拦截器实现的OkHttp Hook,评论区有处理加固的版本 珍惜大佬关于Okhttp是三篇文章