背景
Charles功能强大,不仅可以用来抓包,还可以进行断点、map、rewrite等操作, 适用多种场景。我之前虽然也也用过Charles进行过抓包,不过一年半载后就忘记怎么操作了,这几天去网上翻文章,重新捋流程,踩了一些坑,浪费一堆时间才重新掌握最基础的抓包操作(时间已溜走,只剩两行泪)。为了防止以后再忘,记录一下Charles抓http/https包的设置方式。
工具
Charles
正版下载地址:https://www.charlesproxy.com/
貌似收费,不过网上资源无限…
抓Http包
抓Http的包比较简单,因为Http是明文传输,所以只要两步。
步骤一:配置Charles代理端口
操作: Proxy -> Proxy Setting…
端口可以随便指定,不要和其他程序有端口冲突就行,我这里指定为8888。
步骤二:配饰Android上网络代理
注意这里手机上连的Wifi要和电脑Wifi一样,在同一网段。
操作: WALN -> 某wifi的网络详情 -> 代理 -> 选择手动
配置为手动后,会有主机名和端口要填,这里主机名填写你电脑的ip地址
,端口填步骤一设置的Port
填写完后保存,这时就可以抓手机上的http包了
获取本机ip地址命令:
Mac:ifconfig en0
Windows:ipconfig
抓Https包
虽然Http的包可以,但这时候Https的网络连接会显示⬆️或❌,这让人很不爽。Https是建立在SSL/TLS层的请求,也就是加了密后的Http,所以这时候是看不到什么有用的信息的。不过Https加密有证书机制,下面就要在手机上配置一个信任Charles的证书,这也是抓Https包的原理
在上面两个步骤基础上
步骤三:Charles添加SSL Proxying
操作: Proxy -> SSL Proxying Setting… -> SSL Proxying
点击Add
可以添加你想要抓的Https连接,这里可以如上图配置,*
是一个通配符,表示抓所有Https的连接
步骤三:下载Charles提供的证书
**操作:**Help -> SSL Proxying -> Save CharLes Root Certificate…
这里会提示下载一个后缀名为.pem
的证书文件,将其保存到桌面
步骤四:手机上安装证书
首先是想办法将这个证书移动到手机,方法没规定,可以使用QQ,微信之类的,只要能在手机中找到它就🉑️
这里用adb命令
完成
命令:
adb push <文件在电脑上的路径> <推送到手机目标路径>
例如:adb push /Users/baize/Desktop/charles-ssl-proxying-certificate.pem sdcard/AAA/charles.pem
我手机上的文件比较多,所以特意建了个AAA文件夹,方便查找
现在证书已经推到了手机上,使用adb推送还需要注意:
-
手机目标路径可以和在电脑上的文件名不一致,adb会自动重命名,但后缀名不要变
-
如果提示
adb: error: failed to get feature set: more than one device/emulator
,请用adb devices
确认电脑连了几个手机,要保证只有一个手机和电脑连接
到这一步,就有差异了,有的手机直接点文件就提示安装,有的手机则麻烦一点,比如我的小米8:
- 设置 -> 搜索
证书
选择安装证书
,然后选择刚刚推送到手机的charles.pem
文件,输入密码,然后会提示填写证书安装信息:
- 注意,用途选择WLAN,不要选VPN和应用
如果顺利,点击确定后会提示已安装xxx
,这时Chartles就可以抓Https的包了。如果安装不成功或者选择不了.pem
文件,那么尝试把后缀名改为.crt
重复安装操作。
为什么Charles配置了Https,还是不能抓App的包?
按照上文配置好 charles 后,赶紧写个网络请求测一测效果,新建一个Android 工程,然后添加网络请求功能,来请求一下百度的网页:
fun requestNet(v: View) {
thread {
var connection: HttpURLConnection? = null
try {
val response = StringBuilder()
val url = URL("https://www.baidu.com")
connection = url.openConnection() as HttpURLConnection
val input = connection.inputStream
val reader = BufferedReader(InputStreamReader(input))
reader.use {
reader.forEachLine {
response.append(it)
}
}
Log.d("yanze",response.toString())
} catch (e: Exception) {
e.printStackTrace()
} finally {
connection?.disconnect()
}
}
}
不要忘了加网络请求权限:
<uses-permission android:name="android.permission.INTERNET" />
这就完成了,来运行一下:
嗯,网络可以拿到数据了,再看一下 Charles 抓包情况:
抓到的是一堆乱码,再换ios系统手机测试,发现ios系统是可以直接抓的,看来是Android系统的问题了。
实际上这是因为Android在7.0系统中进行了一项安全升级。从Android 7.0系统开始,只是在手机上安装了抓包工具的证书,仍然是无法对https请求进行抓包的,还必须要在应用程序的代码中加入一段网络安全配置才行。
网络安全配置
- 首先在 res/xml 下创建一个
network_security_config.xml
文件,然后加入如下配置:
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="user"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
- 然后再
AndroidManifest
中使用它:
<application
...
android:networkSecurityConfig="@xml/network_security_config">
...
</application>
<certificates src="user"/>
起作用的是这句代码,意思是信任用户安装的证书(Charles 证书是我们手动安装的),这样就可以对当前程序进行网络抓包了。
来重新运行程序看下抓包效果:
可以正常拿到网页了,可能 charles 对html做了处理,并不能看到网页源代码,把请求结果下载下来看一下:
确实是在app中请求到的数据,大功告成~
总结
Charles抓包其实很简单,没有一些博客中说的那么复杂,最后总结一些流程:
Http:Chartles设置一下端口,手机配置一下代理
Https:Charles添加一下要抓连接的Host,下载证书并装到手机上
如果还是不能抓包,请考虑一下Charles的版本和破解影响,最后2021,新年快乐~
ps:2021.12.14
更新一下 ios 系统证书安装,ios 和安卓系统配置证书的方式有些不一样,IOS安装Charles 证书 这篇文章描述的简介易懂
参考
https://blog.csdn.net/luochoudan/article/details/72801573
https://guolin.blog.csdn.net/article/details/117192301