当前位置: 首页 > news >正文

recaptcha v3 无感

最近正在学习recaptcha v3无感流程。

感觉这个验证码整体流程非常精妙:全部流程都是通过MessageChannelpostMessage通讯所有数据,例如传参、加解密数据。

以下需要讲解的是:通过babel解混淆,以及 JS 代码的关键定位语句。


先讲解babel解混淆

它的js代码混淆非常厉害:

先是把函数都放到数组里面:

data1=[function(){},function(){},function(){}]data2=[function(){},function(){},function(){}]// .... 非常多

然后每个函数里面是由多个分支任务实现,通过第一个形参e(我这里是这个),来实现走向哪个分支任务跑。

走向的话还是通过了非常多的计算&&||,也称混淆,用来比较计算形参e,加了非常多的嵌套:

// case1(e+2^25)<e&&e-3<<1>=e&&func1(0,1)// case2function(e,M,k,q,U,Q,u){((Q=[15,"call",3],e>>2)&3)==1&&(U.R=M,c_func_15(4,M,function(){U.R&&bY.call(k,q);}));if((e|16)==(e))y["call"](this,M,0,cK.D$);returnu;}

然后非常多的括号、逗号、三元运算符,以及使用&&||代替if判断语句;一些简单的数组实现加密字符串;以及使用非常多的call


流程截图

先看下图片整体流程是如何的。

源代码


解混淆代码


我抽了一些重要的部分展示的。
发现,有些有点重复了(主要嵌套太多了),但是不要紧就没有没有处理,整体流程没有问题就好了

太多递归处理了,我怕出现异常或者不可控的解密结果;我是分了很多步才跑完的,中间太多了需要考虑的了。


如何还原到recaptcha_zh_cn_decode.sequence.control.ifconst.dispatch.js

最终文件路径:recaptcha/recaptcha_zh_cn_decode.sequence.control.ifconst.dispatch.js。下面是仓库里当前实现是怎么一步步得到它的(按脚本顺序,前一步的输出是后一步的输入)。

各阶段写盘前都会用上一级的formatter_worker/FormatterWorker.js做格式化。


1.babel_main.js

  • recaptcha_zh_cn.js,用@babel/parser解析成 AST。
  • 按约定模式找到要解密的调用(例如f[18](...)),用decode.js里的de配合e_code.txt里的数据算出明文字符串并替换。
  • 顺带做数组字面量、逗号表达式与赋值等相关整理,给后面 AST 变换铺路。
  • 当前脚本把结果写到recaptcha_zh_cn_decode1.js。下一步restore_sequence.js默认读的是recaptcha_zh_cn_decode.js,所以要自己复制或改名,或在跑restore_sequence.js时把第一个命令行参数指向上一步的真实路径。


2.restore_sequence.js(可多轮)

  • 输入默认:recaptcha_zh_cn_decode.js(可用 argv 覆盖)。
  • 输出默认:recaptcha_zh_cn_decode.sequence.js
  • 作用:把能安全处理的逗号表达式SequenceExpression)拆成顺序语句,让执行顺序摊开。
  • 多轮:同一文件反复扫,直到一轮里几乎不再产生改动;默认最多 6 轮,第三个命令行参数可改轮数。


3.restore_control_flow.js(可多轮)

  • 输入默认:recaptcha_zh_cn_decode.sequence.js
  • 输出默认:recaptcha_zh_cn_decode.sequence.control.js
  • 作用:把cond && stmt这类当分支用的表达式,尽量改成if (cond) { ... }等形式,控制流更好读。
  • 同样是多轮 + 默认可调轮数,道理和上一步一样。


4.restore_if_e_constants.js

  • 输入默认:recaptcha_zh_cn_decode.sequence.control.js
  • 输出默认:recaptcha_zh_cn_decode.sequence.control.ifconst.js
  • 作用:只处理名字符合X_func_数字、且第一个形参是e的函数。对这些函数里if的条件,若能在「只涉及e与可静态推断内容」的前提下枚举出会进入分支的e,就改写成[...].includes(e);对「真分支是空块、实际逻辑在另一侧」这类混淆,按取反后的语义来归并,避免误判。
  • 单轮脚本,输入输出路径可用 argv 指定。


5.restore_dispatch_by_calls.js

  • 输入默认:recaptcha_zh_cn_decode.sequence.control.ifconst.js
  • 输出默认:recaptcha_zh_cn_decode.sequence.control.ifconst.dispatch.js(即最终文件)。
  • 作用:在函数体静态推断仍不完整时,到调用点收集「第一个实参是哪些常量」,用来补全或修正对e的分发说明。
  • 遇到bind/apply等看不清第一个参数的情况,会退化为占位或保留原条件注释;推不全或列表过长时,会用约定好的占位写法(例如'~'、截断),避免生成巨大无意义的数字列表。


链路与命令(备忘)

步骤脚本默认产出
1babel_main.jsrecaptcha_zh_cn_decode1.js
2restore_sequence.jsrecaptcha_zh_cn_decode.sequence.js
3restore_control_flow.jsrecaptcha_zh_cn_decode.sequence.control.js
4restore_if_e_constants.jsrecaptcha_zh_cn_decode.sequence.control.ifconst.js
5restore_dispatch_by_calls.jsrecaptcha_zh_cn_decode.sequence.control.ifconst.dispatch.js

recaptcha目录下,若第一步生成的是recaptcha_zh_cn_decode1.js,可连续执行:

nodebabel_main.jsnoderestore_sequence.js ./recaptcha_zh_cn_decode1.js ./recaptcha_zh_cn_decode.sequence.jsnoderestore_control_flow.js ./recaptcha_zh_cn_decode.sequence.js ./recaptcha_zh_cn_decode.sequence.control.jsnoderestore_if_e_constants.js ./recaptcha_zh_cn_decode.sequence.control.js ./recaptcha_zh_cn_decode.sequence.control.ifconst.jsnoderestore_dispatch_by_calls.js ./recaptcha_zh_cn_decode.sequence.control.ifconst.js ./recaptcha_zh_cn_decode.sequence.control.ifconst.dispatch.js

restore_sequence.jsrestore_control_flow.js若要多轮,在命令末尾加第三个参数(数字)即可。


中途有很多这样子的,也解密:

data=[function(){return0},function(){return1},function(){return2}]// ↓data_func_0=function(){return0}data_func_1=function(){return1}data_func_2=function(){return2}// 然后调用者 也要改动哦// 源代码data[0]()data[1]()data[2]()// 解密data_func_0()data_func_1()data_func_2()// 为什么要这样呢???// 因为这样子我们静态分析流程时候,按住CTRL + 点击这个函数名,就可以跳转所有关联的代码中(vscode)// 源代码是不能的

解完后的代码,有几个需要注意的:

因为我发现有很多函数调用都不是明摆着的,所以看不到引用的,好像都是基于匿名bind的,所以会导致找不到进入分支的地方。因为我都是通过引用调用才得出那些任务是什么数字的走向。

可能说的不太详细,简单来说,就是没有找到有关的走向。

我之前是直接把所有有可能的数字都会填上的,但是这个太多了,我就直接放弃了,现在是通过引用的目录得到分支里面的数字。

三张图片解答,希望您能看得懂!

还有一点细节:

if((e^35)>>4){}else{d=G_func_32(15,f_func_17(23,28),M);}// ** 之前的取值都是以真取出来的 **// 像这样子的为什么会出现 {} 空语句,都是我先通过 && 或者 || 这个解出来的,得出if语句的// 那么如果是真的话,就是空语句,那对于我们而言是没有用的,不管这个// 所以我们要取反,那就是取假的,不符合的,这样子这条分支任务代码才有意义// 中间有很多这样子的语句,细节非常重要的

最后说明一点:中间还有好多的细节,我都没有处理好,太复杂了或者语句有冲突,可能需要一些小工具单独做的。


简单说说调试这个代码的重点部分


如果觉得本篇文章不错的话,记得点点赞哦!
bro下次再见啦,拜~~~

http://www.jsqmd.com/news/671627/

相关文章:

  • 盘点信誉好的欠款律师咨询公司,为你推荐靠谱之选 - 工业设备
  • 辨析高中数学权老师教学案例,对培养学习习惯、提高成绩有无显著效果 - 工业品牌热点
  • Audio Slicer终极指南:3分钟掌握音频智能分割技巧
  • 春秋云境CVE-2020-5513
  • 如何用纯JavaScript在浏览器中零成本将PPTX转换为交互式HTML?3分钟快速上手指南
  • 给K210和STM32F103牵线搭桥:保姆级串口通信配置与调试避坑指南
  • 拆解苹果AirTag和三星SmartTag+:看看巨头们是如何把UWB这颗“金钥匙”塞进指甲盖里的
  • 3分钟掌握VADER情感分析:社交媒体文本情感识别的Python神器
  • 跨平台图表绘制终极指南:drawio-desktop完整使用教程
  • 2026年有实力的特种材料厂家推荐,山东德企安全性能可靠吗 - myqiye
  • CyberSelf:实验室专属赛博师兄计划(5)——CampusLab维度知识库搭建
  • 2026年4款降AI工具处理万字以上长文效果对比:全文稳定性测评 - 还在做实验的师兄
  • 终极BIOS解锁指南:联想笔记本隐藏设置一键开启
  • Dify 2026工作流引擎性能实测报告:并发10K节点调度延迟压降至≤87ms,你还在用v1.12?
  • 2026优质淀粉大搜罗:口碑生粉厂家大盘点,餐饮专供马铃薯淀粉/球团粘合剂/型煤淀粉/纸箱淀粉/生粉,淀粉厂商推荐 - 品牌推荐师
  • 别再被pip坑了!安装PyTorch时遇到‘Bad CRC-32’错误,试试这个--no-cache参数
  • NAS音乐必备神器,全平台音乐收割机!极空间部署『Go Music DL』
  • 掌握Spotify更新主动权:BlockTheSpot版本控制完全实战指南
  • 2026年口碑好的私密护理生产企业推荐,哪家更值得合作 - 工业品牌热点
  • 突破视频下载限制:Python自动化HLS流媒体保存方案
  • Day7| 142. 环形链表 II
  • PCIe 6.0的流控新玩法:Shared Flow Control如何解决多VC的“旱涝不均”问题?
  • Linux内核FunctionFS实战:从原理到动手,为你的定制设备添加ADB功能
  • 2026年中文文学论文降AI工具推荐:文学批评和文本分析部分降AI方案 - 还在做实验的师兄
  • 别让闲置盒马鲜生礼品卡浪费!教你高效回收变现方法 - 团团收购物卡回收
  • Windows 11右键菜单终极自定义指南:解锁高效文件管理新境界
  • 手把手教你用Screen和Xvfb在Linux后台稳定运行The Forest联机服务器
  • 联想拯救者工具箱终极指南:开源轻量级硬件管理神器完全解析
  • 盒马购物卡回收全攻略,手把手教你变现! - 团团收购物卡回收
  • Dify私有化落地信创替代方案(从CentOS停服到等保三级合规的完整路径)