微信6.7.3版本分析总结
网络分析
一般为了获取应用的数据,可以首先通过抓包的方式分析其网络协议,如果能够分析清楚所有的网络协议,那么就可以在PC端进行模拟,而没必要去使用手机端爬取数据了。
一般的应用会使用Http/s协议进行数据传输,那么使用常见的网络代理软件(Charles、Fiddler)设置代理,并且在手机端安装代理软件的证书即可,而且需要在手机上设置wifi代理。但是在手机上设置了wifi代理并不意味着应用一定会使用该代理,应用可以设置不使用该wifi代理。那么这时候如果想要查看手机上的网络请求,就可以使用tcpdump工具,可以得到pcap包,然后使用wireshark或者Charles打开pacp包进行分析即可。
Postman模拟请求
使用该软件对请求进行模拟时,需要注意对该软件进行设置,比如去除SSL证书验证等设置。另外该软件对于访问过的域名会保存返回的Cookie,可以点击界面上的Cookies对各个域名的Cookie进行清除或管理。
网络访问模板
- 获取公众号最新Cookie:
request
https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzA4ODQ5MDcwNw==&scene=126&devicetype=android-21&version=26070333&lang=zh_CN&nettype=WIFI&a8scene=3&pass_ticket=WPx%2Bo2YN1JAF%2FmL7nV7V%2BfEvdXi%2FZpMDqDKiSLIWGssGQPh9ynzmVAALv%2BGxAiQZ&wx_header=1
参数:
- action=home
- __biz=MzA4ODQ5MDcwNw==(**该参数为公众号唯一标识,可变**)
- scene=126
- devicetype=android-21
- version=26070333
- lang=zh_CN
- nettype=WIFI
- a8scene=3
- pass_ticket=WPx%2Bo2YN1JAF%2FmL7nV7V%2BfEvdXi%2FZpMDqDKiSLIWGssGQPh9ynzmVAALv%2BGxAiQZ
- wx_header=1
Header:
- Host: mp.weixin.qq.com
- Connection: keep-alive
- User-Agent: Mozilla/5.0 (Linux; Android 5.0.2; Lenovo A7600-m Build/LRX21M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/044306 Mobile Safari/537.36 MicroMessenger/6.7.3.1360(0x26070333) NetType/WIFI Language/zh_CN Process/toolsmp
- x-wechat-key: 799cb18701a7441ff905da2d25b98adec65b40d6f775c4f0d18d371b8ba9e7adec7d711a97eaacf507fe43dc9ef343b4145d11ee580dadc6143f7263aba28c1482c023ee3d347696af8e2462951da32e(该参数也会变,变化方式暂时未知!!!)
- x-wechat-uin: Mzg5OTI5MDk0
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,image/wxpic,image/sharpp,image/apng,image/tpg,/;q=0.8
- Accept-Encoding: gzip, deflate
- Accept-Language: zh-CN,en-US;q=0.8
- Cookie: wxuin=389929094; devicetype=android-21; version=26070333; lang=zh_CN; pass_ticket=WPx%2Bo2YN1JAF%2FmL7nV7V%2BfEvdXi%2FZpMDqDKiSLIWGssGQPh9ynzmVAALv%2BGxAiQZ; wap_sid2=CIax97kBElx4UEZlcUVZX1VoQnc4aGVvRWJyUG1WTDBaTGVGOXJvSDN1eUtaMkVvTk9JZ2h6U2RjOWlxbFoxN1dhOVEwTTd1Nmx2N29DQlR2dE8wR0d1RjliZF9mTk1EQUFBfjCtzrXeBTgNQJVO
- Q-UA2: QV=3&PL=ADR&PR=WX&PP=com.tencent.mm&PPVN=6.7.3&TBSVC=43617&CO=BK&COVC=044306&PB=GE&VE=GA&DE=PHONE&CHID=0&LCID=9422&MO= LenovoA7600-m &RL=720*1280&OS=5.0.2&API=21
- Q-GUID: 22ced77acee5c74a8d86eaef13b788cb
- Q-Auth: 31045b957cf33acf31e40be2f3e71c5217597676a9729f1b
其中Cookie:
- wxuin=389929094
- devicetype=android-21
- version=26070333
- lang=zh-CN
- pass_ticket=WPx%2Bo2YN1JAF%2FmL7nV7V%2BfEvdXi%2FZpMDqDKiSLIWGssGQPh9ynzmVAALv%2BGxAiQZ
- wap_sid2=CIax97kBElx4UEZlcUVZX1VoQnc4aGVvRWJyUG1WTDBaTGVGOXJvSDN1eUtaMkVvTk9JZ2h6U2RjOWlxbFoxN1dhOVEwTTd1Nmx2N29DQlR2dE8wR0d1RjliZF9mTk1EQUFBfjCtzrXeBTgNQJVO(该参数需设置为当前最新Cookie中wap_sid2的值)
response
只需要获得头部的Set-Cookie中的wap_sid2的值作为最新的值并保存,记为latest_wap_sid2。示例:Set-Cookie: wap_sid2=CIax97kBElx4UEZlcUVZX1VoQnc4aGVvRWJyUG1jeEIzWlZDN2JuOElJaUV3ekd5SGc4OGN1aFV6S0hDLVJvUV9NOTgxWHI4M05mM1poc2NkcUxiU05YS3JOMmdFZE1EQUFBfjDD0bXeBTgNQJVO;
-
获取公众号历史消息:
request
https://mp.weixin.qq.com/mp/profile_ext?action=getmsg&__biz=MzAwNTQ3NDQ5Ng==&f=json&offset=10&count=10&is_ok=1&scene=126&uin=777&key=777&pass_ticket=WPx%2Bo2YN1JAF%2FmL7nV7V%2BfEvdXi%2FZpMDqDKiSLIWGssGQPh9ynzmVAALv%2BGxAiQZ&wxtoken=&appmsg_token=979_Ds%252FMzzoq5Z5ZLxjnVOhVIfEww_Wj_5gl4-YN8w~~&x5=1&f=json
参数:
- action=getmsg
- __biz=MzAwNTQ3NDQ5Ng==
- f=json
- offset=10
- count=10
- is_ok=1
- scene=126
- uin=777
- key=777
- pass_ticket=WPx%2Bo2YN1JAF%2FmL7nV7V%2BfEvdXi%2FZpMDqDKiSLIWGssGQPh9ynzmVAALv%2BGxAiQZ
- wxtoken=
- appmsg_token=979_Ds%252FMzzoq5Z5ZLxjnVOhVIfEww_Wj_5gl4-YN8w~~
- x5=1
- f=json
Header:
- Host: mp.weixin.qq.com
- Connection: keep-alive
- X-Requested-With: XMLHttpRequest
- User-Agent: Mozilla/5.0 (Linux; Android 5.0.2; Lenovo A7600-m Build/LRX21M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/044306 Mobile Safari/537.36 MicroMessenger/6.7.3.1360(0x26070333) NetType/WIFI Language/zh_CN Process/toolsmp
- Accept: /
- Referer: https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzA4ODQ5MDcwNw==&scene=126&devicetype=android-21&version=26070333&lang=zh_CN&nettype=WIFI&a8scene=3&pass_ticket=WPx%2Bo2YN1JAF%2FmL7nV7V%2BfEvdXi%2FZpMDqDKiSLIWGssGQPh9ynzmVAALv%2BGxAiQZ&wx_header=1
- Accept-Encoding: gzip, deflate
- Accept-Language: zh-CN,en-US;q=0.8
- Cookie: wxuin=389929094; devicetype=android-21; version=26070333; lang=zh_CN; pass_ticket=WPx%2Bo2YN1JAF%2FmL7nV7V%2BfEvdXi%2FZpMDqDKiSLIWGssGQPh9ynzmVAALv%2BGxAiQZ; wap_sid2=CIax97kBElx4UEZlcUVZX1VoQnc4aGVvRWJyUG1jeEIzWlZDN2JuOElJaUV3ekd5SGc4OGN1aFV6S0hDLVJvUV9NOTgxWHI4M05mM1poc2NkcUxiU05YS3JOMmdFZE1EQUFBfjDD0bXeBTgNQJVO
- Q-UA2: QV=3&PL=ADR&PR=WX&PP=com.tencent.mm&PPVN=6.7.3&TBSVC=43617&CO=BK&COVC=044306&PB=GE&VE=GA&DE=PHONE&CHID=0&LCID=9422&MO= LenovoA7600-m &RL=720*1280&OS=5.0.2&API=21
- Q-GUID: 22ced77acee5c74a8d86eaef13b788cb
- Q-Auth: 31045b957cf33acf31e40be2f3e71c5217597676a9729f1b
Cookie中的wap_sid2的值即为上一步中获得的最新值latest_wap_sid2。
逆向分析
静态分析
公众号主页点击全部消息流程初步分析
- 公众号主页Activity:com.tencent.mm.plugin.profile.ui.ContactInfoUI
- 点击“全部消息”按钮回调函数,ContactInfoUI类中的:
public final boolean a(f fVar, Preference preference)
- 进而调用接口获取全部历史消息:com.tencent.mm.plugin.profile.ui.newbizinfo.b类中的
public final boolean xQ(String str)
,设置Intent:
java
Intent intent = new Intent();
intent.putExtra("rawUrl", str2);
intent.putExtra("useJs", true);
intent.putExtra("vertical_scroll", true);
intent.putExtra("geta8key_scene", 3);
intent.putExtra("KPublisherId", "brand_profile");
intent.putExtra("prePublishId", "brand_profile");
intent.setClassName("com.tencent.mm", "com.tencent.mm.plugin.webview.ui.tools.WebviewMpUI"); - 进而调用接口设置intent传递参数:com.tencent.mm.br.d类中的
public static void b(Context context, String str, String str2, Intent intent)
,实际干活的是private static void b(Context context, final String str="webview", String str2=".ui.tools.WebViewUI", Intent intent, Bundle bundle)
- 进而调用接口动态加载插件模块:com.tencent.mm.br.d类中的
public static synchronized c a(String str, a aVar, b bVar)
,aVar是成功的回调函数,bVar是失败的回调函数。 - 启动WebView的Activity:com.tencent.mm.plugin.webview.ui.tools.WebviewMpUI,实际干活的是其父类:com.tencent.mm.plugin.webview.ui.tools.WebViewUI
然而发现这样分析效率太低,而且抓不住重点。
提高效率的方法
jadx
使用jadx打开apk文件,对于被混淆的应用使用其Tools菜单中的Deobfuscation工具去混淆,然后使用其File菜单中的Save as gradle project功能导出为gradle工程,进而可以使用Android studio打开该工程。
但是有些时候对于程序代码庞大应用,Save as gradle project功能在使用时会卡死,这时候可以多试几次,如果一直卡死的话也就无能为力了。
Android Studio的强大
Android Studio除了可以打开jadx导出的gradle工程,还可以打开apktool工具反编译apk文件而得到的工程,该工具的强大在于搜索功能,不论应用的代码量有多大,不论搜索的范围有多大,不论搜索的字符串或者smali代码有多长,其搜索的速度都非常的快,这样就可以快速的定位字符串或者任何一个类、接口等,以及它的子类甚至函数调用等等。只需要在搜索的时候根据需要来构造搜索字符串即可。
jeb与Android Killer辅助分析
jeb要比jadx反编译的效果好一些,但是其对大应用稳定性不好,打开大应用的apk文件时往往直接卡死,这样就无能为力了,不过可以利用它来分析单个的dex文件,当在jadx中发现某一部分的反编译效果不好时,可以从Android Studio打开的smali工程中找到对应的dex文件,然后使用jeb打开该dex文件进行辅助分析。
Android Killer的独特功能在于其对smali代码会有语法提示,另一个功能是存在一个可以选择的当前smali文件中包含的所有方法的列表。当对smali语法存在部分困惑时,可以打开Android Killer进行分析参考。
动态分析
界面代码定位
使用adb shell dumpsys activity top
命令可以获取手机当前界面的包名与Activity。
Android Studio + smalidea 调试smali代码
设置设备可调试环境
使用mprop小工具可以设置设备的ro.debuggable=1,但是如果设备重启则失效,需要重新设置。
mprop小工具运行脚本如下:
@echo off
adb push .\libs\armeabi-v7a\mprop /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/mprop"
:: inject & hack
adb shell su -c "/data/local/tmp/mprop"
:: verbose mode ==> dump memory
:: adb shell "/data/local/tmp/mprop -v" > myprop.txt
:: change ro.xx property
adb shell su -c "setprop ro.debuggable 1"
adb shell su -c "/data/local/tmp/mprop -r"
adb shell "getprop ro.debuggable"
pause
调试步骤:
- 使用apktool反编译apk文件得到反编译目录,需要保证该apk中android::debuggable=”true”,或者保证设备的ro.debuggable=1,否则无法开启8700调试端口。
- 用Android studio打开反编译目录,从硬盘安装插件smalidea并重启Android studio。
- Android studio设置远程调试选项,Run->Edit configurations->添加Remote->设置调试端口8700.
- 启动monitor,其会自动选择接下来被调试的应用,并且开启8700端口。
- 使用adb以debug的方式启动apk:
- adb shell am start -D -n packageName/ActivityName
- Android studio中下断点,点击debug调试按钮,等待APP界面提示无响应是否关闭时再进行单步调试,添加watches等。
Xposed Hook代码运行时调试
这种方法即使用Xposed框架对感兴趣的代码进行Hook,感兴趣的代码比如程序自带的日志输出代码等。
Hook的代码主要做几件事情:
1. 打印函数调用参数。
2. 利用Java反射来获取其他感兴趣的Object,打印该Object。
3. 构造异常栈并打印,查看函数调用栈。
针对Binder机制的分析技巧
当代码中使用Binder机制时,可以利用Binder服务器端的enforceInterface函数中的参数与Binder客户端的writeInterfaceToken函数中的参数完全相等这么一个特征,进而把服务端和客户端的代码串联起来。
针对WebView的分析技巧
WebView主要是用来加载网页的,不了解的话可以先学习一下它的用法,网上教程很多。
应用一般会自定义一个WebViewClient用于处理各种事件,各种事件发生时都有相应的回调方法,当结束加载网页时会回调onPageFinished方法,因此可以Hook该方法来做一些事情。比较基本的事情是查看网页源码,这个网上资料也有不少,需要注意的是在高版本的Android API应用中,与JS交互的Java函数必须添加JavascriptInterface注解。