爬虫 ----hook

news/2024/9/23 7:01:00 标签: javascript, 前端, 开发语言

目录

定义:

了解什么是hook?

举例

hook XHR请求

 XMLHttpRequest

案例地址:

Interceptors-拦截器

 HOOK cookie操作

cookie 示范

常见的hook代码总结

1.Hook Cookie

2.Hook Header

3.Hook URL

4.Hook JSON.stringify

5.Hook JSON.parse

6.Hook eval

7.Hook Function

8.解决浏览器控制台console被禁用无法打印问题

其他HOOK:


知识星球:知识星球 | 深度连接铁杆粉丝,运营高品质社群,知识变现的工具

定义:

Hook 是一种钩子技术,在系统没有调用函数之前,钩子程序就先得到控制权,这时钩子函数既可以加工处理(改变)该函数的执行行为,也可以强制结束消息的传递。简单来说,修改原有的 JS 代码就是 Hook

Hook 技术之所以能够实现有两个条件:

  • 客户端拥有JS的最高解释权,可以决定在任何时候注入JS,而服务器无法阻止或干预。服务端只能通过检测和混淆的手段,另 Hook 难度加大,但是无法直接阻止。
  • 除了上面的必要条件之外,还有一个条件。就是 JS 是一种弱类型语言,同一个变量可以多次定义、根据需要进行不同的赋值,而这种情况如果在其他强类型语言中则可能会报错,导致代码无法执行。js 的这种特性,为我们 Hook 代码提供了便利。

了解什么是hook?

在 JS 逆向中,我们通常把替换原函数的过程都称为 Hook。一般使用Object.defineProperty()来进行hook。那么我们了解一下该方法的使用。

Object.defineProperty(obj, prop, descriptor)

obj:对象;

prop:对象的属性名;

descriptor:属性描述符;

属性描述符的取值通常为以下:

var people = {
    name: '张三',
};

Object.defineProperty(people, 'age', {
    get: function () {
        console.log('获取值!');
        return count;
    },
    set: function (val) {
        console.log('设置值!');
        count = val + 1;
    },
});

people.age = 18;
console.log(people.age); 

通过这样的方法,我们就可以在设置某个值的时候,添加一些代码,比如 debugger;,让其断下,然后利用调用栈进行调试,找到参数加密、或者参数生成的地方,需要注意的是,网站加载时首先要运行我们的 Hook 代码,再运行网站自己的代码,才能够成功断下,这个过程我们可以称之为 Hook 代码的注入。

举例

我们知道在 JavaScript 中 JSON.stringify() 方法用于将JavaScript 对象或值转换为 JSON 字符串,JSON.parse() 方法用于将一个 JSON字符串转换为JavaScript 对象,某些站点在向web 服务器传输用户名密码时,会用到这两个方法

(function() {
    var _stringify = JSON.stringify;
    JSON.stringify = function(ps) {
        console.log("Hook JSON.stringify ——> ", ps);
        debugger;
        return _stringify(ps);  // 不改变原有的执行逻辑 
    }
})();
​
​
(function() {
    var _parse = JSON.parse;
    JSON.parse = function(ps) {
        console.log("Hook JSON.parse ——> ", ps);
        debugger;
        return _parse(ps);  // 不改变原有的执行逻辑 
    }
})();
​

首先定义了一个变量 stringify 保留原始 JSON.stringify 方法,然后重写 JSON.stringify 方法,遇到 JSON.stringify 方法就会执行 debugger 语句,会立即断下,最后将接收到的参数返回给原始的 JSON.stringify 方法进行处理,确保数据正常传输

hook XHR请求

 XMLHttpRequest

https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest

XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest 在 AJAX 编程中被大量使用。

XMLHttpRequest.open()

方法初始化一个新创建的请求,或重新初始化一个请求。

xhrReq.open(method, url, async);

XMLHttpRequest.send()

发送请求。如果请求是异步的(默认),那么该方法将在请求发送后立即返回。

方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。

xhrReq.send(body)

XMLHttpRequest.setRequestHeader()

设置 HTTP 请求头的值。必须在 open() 之后、send() 之前调用 setRequestHeader() 方法。

myReq.setRequestHeader(header, value);    // headers['key'] = value

XMLHttpRequest.onreadystatechange

当 readyState 属性发生变化时,调用的事件处理器。

http://www.cninfo.com.cn/new/commonUrl?url=disclosure/list/notice#szseGem
​
​
// 请求参数
body = 'column=szse_gem_latest&pageNum=2&pageSize=30&sortName=&sortType=&clusterFlag=true'
​
// 构造请求
let e = {
    'url':"http://www.cninfo.com.cn/new/disclosure",
    'method':'POST',
    "data": body
}
var h  = new  XMLHttpRequest(); 
// 初始化链接
h.open(e.method,e.url,true);
// 设置头部
h.setRequestHeader('accept','application/json;charset=UTF-8');
// 接收响应
    h.onreadystatechange = function (){
        if (h.status===200){
            console.log(JSON.parse(h.response))
        }
    }
// 发请求  
h.send(e.data)

案例地址:

七麦数据 -专业移动产品商业分析平台-关键词优化-ASA优化-七麦科技

定义了一个变量 open 保留原始 XMLHttpRequest.open 方法,然后重写 XMLHttpRequest.open 方法,判断如果 rnd 字符串值在 URL 里首次出现的位置不为 -1,即 URL 里包含 analysis字符串,则执行 debugger 语句,会立即断下。

// 如果是正数 表示存在里面
// 如果是-1 表示不在里面
(function () {
    var open = window.XMLHttpRequest.prototype.open;
    window.XMLHttpRequest.prototype.open = function (method, url, async) {
        if (url.indexOf("analysis") != -1) {
            debugger;
        }
        return open.apply(this, arguments);
    };
})();
​
​
(function () {
    var open = window.XMLHttpRequest.prototype.open;
    window.XMLHttpRequest.prototype.open = function (method, url, async) {
        if (url.indexOf("analysis") != -1) {
            debugger;
        }
        return open.apply(this, arguments);
    };
})();
​
​

Interceptors-拦截器

  • 请求拦截器:在发送请求之前,可以借助一些函数来对请求的内容和参数做一些检测。若有问题可以直接取消请求。
  • 响应拦截器:当服务器返回响应数据时,响应拦截器会在我们拿到结果前预先处理响应数据。例如对响应数据做一些格式化处理,或者当响应失败时,可以做一些失败提醒和纪录。
// npm install axios
axios = require('axios')
//设置请求拦截器
axios.interceptors.request.use(function (config) {
    console.log('请求拦截器 成功')
    config.headers['sign'] = 'lili'
    return config;
}, function (error) {
    console.log('请求拦截器 失败')
    return Promise.reject(error);
});
​
//设置响应拦截器
axios.interceptors.response.use(function (response) {
    console.log('响应拦截器 成功')
    console.log('调解密函数进行解密数据')
    //return response;
    return response.data; //修改响应数据
}, function (error) {
    console.log('响应拦截器 失败')
    return Promise.reject(error);
});
​
//发送请求
axios.get('http://httpbin.org/get').then(res=>console.log(res))

 HOOK cookie操作

WEBAPI地址:https://developer.mozilla.org/zh-CN/docs/Web/API

Object.defineProperty为对象的属性赋值,替换对象属性

基本语法:Object.defineProperty(obj, prop, descriptor),它的作用就是直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,接收的三个参数含义如下:

  • obj:需要定义属性的当前对象;
  • prop:当前需要定义的属性名;
Object.defineProperty(user,"age",{
 get:function(){
      console.log("这个人来获取值了!!");
      return count;
 },
​
 set:function(newVal){
      console.log("这个人来设置值了!!");
      count=newVal+1;
 }
})

cookie 示范

示范例子:A股市场_同花顺行情中心_同花顺财经网

cookie 钩子用于定位 cookie 中关键参数生成位置,以下代码演示了当 cookie 中匹配到了 v, 则插入断点:

(function () {
  var cookieTemp = '';
  Object.defineProperty(document, 'cookie', {
    set: function (val) {
      if (val.indexOf('v') != -1) {
        debugger;
      }
      console.log('Hook捕获到cookie设置->', val);
      cookieTemp = val;
      return val;
    },
    get: function () {
      return cookieTemp;
    },
  });
})();

注:正常hook cookie操作的时候需要清除下cookie

常见的hook代码总结

1.Hook Cookie

Cookie Hook 用于定位 Cookie 中关键参数生成位置,以下代码演示了当 Cookie 中匹配到了 __dfp 关键字, 则插入断点:

(function () {
  'use strict';
  var cookieTemp = '';
  Object.defineProperty(document, 'cookie', {
    set: function (val) {
      if (val.indexOf('__dfp') != -1) {
        debugger;
      }
      console.log('Hook捕获到cookie设置->', val);
      cookieTemp = val;
      return val;
    },
    get: function () {
      return cookieTemp;
    },
  });
})();

2.Hook Header

hook到Authorization下断点


(function () {
    var org = window.XMLHttpRequest.prototype.setRequestHeader;
    window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
        if (key == 'Authorization') {
            debugger;
        }
        return org.apply(this, arguments);
    };
})();
 

3.Hook URL

URL Hook 用于定位请求 URL 中关键参数生成位置,以下代码演示了当请求的 URL 里包含 login 关键字时,则插入断点:


(function () {
    var open = window.XMLHttpRequest.prototype.open;
    window.XMLHttpRequest.prototype.open = function (method, url, async) {
        if (url.indexOf("login") != -1) {
            debugger;
        }
        return open.apply(this, arguments);
    };
})();
 

4.Hook JSON.stringify

JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串,在某些站点的加密过程中可能会遇到,以下代码演示了遇到 JSON.stringify() 时,则插入断点:

(function() {
    var stringify = JSON.stringify;
    JSON.stringify = function(params) {
        console.log("Hook JSON.stringify ——> ", params);
        debugger;
        return stringify(params);
    }
})();

运行运行

5.Hook JSON.parse

JSON.parse() 方法用于将一个 JSON 字符串转换为对象,在某些站点的加密过程中可能会遇到,以下代码演示了遇到 JSON.parse() 时,则插入断点:

(function() {
    var parse = JSON.parse;
    JSON.parse = function(params) {
        console.log("Hook JSON.parse ——> ", params);
        debugger;
        return parse(params);
    }
})();

运行运行

6.Hook eval

JavaScript eval() 函数的作用是计算 JavaScript 字符串,并把它作为脚本代码来执行。如果参数是一个表达式,eval() 函数将执行表达式。如果参数是 Javascript 语句,eval() 将执行 Javascript 语句,经常被用来动态执行 JS。以下代码执行后,之后所有的 eval() 操作都会在控制台打印输出将要执行的 JS 源码:

(function() {
    // 保存原始方法
    window.__cr_eval = window.eval;
    // 重写 eval
    var myeval = function(src) {
        console.log(src);
        console.log("=============== eval end ===============");
        debugger;
        return window.__cr_eval(src);
    }
    // 屏蔽 JS 中对原生函数 native 属性的检测
    var _myeval = myeval.bind(null);
    _myeval.toString = window.__cr_eval.toString;
    Object.defineProperty(window, 'eval', {
        value: _myeval
    });
})();

7.Hook Function

以下代码执行后,所有的函数操作都会在控制台打印输出将要执行的 JS 源码:

(function() {
    // 保存原始方法
    window.__cr_fun = window.Function;
    // 重写 function
    var myfun = function() {
        var args = Array.prototype.slice.call(arguments, 0, -1).join(","),
            src = arguments[arguments.length - 1];
        console.log(src);
        console.log("=============== Function end ===============");
        debugger;
        return window.__cr_fun.apply(this, arguments);
    }
    // 屏蔽js中对原生函数native属性的检测
    myfun.toString = function() {
        return window.__cr_fun + ""
    }
    Object.defineProperty(window, 'Function', {
        value: myfun
    });
})();

参考:https://mp.weixin.qq.com/s/IYFyjVrVkHtUdCzn9arkJQ

8.解决浏览器控制台console被禁用无法打印问题

(function(){
      var iframe = document.createElement('iframe');
      document.head.appendChild(iframe);
      window.console = iframe.contentWindow.console;
    }());

其他HOOK:

https://www.cnblogs.com/xiaoweigege/p/14954648.html


http://www.niftyadmin.cn/n/5671605.html

相关文章

速盾:高防cdn防御的时候会封ip吗?

高防CDN(Content Delivery Network)是一种用于提供网站或应用程序防护和内容分发的服务。它通过将内容分发到全球多个服务器上,帮助用户提高网站的访问速度和可用性,并提供强大的防护功能,包括防DDoS攻击、Web应用程序…

YOLOv9改进,YOLOv9主干网络替换为RepViT (CVPR 2024,清华提出,独家首发),助力涨点

摘要 轻量级视觉变换器(ViTs)在资源受限的移动设备上表现出优越的性能和较低的延迟,相比之下轻量级卷积神经网络(CNNs)稍显逊色。研究人员发现了许多轻量级 ViTs 和轻量级 CNNs 之间的结构联系。然而,它们在块结构、宏观和微观设计上的显著架构差异尚未得到充分研究。在…

【记录】Excel|不允许的操作:合并或隐藏单元格出现的问题列表及解决方案

人话说在前:这篇的内容是2022年5月写的,当时碰到了要批量处理数据的情况,但是又不知道数据为啥一直报错报错报错,说不允许我操作,最终发现是因为存在隐藏的列或行,于是就很无语地写了博客,但内容…

docker的核心概念整理:docker-compose

docker-compose 理解一个服务,我们尝试将自己代入,开发者的角色去思考 这个服务,为什么叫这个名字? docker是什么意思? 英文的意思是码头工人 码头工人的主要工作之一 是把货物搬至集装箱, 进而货轮…

Python办公自动化教程(003):PDF的加密

【1】代码 from PyPDF2 import PdfReader, PdfWriter# 读取PDF文件 pdf_reader PdfReader(./file/Python教程_1.pdf) pdf_writer PdfWriter()# 对第1页进行加密 page pdf_reader.pages[0]pdf_writer.add_page(page) # 设置密码 pdf_writer.encrypt(3535)with open(./file/P…

【力扣 | SQL题 | 每日三题】力扣182

1. 力扣182:查找重复的电子邮箱 1.1 题目: 表: Person ---------------------- | Column Name | Type | ---------------------- | id | int | | email | varchar | ---------------------- id 是该表的主键(具有唯…

鸿蒙OpenHarmony【轻量系统内核扩展组件(CPU占用率)】子系统开发

基本概念 CPU(中央处理器,Central Processing Unit)占用率分为系统CPU占用率和任务CPU占用率。 系统CPU占用率:是指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系…

基于微信小程序的家教信息管理系统的设计与实现(论文+源码)_kaic

摘 要 随着互联网时代的来临,使得传统的家教模式已不复存在,亟需一种方便、快捷的在线教学平台。因此,利用Java语言作为支撑和MySQL数据库存储数据,结合微信小程序的便利性,为用户开发出了一个更加人性化、方便的家庭…