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)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/77218.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记录--一个好用的轮子 turn.js 实现仿真翻书的效果

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 国际惯例&#xff0c;官网链接 官网传送门 Github地址 github上有几个demos例子&#xff0c;介绍了基础用法。 我参考官网的例子&#xff0c;写了一个demo示例 安装 turn.js 依赖 jquery 库&#xff0…

MySQL — 存储引擎

文章目录 存储引擎存储引擎类型InnoDBMyISAMMEMORY 存储引擎是数据库的核心&#xff0c;对于mysql来说&#xff0c;存储引擎是以插件的形式运行的。虽然mysql支持种类繁多的存储引擎&#xff0c;但是常用的就那么几种。这篇文章主要是对其进行简单的介绍。 存储引擎 MySQL可插…

linux下绑定进程到指定CPU的操作方法

taskset简介 # taskset Usage: taskset [options] [mask | cpu-list] [pid|cmd [args...]] Show or change the CPU affinity of a process. Options: -a, --all-tasks operate on all the tasks (threads) for a given pid -p, --pid operate on ex…

ensp-GVRP服务

ensp-GVRP服务 日期&#xff1a;6-26 &#x1f4ce;GVRP实验.zip&#x1f4ce;GVRP服务.docx

快速WordPress个人博客并内网穿透发布到互联网

快速WordPress个人博客并内网穿透发布到互联网 文章目录 快速WordPress个人博客并内网穿透发布到互联网 我们能够通过cpolar完整的搭建起一个属于自己的网站&#xff0c;并且通过cpolar建立的数据隧道&#xff0c;从而让我们存放在本地电脑上的网站&#xff0c;能够为公众互联网…

group normalization

1、 Theory look for this link for more information, actually only this image can illustrate the group normalization.you can ignore the rest of this artical. 2、 Code check this link for detailed about the formulation and the theory of the group normalzi…

如何发布自己的npm包

发布一个简单的npm包 首先创建一个文件夹&#xff08;唯一的命名&#xff09;创建package.json包&#xff0c;输出npm init&#xff0c;一直回车就好。创建index.js文件&#xff0c;向外暴露方法。 将包上传或更新到 npm 执行登录命令&#xff1a;npm login 登录npm官网&…

复原 IP 地址——力扣93

文章目录 题目描述回溯题目描述 回溯 class Solution{public:static constexpr int seg_count=4<

开源免费用|Apache Doris 2.0 推出跨集群数据复制功能

随着企业业务的发展&#xff0c;系统架构趋于复杂、数据规模不断增大&#xff0c;数据分布存储在不同的地域、数据中心或云平台上的现象越发普遍&#xff0c;如何保证数据的可靠性和在线服务的连续性成为人们关注的重点。在此基础上&#xff0c;跨集群复制&#xff08;Cross-Cl…

【QT调用ST-link-使用QT编写程序-调用ST-LINK_CLI.exe-烧写STM32F4xxx-基础样例】

【QT结合ST-link&#xff0c;使用QT编写程序&#xff0c;调用ST-LINK_CLI.exe,烧写STM32F4xxx-基础样例】 1、前言2、实验环境3、先前了解-自我总结4、实验过程&#xff08;0&#xff09;硬件连接与供电&#xff08;1&#xff09;安装&使用STM32 ST-LINK Utility&#xff0…

合并果子C++详解

题目描述 在一个果园里&#xff0c;多多已经将所有的果子打了下来&#xff0c;而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。 每一次合并&#xff0c;多多可以把两堆果子合并到一起&#xff0c;消耗的体力等于两堆果子的重量之和。可以看出&#xff0c;…

AOF日志:宕机了,Redis如何避免数据丢失

当服务器宕机后&#xff0c;数据全部丢失&#xff1a;我们很容易想到的一个解决方案是从后端数据库恢复这些数据&#xff0c;但这种方式存在两个问题&#xff1a;一是&#xff0c;需要频繁访问数据库&#xff0c;会给数据库带来巨大的压力&#xff1b;二是&#xff0c;这些数据…

【云原生】K8S超详细概述

目录 一、Kubernets概述1.1 K8S什么1.2为什么要用K8S 二、Kubernetes 集群架构与组件2.1Master组件Kube-apiserverKube-controller-managerKube-scheduler 2.2 配置存储中心etcd 2.3 Node 组件KubeletKube-Proxydocker 或 rocket 三、 Kubernetes 核心概念3.1Pod3.2Pod 控制器K…

React Dva项目 Model中编写与调用异步函数

上文 React Dva项目中模仿网络请求数据方法 中&#xff0c;我们用项目方法模拟了后端请求的数据 那么 今天我们就在models中尝试去使用一下这种异步获取数据的方法 之前 我们在文章 React Dva项目创建Model,并演示数据管理与函数调用 中已经接触过Model了 也可以理解为 它就是 …

STM32入门学习之定时器中断

1.STM32的通用定时器是可编程预分频驱动的16位自动装载计数器。 STM32 的通用定时器可以被用于&#xff1a;测量输入信号的脉冲长度 ( 输入捕获 ) 或者产生输出波 形 ( 输出比较和 PWM) 等。 使用定时器预分频器和 RCC 时钟控制器预分频器&#xff0c;脉冲长度和波形 周…

C# Blazor 学习笔记(7):组件嵌套开发

文章目录 前言相关资料组件嵌套组件模板RenderFragment 意义传统前端样式组件化css 前言 我们在组件化一共有三个目的。 不用写CSS不用写html不用写交互逻辑 简单来说就是Java常说的约定大于配置。我们只需要必须的参数即可&#xff0c;其它的都按照默认配置。我们不需要关系…

穷举深搜暴搜回溯剪枝(3)

一)字母大小写全排列 784. 字母大小写全排列 - 力扣&#xff08;LeetCode&#xff09; 1)从每一个字符开始进行枚举&#xff0c;如果枚举的是一个数字字符&#xff0c;直接忽视 如果是字母的话&#xff0c;进行选择是变还是不变 2)当进行遍历到叶子结点的时候&#xff0c;直接将…

网络安全进阶学习第十一课——MySQL手工注入(2)

文章目录 一、UA注入1、原理2、靶场演示&#xff1a;1&#xff09;一旦页面出现如下现状&#xff0c;就可以使用UA注入2&#xff09;BP抓包3&#xff09;修改User-Agent 二、referer注入1、原理2、靶场演示&#xff1a;1&#xff09;使用BP抓包2&#xff09;修改Referer 三、DN…

0基础学习VR全景平台篇 第76篇:全景相机-圆周率全景相机如何直播推流

圆周率科技&#xff0c;成立于2012年&#xff0c;是中国最早投身嵌入式全景算法研发的团队之一&#xff0c;亦是全球市场占有率最大的全景算法供应商。相继推出一体化智能屏、支持一键高清全景直播的智慧全景相机--Pilot Era和Pilot One&#xff0c;为用户带来实时畅享8K的高清…

【编程】典型题目:寻找数组第K大数(四种方法对比)

【编程】典型题目&#xff1a;寻找数组第K大数&#xff08;四种方法对比&#xff09; 文章目录 【编程】典型题目&#xff1a;寻找数组第K大数&#xff08;四种方法对比&#xff09;1. 题目2. 题解2.1 方法一&#xff1a;全局排序&#xff08;粗暴&#xff09;2.2 方法二&#…