[Web逆向]某某省过验证码逆向---------小白讲解09

本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关.本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责

感谢各位大佬的支持与观看

目标网址:aHR0cHM6Ly93d3cueW5qempnY3guY29tL2RhdGFQdWIvZW50ZXJwcmlzZQ==

前情提要

-------------------------------------------------------------------------------------------------------------------

这一篇我们直接开始讲解主题 :

过完验证码获取到数据这个栈每次翻页都需要过验证码 因此 数据也就在 请求验证码的数据包里 如下图

图片 1.png (310.23 KB, 下载次数: 0)

下载附件

2025-4-15 14:42 上传

所以 对于这个栈我们就需要 只对验证码进行分析 从而请求到我们需要的数据

-----------------------------------------------------------------------------------------------------------------------

第一步

1.1 我们先来分析出 浏览器是通过什么流程 获取到 验证码的 (其中包括 数据包 某个参数 还有图片),

我们可以刷新验证图片 或者 将整个网页都进行刷新,那么我们也只有这一个包

图片 2.png (316.8 KB, 下载次数: 0)

下载附件

2025-4-15 14:44 上传

1.2 这个包里面的数据我们可以看到 是 一些密文 我们在控制台打印来一个个分析

1.2.1 bigImage: 解密下载之后是 验证码的背景图

smallImage: 解密下载之后是 验证码的缺口图片

slideId: 后面参数加密需要

yHeight:目前对我来说 是不知名参数(哪位大佬研究出来是什么 希望评论或私信给我,感谢分享)

图片 3.png (22.33 KB, 下载次数: 0)

下载附件

2025-4-15 14:46 上传

1.3 分析的到位,接着我们就来搞掉这个载荷的密文

进入genVcode数据包 在这里我们可以刷新验证码来断点,不用刷新浏览器

图片 4.png (71.77 KB, 下载次数: 0)

下载附件

2025-4-15 14:47 上传

图片 5.png (283.19 KB, 下载次数: 0)

下载附件

2025-4-15 14:47 上传

1.4 在 send方法里面就是我们要的载荷的密文,经过多次的调试 加密的密文显然不在这里,

这一点可以验证我们在 这个函数的开头下断 如果没有密文,那他就是在这里面,

如果是传入的那我们就需要向上跟栈,去找,如下图

图片 6.png (37.61 KB, 下载次数: 0)

下载附件

2025-4-15 14:48 上传

1.5 我们刷新验证码让断点生效,我们看到了,密文是从上一个栈 传入其中

,所以我们就向上跟栈

图片 7.png (249.84 KB, 下载次数: 0)

下载附件

2025-4-15 14:49 上传

第二步 我们根据箭头向上跟栈,到第四个箭头处,在这里有个拦截器,

我们可以依次进入,在return处下断,在重新发包,让断点生效,

也就是进入到 i 里面

图片 8.png (79.69 KB, 下载次数: 0)

下载附件

2025-4-15 14:50 上传

图片 9.png (30.45 KB, 下载次数: 0)

下载附件

2025-4-15 14:50 上传

2.1 接着我们来展示 i 里面每个函数的下断处,我们让断点生效时

需要将其他断点取消 ,只留这几个 ,拦截器的断点也要取消

图片 10.png (33.08 KB, 下载次数: 0)

下载附件

2025-4-15 14:52 上传

图片 11.png (9.31 KB, 下载次数: 0)

下载附件

2025-4-15 14:52 上传

图片 12.png (21.61 KB, 下载次数: 0)

下载附件

2025-4-15 14:52 上传

图片 13.png (17.84 KB, 下载次数: 0)

下载附件

2025-4-15 14:52 上传

图片 14.png (15.61 KB, 下载次数: 0)

下载附件

2025-4-15 14:52 上传

2.2 最后在Pt.interceptors.request.use 函数体内 停下 我们也看到返回的内容里面有我们需要的密文

所以为了 检验是否在这里面 生成我们在头部也下断 ,另外其他断点就可以取消掉了,以免扰乱思路

图片 15.png (34.02 KB, 下载次数: 0)

下载附件

2025-4-15 14:53 上传

2.3 我们来发包看 密文还在不在 不在就是这个函数里面的 在那就还需要向上跟栈 我们发现出现了明文,

所以我们知道了 密文应该是这个函数里面 生成的,所以,我们就在这个函数,进行调试,来寻找看有没有我们想要的

图片 16.png (26.07 KB, 下载次数: 0)

下载附件

2025-4-15 14:54 上传

图片 17.png (44.59 KB, 下载次数: 0)

下载附件

2025-4-15 14:55 上传

2.4 我们点击图片中按钮来进行代码的调试,因为单步调试会进入其他不相干,

比如只会返回 true或 false所以 我们就直接跳过来查看 看密文 在哪出现

图片 18.png (86.41 KB, 下载次数: 0)

下载附件

2025-4-15 14:56 上传

2.5 我们调试到这里,发现出现了 密文 而这里有个params组成 所以我们就推测

密文是在这里,那么我们就可以开进行 扣取然后将数据加密来测试

图片 19.png (29.24 KB, 下载次数: 0)

下载附件

2025-4-15 14:56 上传

第三步 我们来扣取代码 进行参数加密然后请求

3.1 我们将代码扣取下来,进行分析a$e().encrypt 是我们第一次加密的函数

因为我们浏览器就能一眼看出 他先试用这个进行一次加密

u$e(s) 是我们最终的加密 s 里面的值就是

a$e().encrypt 加密得出

图片 20.png (16.3 KB, 下载次数: 0)

下载附件

2025-4-15 14:58 上传

3.2 对于参数的加密 上述的明文 是我们这个包的 里面有我们要的 验证码图片信息,

大家可以自行查看,所以3.1 所述 的代码整改就是我们的 这个包的参数加密,

那我们运行代码进行一个代码补全 实现最终的加密

图片 21.png (20.6 KB, 下载次数: 0)

下载附件

2025-4-15 14:59 上传

3.3 我们直接选中函数 进入他的位置将他扣取,随后我们就看报错

,少哪一个 我们就直接进入找到位置,进行扣取

图片 22.png (31.31 KB, 下载次数: 0)

下载附件

2025-4-15 15:00 上传

图片 23.png (18.86 KB, 下载次数: 0)

下载附件

2025-4-15 15:00 上传

3.4 我们按照每一个报错补完之后发现 又出现一个报错 就是

我们主函数里面的 o 不能进行实例化,但明明我们扣取完毕,

还是不给我们想要的,且报错,那我们就需要思考究竟是哪些原因,

在这就不卖关子了我们直接演示

图片 24.png (50.16 KB, 下载次数: 0)

下载附件

2025-4-15 15:01 上传

3.5 原因很简单就是少扣取 但是他不给你明确指示

所以在这里展示一种另类且无脑的扣取方法下图 将包含两个箭头处

和他们中间的代码全部扣取下来 这里是做了多次调试

发现报错不给,就多次调试出来的结果

图片 25.png (196.96 KB, 下载次数: 0)

下载附件

2025-4-15 15:02 上传

图片 26.png (120.64 KB, 下载次数: 0)

下载附件

2025-4-15 15:02 上传

第四步 我们运行代码发现报错 在这里的st 是一个判断

他的意思是 用global 还是 globalThis 赋值给st,也就是下图的

var st = typeof globalThis != "undefined" ? globalThis : typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : {};

图片 27.png (67.49 KB, 下载次数: 0)

下载附件

2025-4-15 15:04 上传

图片 28.png (18.24 KB, 下载次数: 0)

下载附件

2025-4-15 15:04 上传

4.1 我们将代码装载运行 在这里需要补上一个 window=global 或者 window = globalThis 两者都可

图片 29.png (18.45 KB, 下载次数: 0)

下载附件

2025-4-15 15:05 上传

4.2 接着运行调试 ,看报错,是我们的最终加密,所以我们接着看报错少那个扣取那个,对于 l$e 这个报错我们需要扣取三个

图片 30.png (59.12 KB, 下载次数: 0)

下载附件

2025-4-15 15:06 上传

图片 31.png (43.84 KB, 下载次数: 0)

下载附件

2025-4-15 15:06 上传

图片 32.png (8.96 KB, 下载次数: 0)

下载附件

2025-4-15 15:06 上传

4.3 当我扣取之后 在紧接着的报错是 某某变量不是方法,就让我们很苦恼,

也就代表着我们的代码没有扣到位,那么我们,可以看到 ,他是new l$e 出现了问题,

在这里我们不去深究它里面是什么,因为我们知道在 3.5 就遇到过这种情况 报错不给,

没有明确指示是哪个问题,所以在经过多次调试,我们就知道我们要按照3.5的扣取方法

图片 33.png (84.71 KB, 下载次数: 0)

下载附件

2025-4-15 15:08 上传

图片 34.png (11.14 KB, 下载次数: 0)

下载附件

2025-4-15 15:08 上传

4.4 也是包括 箭头两处全部扣取,因为几步报错,也不指明,那我们就只能,在他周围尝试着扣取,

因为他们就是在某处定义然后使用,所以我们就将计就计 都拿来吧,就算扣取到没有的,

那我们也不用担心,多次调试优化 就可以得出简洁的代码,所以我们就直接扣取使用

图片 35.png (54.94 KB, 下载次数: 0)

下载附件

2025-4-15 15:09 上传

图片 36.png (64.94 KB, 下载次数: 0)

下载附件

2025-4-15 15:09 上传

4.5 我们运行代码,发现可以了,没有报错也没有输出,也就达到了一半 没有报错,

但是我们得要结果,没结果的事,怎么可能去做,那么下面也就要讲解一个难以发觉的错误,

也就是大量扣取,不容易被发现的浏览器的小动作

图片 37.png (76.23 KB, 下载次数: 0)

下载附件

2025-4-15 15:10 上传

第五步 代码总体没问题,存在于多扣但没有少扣取,所以就是因为我们的代码里有我们不需要的,

才导致打印为空我们可以在本地下断点就可以看到值,所以说在某处 console.log()被改写或者拦截 等等

图片 38.png (82.29 KB, 下载次数: 0)

下载附件

2025-4-15 15:11 上传

5.1 经过多次调试我们发现 代码有两处 写法一样并且运行了,这里的代码是经过多次调试,

得出的结论,发现是这里导致了代码打印为空的操作所以我们将 s$e(); i$e(); 这两处删除或者注释掉,

那么打印自然就出现

图片 39.png (42.45 KB, 下载次数: 0)

下载附件

2025-4-15 15:12 上传

图片 40.png (43.85 KB, 下载次数: 0)

下载附件

2025-4-15 15:12 上传

图片 41.png (94.08 KB, 下载次数: 0)

下载附件

2025-4-15 15:12 上传

5.2 以上就是获取验证码信息的步骤 ,接着我们讲解 怎样过验证码,如下图,这两个验证码,可以任选进行操作

------------------------------------------------------------------------------------------------------------------------------------------

[Python] 纯文本查看 复制代码# 代码1

def huakuiajuli(a,b):

"""

a ----> 背景图片 二进制的

b ----> 滑块图片 二进制的

:return: x坐标

"""

# 读取背景图片 和 滑块图片

a_img = cv2.imdecode(np.frombuffer(a,np.uint8),cv2.IMREAD_GRAYSCALE)

b_img = cv2.imdecode(np.frombuffer(b,np.uint8),cv2.IMREAD_GRAYSCALE) # 滑块

yy = []

xx = []

for y in range(b_img.shape[0]):

for x in range(b_img.shape[1]):

r = b_img[y,x]

if r<200:

yy.append(y)

xx.append(x)

b_img = b_img[min(yy):max(yy),min(xx):max(xx)]

# 识别图片边缘

a_edge = cv2.Canny(a_img,100,200)

b_edge = cv2.Canny(b_img,100,200)

#转换图片格式

a_pic = cv2.cvtColor(a_edge,cv2.COLOR_GRAY2RGB)

b_pic = cv2.cvtColor(b_edge,cv2.COLOR_GRAY2RGB)

#缺口匹配

res = cv2.matchTemplate(a_pic,b_pic,cv2.TM_CCOEFF_NORMED)

min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res) #寻找最优匹配

# 绘制方框

th,tw = b_pic.shape[:2]

tl = max_loc# 左上角点的坐标

br = (tl[0] +tw,tl[1]+th) # 右下角点的坐标

cv2.rectangle(a_img,tl,br,(0,0,255),2) #绘制矩形

cv2.imwrite("ditu01.png",a_img) #保存本地

return max_loc[0]

------------------------------------------------------------------------------------------------------------------------------------------

[Python] 纯文本查看 复制代码# 代码2 形参a,b代表二进制 的 背景图片和 缺口图片

def dddddor_post(a,b):

slide = ddddocr.DdddOcr(det = False,ocr = False,show_ad = False)

bigImage = a

smallImage = b

result = slide.slide_match(bigImage,smallImage,simple_target=True)

return result['target'][0]

---------------------------------------------------------------------------------------------------------------------------------------------

5.3 接着我们过完验证码之后 就需要请求目标数据包了 加密位置都一样只不过不同之处在于参数 所以我们来分析他加密的参数,

滑动验证码就可以看到,我们来分析参数

certificateType:””

key:"query"

name :””

pagelum:1

pageSize: 10

slideld:"1361093404070510592"

width: 143

其中 slideld 在请求的图片的包里 width猜测是滑块轨迹 但经过多次调试 除slideld外 其余都可以固定

图片 42.png (254.68 KB, 下载次数: 0)

下载附件

2025-4-15 15:15 上传

第六步 完成两次请求需要的参数了,接下来就是放出请求的结果有两种第一种 参数没有按照5.3 操作 有响应但是 没有数据

图片 43.png (213.33 KB, 下载次数: 0)

下载附件

2025-4-15 15:16 上传

第二种 显示验证码错误,这是因为 上面提供的两个验证码正确率不是太高 但代码一要不代码二 出现不正确次数少,所以推荐验证码代码 一

图片 44.png (11.1 KB, 下载次数: 0)

下载附件

2025-4-15 15:16 上传

总结

载荷加密,都是同一个 只有参数 不同 所以在操作时要看清楚 明文载荷验证码,

正确率,还请各位大佬自己 改动 已达到百分百正确第一次玩验证码,

还请各位大佬多多指点,有没有讲到的 或不清晰的,还请大佬给予提示

再次感谢各位大佬