python爬虫hook定位技巧、反调试技巧、常用辅助工具

一、浏览器调试面板介绍

在这里插入图片描述

二、hook定位、反调试

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

  • 客户端拥有JS的最高解释权,可以决定在任何时候注入JS,而服务器无法阻止或干预。服务端只能通过检测和混淆的手段,另 Hook 难度加大,但是无法直接阻止。
  • JS 是一种弱类型语言,同一个变量可以多次定义、根据需要进行不同的赋值,而这种情况如果在其他强类型语言中则可能会报错,导致代码无法执行。js 的这种特性,为我们 Hook 代码提供了便利。
    注意:JS 变量是有作用域的,只有当被 hook 函数和 debugger断点在同一个作用域的时候,才能 hook 成功。
  1. 定位header关键字
    (function (){
        var org = window.XMLHttpRequest.prototype.setRequestHeader;
        window.XMLHttpRequest.prototype.setRequestHeader = function (key,value){
            //在请求中发现某个关键字,断点
            if(key=='value'){
                debugger
            }
            return org.apply(this,arguments)
        }
    })()
    
  2. window对象的属性
    // 定义hook属性
    var window_flag_1 = "_t";
    var window_flag_2 = "ccc";
    var key_value_map = {};
    var window_value = window[window_flag_1];
    // hook
    Object.defineProperty(window, window_flag_1, {
        get: function(){
            console.log("Getting",window,window_flag_1,"=",window_value);
            //debugger
            return window_value
        },
        set: function(val) {
            console.log("Setting",window, window_flag_1, "=",val);
            window_value = val;
            key_value_map[window[window_flag_1]] = window_flag_1;
            set_obj_attr(window[window_flag_1],window_flag_2);
    });
    function set_obj_attr(obj,attr){
        var obj_attr_value = obj[attr];
        Object.defineProperty(obj,attr, {
            get: function() {
                console.log("Getting", key_value_map[obj],attr, "=", obj_attr_value);
                //debugger
                return obj_attr_value;
            },
            set: function(val){
                console.log("Setting", key_value_map[obj], attr, "=", val);
                obj_attr_value = val;
        });
    }
    
  3. 定位cookie关键字,示例网站:http://q.10jqka.com.cn/
    
    (function() {
        "use strict";
        var cookieTemp = "";
        Object.defineProperty(document, "cookie", {
            writable: false, // 表示能否修改属性的值,即值是可写的还是只读
            configurable: false, // 表示能否通过 delete 删除属性、能否修改属性的特性,或者将属性修改为访问器属性
            set: function(val) {
                if (val.indexOf("cookie的参数名称") != -1) {
                    debugger ;
                }
              
                cookieTemp = val;
                return val;
            },
     
            get: function() {
                return cookieTemp;
            }
        })
    }
    )();
    
    
  • 访问网站,打开控制台,查看请求头,cookie中v已加密
    在这里插入图片描述
  • 新建代码片段cookie,并点击运行
    在这里插入图片描述
  • 在个股行情下切换tab重新发送请求,一直点击跳过下一个函数调用,看到setCookie时,会发现Fn是键值v,n是value值,rt.update()是生成n的函数,鼠标悬浮到函数中,点击悬浮框中的链接,会跳到rt.update函数中,cookie定位成功
    在这里插入图片描述
  1. 定位url关键字,示例网站:https://www.ynjzjgcx.com/dataPub/enterprise
(function () {
    var open = window.XMLHttpRequest.prototype.open;
    window.XMLHttpRequest.prototype.open = function (method, url, async) {
        if (url.indexOf("key") != -1) {
            debugger;
        }
        return open.apply(this, arguments);
    };
})();
  • 打开网址,完成验证码验证,会发现请求中params参数已加密
    在这里插入图片描述
  • 新建url代码片段,点击运行
    在这里插入图片描述
  • 点击搜索,完成验证码验证,一直点击跳过下一个函数调用,遇到then方法进入点击进入该函数,之所以进入该函数是因为一直点击跳过下一个函数调用在作用域看不到明文信息,所以可能加密是在请求拦截器中处理的
    在这里插入图片描述
  • 进入该函数后,一直点击跳过下一个函数调用,会发现响应拦截器Vt.interceptors.response,在该文件再去找请求拦截器Vt.interceptors.request,并在请求拦截器中打点
    在这里插入图片描述
  • 跳过断点调试,再点击搜索,完成验证码验证,会进入请求拦截器函数,一直点击跳过下一个函数调用,会发现加密参数,是经过gwe函数加密的,定位成功
    在这里插入图片描述
  1. 定位JSON.stringify、JSON.parse,一般用于请求和响应是密文,示例网站:http://birdreport.cn/home/activity/page.html
    '''请求是密文'''
    (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);  // 不改变原有的执行逻辑 
        }
    })(); 
    
  • 访问网站,打开控制面板,找到请求会发现,参数、响应结果、请求头中Sign和Requestid已加密
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 定位参数加密位置,新建json_stringify代码片段,点击运行
    在这里插入图片描述
  • 点击分页重新发送请求,会发现明文参数,且加密位置就在Call Stack(栈)中的某个位置
    在这里插入图片描述
  • 点击第一个栈,在这里发现了请求头中的Sign和Requestid分别对应变量d和f,在方法最前面打个断点,点击never pause here(永不停留),直到断点结束,切换分页
    在这里插入图片描述
  • 切换分页后会发现已经定位到刚才断点的位置,一直点击跳过下一个函数调用,会发现e变量是明文参数,再继续看下面会发现e变量经过了encrypt.encryptUnicodeLong函数的处理,在控制台输入b.data、d、f回车打印出b.data值,点击deactivate breakpoints(禁用断点),再点击never pause here(永不停留)跳过当前断点,再切回Network对比请求中的参数、header中的Sign和Requestid会发现和控制台中一样
    在这里插入图片描述
  • 定位响应加密位置,新建json_parse代码片段,点击运行
    在这里插入图片描述
  • 点击分页重新发送请求,遇到断点点击never pause here(永不停留)跳过当前断点,直到看见控制态输出明文信息
    在这里插入图片描述
  • 再去栈中点击第一个,会发现res是返回结果,而res.data使用了BIRDREPORT_APIJS.decode该方法解密,在控制台输入decode_str点击回车,会发现明文信息
    在这里插入图片描述
  1. constructor构造器构造出来的debugger反调试,示例网站:http://www.spolicy.com/
    var _constructor = constructor;
    Function.prototype.constructor = function(s) {
        if (s == "debugger") {
            console.log(s);
            return null;
        }
        return _constructor(s);
    }
    
  • 访问网站,打开控制面板,会发现,页面一直在debugger,点击栈中的 ’a‘,在控制台输出代码中红色地方会发现这是constructor构造器构造出来的debugger
    在这里插入图片描述
  • 在右侧代码片段创建,constructor_debugger,输入constructor构造器构造出来的debugger反调试代码,并点击运行,会发现反调试成功
    在这里插入图片描述
  1. 浏览器debugger反调试,示例网站:http://www.10010.com/net5/074/
  • 访问网站,打开控制面板,会发现,页面一直在debugger
    在这里插入图片描述
  • 鼠标右击debugger行,点击never pause here(永不停留)
    在这里插入图片描述
  • 点击never pause here后,再点击恢复脚本执行,如再遇到debugger,重复上述步骤,直到不再遇到debugger,会发现反调试成功
    在这里插入图片描述
  1. 多种debugger类型反调试,示例网站:https://www.nmpa.gov.cn/
  • 访问网站,打开控制面板,鼠标右击debugger行,点击never pause here(永不停留),再点击恢复脚本执行
    在这里插入图片描述
  • 在右侧代码片段创建,constructor_debugger,输入constructor构造器构造出来的debugger反调试代码,并点击运行,会发现反调试成功
    在这里插入图片描述
  1. 定时debugger反调试
    setInterval = function () {}
    
  • 创建测试html文件
    <!doctype html>
    <html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
    <h1 id="h1"></h1>
    </body>
    <script>
        var h1 = document.getElementById('h1')
    
        function test() {
            debugger
        };
        
        setInterval(test, 100);
        h1.innerHTML = 'hello word';
    </script>
    </html>
    
  • 浏览器打开该html,在打开控制台会发现一直在debugger,在setInterval处打个断点,并刷新页面
    在这里插入图片描述
  • 在代码片段新建setInterval_debugger,并点击运行,点击跳过当前断点,会发现反调试成功
    在这里插入图片描述
  1. 修改响应文件debugger反调试
  • 创建测试html文件
    <!doctype html>
    <html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
    <h1 id="h1"></h1>
    </body>
    <script>
        var h1 = document.getElementById('h1')
    
        function test() {
            debugger
        };
        
        setInterval(test, 100);
        h1.innerHTML = 'hello word';
    </script>
    </html>
    
  • 浏览器打开该html,在打开控制台会发现一直在debugger,点击Overrides新建文件夹xxx,右击文件选择Override content(覆盖内容)
    在这里插入图片描述
  • 修改保存到本地的文件,删除debugger,Ctrl+s保存刷新页面,会发现调试成功
    在这里插入图片描述
  1. eval构造器构造出来的debugger反调试
    (function() {
        'use strict';
        var eval_ = window.eval;
        window.eval = function(x) {
            eval_(x.replace("debugger;", "  ; "));
        }
    ;
        window.eval.toString = eval_.toString;
    }
    )();
    
  2. 通用反调试
    (function() {
        var _constructor = unsafeWindow.Function.prototype.constructor;
        unsafeWindow.Function.prototype.constructor = function() {
            var fnContent = arguments[0];
            if (fnContent) {
                if (fnContent.includes('debugger')) { 
                    var caller = Function.prototype.constructor.caller; // Non-standard hack to get the function caller
                    var callerContent = caller.toString();
                    if (callerContent.includes(/\bdebugger\b/gi)) { // Eliminate all debugger statements from the caller, if any
                        callerContent = callerContent.replace(/\bdebugger\b/gi, '');
                        eval('caller = ' + callerContent); // Replace the function
                    }
                    return (function () {});
                }
            }
            return _constructor.apply(this, arguments);
        };
    })();
    
三、其他定位
  1. 元素定位断点定位,示例网站:https://oauth.d.cn/auth/goLogin.html
  • 打开网站,输入用户名密码登录会发现,密码被加密
    在这里插入图片描述
  • 定位到立即登录元素,找到事件监听,点击:goLogin.html,进入该元素点击事件方法内
    在这里插入图片描述
  • 在方法内打个断点,随便输入用户名密码点击立即登录,图中所示,会发现密码在红色标记的rsa方法中加密
    在这里插入图片描述
  1. XHR断点定位,示例网站:https://oauth.d.cn/auth/goLogin.html
  • 打开网站,输入用户名密码登录会发现,密码被加密
    在这里插入图片描述
  • 点击headers,复制请求中的路径:auth/login
    在这里插入图片描述
  • 点击sources,把赋值好的路径添加到XHR/fetch中,再点击登录
    在这里插入图片描述
  • 一直点击,跳过下一个函数调用,图中红色标记位置
    在这里插入图片描述
  • 直到在作用域中,遇到明文密码信息,赋值变量到搜索框(Ctrl+F),就能找到加密的位置
    在这里插入图片描述
  1. 方法栈定位, 栈是一种先进后出的特殊线性表结构,可以在断点定位、元素定位之后,使用方法栈定位缩小加密位置范围,示例网站:https://oauth.d.cn/auth/goLogin.html
  • 打开网站,输入用户名密码登录会发现,密码被加密
    在这里插入图片描述
  • 点击headers,复制请求中的路径:auth/login
    在这里插入图片描述
  • 点击sources,把赋值好的路径添加到XHR/fetch中,再点击登录
    在这里插入图片描述
  • 会发现在call stack下有个列表,这从点击到发送请求的栈,加密代码一定在这个栈中,点击绿色标记,在作用域中会发现明文密码信息,赋值变量到搜索框(Ctrl+F),就能找到加密的位置
    在这里插入图片描述
    在这里插入图片描述
四、爬虫辅助工具
  1. https://curlconverter.com/,谷歌浏览器F12,左击请求,选择Copy>Copy as cURL(bash),黏贴到网站输入框,会自动生成python爬虫代码
  2. https://www.sojson.com/encrypt_md5.html md5加密,验证md5加密是否被魔改,如果未被模块,可以使用nodejs cryptoc插件模拟加密和算法库;用于生成加密参数的js文件
  3. https://spidertools.cn/#/crypto,爬虫工具库,包括加解密、json格式化、html格式化、json对比等功能
  4. chrome插件:XPath Helper,可以在浏览器中xpath语法
  5. chrome插件:FeHelper,JSON格式化工具
  6. chrome插件:tampermonkey(篡改猴),hook脚本工具

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Postgresql数据类型-布尔类型

前面介绍了PostgreSQL支持的数字类型、字符类型、时间日期类型&#xff0c;这些数据类型是关系型数据库的常规数据类型&#xff0c;此外PostgreSQL还支持很多非常规数据类型&#xff0c;比如布尔类型、网络地址类型、数组类型、范围类型、json/jsonb类型等&#xff0c;从这一节…

python poetry的教程

Poetry Python世界中&#xff0c;Poetry是一个近年来备受瞩目的工具&#xff0c;它为开发者提供了一个灵活且强大的依赖管理解决方案。Poetry可以帮助开发者管理项目的依赖关系&#xff0c;同时提供了一系列的工具和功能&#xff0c;使开发者能够更轻松地创建和管理复杂的项目。…

简单的小调度器

收集小资源下的简单调度器 https://github.com/sigma318/TOS/tree/master https://github.com/smset028/xxddq

Go cobra简介

当你需要为你的 Go 项目创建一个强大的命令行工具时&#xff0c;你可能会遇到许多挑战&#xff0c;比如如何定义命令、标志和参数&#xff0c;如何生成详细的帮助文档&#xff0c;如何支持子命令等等。为了解决这些问题&#xff0c;github.com/spf13/cobra 就可以派上用场。 g…

说说对高阶组件的理解?应用场景?

一、是什么 高阶函数&#xff08;Higher-order function&#xff09;&#xff0c;至少满足下列一个条件的函数 接受一个或多个函数作为输入输出一个函数 在React中&#xff0c;高阶组件即接受一个或多个组件作为参数并且返回一个组件&#xff0c;本质也就是一个函数&#xf…

Linux环境配置(云服务器)

目录 1.第一步&#xff1a;购买云服务器 2.第二步&#xff1a;下载Xshell 7 3.第三步&#xff1a;打开Xshell&#xff0c;登录云服务器 4.第四步&#xff1a;更加便捷的云服务器登录方式 1.第一步&#xff1a;购买云服务器 &#xff08;推荐&#xff1a;阿里云、华为云、腾…

k8s----27、云原生存储StorageClass、CSI、Rook

1、动态存储介绍 StorageClass:存储类&#xff0c;由K8s管理员创建&#xff0c;用于动态PV的管理&#xff0c;可以链接至不同的后端存储&#xff0c; 比如Ceph、GlusterFS等。之后对存储的请求可以指向StorageClass&#xff0c;然后StorageClass会自动 的创建、删除PV。 实现方…

数据结构(c语言版) 栈

顺序栈 要求&#xff1a;实现顺序栈的入栈&#xff0c;出栈&#xff0c;显示栈 代码 #include <stdio.h> #define MAXSIZE 100struct liststack{int data[MAXSIZE];int top; };//初始化栈 void init(struct liststack * LS){LS->top -1; }//入栈操作 void instack…

Git详解及常用命令

前言 Git 是一个分布式版本控制系统&#xff0c;用于跟踪和管理项目的代码变化。它由Linus Torvalds在2005年创建&#xff0c;现在是开源社区中最流行的版本控制工具之一。 国内码云地址&#xff1a;工作台 - Gitee.com 版本控制系统 (VCS)&#xff1a;Git 用于跟踪文件和目录…

yolov8+多算法多目标追踪+实例分割+目标检测+姿态估计(代码+教程)

多目标追踪实例分割目标检测 YOLO (You Only Look Once) 是一个流行的目标检测算法&#xff0c;它能够在图像中准确地定位和识别多个物体。 本项目是基于 YOLO 算法的目标跟踪系统&#xff0c;它将 YOLO 的目标检测功能与目标跟踪技术相结合&#xff0c;实现了实时的多目标跟…

MUYUCMS v2.1:一款开源、轻量级的内容管理系统基于Thinkphp开发

MuYuCMS&#xff1a;一款基于Thinkphp开发的轻量级开源内容管理系统&#xff0c;为企业、个人站长提供快速建站解决方案。它具有以下的环境要求&#xff1a; 支持系统&#xff1a;Windows/Linux/Mac WEB服务器&#xff1a;Apache/Nginx/ISS PHP版本&#xff1a;php > 5.6 (…

【c++】——类和对象(中)——赋值运算符重载

作者:chlorine 专栏:c专栏 你站在原地不动,就永远都是观众。 【学习目标】 拷贝复制——赋值运算符重载 目录 &#x1f393;运算符重载的初步认识 &#x1f308;运算符重载 &#x1f308;赋值运算符重载格式 (上) &#x1f308;operator__判断俩个日期是否相等 &#x…

【Shell脚本8】Shell printf 命令

Shell printf 命令 printf 命令模仿 C 程序库&#xff08;library&#xff09;里的 printf() 程序。 printf 由 POSIX 标准所定义&#xff0c;因此使用 printf 的脚本比使用 echo 移植性好。 printf 使用引用文本或空格分隔的参数&#xff0c;外面可以在 printf 中使用格式化…

SQL note1:Basic Queries + Joins Subqueries

目录 一、Basic Queries 1、数据库术语 2、查表 3、过滤掉我们不感兴趣的行 4、布尔运算 5、过滤空值&#xff08;NULL&#xff09; 6、分组和聚合 1&#xff09;汇总数据的列 2&#xff09;汇总数据组 7、分组聚合的警告 1&#xff09;SELECT age, AVG(num_dogs) FR…

代挂单页网址发布页+加盟代理+APP下载页源码

代挂单页加盟代理网址发布页app下载页HTML单页版本&#xff0c;自行修改源码内文字。自行修改联系方式、登录地址&#xff01;上传即可使用。源码我已全部打包好&#xff0c;直接上传本站提供的源码&#xff0c;无后台&#xff0c;直接访问即可&#xff01; 源码下载&#xff…

STM32外设系列—MPU6050角度传感器

&#x1f380; 文章作者&#xff1a;二土电子 &#x1f338; 关注公众号获取更多资料&#xff01; &#x1f438; 期待大家一起学习交流&#xff01; 文章目录 一、MPU6050简介二、MPU6050寄存器简介2.1 PWR_MGMT_1寄存器2.2 GYRO_CONFIG寄存器2.3 ACCEL_CONFIG寄存器2.4 PW…

到蒙古包了,这边天气-9度 很冷

【点我-这里送书】 本人详解 作者&#xff1a;王文峰&#xff0c;参加过 CSDN 2020年度博客之星&#xff0c;《Java王大师王天师》 公众号&#xff1a;JAVA开发王大师&#xff0c;专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生&#xff0c;期待你的…

lua脚本实现redis分布式锁(脚本解析)

文章目录 lua介绍lua基本语法redis执行lua脚本 - EVAL指令使用lua保证删除原子性 lua介绍 Lua 是一种轻量小巧的脚本语言&#xff0c;用标准C语言编写并以源代码形式开放&#xff0c; 其设计目的是为了嵌入应用程序中&#xff0c;从而为应用程序提供灵活的扩展和定制功能。 设…

(动手学习深度学习)第13章 计算机视觉---图像增广与微调

13.1 图像增广 总结 数据增广通过变形数据来获取多样性从而使得模型泛化性能更好常见图片增广包裹翻转、切割、变色。 图像增广代码实现

【开源三方库】Easyui:基于OpenAtom OpenHarmony ArkUI深度定制的组件框架

万冬阳 公司&#xff1a;中国科学院软件所 小组&#xff1a;知识体系工作组 简介 Easyui是一套基于ArkTS语言开发的轻量、可靠的移动端组件库&#xff0c;它是对OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09; ArkUI进行深度定制的组件框架。Easyui可扩…