🛫 系列文章导航
- 【Frida】【Android】01_手把手教你环境搭建 https://blog.csdn.net/kinghzking/article/details/136986950
- 【Frida】【Android】02_JAVA层HOOK https://blog.csdn.net/kinghzking/article/details/137008446
- 【Frida】【Android】03_RPC https://blog.csdn.net/kinghzking/article/details/137050967
- 【Frida】【Android】04_Objection安装和使用 https://blog.csdn.net/kinghzking/article/details/137071768
- 【Frida】【Android】05_Objection实战 https://blog.csdn.net/kinghzking/article/details/137071826
▒ 目录 ▒
- 🛫 系列文章导航
- 🛫 导读
- 开发环境
- 1️⃣ HttpURLConnection基础开发示例
- 2️⃣ “自吐”脚本分析
- 准备工作
- URL
- HttpURLConnection分析
- 定位HttpURLConnection真实类名
- HttpsURLConnectionImpl分析
- 3️⃣ “自吐”脚本编写和验证
- 📖 参考资料
🛫 导读
开发环境
版本号 | 描述 | |
---|---|---|
文章日期 | 2024-03-24 | |
操作系统 | Win11 - 22H2 | 22621.2715 |
node -v | v20.10.0 | |
npm -v | 10.2.3 | |
夜神模拟器 | 7.0.5.8 | |
Android | 9 | |
python | 3.9.9 | |
frida | 16.2.1 | |
frida-tools | 12.3.0 | |
objection | 1.11.0 | |
1️⃣ HttpURLConnection基础开发示例
Android系统自带HTTP网络通信库HttpURLConnection,下面通过三个类演示其使用方法:
- import java.net.URL;
- import java.net.HttpURLConnection;
- import java.io.InputStream;
请求流程如下:
- 获取HttpURLConnection实例
通过传入目标网络地址来新建一个URL对象
,然后通过openConnection()
函数获取一个HttpURLConnection实例。- 设置HTTP请求头和参数信息
- 通过setRequestMethod()函数设置HTTP请求方法(一般有GET与POST
两种);- 通过setRequestProperty()设置请求参数;
- 通过setConnectionTimeout()函数设置连接超时时间;
- 通过setReadTimeout()函数设置接收超时时间。
- 执行请求
执行connection.connect()
,进行http请求。- 处理返回结果(输入流)
在设置完请求头和请求参数后,通过调用connection.getInputStream()
函数与服务器连接并获取到服务器返回的输入流,对输入流完成读取。- 关闭连接
在一个连接完成后,通过调用disconnection()
方法将HTTP连接关闭掉。
URL url = new URL("https://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("token","r0ysue666");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.connect(); // 开始连接
InputStream in = connection.getInputStream();
//if(in.available() > 0){
// 每次写入1024字节
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
StringBuffer sb = new StringBuffer();
while ((in.read(buffer)) != -1) {
sb.append(new String(buffer));
}
Log.d("demo", sb.toString());
connection.disconnect();
2️⃣ “自吐”脚本分析
准备工作
- 安装测试APP:com.roysue.httpurlconnectiondemo
- 启动frida-server
- 启动Objection:
objection -g com.roysue.httpurlconnectiondemo explore
URL
在后,先使用Objection来Hook整个URL类。Objection本身的watch class命令虽然能够Hook一个类的全部函数,但是无法Hook一个类的构造函数,因此这里手动使用如下命令Hook URL类的构造函数:
android hooking watch class_method java.net.URL.$init --dump-backtrace --dump-return --dump-args
示例中,定时请求baidu,所以,objection中,会定时打印如下内容:
我们可以看出,APP会触发三个构造函数,而java.net.URL.URL(java.lang.String)
就是我们demo中所调用的函数,其中会有参数https://www.baidu.com
。
HttpURLConnection分析
根据我们在上一步整理的关键收发包函数会发现剩下的都是HttpURLConnection类中的函数,因此只要使用如下命令去watch整个HttpURLConnection类的所有函数即可,当然不能忘了构造函数。
android hooking watch class java.net.HttpURLConnection
android hooking watch class_method java.net.HttpURLConnection.$init
当Hook上这个类的所有函数后会发现只有构造函数和一个java.net.HttpURLConnection.getFollowRedirects()函数被调用了,其结果如图所示:
这和我们的预期(会hook很多函数,如setRequestMethod等)是不符的。
我们通过
android heap search instances java.net.HttpURLConnection
命令,无法找到任何HttpURLConnection的对象。也就是说,hook的对象是不对的。
定位HttpURLConnection真实类名
通过以下网站:
- https://www.apiref.com/android-zh/java/net/HttpURLConnection.html#
- https://www.android-doc.com/reference/java/net/HttpURLConnection.html
我们可以看出,HttpURLConnection是个抽象类,也就是说url.openConnection()
获得的对象,很可能是其子类。
我们可以通过frida获取其对象内容:
- 通过
frida -UF
连接- 执行下面js语句
- 最终可以发现真实的类是
com.android.okhttp.internal.huc.HttpsURLConnectionImpl
Java.perform(function(){
var URL = Java.use('java.net.URL')
URL.openConnection.overload().implementation = function(){
var result = this.openConnection()
console.log('openConnection() returnType =>',result.$className)
return result
}
})
ps: 也可以通过Android Studio调试源码确认该类型。
HttpsURLConnectionImpl分析
回到objection,我们hook该类:
android hooking watch class com.android.okhttp.internal.huc.HttpsURLConnectionImpl
最终会发现Demo使用的每个函数都被调用到了,如下图所示:
3️⃣ “自吐”脚本编写和验证
结合上面的分析,我们可以写如下代码进行HttpURLConnection“自吐”:
运行测试结果如下:
function main(){
Java.perform(function(){
var URL = Java.use('java.net.URL')
URL.$init.overload('java.lang.String').implementation = function(urlstr){
console.log('url => ',urlstr)
var result = this.$init(urlstr)
return result
}
var HttpURLConnectionImpl = Java.use('com.android.okhttp.internal.huc.HttpURLConnectionImpl')
HttpURLConnectionImpl.setRequestProperty.implementation = function(key,value){
var result = this.setRequestProperty(key,value)
console.log('setRequestProperty => ',key,':',value)
return result
}
})
}
setImmediate(main)
📖 参考资料
- frida 常见问题和报错https://crifan.github.io/reverse_debug_frida/website/summary_note/common_issue/
- objection地址:https://github.com/sensepost/objection
ps: 文章中内容仅用于技术交流,请勿用于违规违法行为。