逆向爬虫28 webpack扣取码

目标:

  1. 了解 js 模块化打包webpack代码的特点。
  2. 掌握扣取 webpack 代码的方法。

一. 模块化 webpack 代码特点

有的时候, 我们发现一些网站的 js 代码的函数不是以全部并列顶格书写的。

function a(){}
function b(){}
function c(){}
// ... 一系列函数
function z(){}

而是以下面形式书写

// 自执行函数, 参数是一个数组, 数组里打包了一堆函数
!function(arr){}([function a(){},function b(){},function c(){},// ... 一系列函数function z(){}
])

亦或是

// 自执行函数, 参数是一个对象, 对象里打包了一堆函数
!function(obj){}({a: function(){},b: function(){},c: function(){},// ... 一系列函数z: function(){}
})

遇到上述型类型情况网页的代码, 我们应该怎么扣取相应的加密函数, 放进 execjs 模块中运行呢?其实这是前端 webpack 技术模块化打包后呈现的代码, 这类代码的完整特征呈下述形状

// 自执行函数
!function (allModule) {// 函数加载器function useModule(whichModule) {// 利用 call 或 apply 调用函数allModule[whichModule].call(null, "hello world!");}// 加载并运行了下面数组中的第1个函数useModule(0)
}([// 用数组打包起来的函数列表function module0(param) {console.log("module0: " + param)},function module1(param) {console.log("module1: " + param)},function module2(param) {console.log("module2: " + param)},
]);

它有以下四个特征:

自执行函数!function(){}()

自执行函数参数[function a(){}, function b(){}, ...]{a: function(){}, b: function(){}, ...}

函数加载器function useModule(){}

函数加载器中有callapply 函数

更多webpack基础内容可以参考下面这个链接:

爬虫逆向基础,理解 JavaScript 模块化编程 webpack

二. 扣取 webpack 方法

因为这是第一次在我的博文中提到扣取 js 代码, 因此就先来谈谈下面两个问题:

  1. 为什么要扣 js 代码?扣 js 代码在 js逆向中的作用。
  2. 怎么扣代码才算是最好的扣法。

首先要弄明白我们为什么要扣 js 代码, 扣代码的作用在于, 我们想复用目标网站已经写好的加密或解密算法, 因为这些代码是维护网站的程序员们写的前端代码, 在浏览器中运行, 并且一定可以与他们的后端服务器进行交互工作, 因此如果能够直接使用他们写好的 js 加密或解密算法, 可以省去我们将加密或解密算法翻译成 python 或其他语言的过程, 在 python 中, 正好有一个 execjs 模块, 可以用来执行 js 代码, 如果我们能够把目标网站中的 js 加密或解密函数从浏览器中扣取下来, 保存到本地, 并用 execjs 模块加载执行, 我们就可以相当轻松地得到和浏览器一样加解密效果。

知道了为什么要扣 js 代码之后, 我们再来讨论一下, 怎么扣才算是最好的扣法, 因为我们并不打算在读懂 js 代码后, 自己用 python 或其他语言来自己实现相同的功能, 因此我们就要做到最大程度地复用网站上现有地 js 代码, 而这个过程中, 希望能做到尽量少改动 js 代码, 原因是改的地方越多, 改错的可能性就越大, 后期的维护和扩展成本也就越高。理论上最好的扣法是, 把和你需要的加密和解密相关的函数扣取出来, 并把它们封装成自定义的加密和解密函数, 这部分代码工作时, 由外部的 python execjs 模块调用自定义的加解密函数来完成加解密的工作。

基于上述两个问题, 我们来给出下面这个针对 webpack 样式的代码扣取方法

找到加载器 (加载模块的方法)
找到调用的模块
构造一个自执行方法
导出加载器
编写自定义方法 按照流程加密

三. 扣取 webpack 实例

由于不能指名道姓地公开网站的逆向方案, 因此下面的案例我不会贴出网址, 只是基于一个 webpack 的 js 文件, 扣取内部的加密算法。

下图是一个网站中包含加密函数的 js文件

把它全选复制到本地 IDE 中

可以看到它满足 webpack 代码的所有特点, 因此我们可以先把 自执行函数 函数加载器 先扣下来, 自执行函数里除了 函数加载器 之外的东西可以不要

!function(t) {var i = {};function e(s) {if (i[s])return i[s].exports;var n = i[s] = {exports: {},id: s,loaded: !1};return t[s].call(n.exports, n, n.exports, e),n.loaded = !0,n.exports}
}({});

下图是我在网页输入用户名密码后, 点击登陆后找到的加密函数位置

这里我们找到了第一个用到的函数模块, 就是对象中的第四个函数, 因此把它扣下来即可, 为了外部自定义函数方便调用, 这里我把 key 值从 3 换成了 encrypt

!function(t) {var i = {};function e(s) {if (i[s])return i[s].exports;var n = i[s] = {exports: {},id: s,loaded: !1};return t[s].call(n.exports, n, n.exports, e),n.loaded = !0,n.exports}
}({encrypt: function(t, e, i) {var s;s = function(t, e, s) {function n() {"undefined" != typeof r && (this.jsencrypt = new r.JSEncrypt,this.jsencrypt.setPublicKey("-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDq04c6My441Gj0UFKgrqUhAUg+kQZeUeWSPlAU9fr4HBPDldAeqzx1UR92KJHuQh/zs1HOamE2dgX9z/2oXcJaqoRIA/FXysx+z2YlJkSk8XQLcQ8EBOkp//MZrixam7lCYpNOjadQBb2Ot0U/Ky+jF2p+Ie8gSZ7/u+Wnr5grywIDAQAB-----END PUBLIC KEY-----"))}var r = i(4);n.prototype.encode = function(t, e) {var i = e ? e + "|" + t : t;return encodeURIComponent(this.jsencrypt.encrypt(i))},s.exports = n}.call(e, i, e, t),!(void 0 !== s && (t.exports = s))}
});

接下来我们利用浏览器调试, 追到 594 行代码 this.jsencrypt.encrypt(i) 函数内部

在本地 IDE 中查看3340行属于哪个函数

扣下来的效果如下, 由于代码太长, 这里就放截图效果

从中我们可以看出, 原本标号为 3 的函数又加载了 标号为 4 的函数, 因此我们需要再确认一下, 标号 4 的函数是否有加载其他标号的函数, 另外 4 号函数为什么没有重命名呢?因为是内部调用的函数, 不是接口函数, 我们无需关心它的名字。

如何快速查看 4 号函数是否有再加载其他函数呢?可以使用 IDE 中的搜索功能 (ctrl + f ), 开启正则表达式匹配

现在前三步已经完成了

找到加载器 (加载模块的方法)      完成
找到调用的模块                完成
构造一个自执行方法             完成
导出加载器
编写自定义方法 按照流程加密

接下来是 导出加载器

加载器也导出了, 下一步就是先把这段代码复制到浏览器中运行一下, 看看有没有问题。

因此可以封装如下自定义加密函数

然后把它放进 js 调试工具中试试, 分别报了找不到 navigator 和 window 两个对象, 加上之后就运行成功了。

最终, 扣出来并修改好的js文件长这个样子。

四. 用python execjs调用该模块

from time import time
import execjsdef getPwd(pwd):""" 密码加密 param:pwd: 密码明文return:encrypt_pwd: 密码密文"""node = execjs.get()fp = open('encrypt.js','r',encoding='gbk')ctx = node.compile(fp.read())funcName = f"jiami('{pwd}', {int(time()*1000)})"print(funcName)encrypt_pwd = ctx.eval(funcName)print(encrypt_pwd)return encrypt_pwddef run():pwd = '123456'encrypt_pwd = getPwd(pwd)if __name__ == '__main__':run()

对了, 中间出了个编码问题, 是因为抠出来的 js 文件中存在 gbk 编码的字符, 因此我以 gbk 编码重新打开了一个新的空的 js 文件, 并将这抠出来的 js 代码复制到里面, 保存。在 python 以 gbk 方式打开它, 就可以了

逆向爬虫28 webpack扣代码相关推荐

  1. 逆向爬虫35 常见加密的python实现

    逆向爬虫35 常见加密的python实现 目的:将App逆向中常见的算法用python实现,方便以后的使用 Java常见加密 隐藏字符串 字符串是以字节编码数组的形式存储或网络传输的,因此可以通过指定 ...

  2. 逆向爬虫18 Scrapy抓取全站数据和Redis入门

    逆向爬虫18 Scrapy抓取全站数据和Redis入门 一.全站数据抓取 1. 什么是抓取全站数据? 我们曾经在过猪八戒,图片之家,BOSS直聘等网站,利用网站官方提供的搜索功能,搜索指定关键词的内容 ...

  3. 逆向爬虫32 某视频刷播放

    逆向爬虫32 某视频刷播放 目标:利用爬虫刷某视频播放量 思路:和某站一样,先抓包验证哪个数据包可以使播放量增加,这个过程就省略了,经过测试发现是下图这个数据包 观察请求参数 ctime: 动态时间 ...

  4. 携程逆向爬虫 | PC网页端 | 旅游景点评论爬虫

    目录 导语 1. 获取所有城市_id 2. 分析评论信息位置 3. 获取当前市 景点页数 4.获取当前景点的评论页数 5. 总体爬虫效果 6. 注意 导语 自携程更新后,这是全网首篇,关于新版携程的逆 ...

  5. 逆向爬虫14 Mongo入门

    逆向爬虫14 Mongo入门 一.MongoDB和MySQL的区别 MongoDB 是一种 非关系型数据库,存放任意形式的 json 格式数据:而 MySQL 是一种 关系型数据库,只能存放事先定义好 ...

  6. python爬虫之逆向破解_js逆向爬虫实战(2)--新快之加密参数破解

    爬虫js逆向系列 我会把做爬虫过程中,遇到的所有js逆向的问题分类展示出来,以现象,解决思路,以及代码实现.我觉得做技术分享,不仅仅是要记录问题,解决办法,更重要的是要提供解决问题的思路.怎么突破的, ...

  7. 逆向爬虫20 Scrapy-Splash入门

    逆向爬虫20 Scrapy-Splash入门 一. Splash 在学习Splash之前,先要明白为什么要学它,它能帮我们完成什么工作,什么情况下适合使用Splash? splash是一个可以动态渲染 ...

  8. 逆向爬虫27 sojson反调加密

    逆向爬虫27 sojson反调加密 目标: 掌握sojson的加密的特点和原理. 使用静态文件替换sojson反调. 一. sojson加密特点和原理 sojson是一种常用的js反调和加密手段, 在 ...

  9. 使用Webpack的代码分离实现Vue懒加载(译文)

    当一个Vue的项目体积变得十分庞大的时候,使用Webpack的代码分离功能将Vue Components,routes或Vuex的代码进行分离并按需加载,会极大的提高App的首屏加载速度. 在Vue的 ...

最新文章

  1. Pandas把dataframe的索引、复合索引变换为数据列:包含单索引到单列(重命名)、复合索引到多数据列、复合索引的其中一个水平变换为数据列、
  2. 干货丨一份不可多得的深度学习技巧指南
  3. Java 8 Lambda
  4. 浅谈equals和==的区别
  5. Visual Studio 2008 每日提示(四)
  6. 返回顶部小火箭(仿电脑管家)
  7. php 序列化方法,PHP序列化操作方法分析
  8. Xftp5如何设置默认的文件夹
  9. nes 红白机模拟器 第4篇 linux 手柄驱动支持
  10. 使用前端技术实现静态图片局部流动效果
  11. 零信任嵌入式安全沙箱技术,企业应用软件的技术底座
  12. 计算机内存不足无法打印照片,打印机内存不足无法打印怎么办_打印机提示内存不足怎么解决...
  13. 微信小程序中下载app的方法
  14. HEU Monkey CC
  15. 二代测序原理(Illumina)
  16. 3D打印设备的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  17. 信息论:数据压缩和信源编码
  18. LeetCode每日一题——1758. 生成交替二进制字符串的最少操作数
  19. 单片机外围电路设计之三:电感
  20. bzoj 1539: [POI2005]Dwu-Double-row

热门文章

  1. C++项目实战-先把项目跑起来看看
  2. 将一个Vue项目跑起来
  3. 在python中、int表示的数据类型是_python--002--数据类型(int、str)
  4. 安装算量软件免费吗?鹏业安装算量(在线版):更简单、更高效
  5. Github标星超7k!从零开始,最简明扼要的数据科学学习路径
  6. 微信小程序组件化的解决方案
  7. 计算机创新创业项目点子,创新创业项目有哪些(创业点子大全500个)
  8. Python正则表达式一文详解+实例代码展示
  9. 關於微軟TTS的筆記
  10. xbox手柄适配器驱动_XBox无线适配器MN-740更新