逆向抓包大神

0x01 前言

抓包应该是我们逆向的第一步,只有先抓到包,才能决定我们是否要进行脱壳、逆向。万一他没有加密、万一数据不是我们想要的那岂不是白忙活了。但是目前很APP都设置了门槛,比如新版的抖音、淘宝、天眼查等挂上代理就直接无数据或者就显示不出你想要的数据。还没有开始就直接结束了,让人懊恼不已。没办法只能上科技与狠活了。(感谢r0ysue肉师傅,以下很多素材都来源于他)

0x02 普通验证型

这个一般我们设置好IP和端口,导入证书不出意外是没问题。常见的抓包工具fiddler、charles、Burpsuite、httpcanary

0x03 双向验证型

针对双向证书绑定的APP,打印和保存证书,再导入到抓包工具中。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

function hook_KeyStore_load() {

    Java.perform(function () {

        var ByteString = Java.use("com.android.okhttp.okio.ByteString");

        var myArray = new Array(1024);

        var i = 0

        for (i = 0; i < myArray.length; i++) {

            myArray[i] = 0x0;

        }

        var buffer = Java.array('byte', myArray);

        var StringClass = Java.use("java.lang.String");

        var KeyStore = Java.use("java.security.KeyStore");

        KeyStore.load.overload('java.security.KeyStore$LoadStoreParameter').implementation = function (arg0) {

            //可以在此打印调用栈观察信息

            console.log("KeyStore.load1:", arg0);

            this.load(arg0);

        };

        KeyStore.load.overload('java.io.InputStream''[C').implementation = function (arg0, arg1) {

            //可以在此打印调用栈观察信息

            console.log("KeyStore.load2:", arg0, arg1 ? StringClass.$new(arg1) : null);

            if (arg0) {

                var file = Java.use("java.io.File").$new("/sdcard/Download/" + String(arg0) + ".p12");

                var out = Java.use("java.io.FileOutputStream").$new(file);

                var r;

                while ((r = arg0.read(buffer)) > 0) {

                    out.write(buffer0, r)

                }

                console.log("save success!")

                out.close()

            }

            this.load(arg0, arg1);

        };

        console.log("hook_KeyStore_load...");

    });

}

将证书导出后,charles进行证书配置。

逆向抓包大神_第1张图片

ssl pinning 证书在代码中的额外校验:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

function hook_ssl() {

    Java.perform(function () {

        var ClassName = "com.android.org.conscrypt.Platform";

        var Platform = Java.use(ClassName);

        var targetMethod = "checkServerTrusted";

        var len = Platform[targetMethod].overloads.length;

        console.log(len);

        for (var i = 0; i < len++i) {

            Platform[targetMethod].overloads[i].implementation = function () {

                console.log("class:", ClassName, "target:", targetMethod, " i:", i, arguments);

            }

        }

    });

}

objection SSL

objection 中的 Bypass SSL pinning hook的证书种类:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

sslContextEmptyTrustManager

    const x509TrustManager: X509TrustManager = Java.use("javax.net.ssl.X509TrustManager");

    const sSLContext: SSLContext = Java.use("javax.net.ssl.SSLContext");

okHttp3CertificatePinnerCheck

    const certificatePinner: CertificatePinner = Java.use("okhttp3.CertificatePinner");

okHttp3CertificatePinnerCheckOkHttp

    const certificatePinner: CertificatePinner = Java.use("okhttp3.CertificatePinner");

appceleratorTitaniumPinningTrustManager

   const pinningTrustManager: PinningTrustManager = Java.use("appcelerator.https.PinningTrustManager");

//Android 7+ TrustManagerImpl.verifyChain()

trustManagerImplVerifyChainCheck

    const trustManagerImpl: TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl");

    const TrustManagerImplverifyChain = trustManagerImpl.verifyChain;

// Android 7+ TrustManagerImpl.checkTrustedRecursive()

trustManagerImplCheckTrustedRecursiveCheck

    const trustManagerImpl: TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl");

    const TrustManagerImplcheckTrustedRecursive = trustManagerImpl.checkTrustedRecursive;

phoneGapSSLCertificateChecker

    const sslCertificateChecker: SSLCertificateChecker = Java.use("nl.xservices.plugins.SSLCertificateChecker");

DroidSSLUnpinning

DroidSSLUnpinning 这个工具是WooyunDota瘦蛟舞大佬总结的,github上有源码,以下我也贴出来了,他总结了一些常见的证书过检测的方法。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

Java.perform(function() {

/*

hook list:

1.SSLcontext

2.okhttp

3.webview

4.XUtils

5.httpclientandroidlib

6.JSSE

7.network\_security\_config (android 7.0+)

8.Apache Http client (support partly)

9.OpenSSLSocketImpl

10.TrustKit

11.Cronet

*/

    // Attempts to bypass SSL pinning implementations in a number of

    // ways. These include implementing a new TrustManager that will

    // accept any SSL certificate, overriding OkHTTP v3 check()

    // method etc.

    var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');

    var HostnameVerifier = Java.use('javax.net.ssl.HostnameVerifier');

    var SSLContext = Java.use('javax.net.ssl.SSLContext');

    var quiet_output = false;

    // Helper method to honor the quiet flag.

    function quiet_send(data) {

        if (quiet_output) {

            return;

        }

        send(data)

    }

    // Implement a new TrustManager

    // ref: https://gist.github.com/oleavr/3ca67a173ff7d207c6b8c3b0ca65a9d8

    // Java.registerClass() is only supported on ART for now(201803). 所以android 4.4以下不兼容,4.4要切换成ART使用.

    var X509Certificate = Java.use("java.security.cert.X509Certificate");

    var TrustManager;

    try {

        TrustManager = Java.registerClass({

            name: 'org.wooyun.TrustManager',

            implements: [X509TrustManager],

            methods: {

                checkClientTrusted: function(chain, authType) {},

                checkServerTrusted: function(chain, authType) {},

                getAcceptedIssuers: function() {

                    // var certs = [X509Certificate.$new()];

                    // return certs;

                    return [];

                }

            }

        });

    } catch (e) {

        quiet_send("registerClass from X509TrustManager >>>>>>>> " + e.message);

    }

    // Prepare the TrustManagers array to pass to SSLContext.init()

    var TrustManagers = [TrustManager.$new()];

    try {

        // Prepare a Empty SSLFactory

        var TLS_SSLContext = SSLContext.getInstance("TLS");

        TLS_SSLContext.init(null, TrustManagers, null);

        var EmptySSLFactory = TLS_SSLContext.getSocketFactory();

    } catch (e) {

        quiet_send(e.message);

    }

    send('Custom, Empty TrustManager ready');

    // Get a handle on the init() on the SSLContext class

    var SSLContext_init = SSLContext.init.overload(

        '[Ljavax.net.ssl.KeyManager;''[Ljavax.net.ssl.TrustManager;''java.security.SecureRandom');

    // Override the init method, specifying our new TrustManager

    SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) {

        quiet_send('Overriding SSLContext.init() with the custom TrustManager');

        SSLContext_init.call(this, null, TrustManagers, null);

    };

    /*** okhttp3.x unpinning ***/

    // Wrap the logic in try/catch as not all applications will have

    // okhttp as part of the app.

    try {

        var CertificatePinner = Java.use('okhttp3.CertificatePinner');

        quiet_send('OkHTTP 3.x Found');

        CertificatePinner.check.overload('java.lang.String''java.util.List').implementation = function() {

            quiet_send('OkHTTP 3.x check() called. Not throwing an exception.');

        }

    } catch (err) {

        // If we dont have a ClassNotFoundException exception, raise the

        // problem encountered.

        if (err.message.indexOf('ClassNotFoundException'=== 0) {

            throw new Error(err);

        }

    }

    // Appcelerator Titanium PinningTrustManager

    // Wrap the logic in try/catch as not all applications will have

    // appcelerator as part of the app.

    try {

        var PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager');

        send('Appcelerator Titanium Found');

        PinningTrustManager.checkServerTrusted.implementation = function() {

            quiet_send('Appcelerator checkServerTrusted() called. Not throwing an exception.');

        }

    } catch (err) {

        // If we dont have a ClassNotFoundException exception, raise the

        // problem encountered.

        if (err.message.indexOf('ClassNotFoundException'=== 0) {

            throw new Error(err);

        }

    }

    /*** okhttp unpinning ***/

    try {

        var OkHttpClient = Java.use("com.squareup.okhttp.OkHttpClient");

        OkHttpClient.setCertificatePinner.implementation = function(certificatePinner) {

            // do nothing

            quiet_send("OkHttpClient.setCertificatePinner Called!");

            return this;

        };

        // Invalidate the certificate pinnet checks (if "setCertificatePinner" was called before the previous invalidation)

        var CertificatePinner = Java.use("com.squareup.okhttp.CertificatePinner");

        CertificatePinner.check.overload('java.lang.String''[Ljava.security.cert.Certificate;').implementation = function(p0, p1) {

            // do nothing

            quiet_send("okhttp Called! [Certificate]");

            return;

        };

        CertificatePinner.check.overload('java.lang.String''java.util.List').implementation = function(p0, p1) {

            // do nothing

            quiet_send("okhttp Called! [List]");

            return;

        };

    } catch (e) {

        quiet_send("com.squareup.okhttp not found");

    }

    /*** WebView Hooks ***/

    /* frameworks/base/core/java/android/webkit/WebViewClient.java */

    /* public void onReceivedSslError(Webview, SslErrorHandler, SslError) */

    var WebViewClient = Java.use("android.webkit.WebViewClient");

    WebViewClient.onReceivedSslError.implementation = function(webView, sslErrorHandler, sslError) {

        quiet_send("WebViewClient onReceivedSslError invoke");

        //执行proceed方法

        sslErrorHandler.proceed();

        return;

    };

    WebViewClient.onReceivedError.overload('android.webkit.WebView''int''java.lang.String''java.lang.String').implementation = function(a, b, c, d) {

        quiet_send("WebViewClient onReceivedError invoked");

        return;

    };

    WebViewClient.onReceivedError.overload('android.webkit.WebView''android.webkit.WebResourceRequest''android.webkit.WebResourceError').implementation = function() {

        quiet_send("WebViewClient onReceivedError invoked");

        return;

    };

    /*** JSSE Hooks ***/

    /* libcore/luni/src/main/java/javax/net/ssl/TrustManagerFactory.java */

    /* public final TrustManager[] getTrustManager() */

    /* TrustManagerFactory.getTrustManagers maybe cause X509TrustManagerExtensions error  */

    // var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");

    // TrustManagerFactory.getTrustManagers.implementation = function(){

    //     quiet_send("TrustManagerFactory getTrustManagers invoked");

    //     return TrustManagers;

    // }

    var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection");

    /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */

    /* public void setDefaultHostnameVerifier(HostnameVerifier) */

    HttpsURLConnection.setDefaultHostnameVerifier.implementation = function(hostnameVerifier) {

        quiet_send("HttpsURLConnection.setDefaultHostnameVerifier invoked");

        return null;

    };

    /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */

    /* public void setSSLSocketFactory(SSLSocketFactory) */

    HttpsURLConnection.setSSLSocketFactory.implementation = function(SSLSocketFactory) {

        quiet_send("HttpsURLConnection.setSSLSocketFactory invoked");

        return null;

    };

    /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */

    /* public void setHostnameVerifier(HostnameVerifier) */

    HttpsURLConnection.setHostnameVerifier.implementation = function(hostnameVerifier) {

        quiet_send("HttpsURLConnection.setHostnameVerifier invoked");

        return null;

    };

    /*** Xutils3.x hooks ***/

    //Implement a new HostnameVerifier

    var TrustHostnameVerifier;

    try {

        TrustHostnameVerifier = Java.registerClass({

            name: 'org.wooyun.TrustHostnameVerifier',

            implements: [HostnameVerifier],

            method: {

                verify: function(hostname, session) {

                    return true;

                }

            }

        });

    } catch (e) {

        //java.lang.ClassNotFoundException: Didn't find class "org.wooyun.TrustHostnameVerifier"

        quiet_send("registerClass from hostnameVerifier >>>>>>>> " + e.message);

    }

    try {

        var RequestParams = Java.use('org.xutils.http.RequestParams');

        RequestParams.setSslSocketFactory.implementation = function(sslSocketFactory) {

            sslSocketFactory = EmptySSLFactory;

            return null;

        }

        RequestParams.setHostnameVerifier.implementation = function(hostnameVerifier) {

            hostnameVerifier = TrustHostnameVerifier.$new();

            return null;

        }

    } catch (e) {

        quiet_send("Xutils hooks not Found");

    }

    /*** httpclientandroidlib Hooks ***/

    try {

        var AbstractVerifier = Java.use("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier");

        AbstractVerifier.verify.overload('java.lang.String''[Ljava.lang.String''[Ljava.lang.String''boolean').implementation = function() {

            quiet_send("httpclientandroidlib Hooks");

            return null;

        }

    } catch (e) {

        quiet_send("httpclientandroidlib Hooks not found");

    }

    /***

android 7.0+ network_security_config TrustManagerImpl hook

apache httpclient partly

***/

    var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl");

    // try {

    //     var Arrays = Java.use("java.util.Arrays");

    //     //apache http client pinning maybe baypass

    //     //https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#471

    //     TrustManagerImpl.checkTrusted.implementation = function (chain, authType, session, parameters, authType) {

    //         quiet_send("TrustManagerImpl checkTrusted called");

    //         //Generics currently result in java.lang.Object

    //         return Arrays.asList(chain);

    //     }

    //

    // } catch (e) {

    //     quiet_send("TrustManagerImpl checkTrusted nout found");

    // }

    try {

        // Android 7+ TrustManagerImpl

        TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {

            quiet_send("TrustManagerImpl verifyChain called");

            // Skip all the logic and just return the chain again :P

            //https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2017/november/bypassing-androids-network-security-configuration/

            // https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#L650

            return untrustedChain;

        }

    } catch (e) {

        quiet_send("TrustManagerImpl verifyChain nout found below 7.0");

    }

    // OpenSSLSocketImpl

    try {

        var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');

        OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, authMethod) {

            quiet_send('OpenSSLSocketImpl.verifyCertificateChain');

        }

        quiet_send('OpenSSLSocketImpl pinning')

    } catch (err) {

        quiet_send('OpenSSLSocketImpl pinner not found');

    }

    // Trustkit

    try {

        var Activity = Java.use("com.datatheorem.android.trustkit.pinning.OkHostnameVerifier");

        Activity.verify.overload('java.lang.String''javax.net.ssl.SSLSession').implementation = function(str) {

            quiet_send('Trustkit.verify1: ' + str);

            return true;

        };

        Activity.verify.overload('java.lang.String''java.security.cert.X509Certificate').implementation = function(str) {

            quiet_send('Trustkit.verify2: ' + str);

            return true;

        };

        quiet_send('Trustkit pinning')

    } catch (err) {

        quiet_send('Trustkit pinner not found')

    }

    try {

        //cronet pinner hook

        //weibo don't invoke

        var netBuilder = Java.use("org.chromium.net.CronetEngine$Builder");

        //https://developer.android.com/guide/topics/connectivity/cronet/reference/org/chromium/net/CronetEngine.Builder.html#enablePublicKeyPinningBypassForLocalTrustAnchors(boolean)

        netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.implementation = function(arg) {

            //weibo not invoke

            console.log("Enables or disables public key pinning bypass for local trust anchors = " + arg);

            //true to enable the bypass, false to disable.

            var ret = netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true);

            return ret;

        };

        netBuilder.addPublicKeyPins.implementation = function(hostName, pinsSha256, includeSubdomains, expirationDate) {

            console.log("cronet addPublicKeyPins hostName = " + hostName);

            //var ret = netBuilder.addPublicKeyPins.call(this,hostName, pinsSha256,includeSubdomains, expirationDate);

            //this 是调用 addPublicKeyPins 前的对象吗? Yes,CronetEngine.Builder

            return this;

        };

    } catch (err) {

        console.log('[-] Cronet pinner not found')

    }

});

使用方法:
1 attach : frida -U com.example.mennomorsink.webviewtest2 --no-pause -l hooks.js
2 spawn : frida -U -f com.example.mennomorsink.webviewtest2 -l hooks.js --no-pause

混淆

如果APP出现了混淆,使用 objection、DroidSSLUnpinning都无法成功hook住,首先不要慌,我们的目标还是先搞清楚他用的是什么框架。可以hook java.io.File类,因为校验证书的过程中,必然要打开它,通过打印的调栈再结合源码可以分析出到底使用了什么框架。

1

android hooking watch class_method  java.io.File.$init --dump-args --dump-backtrace --dump-return

0x04 r0capture

r0capture安卓应用层抓包通杀脚本这个工具比较厉害,无视所有证书校验或绑定,不用考虑任何证书的事情。
Spawn 模式:
python3 r0capture.py -U -f com.coolapk.market -v

Attach 模式,抓包内容保存成pcap文件供后续分析:
python3 r0capture.py -U 酷安 -v -p iqiyi.pcap逆向抓包大神_第2张图片

 

你可能感兴趣的:(逆向,python,开发语言)