JavaScript逆向爬虫实战分析

简介: JavaScript逆向爬虫实战分析

JavaScript逆向爬虫实战分析
以一个简单的网站https://login1.scrape.center/为例。这个网站只有“用户名”文本框、“密码”文本框和“登录”按钮,入图所示:

image.png

但是不同的是,点击“登录”按钮的时候,表单提交POST的内容并不是单纯的用户名和密码,而是一个加密后的token。输入用户名和密码(都是admin),点击“登录”按钮,观察网络请求的变化,结果如下图所示:

image.png
image.png

我们不需要关心响应的结果和状态,主要看请求的内容就可以了。能看到,点击“登录”按钮时,发起了一个POST请求,内容为:

{“token”:“eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJhZG1pbiJ9”}

确实,没有诸如username和password的内容,怎么模拟登录呢?模拟登录的前提就是找到当前的token生成的逻辑,那么问题来了,这个token和用户名、密码到底是什么关系呢?如何寻找其中的蛛丝马迹呢?

思考一下,输入的 是用户名和密码,但是提交的时候变成了一个token,经过观察并结合一些经验可以看出,token的内容非常像Base64编码。这就说明,网站可能首先将用户名和密码混为一个新的字符串,经过一次Base64编码,最后将其赋值为token来提交了。所以,经过初步观察,可以获取这些信心。

那就验证一下吧!探究网站JavaScript代码里面如何实现的。首先,看一下网站的源码,打开Sources面板,看起来都是webpack打包之后的内容经过了一些混淆,如图所示:

image.png

这么多混淆代码,怎么去找token的生成位置呢?解决方法其实有两种,一种是前文所讲的Ajax断点,另一种就是Hook。

Ajax断点
由于这个请求正好是Ajax请求,所以我们可以添加一个XHR断点来监听,把POST的网址加到断点上面。在Sources面板右侧添加一个XHR断点,匹配内容就填当前域名,如图所示:
这时候如果我们再点击“登录”按钮,发起一次Ajax请求,就可以进入断点了,然后再看堆栈信息,就可以一步步找到编码的入口了。再次点击“登录”按钮,页面进入断点状态,停下来了,结果如图所示:

image.png

一步步找,最后可以找到入口其实在onSubmit方法那里。而我们真正想找的用户名和密码经过处理,再进行Base64编码的地方,这些请求的调用实际上和我们找寻的入口没有很大的关系。另外,如果我们想找的入口位置并不伴随这一次Ajax请求,这个方法就没法用了。

下面再看一下另一个方法——Hook。

Hook
第二种可以快速定位入口的方法,就是使用Tampermonkey自定义JavaScript,实现某个JavaScript方法的Hook。Hook哪里呢?很明显,Hook Base64编码的位置就好了。

JavaScript里面的Base64编码是怎么实现的?就是btoa方法,在JavaScript中该方法用于将字符串编码成Base64字符串,因此我们来Hook btoa方法就好了。

这里新建一个Tampermonkey脚本,内容如下:

// ==UserScript==
// @name         HookBase64
// @namespace    https://login1.scrape.center/
// @version      0.1
// @description  Hook Base64 encode function
// @author       xiaowei
// @match        https://login1.scrape.center/
// @grant        none
// ==/UserScript==

(function() {
   
    'use strict';

    // Your code here...
    function hook(object, attr){
   
        var func = object[attr]
        object[attr] = function(){
   
            console.log('hooked', object,attr)
            var ret = func.apply(object, arguments)
            debugger
            return ret
        }
    }
    hook(window, 'btoa')
})();

定义一些UserScript Header,包括@name和@match等。这里比较重要的就是@name,表示脚本名称;另外一个就是@match,它代表脚本生效的网址。定义了hook方法,这里给其传入object和attr参数,意思就是Hook object对象的attr参数。例如,如果我们想Hook alert方法,那就把object设置为window, 把attr设置为字符串alert。这里我们想要Hook Base64编码方法,而在JavaScript中,Base64编码是用btoa方法实现的,所以这里只需要Hook window对象的btoa方法就好了。

Hook是怎么实现的呢?var func = object[attr],相当于先把它赋值为一个变量,即我们调用func方法就可以实现和原来相同的功能。接着,我们直接改写这个方法的定义,将object[attr]改写成一个新的方法。在新的方法中,通过func.apply方法又重新调用了原来的方法。这样我们就可以保证前后方法的执行效果不受影响,之前这个方法该干啥还干啥。

但是和之前不同的是,现在自定义方法之后,可以在func方法执行前后加入自己的代码,如通过console.log将信息输出到控制台,通过debugger进入断点等。在这个过程中,先临时保存下来func方法,然后定义一个新的方法,接管程序控制权,在其中自定义我们想要的实现,同时在新的方法里面重新调用回func方法,保证前后结果不受影响。所以,我们达到了在不影响原有方法效果的前提下,实现在方法前后自定义的功能,这就是Hook的过程。

调用hook方法,传入window对象和btoa字符串,保存。接下来刷新页面,可以看到这个脚本在当前页面生效了,Tempermonkey插件面板提示了已经启用。同时,在Sources面板下的Page选项卡中,可以观察到我们定义的JavaScript脚本被执行了,如图所示:

image.png

成功Hook住了,这说明JavaScript代码在执行过程中调用到了btoa方法。这时看一下控制台,也输出了window对象和btoa方法,验证正确,如下图所示:

image.png

这样就顺利找到了Base64编码操作这个路口,然后看一下堆栈信息,清晰地呈现了btoa方法逐层调用的过程,如图所示:

image.png

再观察下Local面板,看看arguments变量是怎么样的?如图所示:

image.png

一目了然,arguments就是传给btoa方法的参数,ret就是btoa方法返回的结果。arguments就是username和password通过JSON序列化之后的字符串,经过Base64编码之后得到的值恰好就是Ajax请求参数token的值。

还可以通过调用栈找到onSubmit方法的处理源码:

onSubmit: function() {
   
                    var e = c.encode(JSON.stringify(this.form));
                    this.$http.post(a["a"].state.url.root, {
   
                        token: e
                    }).then((function(e) {
   
                        console.log("data", e)
                    }
                    ))
                }

发现,encode方法其实就是调用了btoa方法,就是一个Base64编码的过程,答案其实已经很明了了。进一步添加断点验证一下流程,比如在调用encode方法的那行添加断点,如图所示:

image.png

添加断点之后,可以点击Resume script execution按钮恢复JavaScript的执行,跳过当前Tempermonkey定义的断点位置,如图所示:

image.png

然后重新点击“登录”按钮,可以看到这时候代码就停在当前添加断点的位置,如图所示:

image.png

这时候可以在Watch面板下输入this.form,验证此处是否为在表单中输入的用户名和密码,如图所示:
image.png

没问题,然后逐步调试。可以观察到,下一步就跳到了我们Hook的位置,这说明调用了btoa方法,如图所示。可以看到,返回的结果正好就是token的值。

image.png

到这里,已经非常清晰了,整体逻辑就是对登录表单的用户名和密码进行JSON序列化,然后调用encode

(也就是btoa方法),并把encode方法的结果赋值为token发起登录的Ajax请求,逆向完成。

所以,通过Tampermonkey自定义JavaScript脚本的方式,实现了某个方法调用的Hook,使得我们能快速定位到加密入口的位置,非常方便。触类旁通,如Hook encode方法、decode方法、stringify方法、log方法、alert方法等,简单高效。

相关文章
|
3月前
|
数据采集 存储 数据可视化
分布式爬虫框架Scrapy-Redis实战指南
本文介绍如何使用Scrapy-Redis构建分布式爬虫系统,采集携程平台上热门城市的酒店价格与评价信息。通过代理IP、Cookie和User-Agent设置规避反爬策略,实现高效数据抓取。结合价格动态趋势分析,助力酒店业优化市场策略、提升服务质量。技术架构涵盖Scrapy-Redis核心调度、代理中间件及数据解析存储,提供完整的技术路线图与代码示例。
345 0
分布式爬虫框架Scrapy-Redis实战指南
|
3月前
|
数据采集 存储 机器学习/深度学习
Fuel 爬虫:Scala 中的图片数据采集与分析
Fuel 爬虫:Scala 中的图片数据采集与分析
|
1月前
|
人工智能 自然语言处理 JavaScript
通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
通义灵码基于自然语言需求,快速生成完整Vue组件。例如,用Vue 2和JavaScript实现贪吃蛇游戏:包含键盘控制、得分系统、游戏结束判定与Canvas动态渲染。AI生成的代码符合规范,支持响应式数据与事件监听,还能进阶优化(如增加启停按钮、速度随分数提升)。传统需1小时的工作量,使用通义灵码仅10分钟完成,大幅提升开发效率。操作简单:安装插件、输入需求、运行项目即可实现功能。
126 4
 通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
|
1月前
|
数据采集 消息中间件 Kubernetes
Kubernetes上的爬虫排队术——任务调度与弹性扩缩容实战
本教程介绍如何在 Kubernetes 上构建可扩展的爬虫系统,解决传统单机爬虫瓶颈。核心内容包括:使用 Docker 打包爬虫任务、RabbitMQ 实现任务队列、爬虫代理防限制、随机 User-Agent 模拟请求,以及通过 Horizontal Pod Autoscaler (HPA) 实现根据任务压力自动扩缩容。适合需要处理大规模网页采集的开发者学习与实践。
Kubernetes上的爬虫排队术——任务调度与弹性扩缩容实战
|
29天前
|
数据采集 人工智能 边缘计算
爬虫IP代理效率优化:策略解析与实战案例
本文深入探讨了分布式爬虫中代理池效率优化的关键问题。首先分析了代理效率瓶颈的根源,包括不同类型代理的特点、连接耗时及IP失效问题。接着提出了六大核心优化策略:智能IP轮换矩阵、连接复用优化、动态指纹伪装、智能重试机制等,并结合电商价格监控、社交媒体舆情分析和金融数据抓取三个实战案例,展示了优化效果。同时建立了三维效率评估体系,从质量、成本和稳定性全面衡量性能。最后展望了AI驱动调度、边缘计算融合等未来演进方向,帮助爬虫系统实现从“暴力采集”到“智能获取”的进化,大幅提升效率并降低成本。
48 0
|
2月前
|
数据采集 存储 缓存
Python爬虫与代理IP:高效抓取数据的实战指南
在数据驱动的时代,网络爬虫是获取信息的重要工具。本文详解如何用Python结合代理IP抓取数据:从基础概念(爬虫原理与代理作用)到环境搭建(核心库与代理选择),再到实战步骤(单线程、多线程及Scrapy框架应用)。同时探讨反爬策略、数据处理与存储,并强调伦理与法律边界。最后分享性能优化技巧,助您高效抓取公开数据,实现技术与伦理的平衡。
124 4
|
3月前
|
数据采集 前端开发 JavaScript
金融数据分析:解析JavaScript渲染的隐藏表格
本文详解了如何使用Python与Selenium结合代理IP技术,从金融网站(如东方财富网)抓取由JavaScript渲染的隐藏表格数据。内容涵盖环境搭建、代理配置、模拟用户行为、数据解析与分析等关键步骤。通过设置Cookie和User-Agent,突破反爬机制;借助Selenium等待页面渲染,精准定位动态数据。同时,提供了常见错误解决方案及延伸练习,帮助读者掌握金融数据采集的核心技能,为投资决策提供支持。注意规避动态加载、代理验证及元素定位等潜在陷阱,确保数据抓取高效稳定。
98 17
|
3月前
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
3月前
|
数据采集 XML 存储
Python爬虫实战:一键采集电商数据,掌握市场动态!
这个爬虫还挺实用,不光能爬电商数据,改改解析规则,啥数据都能爬。写爬虫最重要的是要有耐心,遇到问题别着急,慢慢调试就成。代码写好了,运行起来那叫一个爽,分分钟几千条数据到手。
|
3月前
|
数据采集 存储 安全
Python爬虫实战:利用短效代理IP爬取京东母婴纸尿裤数据,多线程池并行处理方案详解
本文分享了一套结合青果网络短效代理IP和多线程池技术的电商数据爬取方案,针对京东母婴纸尿裤类目商品信息进行高效采集。通过动态代理IP规避访问限制,利用多线程提升抓取效率,同时确保数据采集的安全性和合法性。方案详细介绍了爬虫开发步骤、网页结构分析及代码实现,适用于大规模电商数据采集场景。