Android 提供多种向用户呈现内容的方式,要提供与平台其他部分一致的用户体验,通常最好构建一个原生应用,并在其中融入框架提供的体验,某些应用可能需要增强对界面的控制,在这种情况下,可以使用 WebView
显示受信任的第一方内容。
以上内容修改编辑自 Android 开发文档:https://developer.android.com/guide/webapps
通过以上的内容可以知道 h5 app 可以通过 webview 控件向我们提供在线的网页展示,今天我们搞的 App 就是这样的
如何判断 app 的类型?
这个网上的文章可太多了
参考链接:
1、https://blog.csdn.net/jackli11241201/article/details/91361692
2、https://buhuibaidu.me/?s=如何判断app是否是 h5
3、通过使用本地的 SDK/tools/bin/uiautomatorviewer 分辨加载页面的组件是否是 webview 判断
H5 App 的分析流程
按照上面的展示图,大概浅显的理解 H5 app 就是把网页图塞到了 app 里面展示出来的(其实没这么简单,大概理解个意思)
“H5 的 app 通常是界面里嵌入一个WebView控件,然后使用它来加载网页
正常的 APP 的分析流程一般是这样的:
关键参数的加密逻辑是在 Java 层或者 So 层,我们可以通过搜索关键词或者 Frida 等调试工具动态调试定位
然后的我们拿到的 APP 是 H5 的话,在分析这一步就有问题了
H5 App 是将网页的内容套了一个 App 的壳然后给用户使用,网页上算法加密一般是用 Js 完成加密
那么问题来了, 怎么调试定位 H5 App 里面的 Js 加密逻辑呢?
通过百度可以得到以下答案
1、在 H5 App 没有反调试的情况下
2、设备USB
连接电脑,打开 PC
的 Chrome
访问网址 chrome://inspect
3、取消Discover network targets
- 这一步是关闭网络上的设备,防止干扰,不关闭也可以
4、在Devices
中可以看到对应的设备的WebView
5、点击 inspect
小试牛刀
既然这样就拿一台设备试一试
果然可以看到我们的设备,打开设备的浏览器看看(自带的 Google 怎么说也不会反调试吧)
用手机的 Chrome 浏览器打开百度,然后 PC 重新访问一下chrome://inspect
页面
可以看到 PC 页面更新成上面这样了,我们试着调试一下手机百度的页面
点击inspect
,跳转到下面的页面,这个时候在下图右侧做的所有操作都同步到手机上了
这就和在浏览器里调试不能说是完全相同,但也可以说是一模一样了。【狗头】
注意事项
1、咸鱼 PC 使用的 Chrome 版本 100.0.4896.60(正式版本),环境一模一样保平安,其他版本我也没测试过
2、打开手机页面的时候,可能或出现白屏或者 404 的情况,导致这个现象的原因可能是因为你没有使用魔法上网,在打开这个页面的时候会下载文件,没有魔法上网的话就出错了
建议在第一次打开的时候将魔法上网切换到全局模式保证可以一步到位
H5 App 的反调试对抗
这个 App 比较上古,已经不提供服务了,本来想用大黄鸟抓包,但是没抓到需要的登陆包
应该是服务器都挂逼了
不过不影响我们进行今天的内容 >> 关于 H5 应用的反调试对抗
我们按照刚刚的步骤发现,Chrome 里并没有显示inspect
,猜测是 App 反调试了
先百度了解一下h5 app 的反调试
参考链接:https://its401.com/article/freak_csh/95585148
也就是说当WebView.setWebContentsDebuggingEnabled(false);
的时候就没办法调试了
那我们把目标 app 拖到 Jadx 里以setWebContentsDebuggingEnabled
为关键词搜索,看看是否能够找到目标位置
结果有三个,我们一个个看
第一个写入的是 true
第二个通过反射写入 False
第三个是一个判断,待定
这样看的话是第二个位置嫌疑最大
我们用 Frida hook 一下看看
代码语言:javascript复制// 错误实例
function main() {
console.log("Enter the Script!");
Java.perform(function x() {
console.log("Inside Java perform");
Java.choose("类名.ui.WebViewImpl", {
onMatch: function (x) {
console.log("find instance :" x);
x.setWebViewData.implementation = function(){
console.log("x.setWebViewData.implementation");
}
},
onComplete: function () {
console.log("end");
}
});
});
}
setImmediate(main);
本来用上面的那个代码发现 hook 不上
代码语言:javascript复制// 正确实例
console.log("脚本加载成功");
function main(){
Java.perform(function(){
const WebViewImpl = Java.use('类名.ui.WebViewImpl');
WebViewImpl['setWebViewData'].implementation = function(){
console.log("替换为空");
};
})
}
setImmediate(main)
感谢花哥的指点
本来我是 search 实例然后将方法置空,但是发现的总是进不去implementation
的逻辑,然后的求助花哥,花哥提示我可以不用搜索类实例直接implementation
,测试了一下发现可以进入implementation
的逻辑了。
不过用 Frida 并没有绕过检测,感觉还是我有一些地方疏漏了,如果有知道的大佬后台留言 dddd ,万分感谢
无奈之下,随后测试了下 xposed ,用 xposed 实现一下
代码语言:javascript复制public class HookMain implements IXposedHookLoadPackage {
String TAG = "xianyuplus";
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
XposedBridge.log("Loaded app :" loadPackageParam.packageName );
XposedHelpers.findAndHookMethod("类名.ui.WebViewImpl",loadPackageParam.classLoader,"setWebViewData", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
return null;
}
});
}
}
结果相当 nice,直接将setWebViewData
方法替换为空就可以解决反调试了
ps:需要注意的是这里的setWebViewData
内部逻辑只有webview
反调试相关的逻辑所以直接置空是可以的,如果有其他的逻辑的话就不能这样替换置空了
以上就是本次的全部内容了,因为 app 的服务端已经挂逼了,所以没办法测试,之后有新的 H5 app 样本的话就再水一篇。