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

news2024/11/25 20:44:41
一、浏览器调试面板介绍

在这里插入图片描述

二、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脚本工具

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue23-props配置功能

Vue2&3-props配置功能 Vue2-props配置 功能&#xff1a;接收从其他组件传过来的数据&#xff0c;将数据从静态转为动态注意&#xff1a; 同一层组件不能使用props&#xff0c;必须是父组件传子组件的形式。父组件传数据&#xff0c;子组件接收数据。不能什么数据都接收&a…

虚幻C+++基础 day3

常见的游戏机制 Actor机关门 创建一个Actor类&#xff0c;添加两个静态网格与一个触发器 UBoxComponentUStaticMeshComponent 头文件&#xff1a; #include “Components/BoxComponent.h”#include “Components/StaticMeshComponent.h” TriggerDoor.h // Fill out your …

两个int(32位)整数m和n的二进制表达中,求有多少个位(bit)不同?

我先来讲一讲这道题的大概意思&#xff1a;假设我们输入的是 0 和 1: 0的32位二进制中为&#xff1a;000……0(32位) 1的32位二进制中为&#xff1a;000……1(32位) 那么就有一位不同。 方法一&#xff1a; 既然是二进制中&#xff0c;那么就是满二进一&#xff0c;就像…

操作系统·进程管理

2.1 前趋图和程序执行 2.1.1 前趋图 前趋图是一个有向无循环图&#xff0c;记为DAG&#xff0c;可用于描述程序/进程之间执行的前后关系&#xff0c;无循环关系可实现顺序执行。 2.1.2 程序的顺序执行 在计算机系统中只有一个程序在运行&#xff0c;这个程序独占系统中所有资…

基于FPGA的PCIe-Aurora 8/10音频数据协议转换系统设计阅读笔记

文章可知网下载阅读&#xff0c;该论文设计了一种 PC 到光纤模块&#xff08;基于Aurora的光纤传输&#xff09;的数据通路&#xff0c;成功完成了Aurora 以及 DDR 等模块的功能验证。 学习内容&#xff1a; 本次主要学习了Pcie高速串行总线协议、Aurora高速串行总线协议、DDR相…

Android 11.0 禁止弹出系统simlock的锁卡弹窗功能实现

1.前言 在11.0的系统rom产品定制化开发中,在关于定制sim卡定制机的一款产品中,需要实现simlock锁卡功能,在系统实现锁卡功能以后,在开机的过程中,或者是在插入sim卡 后,当系统检测到是禁用的sim卡后,就会弹出simlock锁卡弹窗,要求输入puk 解锁密码,功能需求禁用这个弹…

树莓派4B的测试记录(CPU、FFMPEG)

本文是用来记录树莓派 4B 的一些测试记录。 温度 下面记录中的风扇和大风扇是这样的&#xff1a; 为什么要用大风扇呢&#xff1f;因为小风扇在外壳上&#xff0c;气流通过外壳的珊格会有啸叫&#xff0c;声音不大但是很烦人&#xff0c;大风扇没这个问题&#xff0c;并且同样…

QMetaType和QVariant使用

描述 QMetaType和QVariant可以结合使用&#xff0c;用于在运行时确定数据类型。 QMetaType是Qt提供的用于管理各种数据类型的类&#xff0c;它可以帮助我们在运行时动态地创建、销毁、复制和比较数据类型。我们可以使用QMetaType来注册我们自己的数据类型&#xff0c;并为其提…

用于图像处理的高斯滤波器 (LoG) 拉普拉斯

一、说明 欢迎来到拉普拉斯和高斯滤波器的拉普拉斯的故事。LoG是先进行高斯处理&#xff0c;继而进行拉普拉斯算子的图像处理算法。用拉普拉斯具有过零功能&#xff0c;实现边缘岭脊提取。 二、LoG算法简述 在这篇博客中&#xff0c;让我们看看拉普拉斯滤波器和高斯滤波器的拉普…

【STM32】STM32的Cube和HAL生态

1.单片机软件开发的时代变化 1.单片机的演进过程 (1)第1代&#xff1a;4004、8008、Zilog那个年代&#xff08;大约1980年代之前&#xff09; (2)第2代&#xff1a;51、PIC8/16、AVR那个年代&#xff08;大约2005年前&#xff09; (3)第3代&#xff1a;51、PIC32、Cortex-M0、…

Python Selenium Headless:以 Headless 模式打开 Chrome 浏览器

本篇文章介绍了如何在 Python 中使用 Selenium 运行浏览器无头模式。 在 Python 中使用 Selenium 以无头模式运行 Chrome 浏览器 要说 headless 浏览器,你也可以称它们为真正的浏览器,只不过它们是在后台运行的; 您将无法在任何地方看到它们,但它们仍在后台运行。 在某些…

拓世科技集团打造数字人营销解决方案,为车企提供新的“增长担当”

汽车&#xff0c;已经渐渐融入了现代人的日常生活&#xff0c;从高端的身份标志转变为普罗大众的出行选择&#xff0c;它驶入了千家万户&#xff0c;成为了我们日常出行的可靠伙伴&#xff0c;见证着人们的生活故事和时代的变迁。 中国汽车市场的蓬勃发展引起了业内外的广泛关…

达梦数据库-Win10安装

目录结构 前言达梦数据库达梦数据库适用场景达梦数据库 PK MySQL达梦数据库安装数据库下载解压下载的压缩文件安装详细步骤安装关键节点配置 DM管理工具启动DM管理工具DM管理工具连接达梦数据库 参考链接 前言 达梦数据库Win10系统安装整理&#xff1b; 达梦数据库 达梦数据库…

Netty第三部

继续Netty第二部的内容 一、ChannelHandler 1、ChannelHandler接口 ChannelHandler是Netty的主要组件&#xff0c;处理所有的入站和出站数据的应用程序逻辑的容器&#xff0c;可以应用在数据的格式转换、异常处理、数据报文统计等 继承ChannelHandler的两个子接口&#xff…

uniapp踩坑之项目:隐藏显示密码功能

1.input组件的password设置为动态前面加:冒号&#xff1b; 2.动态切换眼睛图标使用:style //html <view> 密码&#xff1a;<input placeholder"请输入密码" :password"openPassword" type"text" placeholder-style"color:#e2e2e2;…

QT QStackedWidget

QStackedWidget是一个特殊的布局容器&#xff0c;它可以管理多个页面&#xff0c;并且只能显示其中一个页面。这些页面是QWidget或其派生类的实例&#xff0c;并通过调用addWidget()函数添加到堆栈中。 例如&#xff1a; #include <QWidgets> #include <QStackedWid…

PTE-RA总结

目录 FIBW刷题记录 1.The Plains Indians were people who did not like 2.An economic depression is a period of sustained 3.Pidgins are languages that are born after contact between 4.It is tempting to try to prove that good looks 5.The stock of Austral…

华为云,阿里云,腾讯云 安全组配置规则

1.安全组常用端口 端口服务说明21FTPFTP服务所开放的端口&#xff0c;用于上传、下载文件。22SSHSSH端口&#xff0c;用于通过命令行模式或远程连接软件&#xff08;例如PuTTY、Xshell、SecureCRT等&#xff09;连接Linux实例。23TelnetTelnet端口&#xff0c;用于Telnet远程登…

红队系列-IOT安全深入浅出

红队专题 设备安全概述物联网设备层次模型设备通信模型 渗透测试信息收集工具 实战分析漏洞切入点D-link 850L 未授权访问 2017 认证绕过认证绕过 D-link DCS-2530Ltenda 系列 路由器 前台未授权RTSP 服务未授权 访问 弱口令命令注入思科 路由器 固件二进制 漏洞 IoT漏洞-D-Lin…

HBase学习笔记(1)—— 知识点总结

目录 HBase概述 HBase 基本架构 HBase安装部署启动 HBase Shell HBase数据读写流程 HBase 优化 HBase概述 HBase是以 hdfs 为数据存储的&#xff0c;一种分布式、非关系型的、可扩展的 NoSQL 数据库 关系型数据库和非关系型数据库的区别&#xff1a; 关系型数据库和非关…