JS逆向:某验点选验证码加密分析

前言

好久没发文章了,自己越来越懒了,当然也存在一些其他的原因。

这次来个某验的点选。点选验证码没有看上去的那么神,验证的话主要是传点的坐标,对于轨迹的验证并不严格,或者说根本没验证轨迹。点选的轨迹,你自己点几个体会体会,其实是很复杂的,不像滑块那样容易判断。

Go

打开网站,本次选择的网站是A+1站。直接登录一下,抓包。对不起,又要骚扰电话号13+9个8的大哥了。

重点请求有两个,分别标了红色,一个不太确定的请求标了黄色。先看一下参数和响应内容。

第一个ajax.php,gt、challenge、pt、以及巨长的w:

响应里没什么东西,看一下只有一个result,click应该代表着验证码类型是点选。

第二个是get.php,一些常规参数,应该多数都可以写死:

响应的话,验证码的图片链接就在这里面了。这里的图片也是一个原图,并没有做切片处理。

第三个,想必就是结果了。

没什么可说的,重要信息都在w里。

我们先重点看一下最后一个,也就是进行验证的请求。

依旧是Initiator定位到关键代码处下断,用其他的方法也可以,都一样的。

点一下登录就断下来了,不过这里并不是我们需要的。第三个请求就是提交结果,那我们只需要跟点选完点击确认后的包就可以了。所以直接过掉,F8让他正常往下走。

也就是在这个地方的时候断下来就可以

跟着调用栈看一看,找找w的来源。

最后定位到这,大概是这里来的。

为啥呢,因为这个unicode就是代表字符“w”:

可以知道w是由c和_拼接而来。这个代码混淆的有些不太方便看,我们用AST处理一下。我只是简单的还原了一下可读性,如果想深入还原,自行处理吧。。

里面GZPdy开头的函数是在源代码里拷出来的,也就是开头的那几个函数,是这段代码中的解密函数。他这个解密函数不算复杂,直接解就可以。

接下来做什么?你肯定在想,FD替换文件啊。好的,小伙子我觉得你已经懂的够多了,不需要再看下去了hhhh。然鹅,没有那么顺利。我注入代码后发现过不了检测了,看来他的代码里有CRC校验,检测出我们对他的代码进行了改动。对此,我们有两种方法,第一种,找到CRC检测的地方,干掉他。第二种不处理原网页代码,对照分析。我选择第二种了。最近分析了一些站,由于懒。。懒得还原混淆,有些习惯直接硬撸了,所以不费那精力去找了,何况想找出校验的地方也不会那么轻松的找到。

回到网页里,刚才我们找到w是由c和_拼接来的。往上翻一下就看到c和_了:

这什么东西,看不懂。那就看看反混淆后的代码长啥样。找一行附近的代码,要确定不会被反混淆处理的,否则是找不到的,然后拿着他去我们的代码里搜。

_调了一个779的方法,a是对一个东西encrypt加密,然后再处理一下得到了c。我们先看看_,调用这个方法每次得到的结果都不一样。这么长的一个东西,肯定不会是随机来的吧。。。

进这个方法里看看。

然后就看不出什么了,下个断。后面的参数是一个字符串

这段代码是如果ke这个字符串存在,就返回ke,如果不存在,就调用$_Io()赋值给ke,相当于单例模式。

看看$_Io是什么:一个平坦化,加上几句废话,实际上就是4个oe()拼接

这个oe返回一个四位的随机字符,自行验证..所以这个方法就是,判断有没有已经生成好的ke,如果没有就生成一个16位随机字符的ke。然后跳出去,看看这个new H():

对照着看,你这个setPublic提起了我的兴趣..公钥 RSA呗,怪不得每次结果都在变。

_就完事了,然后a:

先看看他两个参数都是什么

后面那个就是取出前面的16位字符串:

前面的就是验证信息了,他们两个传到X[$_BJJCm(374)]里:

老规矩,看看反混淆的:

iv,16个0,加上传进来的这个东西是16位字符串,和下面这种写法,我明白了。你呢?

就是AES啊,国际用法RSA+AES,RSA负责加密AES的密钥,而AES用来加密数据。非对称加密,安全是安全,速度也是很慢的,就注定他不适合加密大量数据。

这里是用的字节流方式加密,所以结果也是一个字节流

这个函数,看来就不是base64了,可能是他自己写的一种编码

你也甭管他这是啥,用就抠就行了,也不是太复杂,改写其他语言也不难~~

最后一个谜团就是上面一大坨的o都是什么,其实我刚看到这个o的值的时候,心里默念了一句草(指一种植物),玛德看上去很多加密,后面发现其实里面很多都是可以写死的。往上找就完了,不过要往上找的稍微远一点:

依旧是对照着看:

我就挑重要的说一下了,passtime,看名字你都知道,从点击验证码到结束花费的时间。a,重中之重。

看出来了吗?坐标啊,只不过是个百分比的形式。pic:图片的url

tt,麻烦一点,传了三个参数。

后面那两个可以搜一下,原来是前面的get.php里返回来的。

然后就是e,也就是s

这个东西也是不变的,感兴趣可以跟一下看看他是啥。

ep,没错,里面的ca是轨迹。但是你试一下就知道,在点选这里,根本没有验证轨迹,所以。。不传或者写死也无所谓。

tm有时候也会是一些奇奇怪怪的时间戳数组:

然后o的第一部分加密就结束了。看下第二部分:

gt和challenge都是知道的,前面发包的时候都拿到了,passtime也知道。里面执行了非常多不仅限于以下截图的套娃函数


最后拼接取小写

就完事了,这就是o里的全部内容。

第二个请求get.php里没啥子东西,直接提交就行了。而这第一个,能不能省不省先不说,咱也不知道,不过来都来了就康康吧。

这丫并不是前面那个7000行的click.js了,变成1万+的fullpage.js。不过都一样,这个fullpage主要是用于无感验证的,其实很多方法都是互通的。

直接搜下w的unicode:"\u0077",结果不多,就三处,全打上断点刷新

有点尴尬,没断下来。。没事,那我们还是按之前的方法找。最后定位到这里

老规矩。。。

好,现在知道PiLp就是w了,然后线索就断了。。这波不慌,反向搜索(1330)

继续刷新,差不多的东西····

比较有意思的是captcha_token,是对他的两个函数toString然后取哈希,也就是验证代码是否被修改了,按真实的值写死就可以。

其他的东西都是验证一些指纹,包括声音js、显卡信息等,也是很多东西都可以写死的。。都不难,麻烦一些,略过,大家自己动手找一找吧。最后看看随手记的小本本→.→:

反正基本上你把这个请求的参数都补齐,无感也就搞定的差不多了。

总结

有一些小伙伴问我之前的文章怎么都没了,一些原因。。没有做脱敏,闹了些不太愉快的事情,所以暂时都被我下了,之后还会不会还原,看情况吧。。。包括这篇文章,我也没办法保证会留多久。。逆向方面的东西比较敏感,很多都是你一举报一个准。

其实写文章的本意是记一下思路,自己之后方便看。很多东西我也是现学现卖,一些技巧很久不用也会忘记,哪天真遇到的时候对这个有印象,一翻就出来了。不想被有心人利用。

说多了。某验要比某盾某美难一些,主要是流程长,麻烦。。点选相比其他几个算是比较简单的,主要问题在于坐标的获取。无感是一个完整环境的模拟,滑动的难点就在于完美的一套轨迹。多搞几个,你就会发现其实验证码也就这点东西。当然,刨除那些真·非人类的验证码,没读过几年书不配上网那种。。

一些地方分析的比较粗糙,能力有限难免疏漏。如果有疏漏的重点或者错误之处,还请各位指出。

推荐阅读更多精彩内容