一般App数据加密分为Java层跟So层,但对于H5App来讲的话,它是界面里嵌入一个WebView,在WebView里显示网页,在网页里面用JS加密,在通过Java和JS交互,用Java提交数据或者直接用网页提交数据两种方式
可以利用uiautomatorviewer.bat 来查看界面信息
大多数H5App的JS文件都存放在assets目录,少部分会存在res目录,存放在这两个地方获取比较方便,放在别的地方比如classes.dex的话获取比较麻烦,并且对classes.dex还要做一个处理
还有一个点就是JS文件是可以加密的,只要在加载到WebView之前进行一个解密就行
1
2
3
4
5
setWebContentsDebuggingEnabled
/
/
是否允许调试
/
/
shouldInterceptRequest、WebResourceResponse
public WebResourceResponse shouldInterceptRequest(WebView p0,String p1)
/
/
拦截器 jadx会反编译不出来建议用jeb或者gda 里面可以对js文件做一些处理
WebResourceResponse shouldInterceptRequest(WebView webView, WebResourceRequest webResourceRequest)
WebResourceResponse shouldInterceptRequest(WebView webView, String
str
)
远程调试需要满足三个条件:
Chrome WebView 版本要大于手机端 WebView 版本 (chrome更新到最新版就能解决)inspect 打开空白 则需要下载离线包如果连 WebView 下的一些信息都没显示出来则代表你没有调试权限 setWebContentsDebuggingEnabled
这个的值必须为true
才有调试权限,App发布一般都会把这个值设置成假不让你调试,直接Hook掉就行
setWebContentsDebuggingEnabled
三个检测点:
chrome 浏览器调试 地址 chrome://inspect Devices 下两个选项都勾选上浏览器版本 > 手机端 WebView 版本 点击 WebView 下方的 inspect 开始调试
PS: 由于手机端 WebView 版本不一致,所以第一次运行需要从谷歌站点下载一系列的离线包,否者打开 DevTools 就是空白界面 (科学上网会自动下载)
Android远程调试WebView的方法
Android 设备WebView远程调试
1. Network 能抓到数据(网页发包)
inspect 开始调试 , 切换到 Network 选项卡抓取数据 如果有抓取到数据也为网页发包 否则就是Java层发包 这个app是网页发包的
抓到的数据包 函数调用栈 接下来就是Js逆向分析 断点调试一顿分析就完事了
1
2
/
/
提交的数据
appid
=
quickdogrestful&mobile
=
139xxxxxxxx
&password
=
a12345678&device_id
=
863254033385807
%
2C863254033385815
&device_info
=
MI
%
206
%
20Xiaomi
&app_version
=
1.0
.
3.4
&nonce
=
a×tamp
=
1623410323.775
&sign
=
573080b9042317ee8b30ab6411c9b56e
2. Network 无法抓到数据(不是网页发包)
这种大概率就是JS加密 然后Java发包的 就只能找参数静态分析了
1
2
3
4
5
6
7
8
9
10
11
/
/
抓包数据
POST
/
/
api
/
user
/
login.do HTTP
/
1.1
user
-
agent: Mozilla
/
5.0
(Linux; Android
9
; MI
6
Build
/
PKQ1.
190118.001
; wv) AppleWebKit
/
537.36
(KHTML, like Gecko) Version
/
4.0
Chrome
/
74.0
.
3729.136
Mobile Safari
/
537.36
uni
-
app Html5Plus
/
1.0
(Immersed
/
24.0
)
Content
-
Type
: application
/
x
-
www
-
form
-
urlencoded; charset
=
utf
-
8
Content
-
Length:
138
Host: app168.zhongjianlepai.com
Connection: Keep
-
Alive
Accept
-
Encoding: gzip
Cookie: aliyungf_tc
=
b05125519e32b58949efe39018fbd902f0c0c052f4429ff19bd0ba4172416ff6; JSESSIONID
=
A8B840C693E48003233EE93EED504656; eiis
-
sessionid
=
3f17f8ce
-
4735
-
4670
-
ad2f
-
6036da767e52
phoneNum
=
139xxxxxxxx
&pwd
=
a12345678&isTakecookie
=
false&appVersion
=
1.2
.
2
×tamps
=
1623410775656
&signature
=
21549323b5116195020eee9808de314b
解压App一顿分析 app-services.js 定位关键函数
修改为下面代码保存Js文件 然后覆盖进apk文件里 功能->APK签名->安装 再抓包
跟之前的URL对比 就可以查看我们提交的参数
1
2
3
r.login
=
function(t, e, s) {
t[
"appVersion"
]
=
a.default.APP_VERSION,
i.default.request(
"/api/user/login.do?"
+
JSON.stringify(t)
+
JSON.stringify(e)
+
JSON.stringify(s) ,
"POST"
, t, e, s)}
1
2
3
4
5
POST
/
/
api
/
user
/
login.do?{
%
22phoneNum
%
22
:
%
22139xxxxxxxx
%
22
,
%
22pwd
%
22
:
%
22a12345678
%
22
,
%
22isTakecookie
%
22
:false,
%
22showLoading
%
22
:true,
%
22loaddingText
%
22
:
%
22
%
E7
%
99
%
BB
%
E9
%
99
%
86
%
E4
%
B8
%
AD...
%
22
,
%
22appVersion
%
22
:
%
221.2
.
2
%
22
}undefinedundefined HTTP
/
1.1
t
=
{
"phoneNum"
:
"139xxxxxxxx"
,
"pwd"
:
"a12345678"
,
"isTakecookie"
:false,
"showLoading"
:true,
"loaddingText"
:
"登陆中..."
,
"appVersion"
:
"1.2.2"
}
e,s
=
undefined
这串数据提交还没有包含 signature
那就继续查找下一个关键点 全局搜索signature
查找关键函数 最后抓包对比
1
2
3
4
5
6
7
8
9
10
/
/
传进去的参数
{
"phoneNum"
:
"139xxxxxxxx"
,
"pwd"
:
"a12345678"
,
"isTakecookie"
:false,
"showLoading"
:true,
"loaddingText"
:
"登陆中..."
,
"appVersion"
:
"1.2.2"
}
/
/
经过排序加salt 放入n.default(i)处理MD5
appKey
=
syc0049ec3d91b9028&appVersion
=
1.2
.
2
&phoneNum
=
139xxxxxxxx
&pwd
=
a12345678×tamps
=
1623410775656
&key
=
2e4dea7ba1dc4d1991cbcdd7756e548e
MD5:
21549323b5116195020eee9808de314b
/
/
上面的抓包数据做对比
phoneNum
=
139xxxxxxxx
&pwd
=
a12345678&isTakecookie
=
false&appVersion
=
1.2
.
2
×tamps
=
1623410775656
&signature
=
21549323b5116195020eee9808de314b
uni-app 核心请求
关键词 uni.request
最后总结一下: Network 能抓包的话可以动态调式 分析起来方便一点 不然的话就只能 静态分析 + 猜测 修改H5代码 签名App抓包来分析