行业知识
【JavaScript 逆向】dy滑块纯算,底图还原,captchaBody,轨迹算法,abogus
2026-10-25 12:58:34
来源:互联网转载
文章目录
- 声明
- 一、抓包分析
- 二、mobile加密
- 三、底图还原
- 四、captchaBody
- 插桩分析
- 轨迹
- 五、结果展示
声明
本案例中所有内容仅供个人学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
一、抓包分析
触发验证码 将返回detail用于下个请求获取图片
通过detail获取图片, id , tip_y(这个后面轨迹需要用到,最开始一直没找到这个值)
通过轨迹生成的captchaBody 进行校验
流程比较简单,最头疼的是jsvmp,还有轨迹
二、mobile加密
直接进js抠出来就完事了,这里直接用Python改写
def mobile_encode(t): """ 异或运算(XOR) """ t = '+86 ' + t def encode_char(c): code = ord(c) if 0 12, 128 | 63 & code >> 6, 128 | 63 & code] encoded = [encode_char(char) for char in str(t)] result = [] for byte_list in encoded: for byte in byte_list: result.append(hex(5 ^ byte)[2:]) return "".join(result)
三、底图还原
打开开发者工具可以算出 返回乱序图片和还原后的图片的缩放比
图片还原可以通过canvas断点找到js还原图片的方法
这里仅竖着切割,我们可以不用去扣js 顺序固定的 [4, 0, 3, 5, 2, 1]
直接改写Python实现还原
def parse_bg_captcha(img, save_path=None): """ 滑块乱序背景图还原 还原前 h: 344, w: 552 还原后 h: 212, w: 340 :param img: 图片路径str/图片路径Path对象/图片二进制 eg: 'assets/bg.webp' Path('assets/bg.webp') :param save_path: 保存路径, /; default: None :return: 还原后背景图 RGB图片格式 """ if isinstance(img, (str, Path)): _img = Image.open(img) elif isinstance(img, bytes): _img = Image.open(io.BytesIO(img)) else: raise ValueError(f'输入图片类型错误, 必须是//: {type(img)}') # 定义切割的参数 cut_width = 92 cut_height = 344 k = [4, 0, 3, 5, 2, 1] # 创建新图像 new_img = Image.new('RGB', (_img.width, _img.height)) # 按照指定顺序进行切割和拼接 for idx in range(len(k)): x = cut_width * k[idx] y = 0 img_cut = _img.crop((x, y, x + cut_width, y + cut_height)) # 垂直切割 new_x = idx * cut_width new_y = 0 new_img.paste(img_cut, (new_x, new_y)) # 调整图像大小 # new_img = new_img.resize((340, 212)) if save_path is not None: save_path = Path(save_path).resolve().__str__() new_img.save(save_path) img_byte_array = io.BytesIO() new_img.save(img_byte_array, format='PNG') img_byte_array = img_byte_array.getvalue() return img_byte_array四、captchaBody
jsvmp 代码结构
jsvmp一般采取补环境(是个webpack)和插桩本文主要讲解插桩日志分析他的算法
插桩分析
有很多个vmp 需要每个for循环处进行插桩,还有关键的运算位置需要单独打印出来
还有fromCharCode charAt charCodeAt都需要打印,有完整的日志才能更快更准的分析出。
console.log('待加密———>',m,'\n加密————>',b)日志中你会看到aes 和 sha512算法
下面这段js你可能会需要用到
function hexStringToArrayBuffer(hexString) { // remove the leading 0x hexString = hexString.replace(/^0x/, ''); // ensure even number of characters if (hexString.length % 2 != 0) { console.log('WARNING: expecting an even number of characters in the hexString'); } // check for some non-hex characters var bad = hexString.match(/[G-Z\s]/i); if (bad) { console.log('WARNING: found non-hex characters', bad); } // split the string into pairs of octets var pairs = hexString.match(/[\dA-F]{2}/gi); // convert the octets to integers var integers = pairs.map(function(s) { return parseInt(s, 16); }); var array = new Uint8Array(integers); console.log(array); return array.buffer;}轨迹
code:500,msg:"VerifyErr" //滑块缺口距离错误code:500,msg:"VerifyModelErr" //滑块位置正确轨迹有问题
五、结果展示
这里就不讲太多了,有问题可以私信我。
abogus这里没有校验,下篇文章再讲。