Apache http client 因为从api23起被Android抛弃,因此使用率较低。目前更多使用的是HttpURLConnection类或第三方库OKhttp3.0进行HTTPS通信。其中OKhttp3.0的部分运用与HttpURLConnection相同,客户端都可以通过实现X509TrustManager接口的checkServerTrusted方法,将服务器证书与APP预埋证书做对比,来完成强校验。此外,也可以再通过实现HostnameVerifier接口的verify方法,校验服务器证书中的一般名称(CN)是否与域名相符。通过使用上述方法,完成客户端对服务端的证书强校验。
(2) 应用分析
由于这次是自编译的文件,就不通过APK反编译等方法查看代码了,直接看主要通信类HttpClientSslHelper的源码。
- public class HttpClientSslHelper {
- public static boolean isServerTrusted1 = true; //强校验关键参数
- private static SSLContext sslContext = null;
- public static OkHttpClient getSslOkHttpClient(Context context) {
- OkHttpClient.Builder builder = new OkHttpClient.Builder();
- builder.sslSocketFactory(getSslContextByCustomTrustManager(context).getSocketFactory())
- .hostnameVerifier(new HostnameVerifier() {
- @Override //实现自定义的HostnameVerifier 对象的verify校验方法
- public boolean verify(String hostname, SSLSession session) {
- Log.d("HttpClientSslHelper", "hostname = " + hostname);
- if ("192.168.96.1".equals(hostname)) {
- //根据isServerTrusted1的值进行校验,若为True,则校验成功,执行后续连接
- return isServerTrusted1;
- } else {
- //由于是实验环境,if语句总为真,不会执行else语句
- HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
- return hv.verify("localhost", session);
- }
- }
- });
- return builder.build();
- }
-
- public static SSLContext getSslContextByCustomTrustManager(Context context) {
- if (sslContext == null) {
- try {
- CertificateFactory cf = CertificateFactory.getInstance("X.509","BC");
- InputStream caInput = new BufferedInputStream(context.getResources().getAssets().open("server.cer"));
- final Certificate ca;
- try {
- ca = cf.generateCertificate(caInput);
- } finally {
- caInput.close();
- }
- sslContext = SSLContext.getInstance("TLS");
- //自定义X509TrustManager接口的checkClientTrusted、checkServerTrusted和getAcceptedIssuers方法
- sslContext.init(null, new X509TrustManager[]{new X509TrustManager() {
- public void checkClientTrusted(X509Certificate[] chain,
- String authType) throws CertificateException {
- Log.d("HttpClientSslHelper", "checkClientTrusted --> authType = " + authType);
- //校验客户端证书
- }
-
- public void checkServerTrusted(X509Certificate[] chain,
- String authType) throws CertificateException {
- Log.d("HttpClientSslHelper", "checkServerTrusted --> authType = " + authType);
- //校验服务器证书
- for (X509Certificate cert : chain) {
- cert.checkValidity();
- try {
- //关键点,用APP中内置的服务端证书server.cer来校验网络连接中服务器颁发的证书
- cert.verify(ca.getPublicKey());
- } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException | SignatureException e) {
- e.printStackTrace();
- //校验失败,则更改isServerTrusted1值为false
- isServerTrusted1 = false;
- }
- }
- }
-
- public X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
- }}, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return sslContext;
- }
- }
由上可知,将HttpClientSslHelper类的getSslContextByCustomTrustManager方法重写,重新实现checkServerTrusted方法,让其不修改isServerTrusted1的值,即可绕过证书强校验。
(3) 开始Hook
重新实现checkServerTrusted方法 (编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|