关注微信公众号:K哥爬虫,持续分享爬虫进阶、JS/安卓逆向等技术干货!

声明

本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

逆向目标

  • 目标:某投资领域 SAAS 系统 PEDATA MAX 资讯,返回结果加密
  • 主页:aHR0cHM6Ly9tYXgucGVkYXRhLmNuL2NsaWVudC9uZXdzL25ld3NmbGFzaA==
  • 接口:aHR0cHM6Ly9tYXgucGVkYXRhLmNuL2FwaS9xNHgvbmV3c2ZsYXNoL2xpc3Q=
  • 逆向参数:请求返回的加密结果,data: "L+o+YmIyNDE..."

抓包分析

我们在首页,点击查看全部24小时资讯,往下拉,资讯是以 Ajax 形式加载的,我们选中开发者工具 XHR 进行筛选,很容易找到一个 list 请求,其返回值 data 是一串经过加密后的字符串,exor 不知道是啥,但是后面可能有用,ts 是时间戳,如下图所示:

Payload 里的参数没有什么特别的,就是一些翻页信息,我们再看看请求 header,这里注意 CookieHTTP-X-TOKEN 两个参数,访问这个页面需要登录账号,一般来说,Cookie 是用来标识不同用户的,但经过 K 哥测试发现,此案例中,这个 HTTP-X-TOKEN 参数才是用来识别用户的,所以不需要 Cookie 也行,随便提一嘴,Cookie 中我们经常看到有 Hm_lvt_xxxHm_lpvt_xxx 是用于百度联盟广告的数据统计的,与爬虫无关。

加密逆向

我们注意到返回的是一个字典,在获取到加密数据后,肯定会有一个取值的过程,所以我们直接搜索键,搜索 exor 结果只有一个:

这里 e.data 就是返回的字典,e.data.datae.data.exor 依次取加密值和 exor,这里就可以猜测是将加密值取出来进行解密操作了,我们在此函数结尾处也打个断点,看看这段代码执行完毕后,data 的值是否变成了明文:

不出所料,Object(p["y"])(e.data.data, e.data.exor) 这段代码就是解密函数了,Object(p["y"]) 其实是调用了 M 方法,跟进去看看:

传入的 t 和 n 分别是加密值和 exor,最后返回的 JSON.parse(c) 就是解密结果:

关键代码:

function M(t, n) {
var a = L(Object(s["a"])(), n)
, r = Y(B(t), a)
, c = o.a.gunzipSync(e.from(r)).toString("utf-8");
return JSON.parse(c)
}

挨个函数扣下来,简单的就不讲了, 其中 Object(s["a"]),选中它,其实是调用了 c 方法,跟进 c 方法,实际上是取了 loginToken,这个 loginToken 就是我们前面分析的请求头中的 HTTP-X-TOKEN,包含了你的登录信息。

拓展知识:window.localStorage 属性用于在浏览器中存储键值对形式的数据,localStoragesessionStorage 类似,区别在于:localStorage 中的数据可以长期保留,没有过期时间,直到被手动删除。sessionStorage 的数据仅保存在当前会话中,在关闭窗口或标签页之后将会删除这些数据。

再往下看,有个 o.a.gunzipSync(),先放一下,先看看传入的参数 e.from(r),跟进看可能看不出来什么,直接对比 re.from(r),会发现都是 Uint8Array 的数据,一模一样的,如下图所示:

再来看看 o.a.gunzipSync(),实际上调用的是 chunk-vendors.js 里的匿名函数,不知道这个 JS 不要紧,我们注意到 chunk-vendors.js 里面的代码有超过14万行,再加上这个奇怪的名字,什么模块供应商,不难想到这是一个系统或者第三方生成的 JS,事实上它是 vue 应用程序构建过程中创建的文件,对于我们爬虫工程师来讲,粗暴的将其理解为类似 jquery.js 一样的东西也行,我们一般是不会去扣 jquery.js 里面的代码的,同样这个 chunk-vendors.js 也不可能傻傻的去扣。

我们重点看看这个函数名,gunzipSync,其他不认识,但认识 zip 吧,可以联想到应该与压缩有关,不了解同样不要紧,直接使出百度大法:

这直接给出了 nodejs 里面的实现方法,用的是 zlib 模块,随便找个示例看看用法:

var zlib = require('zlib');
var input = "Nidhi";
var gzi = zlib.gzipSync(input);
var decom = zlib.gunzipSync(new Buffer.from(gzi)).toString(); console.log(decom);

进一步学习,我们可以知道 zlib.gunzipSync() 方法是 zlib 模块的内置应用程序编程接口,用于使用 Gunzip 解压数据块。传入的数据可以是 Buffer、TypedArray、DataView、ArrayBuffer、string 类型,在官方文档中我们可以看到更新历史里面,在 v8.0.0 以后,传入的数据就支持 Uint8Array 了:

结合前面我们对 r 值的分析,所以在 nodejs 里,直接把 r 值传入到 zlib.gunzipSync() 方法里就可以了,将用到的 L、V、B 三个方法扣出来,然后配合 zlib 库,改写一下就能拿到解压后的数据了:

function getDecryptedData(encryptedData, exor, loginToken) {
var a = L(loginToken, exor);
var r = Y(B(encryptedData), a)
var decryptedData = zlib.gunzipSync(r).toString();
return decryptedData
}

完整代码

GitHub 关注 K 哥爬虫,持续分享爬虫相关代码!欢迎 star !https://github.com/kgepachong/

以下只演示部分关键代码,不能直接运行! 完整代码仓库地址:https://github.com/kgepachong/crawler/

JavaScript 加密代码

/* ==================================
# @Time : 2021-12-31
# @Author : 微信公众号:K哥爬虫
# @FileName: main.js
# @Software: PyCharm
# ================================== */ var zlib = require('zlib'); function L(e, t) {
if ("1" == t)
return [7, 65, 75, 31, 71, 101, 57, 0];
for (var n = [], a = 0, r = t.length; a < r; a += 2)
n.push(e.substr(1 * t.substr(a, 2), 1).charCodeAt());
return n
} function Y(e, t) {
for (var n, a = new Uint8Array(e.length), r = 0, c = e.length; r < c; r++)
n = t[r % t.length],
a[r] = e[r].charCodeAt() ^ n;
return a
} function B(e) {
var t, n, a, r, c, u, i, o = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", s = "", f = 0;
e = e.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (f < e.length)
r = o.indexOf(e.charAt(f++)),
c = o.indexOf(e.charAt(f++)),
u = o.indexOf(e.charAt(f++)),
i = o.indexOf(e.charAt(f++)),
t = r << 2 | c >> 4,
n = (15 & c) << 4 | u >> 2,
a = (3 & u) << 6 | i,
s += String.fromCharCode(t),
64 != u && (s += String.fromCharCode(n)),
64 != i && (s += String.fromCharCode(a));
return s
} function getDecryptedData(encryptedData, exor, loginToken) {
var a = L(loginToken, exor);
var r = Y(B(encryptedData), a)
var decryptedData = zlib.gunzipSync(r).toString();
return decryptedData
}

Python 示例代码

# ==================================
# --*-- coding: utf-8 --*--
# @Time : 2021-12-31
# @Author : 微信公众号:K哥爬虫
# @FileName: main.py
# @Software: PyCharm
# ================================== import execjs
import requests news_est_url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
login_token = "token 换成你自己的!"
headers = {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json",
"Host": "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler",
"HTTP-X-TOKEN": login_token,
"Origin": "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler",
"Referer": "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
} def get_decrypted_data(encrypted_data, exor):
with open('pedata_decrypt.js', 'r', encoding='utf-8') as f:
pedata_js = f.read()
decrypted_data = execjs.compile(pedata_js).call('getDecryptedData', encrypted_data, exor, login_token)
return decrypted_data def get_encrypted_data():
data = {
"type": "",
"module": "LP",
"page":
{
"currentPage": 1,
"pageSize": 10
}
}
response = requests.post(url=news_est_url, headers=headers, json=data).json()
encrypted_data, exor = response["data"], response["exor"]
return encrypted_data, exor def main():
encrypted_data, exor = get_encrypted_data()
decrypted_data = get_decrypted_data(encrypted_data, exor)
print(decrypted_data) if __name__ == '__main__':
main()

【JS 逆向百例】PEDATA 加密资讯以及 zlib.gunzipSync() 的应用的更多相关文章

  1. 我去!爬虫遇到JS逆向AES加密反爬,哭了

    今天准备爬取网页时,遇到『JS逆向AES加密』反爬.比如这样的: 在发送请求获取数据时,需要用到参数params和encSecKey,但是这两个参数经过JS逆向AES加密而来. 既然遇到了这个情况,那 ...

  2. 爬虫05 /js加密/js逆向、常用抓包工具、移动端数据爬取

    爬虫05 /js加密/js逆向.常用抓包工具.移动端数据爬取 目录 爬虫05 /js加密/js逆向.常用抓包工具.移动端数据爬取 1. js加密.js逆向:案例1 2. js加密.js逆向:案例2 3 ...

  3. 兄弟,别再爬妹子图了整点JS逆向吧--陆金所密码加密破解

    好久没有写爬虫文章了,今晚上得空看了一下陆金所登录密码加密,这个网站js加密代码不难,适合练手,篇幅有限,完整js代码我放在了这里从今天开始种树,不废话,直接开整. 前戏热身 打开陆金所网站,点击到登 ...

  4. 这个爬虫JS逆向加密任务,你还不来试试?逆向入门级,适合一定爬虫基础的人

    友情提示:在博客园更新比较慢,有兴趣的关注知识图谱与大数据公众号吧.这次选择苏宁易购登录密码加密,如能调试出来代表你具备了一定的JS逆向能力,初学者建议跟着内容调试一波,尽量独自将JS代码抠出来,实在 ...

  5. 爬虫必看,每日JS逆向之爱奇艺密码加密,今天你练了吗?

    友情提示:优先在公众号更新,在博客园更新较慢,有兴趣的关注一下知识图谱与大数据公众号,本次目标是抠出爱奇艺passwd加密JS代码,如果你看到了这一篇,说明你对JS逆向感兴趣,如果是初学者,那不妨再看 ...

  6. 网络爬虫之记一次js逆向解密经历

    1 引言 数月前写过某网站(请原谅我的掩耳盗铃)的爬虫,这两天需要重新采集一次,用的是scrapy-redis框架,本以为二次爬取可以轻松完成的,可没想到爬虫启动没几秒,出现了大堆的重试提示,心里顿时 ...

  7. JS逆向之补环境过瑞数详解

    JS逆向之补环境过瑞数详解 "瑞数" 是逆向路上的一座大山,是许多JS逆向者绕不开的一堵围墙,也是跳槽简历上的一个亮点,我们必须得在下次跳槽前攻克它!! 好在现在网上有很多讲解瑞数 ...

  8. JS逆向之浏览器补环境详解

    JS逆向之浏览器补环境详解 "补浏览器环境"是JS逆向者升职加薪的必备技能,也是工作中不可避免的操作. 为了让大家彻底搞懂 "补浏览器环境"的缘由及原理,本文将 ...

  9. 兄弟,你爬虫基础这么好,需要研究js逆向了,一起吧(有完整JS代码)

    这几天的确有空了,看更新多快,专门研究了一下几个网站登录中密码加密方法,比起滑块验证码来说都相对简单,适合新手js逆向入门,大家可以自己试一下,试不出来了再参考我的js代码.篇幅有限,完整的js代码在 ...

  10. 通过JS逆向ProtoBuf 反反爬思路分享

    前言 本文意在记录,在爬虫过程中,我首次遇到Protobuf时的一系列问题和解决问题的思路. 文章编写遵循当时工作的思路,优点:非常详细,缺点:文字冗长,描述不准确 protobuf用在前后端传输,在 ...

随机推荐

  1. 10个问题让你快速避开java中的jdbc常见坑

    摘要:JDBC,即Java Database Connectivity,java数据库连接.是一种用于执行SQL语句的Java API,它是Java中的数据库连接规范. 本文分享自华为云社区<1 ...

  2. PPT 客户提案PPT应该怎么样改

    PPT 客户提案PPT应该怎么样改

  3. Jenkins Pipeline 流水线 - 声明式 Demo

    Jenkins Pipeline 流水线 流水线既能作为任务的本身,也能作为 Jenkinsfile 使用流水线可以让我们的任务从UI手动操作,转换为代码化,像dockerfile 一样.从shell ...

  4. JAVA CRC8

    Java CRC8 /** * CRC-8 * * <table width="400px" border="1" cellpadding="0 ...

  5. Appium常用定位方法讲解

    Appium常用定位方法讲解 对象定位是自动化测试中很关键的一步,也可以说是 最关键的一步,毕竟你对象都没定位那么你想操作也不行,下面我们来看常用的一些定位方式. ID定位(取resource-id的 ...

  6. 【django-vue】前后端分离项目

    博客目录 pip永久换源 虚拟环境搭建 项目前后端创建 项目目录调整 封装logger 封装全局异常 封装response 数据库配置 用户表继承AbstractUser配置 开放media访问 路飞 ...

  7. SpringMVC — 数据响应 / 获取请求参数

    SpringMVC的数据响应方式 页面跳转 直接返回字符串 通过ModelAndView对象返回 回写数据 直接返回字符串 返回对象或集合 页面跳转 方式一.返回带有前缀的字符串: 转发:forwar ...

  8. AtCoder Beginner Contest 215 (个人题解 A~F)

    比赛链接:Here AB水题, C - One More aab aba baa 题意: 给出字符串 \(s\) 和整数 \(k\) ,请输出字典序第 \(k\) 大的原字符串 \(s\) 的排序 思 ...

  9. Codeforce :466C. Number of Ways (数学)

    https://codeforces.com/problemset/problem/466/C 解题说明:此题是一道数学题,若平分分成若干种情况,应当整体(sum)考虑,对sum/3进行分析.它是区分 ...

  10. 0x69 图论-二分图的覆盖与独立集

    A:Machine Schedule 输入 5 5 10 0 1 1 1 1 2 2 1 3 3 1 4 4 2 1 5 2 2 6 2 3 7 2 4 8 3 3 9 4 3 0 输出 3 在二分图 ...