web爬虫第五弹 - JS逆向入门(猿人学第一题)
0- 前言
爬虫是一门需要实战的学问。 而对于初学者来说,要想学好反爬,js逆向则是敲门砖。今天给大家带来一个js逆向入门实例,接下来我们一步一步来感受下入门的逆向是什么样的。该案例选自猿人学练习题。猿人学第一题
1- 拿到需求
进入页面拿到需求我们先不要急着看源码, 没事多点点喝杯茶。需求为抓取页面上所有机票的平均值。
2- 参数分析
1- 打开无痕浏览器, 免得上班刷题被网管查到记录。 然后可以放心的多一点看一](https://img-blog.csdnimg.cn/b576674b03fc4d04a2a2add6242ae611.png)
前三页都挺正常的, 看起来就是普普通通的AJAX请求

2- 第四页第五页画风突变,不让看了。一想也是, 防止你手动计算, 只能逆了js才能访问。 好吧, 我们现在来构建一下请求。

3- 复制请求到postman, 可以正常访问。

将代码复制到python, 亦可以正常访问。 哇, 感觉还行啊

再运行一下, 报错了, 看下postman, 也报错了。 看样子是有时效性的参数。 那我们来看看参数吧。

就是这个了, 多抓几次包, 确定page是页数,还有一个m是变动的。 瞅着后面像是个时间戳。前面是一段类似加密参数。 那我们的目标明确了, 就是这个m。 破解了, 就可以正常获取到页面了吧。

3- 逆向过程
1- 首先我们要知道一个参数如何加密的,需要先找到加密代码。 以下提供两个方法:
方法一:从Initiator中进入

最后一个请求在此发出。 我们在此处打上断点, 即为发送请求时所有参数在此以全部加载完。那我们重新请求, 既可以看到参数的变化,从call stack中寻找, 或者search中搜索关键词都行。 慢慢找到参数 m 的生成地方

最终我们在request中找到了m的生成地方, 查看m参数是如何生成的

我们看到参数m 是有 window[‘\x66’] 这个值生成。很明显这个js文件中并没有该值的生成逻辑。 那如何找到 window[‘\x66’] 的加载地方呢。 我们继续往上一个堆栈找, 即anonymous。

进入后我们发现这里有一大段未格式化的js代码。 写的不规范,十有八九就是不想让你看。 如果一个网站js代码不想让别人读,那它一定有问题, 我们把这段代码拿出来格式化一下

去掉一些没有什么卵用的东西, 剩下了两段js代码。
一段是我们在上一个js中看到的oo0O0(mw)函数,
另一段是window的相关属性。

咱们都展开看一下,运行一下, 发现报错。 缺少w函数, 我们缺啥补啥,一个个给他找齐
D:\Scriptspace\逆向\学习逆向第一步\猿人学_第一题\第一段js.js:1
w();
^

只用补齐w() 和 D()两个函数, 再次运行即正常了, 我们拿到参数 mw, 传入oo0O0(mw) 试试效果

结果如下, 又去少了window.a, 继续补, 补到运行不报错为止。

参数全部补齐后, 又报了一个如下错误。

node:buffer:1349
throw lazyDOMException(‘Invalid character’, ‘InvalidCharacterError’);
^
DOMException [InvalidCharacterError]: Invalid character
at new DOMException (node:internal/per_context/domexception:53:5)
at _node_internal (node:internal/util:520:10)
at atob (node:buffer:1349:13)
at oo0O0 (D:\Scriptspace\逆向\学习逆向第一步\猿人学_第一题\第一段js.js:52:10)
at Object. (D:\Scriptspace\逆向\学习逆向第一步\猿人学_第一题\第一段js.js:57:13)
at Module._compile (node:internal/modules/cjs/loader:1254:14)
at Module._extensions…js (node:internal/modules/cjs/loader:1308:10)
at Module.load (node:internal/modules/cjs/loader:1117:32)
at Module._load (node:internal/modules/cjs/loader:958:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
没办法一个个去打印查看一下,并随手chatgpt一下, 经过gpt的解析, 代码应该是如下这样。
其中mw是个变量, 估计是传入的mw的值。目测这就是一个函数啊
atob(window['b'])[J('0x0', ']dQW')](J('0x1', 'GTu!'), "mw" )

我们在控制台将函数打印一下,并提取出来

格式化一整理, 这就是个函数啊, 我们将参数传入。一运行, 成功了。 多次校验, 这个值就是参数m的加密值。 还准备打持久战,怎么稀里糊涂就已经拿到值了。

总结
按照我们原本的思路, 我们的处理逻辑是
1- 我们多次请求, 对页面进行抓包, 分析其参数。 猜想为: 加密参数外加cookie中其他参数案例中: 只有一个m参数为必须参数
2- 对js进行断点调试, 找到m参数生成的地方猜想为: 一段js加密, 或许会有混淆。 案例中: 加密逻辑为一段未格式化的<script>脚本,格式化后就能正常调用。
3- 对加密代码进行解析猜想为: 生成出有一段 oo0O0(mw) 的代码, 和一段window的参数代码。 需要复现两段代码逻辑, 整合后进行解密。案例中: 只处理了 oo0O0(mw) 函数, 并在函数中找到了eval(atob(window['b'])[J('0x0', ']dQW')](J('0x1', 'GTu!'), '\x27' + mw + '\x27')); 这段数据, 在找不到window['b']的生成处后,直接打印了atob(window['b'])得到一段js代码。 解析js代码, 确认直接为加密逻辑
4- 校验, 通过读传参时的js确定参数为时间戳, 并将时间戳传入加密逻辑, 成功获取参数m的值。
js逆向需要我们有一定的js功底, 不同的js逆向难易程度都有所不同。 针对于本案例是属于比较简单的js逆向。有种还未还是解析就已经拿到了加密逻辑的感觉。 适合练手
补充
在前面说到有几个断点调试的方法,在之前的爬虫文章中也提到了, 针对这个案例,补充一下查找断点的方法
第一个:添加 xhr断点, 因为本案例中为ajax请求, 获取到了接口, 可以直接在这里打上断点

第二个:就是本案例中用到的, 直接callstack中断点

第三个: 直接搜索参数中的page, 直接找到加密逻辑。(这个方法有一定的随机性, 谨慎使用)

代码
加密逻辑大家自己搞定, 我这里只放python代码了。将加密逻辑抠出来, 运行这段python直接获取结果。
import execjs, time, urllib.parsedef get_param_m():timestamp = int(time.time()) * 1000 + (16798545 + -72936737 + 156138192)M_time = int(timestamp/1000)mwqqppz = str(timestamp)with open ('猿人学第一题.js',encoding='utf-8') as f:js_data = f.read()js = execjs.compile(js_data)js_result = js.call('hex_md5', mwqqppz)param_m = "{}丨{}".format(js_result, M_time)return param_mdef get_info(page, param_m):import requestsurl = "https://match.yuanrenxue.cn/api/match/1?page={}&m={}".format(page, param_m)url = urllib.parse.quote(url, safe=':/?=&')print(url)headers = {'authority': 'match.yuanrenxue.cn','accept': 'application/json, text/javascript, */*; q=0.01','accept-language': 'zh-CN,zh;q=0.9','cache-control': 'no-cache','cookie': 'Hm_lvt_c99546cf032aaa5a679230de9a95c7db=1690184377,1690941596,1690969392,1690971468; Hm_lvt_9bcbda9cbf86757998a2339a0437208e=1690184376,1690941595,1690969392,1690971468; Hm_lvt_434c501fe98c1a8ec74b813751d4e3e3=1690971476; Hm_lpvt_434c501fe98c1a8ec74b813751d4e3e3=1690971476; tk=-7962460354862954537; sessionid=1mcld1cz4z54nrnhkuxfq7wtysc7vdds; Hm_lpvt_9bcbda9cbf86757998a2339a0437208e=1691027865; Hm_lpvt_c99546cf032aaa5a679230de9a95c7db=1691027869','pragma': 'no-cache','referer': 'https://match.yuanrenxue.cn/match/1','sec-ch-ua': '"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"','sec-ch-ua-mobile': '?0','sec-ch-ua-platform': '"Windows"','sec-fetch-dest': 'empty','sec-fetch-mode': 'cors','sec-fetch-site': 'same-origin','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36','x-requested-with': 'XMLHttpRequest'}response = requests.request("GET", url, headers=headers).json()print(response['data'])sum = 0for val in response['data']:sum += val['value']mean_num = sum/len(response['data'])return mean_numif __name__ == '__main__':sum_num = 0for page in range(1, 6):param_m = get_param_m()print(param_m)res = get_info(page ,param_m)print(res)sum_num += resresult = sum_num/5print(result)

相关文章:
web爬虫第五弹 - JS逆向入门(猿人学第一题)
0- 前言 爬虫是一门需要实战的学问。 而对于初学者来说,要想学好反爬,js逆向则是敲门砖。今天给大家带来一个js逆向入门实例,接下来我们一步一步来感受下入门的逆向是什么样的。该案例选自猿人学练习题。猿人学第一题 1- 拿到需求 进入页面…...
P5731 【深基5.习6】蛇形方阵
题目描述 给出一个不大于 9 9 9 的正整数 n n n,输出 n n n\times n nn 的蛇形方阵。 从左上角填上 1 1 1 开始,顺时针方向依次填入数字,如同样例所示。注意每个数字有都会占用 3 3 3 个字符,前面使用空格补齐。 输入格式…...
Python实现GA遗传算法优化循环神经网络回归模型(LSTM回归算法)项目实战
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法(Genetic Algorithm,GA)最早是由美国的 John holland于20世…...
ESD防静电监控系统在SMT产线中的应用案例
作为电子厂的关键制造环节之一,SMT(表面贴装技术)产线的效率和质量对企业的竞争力至关重要。为了提高生产线的管理效率和保障生产环境的质量,许多电子厂开始采用MES生产管理系统和ESD防静电监控系统的综合解决方案。 在SMT产线中安…...
Vue+Nodejs+Express+Minio 实现本地图片上传
安装Minio,Minio server和Minio client都要下载可以自定义安装目录 安装完成之后,可以将minio配置成环境变量方便使用 配置了环境变量启动命令式 minio server start,默认账号密码minioadmin和minioadmin,点击9000端口的这个链接,即可访问客户端 nodejs连接Minio,简易服务进…...
em3288 linux_4.19 第一次烧写无法进入内核的情况
1. 情况一: /DDR Version 1.11 20210818 In SRX Channel a: DDR3 400MHz Bus Width32 Col10 Bank8 Row15 CS1 Die Bus-Width16 Size1024MB Channel b: DDR3 400MHz Bus Width32 Col10 Bank8 Row15 CS1 Die Bus-Width16 Size1024MB OUT Boot1 Release Time: Jul 22 2…...
【Java多线程学习5】什么是悲观锁,什么是乐观锁?如何实现乐观锁、乐观锁存在哪些问题
【Java多线程学习5】什么是悲观锁,什么是乐观锁?如何实现乐观锁、乐观锁存在哪些问题 一、什么是悲观锁 概述 悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作…...
OSPF协议RIP协议+OSPF实验(eNSP)
本篇博客主要讲解单区域的ospf,多区域的仅作了解。 目录 一、OSPF路由协议概述 1.内部网关协议和外部网关协议 二、OSPF的应用环境 1.从以下几方面考虑OSPF的使用 2.OSPF的特点 三、OSPF重要基本概念 3.1,辨析邻居和邻接关系以及七种邻居状态 3…...
leetcode每日一练-第108题-将有序数组转换为二叉搜索树
一、思路 递归 二、解题方法 在给定中序遍历序列数组的情况下,每一个子树中的数字在数组中一定是连续的,因此可以通过数组下标范围确定子树包含的数字,下标范围记为 [left,right]。对于整个中序遍历序列,下标范围从 left0到 ri…...
王道《操作系统》学习(二)—— 进程管理(二)
2.1 处理机调度的概念、层次 2.1.1 调度的基本概念 2.1.2 调度的三个层次 (1)高级调度(作业调度) (2)中级调度(内存调度) 补充知识:进程的挂起状态和七状态模型 &#x…...
Vulnhub: shenron: 3靶机
kali:192.168.111.111 靶机:192.168.111.171 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.171 修改hosts后访问目标80端口,发现是wordpress wpscan收集目标用户,爆破出密码:ilov…...
Kubernetes高可用集群二进制部署(二)ETCD集群部署
Kubernetes概述 使用kubeadm快速部署一个k8s集群 Kubernetes高可用集群二进制部署(一)主机准备和负载均衡器安装 Kubernetes高可用集群二进制部署(二)ETCD集群部署 Kubernetes高可用集群二进制部署(三)部署…...
mysql主从复制及原理
目录 主从复制原理实现主从复制 主从复制原理 主要基于MySQL二进制日志 主要包括三个线程(2个I/O线程,1个SQL线程) 1、MySQL将数据变化记录到二进制日志中; 2、Slave将MySQL的二进制日志拷贝到Slave的中继日志中; …...
MQTT服务器详细介绍:连接物联网的通信枢纽
随着物联网技术的不断发展,MQTT(Message Queuing Telemetry Transport)协议作为一种轻量级、可靠、灵活的通信协议,被广泛应用于物联网领域。在MQTT系统中,MQTT服务器扮演着重要的角色,作为连接物联网设备和…...
通过VBA宏合并Excel工作表
工作中经常会用到的把几个Excel文件合并到一个,或者是把一个Excel文件里的所有Sheet合并到一个Sheet来进行统计。下面分别提供用vba宏来解决这两个问题的方法。 1、合并Excel文件 打开一个空Excel文件,AltF11,插入一个模块,开始…...
Mac 定时重启 TouchBar 脚本(缓解闪烁问题)
背景 Mac 笔记本 TouchBar 是真的脆啊,合盖使用一段时间就废了,右侧一直闪烁简直亮瞎眼 😂 经过观察,总结出闪烁规律如下: 工作状态:不断操作电脑时,触控栏处于工作状态,几乎不闪…...
Redis主从复制、哨兵机制、集群分片
目录 一.主从复制 1.概述 2.主从架构相比于单点架构的优势 3.主从复制原理和工作流程 第一次同步 第一阶段:建立链接、协商同步 第二阶段:主服务器同步数据给从服务器 第三阶段:主服务器发送新写操作命令给从服务器 基于长连接的命…...
字段填充策略 FieldFill
实体类中有如下属性,通过上面的自动填充属性,我们可以实现在进行插入(insert)操作时对添加了注解TableField(fill FieldFill.INSERT)的字段进行自动填充(解释:后面会写配置自动填充的配置类,该…...
Docker run 启动容器报错
今天在Windows下启动docker容器发现的三个错误: Ports are not available: exposing port TCP 0.0.0.0:1521 -> 0.0.0.0:0: listen tcp 0.0.0.0:1521: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted. 端口…...
Golang之路---03 面向对象——类型断言
类型断言 作用 检查 i 是否为 nil检查 i 存储的值是否为某个类型 使用方式 第一种: t : i.(T)这个表达式可以断言一个接口对象(i)里不是 nil,并且接口对象(i)存储的值的类型是 T,如果断言成…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
