提示!本文章仅供学习交流,严禁用于任何商业和非法用途,如有侵权,可联系本文作者删除!
网站链接:aHR0cHM6Ly93d3cuZ2VldGVzdC5jb20vYWRhcHRpdmUtY2FwdGNoYS1kZW1v
无感验证码:
看看抓包信息,发现请求了两个接口:load、verify,之后看看这两个请求的传参和返回值,首先是load接口,传参如下:
params = {
"captcha_id": "24f56dc13c40dc4a02fd0318567caef5", //定值(可能会根据网站而变化,根据对应网站修改即可)
"challenge": "49e7bad3-1104-4fa2-9159-04bf946db2bb", //生成的uuid
"client_type": "web",
"risk_type": "ai",
"lang": "zh",
"callback": "geetest_1659082343806" //geetest_+当前时间戳
}
返回的参数主要作为verify的请求参数及生成加密参数用的。先给一下uuid的代码,这里就直接给python版的:
def uuid():
def S4():
return hex(int((1 + random.random()) * 0x10000)).replace('0x', '')[1:]
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4())
再来看看verify接口,传参如下:
params = {
"captcha_id": "24f56dc13c40dc4a02fd0318567caef5",//定值
"client_type": "web",
"lot_number": "894175f1770c4573b766c3d87d6fe40e", //load请求中获取的
"risk_type": "ai",
"payload": "GJCKWcAsxxUNcdmX4RCcZ8w4OyV9A2J6AX8SxERed3iWY1tCAixXFcDy2AYYOU46maJOolM1LjAj4536LB6TwTTrYkthVHuVJDRuGzjlqWl1L7UyjkUVpizoT5Uhc4iinjYo6tUDtTej4dVYgfK_ml24nPZnGiu6WOmYJuRyI794CPXjz1_mWFxTJVVprV_OSS3gHHEQtvYSSLxVn-o5yScsFdS3hcIyo11HIwo-IISWhxK5DL9Hzz6-QQ_I2aSKzs4SgiqrdWI44PVKlrRLFZBIg-PZyxzrOaSzwhaJvnMOBHeSvYZCHjnehA8A9M8lrIHJuRL3B0N_uUNaRBrGC4jZa8BkpA_0-txVR_ljNmVkHbdhn-t3vfnzqCXVKLsFUEXDHjXL6t-laKxq_KWvcSV_ZK3XVPFnZHEQumcNtWy0V3nPfD5VUn2hMP1tSwvEzMxSMsgHZN4QdchKWrPuJYFyQox-pYo16_myt3NaWEqpdZ-qPpyoginpTKOOjuCVoYLOHVK5xBRU5SL5-AovitvW4Q2PXzEoQMOBBX05CHd2BgfurbiURUsxIL3trqsa", //payload-> load请求中获取的
"process_token": "bc4bfbc821c882289d0b2a1952638e02b55cef6cccd5ce4967a652c77ac75a74", //load请求中获取的
"payload_protocol": "1",
"pt": "1",
"w": "2f5f85ee6b22593f9e69955f93adf3f25f89dd1ab4827b9981a8de373ae42875e0c957dd9761787b4dbcfe85942e268d8fe31e6a38fdbfb1a6bee4380a2bb19bac758da2e108cba4a96685d58c31bbcbed0538ceaa81b9635a76cadbf35e95c67b9af25f37f7160b294740bdc2eb41aa803897c55d8b1473564021045c142e25dca59153b85201f3d42f68354c5cb37b200fab6a4476a3279c366a3d194ea7c2330c2f4c108971f9a49ace6196692c0647d32fc878b90e7728e004e1864f5553912f350348721f79e6ebda17bfc42d5b3429f8d2dace91f75d9f0ea16e7e59d712fbb8de2f7ec3ffbe4e0b906c49b8133f5bc2f339f150286090f2082eb1678253da509adcaf3bf150e75e1ef85db92765d591ec5b5833c8a822d38bb1fae3b4b1cd79d1d3eb4090b06bb941a095d582bf2bf34d607f72484696519d3c906112e0793f846707afbafcef4bf3c49cce599f9147290fd6cdb5a6b1d58335b2366dfc1822006c5c37fe9b6f0b7f43b2a3ef419cb63aaede2ba34a5d47bf43ca31f65bdac5039e7c985773ae7a9609ec7f10cca28094caab42345de25dee1711d420855fff60c8c11c8c4635495ab4969ea3b0d5e03db9779c32bda2d2fcc763cafb225372da7786e24649cc6a0a0d4b624b0c23b7a6b897db69d621011d754d579330a4ba8a25770aeec6a3a54f53bbd5d3ac20e701e8f5f482423d23ffd52137cf", //需要逆向的参数
"callback": "geetest_1659083827590" //geetest_+当前时间戳
}
返回的参数中有后续请求需要的校验参数。经过上面分析之后很明显无感验证只需要解决w参数即可,下面就直接开始分析该参数如何生成的,在分析之前先做如下准备:
1.找到加密参数所在的js文件-> gcaptcha4.js
2.进入该文件能看到js是混淆过的,所以这一步需要使用ast解混淆
3.拿到解混淆之后的文件,将网页中混淆的文件替换成还原后的文件
4.通过全局搜索的方式定位到加密参数的位置
关于如何解混淆,网上可以自行百度,做完以上准备之后,在加密参数参数的位置打上断点,如下:
上图能看到w参数就是圈出来的r参数,r参数是通过将a参数及转为json字符串后的e进行加密之后得到的,所以目标也就很明确了,找出e和a怎么生成的以及找出加密函数即可。这里先看下e参数,如下:
经过简单分析得出如下结论:
{
"device_id": "211D", //定值
"lot_number": "6c893106f7aa42e19d40317be588d8f2", //load请求中获取
"pow_msg": "1|0|md5|2022-07-31T10:10:23.198209+08:00|24f56dc13c40dc4a02fd0318567caef5|6c893106f7aa42e19d40317be588d8f2||df11a409efc91f36", //需要继续跟堆栈找到生成方式
"pow_sign": "8c300a031decd0905af9454f7d3473a3", //需要继续跟堆栈找到生成方式
"geetest": "captcha", //定值
"lang": "zh", //定值
"ep": "123", // 定值
"h8ff": "188412788", //需要继续跟堆栈找到生成方式
"em": {"ph": 0,"cp": 0, "ek": "11","wd": 1, "nt": 0, "si": 0,"sc": 0}
}
这里先说一下h8ff这个参数,如果有逆向过某验3代的同学应该一看就能知道,这就是某验3代中提到的随机变量,该值是根据gct.js这个文件而变化的,关于该值具体的分析过程就不说了,大家跟一跟堆栈分析下就可以出来了
继续分析,看了上面记录的部分,很明确的就能知道接下来需要干嘛,大家可以在当前断点位置继续往上看,然后会发现并没有找到pow_msg、pow_sign这两个参数哪里来了,这个时候往上一个堆栈看一下,很快就能看到,如下:
这里就直接定位到这两个参数的生成位置了,接下来就很简单了,直接逐一分析,然后抠代码即可,如下:
这里直接按照上图的方式将对应的函数打印出来,然后点击跳转过去,之后将代码抠出来即可,至于传的参数上面都可以看出来是啥,要么是在load请求中就可以拿到的,要么就是可以直接写成定值的,完成之后如下:
这里需要用的加密方式可以自己导入下,就是图中导入的三个,然后将原代码中的替换下,这样就不用去抠它的加密算法了,到这里e参数就分析完成了,接着看看a参数,如下:
看到这么多参数不用慌,既然知道该参数可能需要参与到加密运算中,那么直接跟到加密逻辑中,看看会用到哪些参数,到时候补一下这些参数即可。直接在控制台输入如下,然后点击跳转到加密位置即可:
之后就是打断点单步调试,逐一分析,之后我们发现其实a参数中最终就是拿了一个pt值,通过pt来走不同的逻辑,如下:
所以最终进行加密的时候只需要传e参数和一个pt值即可,而pt是可以直接在load请求中获取到的,至于如何抠这里的代码,大家可以分析代码的时候就可以看出这其实就是一个webpack,所以大家可以按照扣webpack方式将关键代码抠出来就好了,首先是加载器,然后是对应的函数,不报错就可以了,最后将要是用的函数导出来即可,不会抠webpack同学可以自己去找相关文章或者视频看一下,这里就不细讲了,要抠的函数主要是下面几个,之后在要使用的位置调用即可。
最终完成之后如下:
接下来就是验证结果了,如下:
这里能看到全是成功通过,无感验证到此分析完毕.。
滑块验证码:
依然是从抓包信息看起,走一个完整的流程,如下:
可以看到请求的接口和无感验证是一样的,只不过参数不同,先来看看load请求中的传参:
params = {
"captcha_id": "24f56dc13c40dc4a02fd0318567caef5",//定值(可能会根据网站而变化,根据对应网站修改即可)
"challenge": "f9c423a5-1857-464d-b117-c4b395bba7a0",//生成的uuid
"client_type": "web", //定值
"risk_type": "slide", //根据验证码类型改变
"lang": "zh", //定值
"callback": "geetest_1659360967681" //"geetest_"+时间戳
}
返回的参数主要作为verify的请求参数及生成加密参数用的,还有滑块及带滑块缺口的背景图,这个就没啥好说的,再来看看verify接口,请求的参数如下:
params = {
"captcha_id": "24f56dc13c40dc4a02fd0318567caef5", //定值
"client_type": "web", //定值
"lot_number": "d3141ffd05bb470a99596b47e5f86c9a",//load请求中获取
"risk_type": "slide", //根据验证码类型而改变
"payload": "GJCKWcAsxxUNcdmX4RCcZ6TU3H3KZa6tghFmUeSHqAO8PZzghuW9_8XR-PCM56xAttq4z_jwiwHvAhZKjH2ED5TS9zm0zd7q1oCfhKMWDqmj3amOLEfwyPFMqfhv3Px0LfmcLunAX_i2MAWxbBCK5wIIEaFcqXkcHgMVndqDQgHWcVYQNTuXdKcsG9aZbFC7kwr7F66U-K3cdQytA7mFamcb80GlWmoQSoK4m3jWtFvckAKoT1gbb6pVHZZuveGYqd0Jd0OiPaPsikFc8hHwyMmrL-A2zFTpIlZbW2d3TF5l9M5wC8WmWzj-ZjHHAJrVV2bQghM-YDnW0YarIm1n7IeeCJSLIcOeaQTBVl38Wc0j718XINZ69DU2xVeX14oCQjR_kOhqe5K4u7m1kTYjeAoNeCY_ifO9yVnRkKhg8zZVcI5x0PHSsWo5r8s40qrn-SlYFxJVqiyL2eoyVLMgL-vADpH7VCoU9QCEWstnm6nuuUqVMc_YOdnvhqnGybMnc6LECyObUJ1d9sH89utnyEnBM6Tqax0XCis2G3f2XIMRLWqItQGLsNEMCpZCmWn1LfTFUE9YIIms7pzd0mnTzASvUJzuIJZPURLw8PTh4Dg=",//load请求中获取
"process_token": "6a6a4452a2bea22e5e32e4bcf8ee601effdbff515f9f3ff57f142731ecf8336d",//load请求中获取
"payload_protocol": "1", //定值
"pt": "1", //定值
"w": "18eb6a10e05018206aacfab0b8a8993ff20083582469fda2253f078509c3ed0bae76186a5ab9c9e41e0afb607b3640bfff887a17d685995467d5e9d79c09fe43c361e4f929615071cd82e7b139598af20b330d62d64fe2800bfd3a008df4befb8a0d50179ab110589886d08e268c529189aafbe42949f2e5e93df17a3026c958b6d49de4aaaba0f781dfef0650bb0951b3889b53a7a833746cdfb400db8ab2336c8c60fbb442389a0b159dd90911276464f8ea274de6e2e40b7a3376a9ab164edb6c7cfe1f505137377d9d87638ee25b8ed10e70393ecd6c6b5abcd4c41964c414e8e7ec7ff35a2088430fd432eac9cc92bdefb20dda1415bdddf6df71d2f07cf231ce320ae01e5568d79937ab7a759504bdd4b73bc968042329aa3e7e7d4e7e4249f4ff00d5b4fce46a16c70fa3c2b2b4bc70a242a663b2ec9e71e798686bf0fcfff96292142e6b5cdf9db56fc7156129a4e20193a07476b03bb00db5dc671eedcf9cc97aa8ec1cbb0602efd30482d11bde4f49f3a0a46647bbe5de38dcc0b8899eafc0263f6dfb7f9803aef2182f338e4bbc08a92f484b672af85fdb0c2866dd703c58ac9adc39599c8cc8f21104780089cabb5b54ca5e924ed3cdc9ab2d51ce17d2331193cc06b425348e0ce63cb5da79c9789a17642e25ba506930a630b871f4413d1304d0b0cb746dd6a308c29745d2e3753ff0c33f5646a2acf3185d8df07443d08b9bdef992513cc170506c62cc97b7afc6412b3a20e221547acde8d134034e9aacce40683e5ded3cce008a74883c0d7c3a97c962d3c39836e8ccd5620823f9173d71983fe2e9b239b44d3296f7b5fd689cd5874e4032f2d639ec4daffb594590217e3a3c56923edbd569c5fab98e2469aef12c2666b7ed4b6769445507cbe70938bc33aaefda7108b444f07c97114a30ab5db8e5e1c83c104b505e0fa31a162900acd820b87ac3e6851bce29c0bbc8f0b609b63ed531683cdf49e512b587b984e45422f0cd4223e9c86258c66379ec608c84c6f7769a9545941756f7544c16228da9f1cfb9df08418dd5f3ac187156816ad335a76201938b068e1b327ff57d4585e66c6058f1616898401acfd5dc842f019d4691094db4084bc96c5ccf1dc745cf30c9704f04e84b6f9e771d33c40f73f20198f19bc67e735a1803369587e6f8e082fdfae452189678fffcf82ffd3b8378442042d0f23412fb8915c1869fd9012fe46f8bf0ded3d1e34a5f4a02ac02bd76c6b03476a3227c595a3c3d19864dfaa5aaf754f8e7327106fd70a895ebb1522c101597500d773926ce07984da631d31b6bf124c85ac94429690a8a7000f6f0dc1d4b61281386ffadc36b8211a3a5b5817386742835ecdc384346481ccf16654e147c7fe3d778b30c63f3b167eb93c27b897944ec5b21d4b22e1fce231c838348c0d99382481e6202937871db20055375e0df5df19efc20ad3cea9ed5295b80ef5c8ee1ba9b7e5314aa821cb231992b2763998aca74a54a65855301", //要逆向的参数
"callback": "geetest_1659361005049" //"geetest_"+时间戳
}
这个请求参数也是和无感验证一样,所以本次需要逆向的也只有w参数,过程也是和逆向无感验证的中的w参数一样,首先还是在如下位置打上断点,断住之后如下:
这里将e参数也给打印出来了,接下来分析下这个e参数:
{
"setLeft": 174, //滑块移动距离
"track":[[53,124,0],[3,0,117],[5,0,8],[7,0,8],[10,0,8],[12,0,10],[13,0,6],[15,0,8],[15,0,8],[14,0,8],[13,0,8],[11,0,8],[12,0,8],[6,0,8],[6,0,9],[3,0,7],[1,0,8],[1,0,8],[1,0,33],[1,0,9],[1,0,6],[1,0,25],[2,0,17],[1,0,6],[1,0,10],[2,0,6],[2,0,16],[1,0,9],[1,0,17],[1,0,14],[1,0,40],[1,0,8],[1,1,16],[1,0,40],[1,0,33],[1,1,7],[1,0,25],[1,0,87],[1,0,32],[1,0,24],[1,0,56],[0,0,248]],//滑块轨迹
"passtime": 1029, //轨迹滑动总时长
"userresponse": 172.971396760597, // 滑块移动距离/t["$_BGDd"] -> t["$_BGDd"]这个值可以写死
"device_id": "211D", //根据不同的验证类型变化的,对应的验证类型写死即可
"lot_number": "9977c42b7b7846fc907c440f0c901c89", //load请求中获取
"pow_msg": "1|0|md5|2022-08-01T23:09:32.451046+08:00|24f56dc13c40dc4a02fd0318567caef5|9977c42b7b7846fc907c440f0c901c89||571b63846a3eced2", //
"pow_sign": "d9a29389e9713607e83583e43101ce26", //与pow_msg一起生成的
"geetest": "captcha", //定值
"lang": "zh", //定值
"ep": "123", //定值
"bukt": "1724257643", //随机变量,根据gct.js文件变化
"em": { "ph": 0,"cp": 0,"ek": "11","wd": 1, "nt": 0,"si": 0,"sc": 0 } //定值
}
这里的e参数相比无感校验的时候多了些东西,同时也有些参数是在无感验证的时候生成过的,比如pow_msg、pow_sign,这里直接将生成方式拿过来用就好了,上面各个也都注明了,所以只简单说下setLeft、track、passtime这三个参数,首先是setLeft滑块距离,这个可以使用哲哥开源的ddddocr来识别出距离(点击即可跳转到github地址),这个库真的超级实用,至于具体的如何使用可以到github上,也可以直接看公众号中另外一篇文章js逆向验证码篇之某盾,里面有相关的源码,直接拿过来用就可以了,唯一要注意的是该源码在最后返回的距离上加了10,在这里使用的时候直接去掉即可。之后来说一下关于track滑块轨迹的问题,先看下图:
首先能看到track滑块轨迹就是c参数,而c参数是根据_参数来生成的,然后看下_ 参数和c参数各是什么
上面左边是_ 参数,右边是c 参数,_ 参数我称之为累积滑块轨迹,c 参数称之为非累积滑块轨迹,什么叫累积滑块轨迹呢,不管是左图还是右图,每个数组第一个元素都是代表滑块距离,第三个元素代表用时,只不过左图的滑块距离是一个累积的,也可以说是代表当前总的滑动距离,而用时代表当前为止总的用时,右图的滑块距离是一个非累积的,代表当前滑动了多少距离,而用时代表滑动当前距离所消耗的时间,到这里就解释完了上面的滑块轨迹,所以模拟生成这个滑块轨迹也就有了两种方式, 一种是模拟累积滑块轨迹之后抠出代码中的转换函数转成非累积滑块轨迹,另外一种就是直接模拟非累积滑块轨迹,具体的轨迹生成大家可以在网上百度到,这里就不贴出来了,passtime可以自己设定一个随机范围,也可以在模拟轨迹的时候一起生成。
当以上这些参数全部弄好之后,也就代表着e参数好了,之后就可以按照无感验证一样的方式将e参数加密,然后就能得到w参数了,这个加密函数在无感验证的时候就已经抠过了,这里直接复用就好了,最终结果如下:
能看到已经生成了w参数,最后将整个步骤完善一下,测试下最终的结果:
测试了10次,全部都是成功的,这个成功率还是非常高的。最后补充一个坑,不管是在无感验证还是滑块验证中,最后的e参数里面都是有一个随机变量的,这个随机变量会根据gct.js这个文件变更,如果这个值写成定值的话,有可能会导致最终即使通过了验证,但是用返回的token之类的东西去请求数据接口的时候不返回数据。整个过程是比某验3代是要简单很多的,所以逆向的过程也感觉容易很多,至于后面的点选、消消乐也都是差不多的分析方式,整个流程也是一样,无非就是e参数里面的某些参数不一样而已
欢迎关注公众号:【时光python之旅】 (在这里你能学到我的所见、所闻、所思、所学)