news 2026/9/29 4:35:35

AI逆向实战:猿人学反混淆练习平台第八题加密分析全流程拆解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI逆向实战:猿人学反混淆练习平台第八题加密分析全流程拆解

1. 猿人学第八题到底卡在哪:验证码识别与反混淆的真实场景

猿人学反混淆练习平台第八题,页面打开后不是直接给你数据,而是先弹出一组九宫格验证码,提示你按顺序点选目标字符,通过之后才能翻页拿数据。很多人第一次做这题会误以为难点在接口加密参数上,实际抓包会发现请求体里没有 sign、没有 token,只有一个captcha_id和clicks坐标数组。真正的门槛在于:验证码图片是 base64 内嵌的,目标字符是动态下发的,而且每次翻页都可能重新触发验证码校验。

这道题适合已经会写基础 requests 脚本、想进阶到「图像预处理 + 模板匹配 + 请求状态机」的读者。它不需要你破解复杂的 JS 混淆,但需要你把验证码识别、会话保持、翻页重试这三件事串成一个稳定的自动化流程。我试过用纯 OCR 库直接识别,准确率很低,因为验证码里的字符有旋转、有干扰线、有颜色噪声,通用 OCR 模型在这种小样本场景下反而不如自己写特征匹配。

核心检索词先明确:猿人学第八题、反混淆、加密分析、验证码识别、九宫格点选、Python 逆向脚本。下面从环境准备到可运行脚本逐步拆开,每一步都给出可复制的配置和验证动作。

2. TaoToken 前置:用模型对话辅助分析验证码逻辑

在写脚本之前,我习惯先用模型对话把接口返回结构和验证码字段含义理清楚。TaoToken 的模型对话入口可以直接贴抓包返回的 JSON,让模型帮你归纳字段关系,比如targets是目标字符数组、image是 base64 图片、id是本次验证码会话标识。这一步不是必须的,但能省掉很多手动比对的时间。

你可以打开模型对话页面:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite ,把/api2/8的返回样例贴进去,问它「这个 JSON 里每个字段在验证码流程中承担什么角色」。模型会给出字段级解释,你再对照自己的抓包结果验证。

如果你打算长期做这类逆向练习,建议把常用的分析提示词沉淀下来,配合 Coding Plan 做脚本迭代:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。接入文档在 https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite ,API Key 在 https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 控制台里生成。

需要说明的是,TaoToken 在这里的角色是辅助你理解接口语义和生成脚本骨架,不是替你绕过验证码。验证码的识别逻辑仍然要你自己写,模型只能帮你把思路结构化。

3. 可复制配置:会话、请求头与验证码接口参数

先把基础请求配置固定下来。这道题的关键请求头有三个:User-Agent必须设置为yuanrenxue,X-Requested-With设为XMLHttpRequest,Referer指向/match/8。Cookie 里需要带上登录后的sessionid,否则接口会返回未登录状态。

import requests, json, time, base64, io import numpy as np import cv2 from PIL import Image BASE_URL = "https://match.yuanrenxue.cn" SESSION_COOKIE = {"sessionid": "你的sessionid"} USER_AGENT = "yuanrenxue" PAGE_SIZE = 10 TOTAL_PAGES = 5 session = requests.Session() session.headers.update({ "User-Agent": USER_AGENT, "X-Requested-With": "XMLHttpRequest", "Referer": f"{BASE_URL}/match/8", "Accept": "application/json, text/javascript, */*; q=0.01", }) for k, v in SESSION_COOKIE.items(): session.cookies.set(k, v, domain="match.yuanrenxue.cn", path="/")

验证码获取接口是GET /api2/8,带一个毫秒时间戳参数t。返回结构里targets是你要点选的目标字符顺序,image是 base64 图片,id是本次验证码的唯一标识。提交接口是POST /api2/8,表单字段为captcha_id和clicks,clicks是 JSON 数组,每个元素是{"x": ..., "y": ...}坐标。

九宫格坐标计算方式:图片按 3x3 切分,每个格子中心点坐标用col * cell_size + cell_size // 2和row * cell_size + cell_size // 2得到。假设图片宽高都是 300,则 cell_size 为 100。

def cell_center(pos, cell_size=100): row, col = divmod(pos, 3) return {"x": col * cell_size + cell_size // 2, "y": row * cell_size + cell_size // 2}

请求频率要控制,两次请求间隔至少 0.6 秒,遇到 429 就 sleep 3 秒重试。这个限流策略是实测下来比较稳的,太快会触发风控,太慢又影响调试效率。

4. 验证请求与成功结果:从验证码识别到翻页求和

验证码识别的核心思路是「先探测、再匹配」。第一次遇到某个目标字符时,你没有样本,只能随机点四个位置提交,接口会在返回里告诉你picked字段,即你点中的位置对应的真实字符。用这个反馈来积累样本,下次遇到相同字符就能做特征匹配。

图像预处理步骤:把每个格子裁出来,去掉边缘 12% 的 margin,转 HSV 取饱和度大于 40 且灰度小于 245 的区域作为字符掩码,再做开运算和闭运算去噪,最后把字符区域缩放到 64x64 的二值图作为特征。

def preprocess_cell(cell): h, w = cell.shape[:2] margin = int(min(h, w) * 0.12) cell = cell[margin:h-margin, margin:w-margin] hsv = cv2.cvtColor(cell, cv2.COLOR_RGB2HSV) gray = cv2.cvtColor(cell, cv2.COLOR_RGB2GRAY) mask = np.logical_and(hsv[:,:,1] > 40, gray < 245).astype(np.uint8) * 255 kernel = np.ones((3,3), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) ys, xs = np.where(mask > 0) if len(xs) == 0: return np.zeros((64,64), dtype=np.uint8) crop = mask[ys.min():ys.max()+1, xs.min():xs.max()+1] side = max(crop.shape[:2]) + 8 canvas = np.zeros((side, side), dtype=np.uint8) oy = (side - crop.shape[0]) // 2 ox = (side - crop.shape[1]) // 2 canvas[oy:oy+crop.shape[0], ox:ox+crop.shape[1]] = crop return (cv2.resize(canvas, (64,64), interpolation=cv2.INTER_AREA) > 32).astype(np.uint8)

匹配阶段用曼哈顿距离:对每个目标字符,计算当前格子特征与已积累样本均值的平均绝对差,取最小代价的排列组合。因为目标字符通常只有 3 到 4 个,9 选 4 的排列数是 3024,暴力枚举完全可行。

import itertools def predict_positions(cell_features, targets, samples): costs = [] for char in targets: feats = samples.get(char, []) if not feats: costs.append([float("inf")] * 9) continue proto = np.stack([f.astype(np.float32) for f in feats]).mean(axis=0) costs.append([float(np.mean(np.abs(cell_features[p].astype(np.float32) - proto))) for p in range(9)]) best_perm, best_score = None, float("inf") for perm in itertools.permutations(range(9), len(targets)): score = sum(costs[i][perm[i]] for i in range(len(targets))) if score < best_score: best_score, best_perm = score, perm return list(best_perm), best_score

翻页逻辑是一个状态机:请求/api/question/8?page=N&pageSize=10,如果返回里action等于captcha,说明需要先过验证码,调用解题流程,成功后重新请求同一页。拿到数据后累加data数组里的数值,最后打印总和。

def fetch_page(page): while True: resp = session.get(f"{BASE_URL}/api/question/8", params={"page": page, "pageSize": PAGE_SIZE}, timeout=20) data = resp.json() if data.get("action") != "captcha": return data solve_one_captcha() time.sleep(0.8)

运行成功时,控制台会依次打印每页的 JSON 数据和最终 sum 值。如果验证码识别正确,通常 1 到 3 次尝试就能通过;如果样本不足,脚本会自动进入探测模式积累样本,循环几次后识别率会明显上升。

5. 本篇常见错排查:验证码失败、429 与坐标偏移

第一个高频错误是sessionid过期或未正确设置 domain。表现是接口返回{"action": "captcha"}但验证码提交后一直失败。排查方法:打印session.cookies.get_dict(),确认sessionid存在且 domain 为match.yuanrenxue.cn。

第二个错误是坐标计算用了图片原始尺寸而不是格子尺寸。如果图片不是 300x300,cell_size要按width // 3动态计算。表现是提交后返回picked为空或验证码不通过。修正方式:在decode_image之后读取image.shape,把cell_size传进去。

第三个错误是请求间隔太短触发 429。表现是连续几次请求后接口返回 429 状态码。解决方式:在请求封装里加一个last_request_at时间戳,每次请求前检查间隔,不足 0.6 秒就 sleep 补齐。

第四个错误是样本缓存文件损坏。match8_cache.pkl在写入过程中如果程序中断,可能导致下次加载失败。排查方法:在load_cache里加 try/except,加载失败就清空样本重新积累。另外注意 pickle 文件不要跨 Python 版本混用。

第五个错误是目标字符顺序理解反了。targets数组的顺序就是你要点选的顺序,不是集合。比如targets是["A", "B", "C"],你点的第一个格子必须是 A,第二个是 B,第三个是 C。如果顺序错了,即使字符都对也不会通过。

6. 语义一致 CTA:把脚本跑通之后继续迭代

脚本能稳定跑通 1 到 5 页并算出总和之后,你可以把验证码识别模块抽出来做成独立类,方便复用到其他类似题目。如果后续要接入更多逆向练习,建议用 Coding Plan 管理你的脚本迭代和提示词版本:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。遇到接口字段变化或验证码样式调整时,回到模型对话里重新分析返回结构:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite ,比翻文档快很多。

API Key 管理和接入配置都在控制台完成:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。接入文档里有完整的请求示例和参数说明:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。把这篇的脚本保存好,下次遇到九宫格点选类验证码,改一下接口路径和坐标计算就能直接套用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 4:35:12

芯参谋(23):并口/并行NOR_PPI_NOR_软件设计规范

并行NOR_PPI_NOR_软件设计规范 http://39.108.239.75:5001/share/DNylYp0iuzRP5QC http://39.108.239.75:5001/share/DNylYp0iuzRP5QC 并行 NOR Flash&#xff08;PPI NOR&#xff09;软件设计规范 编制日期 2026-09-24 &#xff5c; 版本号 Rev 1.5 面向 异步 SRAM 类并行…

作者头像 李华
网站建设 2026/9/29 4:34:34

AI前端美化规则 Taste Skill:用 SKILL.md 让 Cursor 告别塑料感界面

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 4:34:26

Win10安装JDK1.8完整教程:从下载到环境变量配置与排错

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 4:29:15

同城电商系统:库存变更怎么同步到订单

同城电商系统库存变更若不同步到订单占用层&#xff0c;会出现「后台显示有货、实际已被未支付单占满」。宜库存 物理量 - 占用量&#xff1b;占用在下单创建&#xff0c;支付成功转实扣&#xff0c;超时释放。模型 sku_stock: on_hand sku_hold: sum(active holds) available…

作者头像 李华