关注微信公众号: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"] 包含了 itostv 三个参数,使用 JSON 的 stringify 方法将其转换成字符串,然后调用 QQo0 方法进行加密,如下图所示:

我们先来看看 oQOQ0["blackBox"] 里的四个参数,其中 itosv 三个参数在这个函数开始就已经有定义,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 混淆还原相关推荐

  1. 【JS 逆向百例】webpack 改写实战,G 某游戏 RSA 加密

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...

  2. 【JS逆向百例】某音乐网分离式 webpack 非 IIFE 改写实战

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 文章目录 声明 逆向目标 逆向过程 抓包分析 参数逆向 webpack 改写 IIFE 传数组 ...

  3. 【JS 逆向百例】吾爱破解2022春节解题领红包之番外篇 Web 中级题解

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 逆向目标 本次逆向的目标来源于吾爱破解 2022 春节解题领红包之番外篇 Web 中级题,吾爱破解每年都会有派送红包活动(送吾爱 ...

  4. 【JS 逆向百例】网洛者反爬练习平台第一题:JS 混淆加密,反 Hook 操作

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 文章目录 声明 写在前面 逆向目标 绕过无限 debugger Hook 参数 逆向参数 PyCharm 本地联调 完整代码 J ...

  5. 【JS 逆向百例】W店UA,OB反混淆,抓包替换CORS跨域错误分析

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 文章目录 声明 逆向目标 OB 混淆简介 抓包分析 混淆还原与替换 CORS 跨域错误 逆向分析 本地联调 完整代码 JavaS ...

  6. 【JS 逆向百例】Fiddler 插件 Hook 实战,某创帮登录逆向

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...

  7. 【JS 逆向百例】层层嵌套,某加速商城 RSA 加密

    文章目录 声明 逆向目标 逆向过程 抓包分析 参数逆向 逻辑总结 完整代码 参数 JS 加密关键代码 Python 登录关键代码 声明 本文章中所有内容仅供学习交流,敏感网址.数据接口均已做脱敏处理, ...

  8. 【JS 逆向百例】当乐网登录接口参数逆向

    文章目录 声明 逆向目标 逆向过程 抓包分析 参数逆向 完整代码 d_cn_encrypt.js d_cn_login.py 声明 本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产 ...

  9. 【JS 逆向百例】层层嵌套!某加速商城 RSA 加密

    文章目录 声明 逆向目标 逆向过程 抓包分析 参数逆向 逻辑总结 完整代码 参数 JS 加密关键代码 Python 登录关键代码 关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫 ...

最新文章

  1. java青蛙青蛙跳井_公务员行测技巧:青蛙跳井问题
  2. css学习笔记3--灵活的背景定位
  3. scala中使用特质中的抽象字段和实际字段
  4. 接口测试的时候如何生成随机数据进行测试
  5. Windows环境下Android NDK环境搭建
  6. excel表中怎么插入visio_Microsoft Visio2007中vsdx文件怎么打开|Visio插入表格方法
  7. OpenCv中 width 和 widthStep的区别
  8. RS485通讯上下拉电阻的选择
  9. win10下网易云网络异常问题解决办法
  10. 信息系统集成监理费收取标准_信息系统工程监理资费标准.doc
  11. Word排版之页眉页脚设置
  12. python颜色代码棕色_图表的基本配色方法
  13. 安装 GVM 11 的 OS选择说明
  14. 秦观 满庭芳-山抹微云 改阳韵
  15. 微信小程序-如何解决view中放纯数字或字母不会自动换行?【亲测有效】
  16. Android性能优化之图片压缩综合解决方案
  17. set、env、export的区别
  18. Android 分屏模式 问题总结
  19. Tomoya【省选模拟赛】
  20. 【ZedBoard实验随笔】OV7670 摄像头 简单总结

热门文章

  1. VS2008 JS脚本调试总是调试旧代码 真不知道怎么回事?谁能帮帮我呀!
  2. 拓扑排序两种实现方式
  3. [Java]中[this][super]用法总结
  4. 【发现问题】IDEA设置全局新创建文件默认换行符
  5. java 反射 成员变量_java基础--反射(成员变量)
  6. memcpy函数_[PART][BUG][MSVCRT][C][CCF NOI1097] 关于memcpy的坑
  7. 第一个django项目
  8. freemarker使用说明_SpringBoot+Swagger2集成详细说明
  9. asm扩容流程_Oracle rac asm 扩容
  10. 计算机管理员无法创建密码,找到电脑管理员的密码