本帖最后由 mmortalyi 于 2023-12-23 22:54 编辑
声明本文仅作为技术探讨,如不妥可联系,将第一时间删除本文 本贴为新手向,写的非常详细 分析过程即某某图书馆参考咨询联盟 点击登录,弹出一个简陋的滑块。 看看逻辑是什么 第一个接口,获取图片地址和TOKEN 关键参数 captchaId: captchaKey: token:
全局搜索captchaId的value,captchaId来自于login.action 正则匹配即可 captchaId = re.search(r"captchaId: '(.*?)',", html).group(1)
其余几个value未搜索到,那么搜key captchaKey、token都有,进入下个断点,可以看到 captchaKey生成方法 _0x4471c4 = _0x1b4779(_0x353d93 + (function() { var _0x4887fd = _0x1dda; for (var _0xa5adc8 = [], _0x5cdcca = '0123456789abcdef', _0xccd6e7 = 0x0; _0xccd6e7 < 0x24; _0xccd6e7++) _0xa5adc8[_0xccd6e7] = _0x5cdcca[_0x4887fd(0xce)](Math[_0x4887fd(0xec)](0x10 * Math[_0x4887fd(0x185)]()), 0x1); return _0xa5adc8[0xe] = '4', _0xa5adc8[0x13] = _0x5cdcca[_0x4887fd(0xce)](0x3 & _0xa5adc8[0x13] | 0x8, 0x1), _0xa5adc8[0x8] = _0xa5adc8[0xd] = _0xa5adc8[0x12] = _0xa5adc8[0x17] = '-', _0xa5adc8[_0x4887fd(0xba)](''); }()))
后面一部分是个nonce,还原一下算法(虽然可能没有必要) 里面有一些简单的混淆,解一下,也不会ast,所以苯方法,主要是_0x4887fd这个函数的问题,也就是_0x1dda,进入它 在这儿打个断点,然后copy(_0xd6aec5),复制到js里,相当于获取到了解密函数 解混淆后 (function() { for (var eList = [], ostring = '0123456789abcdef', index = 0; index < 36; index++) eList[index] = ostring.substr(Math.floor(16 * Math.random()), 1); return eList[14] = '4', eList[19] = ostring.substr(3 & eList[19] | 8, 1), eList[8] = eList[13] = eList[18] = eList[23] = '-', eList.join(''); }())
eList[14]、eList[19]可能是检测位置 还原成python代码 def getNonce(): eList = [] ostring = '0123456789abcdef' for i in range(36): eList.append(ostring[random.randint(0, 15)]) eList[14] = '4' eList[19] = ostring[(int(eList[19], 16) & 3) | 8] eList[8] = eList[13] = eList[18] = eList[23] = '-' return "".join(eList)
接下来是token,稍微要复杂一些 关键在于_0x1b4779这个函数,和_0x353d93 + _0x15764b + _0x32b96e + _0x4471c4中其他几个参数,往前打两个断点可以看到就是一个13位时间戳 _0x1b4779看到调用了好几回函数啊,不过看着这32位的返回值 怎么那么像md5呢 我们可以验证一下 那么一句话就结束了 def getMd5(n:str): return hashlib.md5(n.encode()).hexdigest()
timestap = '1703058076634' nonce = getNonce() captchaKey = getMd5(timestap + nonce)
token就是 时间戳+captchaId+'slide'+captchaKey取md5然后+':'+时间戳+过期时间(300000) token = getMd5(timestap + captchaId + 'slide' + captchaKey) + f':{int(timestap)+300000}'
构造获取请求所有参数,并且这个滑块也无需生成轨迹,ddddocr秒了,成功获得validate def getVerification(self): callback = "jQuery19008360078251283902_"+self.timestap _ = int(time.time()*1000) + 3000 url = "http://脱敏/captcha/get/verification/image" nonce = getNonce() captchaKey = getMd5(self.timestap + nonce) token = getMd5(self.timestap + self.captchaId + 'slide' + captchaKey) + f':{int(self.timestap)+300000}' params = { "callback": callback, "captchaId": self.captchaId, "type": "slide", "version": "1.1.14", "captchaKey": captchaKey, "token": token, "referer": "http://脱敏/login/login.action", "_": str(_+1), } response = self.s.get( url, headers=self.headers, params=params ).text response = json.loads(response.replace(callback+'(', '')[:-1]) token = response['token'] cutoutImage = response['imageVerificationVo']['cutoutImage'] shadeImage = response['imageVerificationVo']['shadeImage'] target_bytes = self.s.get(cutoutImage, headers=self.headers).content background_bytes = self.s.get(shadeImage, headers=self.headers).content textClickArr = "[{\"x\":"+ str(generate_distance(target_bytes, background_bytes))+"}]" url = "http://脱敏/captcha/check/verification/result" params = { "callback": callback, "captchaId": self.captchaId, "type": "slide", "token": token, "textClickArr": textClickArr, "coordinate": "[]", "runEnv": "10", "version": "1.1.14", "_": str(_+2), } self.headers['Referer'] = 'http://脱敏/' response = json.loads(requests.get(url, headers=self.headers, params=params).text.replace(callback+'(', '')[:-1]) print(response) if response['result']: return response['extraData'].replace('{"validate":"', '').replace('"}', '') else: return self.getVerification()
def generate_distance(target_bytes, background_bytes): det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False) res = det.slide_match(target_bytes, background_bytes) return res.get('target')[0]
大无语时刻(虚晃一枪)哦天啊,你们知道它的验证密码是否正确的请求不仅仅是明文,而且还不带验证码,(怪不得xxxxxxxx,只能说某些事情发生也不是没有原因的)天啊我前面为什么要分析那么多,这验证码就是个摆设啊,登陆的时候(无cookie,无headers,无validate)完全不用管,白写这么多字。(也就是这个验证码既不起防止机器人登陆的功能,也不起防止密码爆破的作用) 此帖终结 总结这个故事告诉我们,先盘流程再逆向!不然最后会很急。
注:若转载请注明大神论坛来源(本贴地址)与作者信息。
|