Xposed学习之《hook某国外app实现自动识别谷歌验证码》
声明
1.所谓的自动识别谷歌验证码并不是真正的利用人工智能去识别谷歌验证码,在本文章中只是对接某国外的验证码识别平台来达到自动识别的效果,其目的就是为了学习下xposed而已。
2.有哪里说的不对的地方还请大家多多指教,本博主邮箱 itdreamlmc@163.com
3.版权声明:本文为博主原创文章,未经博主允许不得私自转载。
前言
本博主作为一个屌丝java程序猿在业余时间总是闲着无聊想逆向搞些app拿来发泄下,一方面是为了提高自己编程上的安全意识,另一方面也是出于爱好。这不,就在周六的时候一个朋友就发了我这个国外某网络电话的app,这个app有的时候登录会出现谷歌的 I am not a robot 验证码,类似国内12306的验证码,我朋友发我之后问我能不能自动识别这个验证码,不用麻烦的每次都取验证。之后我就 google 了一番,偶然发现了 https://2captcha.com/ 这个强大的验证码识别平台,居然可以自动识别谷歌的验证码。于是看了下官方的api文档,发现对接这个平台识别谷歌验证码只需要调用他们的接口给他们传一个k值,然后返回一个id,之后过几秒钟之后用id去请求另外一个接口获取识别结果,然后将识别结果填写到页面的textarea的 value中验证就行了。
那么问题来了
1.要做识别的是一个 app,我们要怎么拿到k值呢?
2.我们拿到三方平台的识别结果又怎么给他设置并显示到app端呢?
这个时候就想起了四哥的文章,利用xposed 可以hook任意app的某偶些方法实现。于是就开始了我的hook之旅..........
抓包分析
还是老套路,拿到app之后,管他是什么鸟app,直接抓他网络请求数据包然后简单大体上分析分析这种验证码图片是怎么返回的?又是怎么验证的?然后去想想解决方案。
1.首先打开抓包神器Fiddler,然后打开模拟器设置好代理ip跟端口(注:需要配置好Fiddler的证书,因为 这个app的验证码是google验证码,自然所有的网络请求都是https的,如果你不设置fiddler证书,那么自然就抓不到他的请求数据包了)。然后打开app登录账号我们会看到如下请求数据跟验证码。(本来想着抓app的验证码了,结果可到好,今天死活也不出验证码了,我就找来下网页的验证码做个参考,验证码都是一样的)
app登录页 验证码 请求数据我们抓到数据之后按照识别平台的要求需要找到一个k值,跟出现验证码的页面链接然后提供给他们,之后就可以了。分析下抓 到的请求数据,我们可以看到对接谷歌验证码的sdk都会有个链接,且里面有k值,如图所示。
k值图打开 https://2captcha.com/2captcha-api 识别平台api文档,找到接口说明如图所示
请求识别接口请求接口
http://2captcha.com/in.php?key=1abc234de56fab7c89012d34e56fa7b8&method=userrecaptcha&googlekey=6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-&pageurl=http://mysite.com/page/with/recaptcha?appear=1&here=now
key:对接平台的token令牌,申请之后就可以看到
googlekey:就是上边所说的k值
pageurl:就是显示验证码的页面地址
拼接好参数之后,请求接口会给我们返回一个id,之后延迟几秒钟之后我们在访问接口
http://2captcha.com/res.php?key=1abc234de56fab7c89012d34e56fa7b8&action=get&id=2122988149
key:对接平台的token令牌,申请之后就可以看到
id:请求接口一返回的ID
获取响应结果如图所示
响应结果拿到结果之后我玩们在给页面的textAreay设置value值为这个,这样可以通过验证了。
设置值Hook WebView搞定app自动识别
上边说了一大堆废话,其实就是一个简单的思路分析。如果我要达到自动识别的效果,其实最终就是给验证码页面里这个textarea 属性设置上验证码的值就行了。那么问题来了,app都是自动去请求谷歌的验证码,我们要怎么拿到请求的连接,有怎么去自定义响应数据呢?刚看到这个app的时候,为以为这个验证码就应该是一个图片,也是应该是imageview显示的,之后分析了分析,发现不并不是。之后Google了一番,才知道显示这个验证码的页面就是一个webview,对于我一个搞后来java的程序猿来说,对安卓自然也不是很懂,然后又不想放弃,所有就想到了xposed这个吊炸天的框架,既然webview能显示内容,那么肯定是通过某个方法,获取url连接,然后请求网络资源,拿到输入流显示数据。所以说,只要我们知道webview的获取url跟响应数据的方法,那么我们就可以通过xposed去hook这个方法,然后就可以轻松的获取参数响应数据了。
Google了下,就看了这篇文章 http://blog.csdn.net/qq_19431333/article/details/52351437 ,才发现webview请求网络资源的时候,都会调用 shouldInterceptRequest 这个方法,如果这个方法的输入流不为空,则直接获取输入流显示数据,如果这个输入流为空,那么webview 就通过url去请求真正的网络资源。既然是这个样子,那么我们是不是可以来hook这个方法,来判断url是不是我们想要的url,如果这个url有k值 那么我们就去获取这个k保存下来,如果这个url是验证码页面的url,我们拦截下,通过url获取网络资源,然后通过第一步保存的k值去请求三方平台,拿到识别结果才替换进去,给app响应自然就完成了识别。下边是具体实现。
shouldInterceptRequest方法开启webview允许js调用,允许js弹窗
webView.post(new Runnable() {
@Override
public void run() {
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
}
});
调用三方接口获取识别接口
调用三方给textarea设置属性(这里是插入一段 js代码,获取textare document对象进行设置)
设置识别结果String replace = string.replace(oldStr, "测试提交啊");String jsText = "mytoken='"+ globaToken+ "';"+ "function testCall(){alert('success');document.getElementById(\"g-recaptcha-response\").innerHTML=mytoken;}";replace = replace.replace("", jsText + "\n");WebResourceResponse webResourceResponse = new WebResourceResponse("text/html","utf-8", new ByteArrayInputStream(replace.getBytes()));param.setResult(webResourceResponse);
之后打包apk按照到手机上就可以了。
收工,讲的不好请多多关照。