Crack App | 【填坑】某 H5 app 的反调试绕过(Frida 与 Xposed 双版本)
第一时间关注Python技术干货!

图源:极简壁纸
今日目标
这个 app 是之前文章的读者在评论区提供的样本
正好今天填一下之前的坑

所以我上网找了样本,研究一波
aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzgwOTg1NzM=
反调试
虽然知道这个H5 app 是有反调试的,但还是测试一下看看是不是,不要搞出乌龙来了
访问 PC 的chrom://inspect

可以看到能看到有手机设备,但是没办法inspect 这个app,所以是由反调试的
直接拖到jadx里搜索关键词setWebContentsDebuggingEnabled看看这个设置

搜索结果还是很明显的,一下就能搜索到这个关键位置

但是看这个逻辑,不大对劲啊,如果是反调试的话应该是false才对
这里是true,说明是可以接受反调试的
而我们测试的结果是无法调试的,那么这个 app 一定是在某个角落里做了修改
如果绕过反调试的话应该怎么搞?
先试试 Frida hook 绕过
Frida hook 绕过 H5 反调试检测
竟然检索结果只有一个,去找 app 在什么位置修改了这个的值需要费很多功夫,只针对这个反调试的话就有点得不偿失了
所以直接用frida hook 把这个类的所有示例中的这个值都写入为true,就不用一个个分析了
这个setWebContentsDebuggingEnabled来自android.webkit.WebView

那么直接hook android.webkit.WebView 将他初始化后所有的setWebContentsDebuggingEnabled全部写成true应该就没啥问题了
我们写一个demo看看
查个包名

然后hook android.webkit.WebView的$init方法
console.log("脚本加载成功");
function main(){
Java.perform(function(){
var WebView = Java.use('android.webkit.WebView');
WebView.$init.implementation = function(a){
var result = this.$init(a);
return result;
}
});
}
setImmediate(main)
先这么写,然后运行一波看看
frida -U -f [app name] -l script.js --no-pause

系统会提示有重载,我们把所有的重载都hook上
console.log("脚本加载成功");
function main(){
Java.perform(function(){
var WebView = Java.use('android.webkit.WebView');
WebView.$init.overload('android.content.Context').implementation = function(a){
var result = this.$init(a);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet').implementation = function(a,b){
var result = this.$init(a,b);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int').implementation = function(a,b,c){
var result = this.$init(a,b,c);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'int').implementation = function(a,b,c,d){
var result = this.$init(a,b,c,d);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'boolean').implementation = function(a,b,c,d){
var result = this.$init(a,b,c,d);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'java.util.Map', 'boolean').implementation = function(a,b,c,d,e){
var result = this.$init(a,b,c,d,e);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'int', 'java.util.Map', 'boolean').implementation = function(a,b,c,d,e,f){
var result = this.$init(a,b,c,d,e,f);
return result;
}
});
}
setImmediate(main)
这样就可以将所有webview.$init都hook上了
然后我们需要做的是将这些init实例的setWebContentsDebuggingEnabled全都设置为true
console.log("脚本加载成功");
function main(){
Java.perform(function(){
var WebView = Java.use('android.webkit.WebView');
WebView.$init.overload('android.content.Context').implementation = function(a){
var result = this.$init(a);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet').implementation = function(a,b){
var result = this.$init(a,b);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int').implementation = function(a,b,c){
var result = this.$init(a,b,c);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'int').implementation = function(a,b,c,d){
var result = this.$init(a,b,c,d);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'boolean').implementation = function(a,b,c,d){
var result = this.$init(a,b,c,d);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'java.util.Map', 'boolean').implementation = function(a,b,c,d,e){
var result = this.$init(a,b,c,d,e);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'int', 'java.util.Map', 'boolean').implementation = function(a,b,c,d,e,f){
var result = this.$init(a,b,c,d,e,f);
this.setWebContentsDebuggingEnabled(true);
return result;
}
});
}
setImmediate(main);
然后再运行下hook脚本看看是否能够绕过反调试

运行成功,再试下chorme://inspect

就可以看到这个app显示出来了
点击inspect就可以调试了

Xposed 插件绕过反调试
在之前的文章里面我提供了xposed插件用于绕过H5 的反调试,我们测试一下能不能绕过这个app的反调试
安装好插件之后,记得勾选一下

然后打开目标app,然后再访问chrome://inspect

也是可以inspect的
这个插件针对H5反调试还是蛮好用的,有需要的可以访问下方的链接,查看使用方式和插件的获取方式
Crack App | 某保险资讯 App 请求头参数 token 与 sign 加密算法分析
End.
以上就是全部的内容了,咱们下次再会~
公众号配套技术交流群,备注【咸鱼666】,入群交流
我是没有更新就在摸鱼的咸鱼
收到请回复~
我们下次再见。
对了,看完记得一键三连,这个对我真的很重要。
