【JS 逆向百例】反混淆入门,某鹏教育 JS 混淆还原
关注微信公众号:K哥爬虫,持续分享爬虫进阶、JS/安卓逆向等技术干货!
声明
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
逆向目标
- 目标:某鹏教育登录接口加密,含有简单的 JS 混淆
- 主页:
aHR0cHM6Ly9sZWFybi5vcGVuLmNvbS5jbi8=
- 接口:
aHR0cHM6Ly9sZWFybi5vcGVuLmNvbS5jbi9BY2NvdW50L1VuaXRMb2dpbg==
- 逆向参数:Form Data:
black_box: eyJ2IjoiR01KM0VWWkVxMG0ydVh4WUd...
逆向过程
本次逆向的目标同样是一个登录接口,其中的加密 JS 使用了简单的混淆,可作为混淆还原的入门级教程,来到登录页面,随便输入账号密码进行登录,其中登录的 POST 请求里, Form Data 有个加密参数 black_box,也就是本次逆向的目标,抓包如下:
直接搜索 black_box,在 login.js 里可以很容易找到加密的地方,如下图所示:
看一下 _fmOpt.getinfo()
这个方法,是调用了 fm.js 里的 OO0O0()
方法,看这个又是 0 又是 O 的,多半是混淆了,如下图所示:
点进去看一下,整个 fm.js 都是混淆代码,我们选中类似 OQoOo[251]
的代码,可以看到实际上是一个字符串对象,也可以直接在 Console 里输出看到其实际值,这个 OO0O0
方法返回的 oOoo0[OQoOo[448]](JSON[OQoOo[35]](O0oOo[OQoOo[460]]))
,就是 black_box 的值,如下图所示:
仔细观察,可以发现 OQoOo
应该是一个类似数组的东西,通过传入元素下标来依次取其真实值,随便搜索一个值,可以在代码最后面找到一个数组,这个数组其实就是 OQoOo
,可以传入下标来验证一下,如下图所示:
到这里其实就知道了其大致混淆原理,我们可以把这个JS 拿下来,到本地写个小脚本,将这些值替换一下:
# ==================================
# --*-- coding: utf-8 --*--
# @Time : 2021-11-09
# @Author : 微信公众号:K哥爬虫
# @FileName: replace_js.py
# @Software: PyCharm
# @describe: 混淆还原小脚本
# ==================================# 待替换的值(太多了,仅列出少部分)
# 以实际列表为准,要和 fm_old.js 里的列表一致
item = ['referrer', 'absolute', 'replace',...]# 混淆后的 JS
with open("fm_old.js", "r", encoding="utf-8") as f:js_lines = f.readlines()js = ""
for j in js_lines:js += jfor i in item:# Qo00o 需要根据你 fm_old.js 具体的字符串进行替换str_old = "Qo00o[{}]".format(item.index(i))js = js.replace(str_old, '"' + i + '"')# 还原后的 JS
with open("fm_new.js", "w", encoding="utf-8") as f:f.write(js)
使用此脚本替换后,可能会发现 JS 会报错,原因是一些换行符、斜杠解析错误,以及双引号重复使用的问题,可以自己手动修改一下。
这里需要注意的一点,fm.js 后面还有个后缀,类似 t=454594,t=454570 等,不同的后缀得到的 JS 内容也有差异,各种函数变量名和那个列表元素顺序不同,实际上调用的方法是同一个,所以影响不大,只需要注意替换时列表内容、需要替换的那个字符串和你下载的 JS 文件里的一致即可。
将 JS 还原后,我们可以将还原后的 JS 替换掉网站本身经过混淆后的 JS,这里替换方法有很多,比如使用 Fiddler 等抓包工具替换响应、使用 ReRes 之类的插件进行替换、使用浏览器开发者工具自带的 Overrides 功能进行替换(Chrome 64 之后才有的功能)等,这里我们使用 Fiddler 的 Autoresponder 功能来替换。
实测这个 fm.js 的后缀短时间内不会改变,所以可以直接复制其完整地址来替换,要严谨一点的话,我们可以用正则表达式来匹配这个 t 值,在 Fiddler 里面选择 AutoResponder,点击 Add Rule,添加替换规则,正则表达式的方法写法如下:regex:https:\/\/static\.tongdun\.net\/v3\/fm\.js\?t=\d+
,注意 regex 前缀必不可少,上方依次选中 Enable rules(应用规则)、Accept all CONNECTs(接受所有连接)、Unmatched requests passthrough(不匹配规则的就按照之前的请求地址发送过去),Enable Latency 是设置延迟生效时间,不用勾选,如下图所示:
替换后再次登录,下断点,可以看到现在的 JS 已经清晰了不少,再看看这个函数最后的 return 语句,oQOQ0["blackBox"]
包含了 it
、os
、t
、v
三个参数,使用 JSON 的 stringify 方法将其转换成字符串,然后调用 QQo0
方法进行加密,如下图所示:
我们先来看看 oQOQ0["blackBox"]
里的四个参数,其中 it
、os
、v
三个参数在这个函数开始就已经有定义,v
就是 Q0oQQ["version"]
,是定值,直接搜索可以发现这个值是在最开始的那个大列表里,os
为定值,it
是两个时间戳相减的值,O000o
这个方法就是两个值进行相减,oQOQo
这个时间戳可以搜索 var oQOQo
,是一开始加载就生成的时间戳,JS 一开始加载到点击登陆进入加密函数,也就一分钟左右,所以这里我们可以直接生成一个五位随机数(一分钟左右在毫秒上的差值在五位数左右)。
现在就剩下一个 t
参数了,往下看 t
其实就是 Q0oQQ["tokens"]
,中间经过了一个 if-else 语句,可以埋下断点进行调试,发现其实只执行了 else 语句,对 t
赋值也就这一句,所以剩下的代码其实在扣的时候都可以删掉。
这个 tokens 多次测试发现是不变的,尝试直接搜索一下 token 关键字,可以发现其赋值的地方,对 id
按照 | 符号进行分割,取其第 1 个索引值就是 tokens,再看看 id
的值,并没有找到明显的生成逻辑,复制其值搜索一下,发现是通过一个接口返回的,可以直接写死,也可以自己先去请求一下这个接口,取其返回的值,如下图所示:
自此所有参数都找完了,回到原来的 return 位置,还差一个加密函数,即 ooOoO["encode"]()
,直接跟进去,将这个方法扣下来即可,本地调试缺啥补啥,将用到的函数补全就行了。
完整代码
GitHub 关注 K 哥爬虫,持续分享爬虫相关代码!欢迎 star !https://github.com/kgepachong/
以下只演示部分关键代码,不能直接运行! 完整代码仓库地址:https://github.com/kgepachong/crawler/
JavaScript 加密关键代码架构
function oQ0OQ(Q0o0, o0OQ) {return Q0o0 < o0OQ;
}function O000O(Q0o0, o0OQ) {return Q0o0 >> o0OQ;
}function Qo0oo(Q0o0, o0OQ) {return Q0o0 | o0OQ;
}function OOO0Q(Q0o0, o0OQ) {return Q0o0 << o0OQ;
}function OooQo(Q0o0, o0OQ) {return Q0o0 & o0OQ;
}function Oo0OO(Q0o0, o0OQ) {return Q0o0 + o0OQ;
}var oQoo0 = {};
oQoo0["_keyStr"] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
oQoo0["encode"] = function QQQ0(Q0o0) {var o0OQ = 62;while (o0OQ) {switch (o0OQ) {case 116 + 13 - 65: {}case 118 + 8 - 63: {}case 94 + 8 - 40: {}case 122 + 6 - 63: {}}}};
oQoo0["_utf8_encode"] = function oOQ0(Q0o0) {}function OOoO0() {var tokens = "e0ia+fB5zvGuTjFDgcKahQwg2UEH8b0k7EK/Ukt4KwzyCbpm11jjy8Au64MC6s7HvLRacUxd7ka4AdDidJmYAA==";var version = "+X+3JWoUVBc12xtmgMpwzjAone3cp6/4QuFj7oWKNk+C4tqy4un/e29cODlhRmDy";var Oo0O0 = {};Oo0O0["blackBox"] = {};Oo0O0["blackBox"]["v"] = version;Oo0O0["blackBox"]["os"] = "web";Oo0O0["blackBox"]["it"] = parseInt(Math.random() * 100000);Oo0O0["blackBox"]["t"] = tokens;return oQoo0["encode"](JSON.stringify(Oo0O0["blackBox"]));
}// 测试样例
console.log(OOoO0())
Python 登录关键代码
# ==================================
# --*-- coding: utf-8 --*--
# @Time : 2021-11-10
# @Author : 微信公众号:K哥爬虫
# @FileName: open_login.py
# @Software: PyCharm
# ==================================import time
import execjs
import requestslogin_url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"def get_black_box():with open('get_black_box.js', 'r', encoding='utf-8') as f:exec_js = f.read()black_box = execjs.compile(exec_js).call('OOoO0')return black_boxdef login(black_box, username, password):params = {"bust": str(int(time.time() * 1000))}data = {"loginName": username,"passWord": password,"validateNum": "","black_box": black_box}headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"}response = requests.post(url=login_url, params=params, data=data, headers=headers)print(response.json())def main():username = input("请输入登录账号: ")password = input("请输入登录密码: ")black_box = get_black_box()login(black_box, username, password)if __name__ == '__main__':main()
【JS 逆向百例】反混淆入门,某鹏教育 JS 混淆还原相关推荐
- 【JS 逆向百例】webpack 改写实战,G 某游戏 RSA 加密
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...
- 【JS逆向百例】某音乐网分离式 webpack 非 IIFE 改写实战
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 文章目录 声明 逆向目标 逆向过程 抓包分析 参数逆向 webpack 改写 IIFE 传数组 ...
- 【JS 逆向百例】吾爱破解2022春节解题领红包之番外篇 Web 中级题解
关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 逆向目标 本次逆向的目标来源于吾爱破解 2022 春节解题领红包之番外篇 Web 中级题,吾爱破解每年都会有派送红包活动(送吾爱 ...
- 【JS 逆向百例】网洛者反爬练习平台第一题:JS 混淆加密,反 Hook 操作
关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 文章目录 声明 写在前面 逆向目标 绕过无限 debugger Hook 参数 逆向参数 PyCharm 本地联调 完整代码 J ...
- 【JS 逆向百例】W店UA,OB反混淆,抓包替换CORS跨域错误分析
关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 文章目录 声明 逆向目标 OB 混淆简介 抓包分析 混淆还原与替换 CORS 跨域错误 逆向分析 本地联调 完整代码 JavaS ...
- 【JS 逆向百例】Fiddler 插件 Hook 实战,某创帮登录逆向
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...
- 【JS 逆向百例】层层嵌套,某加速商城 RSA 加密
文章目录 声明 逆向目标 逆向过程 抓包分析 参数逆向 逻辑总结 完整代码 参数 JS 加密关键代码 Python 登录关键代码 声明 本文章中所有内容仅供学习交流,敏感网址.数据接口均已做脱敏处理, ...
- 【JS 逆向百例】当乐网登录接口参数逆向
文章目录 声明 逆向目标 逆向过程 抓包分析 参数逆向 完整代码 d_cn_encrypt.js d_cn_login.py 声明 本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产 ...
- 【JS 逆向百例】层层嵌套!某加速商城 RSA 加密
文章目录 声明 逆向目标 逆向过程 抓包分析 参数逆向 逻辑总结 完整代码 参数 JS 加密关键代码 Python 登录关键代码 关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫 ...
最新文章
- java青蛙青蛙跳井_公务员行测技巧:青蛙跳井问题
- css学习笔记3--灵活的背景定位
- scala中使用特质中的抽象字段和实际字段
- 接口测试的时候如何生成随机数据进行测试
- Windows环境下Android NDK环境搭建
- excel表中怎么插入visio_Microsoft Visio2007中vsdx文件怎么打开|Visio插入表格方法
- OpenCv中 width 和 widthStep的区别
- RS485通讯上下拉电阻的选择
- win10下网易云网络异常问题解决办法
- 信息系统集成监理费收取标准_信息系统工程监理资费标准.doc
- Word排版之页眉页脚设置
- python颜色代码棕色_图表的基本配色方法
- 安装 GVM 11 的 OS选择说明
- 秦观 满庭芳-山抹微云 改阳韵
- 微信小程序-如何解决view中放纯数字或字母不会自动换行?【亲测有效】
- Android性能优化之图片压缩综合解决方案
- set、env、export的区别
- Android 分屏模式 问题总结
- Tomoya【省选模拟赛】
- 【ZedBoard实验随笔】OV7670 摄像头 简单总结
热门文章
- VS2008 JS脚本调试总是调试旧代码 真不知道怎么回事?谁能帮帮我呀!
- 拓扑排序两种实现方式
- [Java]中[this][super]用法总结
- 【发现问题】IDEA设置全局新创建文件默认换行符
- java 反射 成员变量_java基础--反射(成员变量)
- memcpy函数_[PART][BUG][MSVCRT][C][CCF NOI1097] 关于memcpy的坑
- 第一个django项目
- freemarker使用说明_SpringBoot+Swagger2集成详细说明
- asm扩容流程_Oracle rac asm 扩容
- 计算机管理员无法创建密码,找到电脑管理员的密码