使用 Charles 捉包调试安卓网络

围巾🧣 2021年10月08日 610次浏览

安装

去官网下载 Linux的包

注册

到该网站生成一个激活码 https://www.zzzmode.com/mytools/charles/

打开应用,输入激活码

有能力还请支持正版

使用

设置

设置使用 Charles 的代理

同一局域网下,连接 WiFi 设置代理

image-20211008191112406

image-20211008191112406

wifi

wifi

HTTPS抓包

对于Android 7.0及以上的设备HTTPS抓包, 除以上步骤外, 还要额外做一些处理.
主要有2种方式:
(1) ROOT方式
(2) 非ROOT方式

ROOT方式抓包

手机ROOT

去网上找对应机型的ROOT方法

系统证书目录安装SSL证书

前面步骤已经介绍了SSL下载和安装过程.

接下来需要额外做的就是将SSL证书安装到系统证书目录.

(1) 将charles-proxy-ssl-proxying-certificate.pem证书文件上传pull到电脑端.
(2) 运行命令生成md5(第一行数字即为md5)

  1. openssl x509 -subject_hash_old -in charles-proxy-ssl-proxying-certificate.pem.crt

(3) 将pem证书文件更名为 <md5>.0
(4) 将更名后的文件push到手机目录: adb push < md5>.0 /system/etc/security/cacerts

  1. 要求有 Root 权限
  2. 由于Android 7 以后 system 分区为已读,直接把文件复制过去是不行的。这时可借用magisk 模块把模块目录下的文件挂载到system 分区就行:
  3. https://github.com/azio7/movecert (修复的,自行替换 placeholder 重新打包 zip 刷入即可)
  4. 原仓库有问题:https://github.com/Magisk-Modules-Repo/movecert
非ROOT方式抓包

这种方式只能抓取当前APP的HTTPS请求或者其他App设置信任用户CA的情况.

(1) 在AndroidManifest.xml文件中配置android:networkSecurityConfig属性

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest ... >
  3. <application android:networkSecurityConfig="@xml/network_security_config" ... >
  4. ...
  5. </application>
  6. </manifest>

(2) 创建并配置res/xml/network_security_config.xml文件

  1. <network-security-config>
  2. <base-config cleartextTrafficPermitted="true">
  3. <trust-anchors>
  4. <certificates src="system" overridePins="true" /> <!--信任系统证书-->
  5. <certificates src="user" overridePins="true" /> <!--信任用户证书-->
  6. </trust-anchors>
  7. </base-config>
  8. </network-security-config>

然后重新打包安装抓包就可以了.

界面查看

image-20211008191403604

image-20211008191403604

断点编辑

Proxy --> BreakPoint Settings

或者右击链接,勾选对应选项

可以自己编辑请求和响应的内容

编辑请求

image-20211008191804357

image-20211008191804357

编辑响应image-20211008191832160

image-20211008191832160

设置本地自定义返回

有时修改返回时,还没改完就请求超时了。这时可将响应存到一个文件,请求后直接返回。

Tools --> Map Local

或者右击链接,勾选对应选项

例如在本地文件放好一个要返回的 json 串

  1. {
  2. "hasNext": true,
  3. "pageList": [
  4. {
  5. "templateType": 2,
  6. "generalItems": [
  7. {
  8. "implUniqueCode": "wd_0220210806201358012520",
  9. "abilityCode": "wd_0120210806195102791485",
  10. "abilityVersion": 2,
  11. "implType": 1,
  12. "style": 1,
  13. "widgetSize": "2*2",
  14. "widgetImplInfo": {
  15. "widgetProviderName": "com.tencent.qqmusiccommon.MIUIWidgetProviderRecentPlay",
  16. "widgetTitle": "最近播放",
  17. "lightPreviewUrl": "https://cdn.cnbj1.fds.api.mi-img.com/mag-developer/2e0b630e-91d6-4e84-994b-a8ead095c804.png?f=webp",
  18. "darkPreviewUrl": "",
  19. "installStatus": 0,
  20. "appName": "QQ音乐",
  21. "appIcon": "http://file.market.xiaomi.com/download/AppStore/0b73f0936b892423cb0def79ea030b3266b2654bb",
  22. "appPackage": "com.tencent.qqmusic",
  23. "appVersionName": "10.16.5.9",
  24. "appVersionCode": 2269,
  25. "appDownloadUrl": "mimarket://details/detailfloat?id=com.tencent.qqmusic&nonce=-2283399555579345375:27212072&ref=xiaomi_me_widget_auto_download&startDownload=true&appClientId=2882303761517502385&finishWhenDownload=false&finishWhenOpen=false&show_cta=true&appSignature=Yju6ZWnkz_AdUynsMTlAc4o5xnDT_tpiuI14_7UnA1s",
  26. "desc": "你听过的都在这里",
  27. "appWidgetWidth": 110,
  28. "appWidgetHeight": 110
  29. },
  30. "mamlImplInfo": {
  31. "productId": null,
  32. "tagName": null,
  33. "tag": null,
  34. "mamlTitle": null,
  35. "mamlSize": null,
  36. "appName": "QQ音乐",
  37. "appIcon": "http://file.market.xiaomi.com/download/AppStore/0b73f0936b892423cb0def79ea030b3266b2654bb",
  38. "appPackage": "com.tencent.qqmusic",
  39. "appVersionName": "10.16.5.9",
  40. "appVersionCode": 2269,
  41. "lightPreviewUrl": null,
  42. "darkPreviewUrl": null,
  43. "desc": null,
  44. "mamlVersion": null,
  45. "mamlWidth": null,
  46. "mamlHeight": null,
  47. "canEdit": null,
  48. "mamlDownloadUrl": null,
  49. "mtzSizeInKb": null
  50. }
  51. },
  52. {
  53. "implUniqueCode": "wd_0220210709102631012943",
  54. "abilityCode": "wd_0120210709102604023334",
  55. "abilityVersion": 2,
  56. "implType": 1,
  57. "style": 1,
  58. "widgetSize": "2*2",
  59. "widgetImplInfo": {
  60. "widgetProviderName": "com.douyu.module.miuiwidget.widgetprovider.DYMIUIWidgetFollow22Provider",
  61. "widgetTitle": "我的关注",
  62. "lightPreviewUrl": "https://cdn.cnbj1.fds.api.mi-img.com/mag-developer/45a2eec2-7722-473f-9a51-e5b2ca17063e.png?f=webp",
  63. "darkPreviewUrl": "https://cdn.cnbj1.fds.api.mi-img.com/mag-developer/88feada5-8f4d-43cd-afb6-be0509aedfac.png?f=webp",
  64. "installStatus": 0,
  65. "appName": "斗鱼",
  66. "appIcon": "http://file.market.xiaomi.com/download/AppStore/06dd3d5b53caa44999242c8d04c8927d350bb6c41",
  67. "appPackage": "air.tv.douyu.android",
  68. "appVersionName": "7.1.0",
  69. "appVersionCode": 10710001,
  70. "appDownloadUrl": "mimarket://details/detailfloat?id=air.tv.douyu.android&nonce=-6155946856269318880:27212072&ref=xiaomi_me_widget_auto_download&startDownload=true&appClientId=2882303761517502385&finishWhenDownload=false&finishWhenOpen=false&show_cta=true&appSignature=WX-Mm7kAjxdp_MSlf2GCgP_x7ZwrK0Eu_S_Ttfd68xo",
  71. "desc": "快速查看你关注的主播,精彩瞬间不错过",
  72. "appWidgetWidth": 147,
  73. "appWidgetHeight": 147
  74. },
  75. "mamlImplInfo": {
  76. "productId": null,
  77. "tagName": null,
  78. "tag": null,
  79. "mamlTitle": null,
  80. "mamlSize": null,
  81. "appName": "斗鱼",
  82. "appIcon": "http://file.market.xiaomi.com/download/AppStore/06dd3d5b53caa44999242c8d04c8927d350bb6c41",
  83. "appPackage": "air.tv.douyu.android",
  84. "appVersionName": "7.1.0",
  85. "appVersionCode": 10710001,
  86. "lightPreviewUrl": null,
  87. "darkPreviewUrl": null,
  88. "desc": null,
  89. "mamlVersion": null,
  90. "mamlWidth": null,
  91. "mamlHeight": null,
  92. "canEdit": null,
  93. "mamlDownloadUrl": null,
  94. "mtzSizeInKb": null
  95. }
  96. }
  97. ]
  98. }
  99. ]
  100. }

弱网模拟

Proxy --> Throttle Settings

在 Throttle preset 可以设置网速的阈值

image-20211008191656942

image-20211008191656942

加密数据修改

有时拦截到的数据是加密的,也可以修改。通用思路如下

  1. 先解密
  2. 再修改
  3. 再加密

AES 加密只要拿到密钥就好,SHA1 加密有自己方的私钥解密就好,公钥比较好拿到。查看加解密过程可以看 OKHTTP 的 加解密拦截器的实现,可以看到密钥信息。自己在 idea 建一个 Java项目来实现加解密

应用请求了但没有捉到包

可能是多次请求失败了,应用选择了不走代理的方法,可以选择结束进程再重新打开。或者应用一开始就是不走代理,例如 flutter 的应用,需要手动配置