js-hooker

news2025/7/13 17:20:08

        该项目是对开源项目进行二开,改写的hook脚本,新增了cookie添加形式的捕获,若有侵权,请联系博主删除。

        下面贴运行截图:

                解释:       绿色: 新增cookie

                  红色 : 删除cookie

                  黄色 : cookie更改

可以根据cookie状态跟踪目标cookie进行分析。

        const debuggerRules = [{"add|update": "epssw"}];

这里是debugger的规则,
支持以下几种格式:

            "add": true, "update": true, "delete": true, "read": true,
形式为规则:cookie名,会在触发的时候下断。

下附代码:

// ==UserScript==
// @name         JS-Cooker
// @description  用于监控js对cookie的修改,或者在cookie符合给定条件时进入断点
// @author       allenyang
// @match       *://*/*
// @run-at      document-start
// @grant       none
// ==/UserScript==

(() => {
        const debuggerRules = [{"add|update": "epssw"}];
        const enableEventDebugger = {
            "add": true, "update": true, "delete": true, "read": true,
        }
        const consoleLogFontSize = 12;
        const ignoreUpdateButNotChanged = false;
        let realDocumentCookieProperty = null;
        const definePropertyIsMe = "allenyang-js-hooker";
        (function () {
            Object.defineProperty = new Proxy(Object.defineProperty, {
                apply: function (target, thisArg, argArray) {
                    const isMe = argArray && argArray.length >= 3 && argArray[2] && definePropertyIsMe in argArray[2];
                    const isDocumentCookie = argArray && argArray.length >= 2 && argArray[0] === document && "cookie" === argArray[1];
                    if (!isMe && isDocumentCookie) {
                        if (argArray && argArray.length >= 3) {
                            realDocumentCookieProperty = argArray[2];
                            return;
                        }
                    }
                    return target.apply(thisArg, argArray);
                }
            });

            Object.defineProperty.toString = function () {
                return "function defineProperty() { [native code] }";
            }
            Object.defineProperties = new Proxy(Object.defineProperties, {
                apply: function (target, thisArg, argArray) {
                    const isDocumentCookie = argArray && argArray.length >= 2 && document === argArray[0] && "cookie" in argArray[1];
                    if (isDocumentCookie) {
                        realDocumentCookieProperty = argArray[1]["cookie"];
                        delete argArray[1]["cookie"];
                        if (!Object.keys(argArray[1]).length) {
                            return;
                        }
                    }
                    return target.apply(thisArg, argArray);
                }
            });

            Object.defineProperties.toString = function () {
                return "function defineProperties() { [native code] }";
            }

        })();
        (function addCookieHook() {
            const handler = {
                get: () => {
                    delete document.cookie;
                    try {
                        if (realDocumentCookieProperty && "get" in realDocumentCookieProperty) {
                            return realDocumentCookieProperty["get"].apply(document, arguments);
                        } else {
                            return document.cookie;
                        }
                    } finally {
                        addCookieHook();
                    }

                }, set: newValue => {
                    allenyang_onSetCookie(newValue);
                    delete document.cookie;

                    try {
                        if (realDocumentCookieProperty && "set" in realDocumentCookieProperty) {
                            realDocumentCookieProperty["set"].apply(document, [newValue]);
                        } else {
                            document.cookie = newValue;
                        }
                    } finally {
                        addCookieHook();
                    }

                }, configurable: true, enumerable: false,
            };
            handler[definePropertyIsMe] = true;
            Object.defineProperty(document, "cookie", handler);
        })();

        function allenyang_onSetCookie(newValue) {
            const cookiePair = parseSetCookie(newValue);
            const currentCookieMap = getCurrentCookieMap();
            if (cookiePair.expires !== null && new Date().getTime() >= cookiePair.expires) {
                onDeleteCookie(newValue, cookiePair.name, cookiePair.value || (currentCookieMap.get(cookiePair.name) || {}).value);
                return;
            }
            if (currentCookieMap.has(cookiePair.name)) {
                onUpdateCookie(newValue, cookiePair.name, currentCookieMap.get(cookiePair.name).value, cookiePair.value);
                return;
            }
            onAddCookie(newValue, cookiePair.name, cookiePair.value);
        }

        function onReadCookie(cookieOriginalValue, cookieName, cookieValue) {

        }

        function onDeleteCookie(cookieOriginalValue, cookieName, cookieValue) {
            const valueStyle = `color: black; background: #E50000; font-size: ${consoleLogFontSize}px; font-weight: bold;`;
            const normalStyle = `color: black; background: #FF6766; font-size: ${consoleLogFontSize}px;`;

            const message = [

                normalStyle, now(),

                normalStyle, "JS Cookie Monitor: ",

                normalStyle, "delete cookie, cookieName = ",

                valueStyle, `${cookieName}`,

                ...(() => {
                    if (!cookieValue) {
                        return [];
                    }
                    return [normalStyle, ", value = ",

                        valueStyle, `${cookieValue}`,];
                })(),

                normalStyle, `, code location = ${getCodeLocation()}`];
            console.log(genFormatArray(message), ...message);

            testDebuggerRules(cookieOriginalValue, "delete", cookieName, cookieValue);
        }

        function onUpdateCookie(cookieOriginalValue, cookieName, oldCookieValue, newCookieValue) {

            const cookieValueChanged = oldCookieValue !== newCookieValue;

            if (ignoreUpdateButNotChanged && !cookieValueChanged) {
                return;
            }

            const valueStyle = `color: black; background: #FE9900; font-size: ${consoleLogFontSize}px; font-weight: bold;`;
            const normalStyle = `color: black; background: #FFCC00; font-size: ${consoleLogFontSize}px;`;

            const message = [

                normalStyle, now(),

                normalStyle, "JS Cookie Monitor: ",

                normalStyle, "update cookie, cookieName = ",

                valueStyle, `${cookieName}`,

                ...(() => {
                    if (cookieValueChanged) {
                        return [normalStyle, `, oldValue = `,

                            valueStyle, `${oldCookieValue}`,

                            normalStyle, `, newValue = `,

                            valueStyle, `${newCookieValue}`]
                    } else {
                        return [normalStyle, `, value = `,

                            valueStyle, `${newCookieValue}`,];
                    }
                })(),

                normalStyle, `, valueChanged = `,

                valueStyle, `${cookieValueChanged}`,

                normalStyle, `, code location = ${getCodeLocation()}`];
            console.log(genFormatArray(message), ...message);

            testDebuggerRules(cookieOriginalValue, "update", cookieName, newCookieValue, cookieValueChanged);
        }

        function onAddCookie(cookieOriginalValue, cookieName, cookieValue) {
            const valueStyle = `color: black; background: #669934; font-size: ${consoleLogFontSize}px; font-weight: bold;`;
            const normalStyle = `color: black; background: #65CC66; font-size: ${consoleLogFontSize}px;`;

            const message = [

                normalStyle, now(),

                normalStyle, "JS Cookie Monitor: ",

                normalStyle, "add cookie, cookieName = ",

                valueStyle, `${cookieName}`,

                normalStyle, ", cookieValue = ",

                valueStyle, `${cookieValue}`,

                normalStyle, `, code location = ${getCodeLocation()}`];
            console.log(genFormatArray(message), ...message);

            testDebuggerRules(cookieOriginalValue, "add", cookieName, cookieValue);
        }

        function now() {
            return "[" + new Date(new Date().getTime() + 1000 * 60 * 60 * 8).toJSON().replace("T", " ").replace("Z", "") + "] ";
        }

        function genFormatArray(messageAndStyleArray) {
            const formatArray = [];
            for (let i = 0, end = messageAndStyleArray.length / 2; i < end; i++) {
                formatArray.push("%c%s");
            }
            return formatArray.join("");
        }

        function getCodeLocation() {
            const callstack = new Error().stack.split("\n");
            while (callstack.length && callstack[0].indexOf("allenyang") === -1) {
                callstack.shift();
            }
            callstack.shift();
            callstack.shift();

            return callstack[0].trim();
        }

        function parseSetCookie(cookieString) {
            // uuid_tt_dd=10_37476713480-1609821005397-659114; Expires=Thu, 01 Jan 1025 00:00:00 GMT; Path=/; Domain=.csdn.net;
            const cookieStringSplit = cookieString.split(";");
            const {key, value} = splitKeyValue(cookieStringSplit.length && cookieStringSplit[0])
            const map = new Map();
            for (let i = 1; i < cookieStringSplit.length; i++) {
                let {key, value} = splitKeyValue(cookieStringSplit[i]);
                map.set(key.toLowerCase(), value);
            }
            // 当不设置expires的时候关闭浏览器就过期
            const expires = map.get("expires");
            return new CookiePair(key, value, expires ? new Date(expires).getTime() : null)
        }

        function splitKeyValue(s) {
            let key = "", value = "";
            const keyValueArray = (s || "").split("=");

            if (keyValueArray.length) {
                key = decodeURIComponent(keyValueArray[0].trim());
            }

            if (keyValueArray.length > 1) {
                value = decodeURIComponent(keyValueArray.slice(1).join("=").trim());
            }

            return {
                key, value
            }
        }

        function getCurrentCookieMap() {
            const cookieMap = new Map();
            if (!document.cookie) {
                return cookieMap;
            }
            document.cookie.split(";").forEach(x => {
                const {key, value} = splitKeyValue(x);
                cookieMap.set(key, new CookiePair(key, value));
            });
            return cookieMap;
        }

        class DebuggerRule {

            constructor(eventName, cookieNameFilter, cookieValueFilter) {
                this.eventName = eventName;
                this.cookieNameFilter = cookieNameFilter;
                this.cookieValueFilter = cookieValueFilter;
            }

            test(eventName, cookieName, cookieValue) {
                return this.testByEventName(eventName) && (this.testByCookieNameFilter(cookieName) || this.testByCookieValueFilter(cookieValue));
            }

            testByEventName(eventName) {
                if (!enableEventDebugger[eventName]) {
                    return false;
                }
                // 事件不设置则匹配任何事件
                if (!this.eventName) {
                    return true;
                }
                return this.eventName === eventName;
            }

            testByCookieNameFilter(cookieName) {
                if (!cookieName || !this.cookieNameFilter) {
                    return false;
                }
                if (typeof this.cookieNameFilter === "string") {
                    return this.cookieNameFilter === cookieName;
                }
                if (this.cookieNameFilter instanceof RegExp) {
                    return this.cookieNameFilter.test(cookieName);
                }
                return false;
            }

            testByCookieValueFilter(cookieValue) {
                if (!cookieValue || !this.cookieValueFilter) {
                    return false;
                }
                if (typeof this.cookieValueFilter === "string") {
                    return this.cookieValueFilter === cookieValue;
                }
                if (this.cookieValueFilter instanceof RegExp) {
                    return this.cookieValueFilter.test(cookieValue);
                }
                return false;
            }

        }
        (function standardizingRules() {

            const ruleConfigErrorMessage = [];

            const newRules = [];
            while (debuggerRules.length) {
                const rule = debuggerRules.pop();
                if (typeof rule === "string" || rule instanceof RegExp) {
                    newRules.push(new DebuggerRule(null, rule, null));
                    continue;
                }
                for (let key in rule) {
                    let events = null;
                    let cookieNameFilter = null;
                    let cookieValueFilter = null;
                    if (key === "events") {
                        events = rule["events"] || "add | delete | update";
                        cookieNameFilter = rule["name"]
                        cookieValueFilter = rule["value"];
                    } else if (key !== "name" && key !== "value") {
                        events = key;
                        cookieNameFilter = rule[key];
                        cookieValueFilter = rule["value"];
                    } else {
                        continue;
                    }
                    if (!cookieNameFilter) {
                        const errorMessage = `必须为此条规则 ${JSON.stringify(rule)} 配置一个Cookie Name匹配条件`;
                        ruleConfigErrorMessage.push(errorMessage);
                        continue;
                    }
                    events.split("|").forEach(eventName => {
                        eventName = eventName.trim();
                        if (eventName !== "add" && eventName !== "delete" && eventName !== "update") {
                            const errorMessage = `此条规则 ${JSON.stringify(rule)} 的Cookie事件名字配置错误,必须为 add、delete、update 三种之一或者|分隔的组合,您配置的是 ${eventName},仅忽略此无效事件`;
                            ruleConfigErrorMessage.push(errorMessage);
                            return;
                        }
                        newRules.push(new DebuggerRule(eventName, cookieNameFilter, cookieValueFilter));
                    })
                }
            }

            if (ruleConfigErrorMessage.length) {
                const errorMessageStyle = `color: black; background: #FF2121; font-size: ${Math.round(consoleLogFontSize * 1.5)}px; font-weight: bold;`;
                let errorMessage = now() + "JS Cookie Monitor: 以下Cookie断点规则配置错误,已忽略: \n ";
                for (let i = 0; i < ruleConfigErrorMessage.length; i++) {
                    errorMessage += `${i + 1}. ${ruleConfigErrorMessage[i]}\n`;
                }
                console.log("%c%s", errorMessageStyle, errorMessage);
            }
            for (let rule of newRules) {
                debuggerRules.push(rule);
            }
        })();
        function testDebuggerRules(setCookieOriginalValue, eventName, cookieName, cookieValue, cookieValueChanged) {
            for (let rule of debuggerRules) {
                if (rule.test(eventName, cookieName, cookieValue)) {
                    debugger;
                }
            }
        }
        class CookiePair {
            constructor(name, value, expires) {
                this.name = name;
                this.value = value;
                this.expires = expires;
            }

        }

    }

)();

       建议配合油猴食用效果更佳~

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

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

相关文章

java:动态代理和cglib代理的简单例子

# 项目代码资源&#xff1a; 可能还在审核中&#xff0c;请等待。。。 https://download.csdn.net/download/chenhz2284/89457803 # 项目代码 【pom.xml】 <dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version&…

系统安全(补充)

拒绝服务漏洞&#xff08;拒绝服务漏洞将导致网络设备停止服务&#xff0c;危害网络服务可用性&#xff09;旁路&#xff08;旁路漏洞绕过网络设备的安全机制&#xff0c;使得安全措施没有效果&#xff09;代码执行&#xff08;该类漏洞使得攻击者可以控制网络设备&#xff0c;…

写给大数据开发:谈谈数仓建模的反三范式

在数仓建设中&#xff0c;我们经常谈论反三范式。顾名思义&#xff0c;反范式化指的是通过增加冗余或重复的数据来提高数据库的读性能。简单来说&#xff0c;就是浪费存储空间&#xff0c;节省查询时间。用行话讲&#xff0c;这就是以空间换时间。听起来像是用大炮打蚊子&#…

opencv 视频处理

概述 OpenCV 的视频模块是其核心组成部分之一&#xff0c;主要负责视频文件的读取、处理、分析以及视频流的捕获和输出。这一模块使得开发者能够轻松地处理来自摄像头、文件或其他视频源的视频数据&#xff0c;进行实时或离线的图像处理和计算机视觉任务。以下是 OpenCV 视频模…

唯一工业操作系统!蓝卓supOS入榜中国500最具价值品牌

6月19日 在第21届世界品牌大会上 世界品牌实验室(World Brand Lab) 正式发布2024年《中国500最具价值品牌》分析报告 蓝卓supOS 以131.65亿元的品牌价值成为 国内首个入榜工业操作系统 国内首个工业操作系统的蜕变之旅 蓝卓supOS快速迭代指数增长 不断引领海内外多个首…

同时使用磁吸充电器和Lightning时,iPhone充电速度会变快吗?

在智能手机的世界里&#xff0c;续航能力一直是用户关注的焦点。苹果公司以其创新的MagSafe技术和传统的Lightning接口&#xff0c;为iPhone用户提供了多样化的充电解决方案。 然而&#xff0c;当这两种技术同时使用时&#xff0c;它们能否带来更快的充电速度&#xff1f;本文…

Day9—Spark运行模式及RDD的创建

Spark概述 大数据开发的总体架构 可以看到&#xff0c;在数据计算层&#xff0c;作为Hadoop核心组成的MapReduce可以结合Hive通过类SQL的方式进行数据的离线计算&#xff08;当然也可以编写独立的MapReduce应用程序进行计算&#xff09;&#xff1b;而Spark既可以做离线计算&a…

【Spring Cloud】Gateway 服务网关限流

文章目录 route限流导入依赖编写配置类测试 自定义API分组总结 网关是所有请求的公共入口&#xff0c;所以可以在网关进行限流&#xff0c;而且限流的方式也很多&#xff0c;我们本次采用前面学过的 Sentinel 组件来实现网关的限流。 Sentinel 支持对 SpringCloud Gateway、Zuu…

网络程序通信的流程---socket与TCP的简单认识

网络程序通信的流程 网络程序通信的流程&#xff1a; 1.通过ip地址找到网络中的设备 2.通过端口号找到对应进程的端口 3.传输数据时还需要使用传输协议&#xff08;TCP&#xff09;&#xff0c;保证数据的可靠性 4.socket完成进程之间网络数据的传输 ip地址的介绍 IP地址…

知识库的创建(5) - FaissKBService

文章目录 前言一、追踪代码二、源码分析三、详解kb_faiss_pool类的load_vector_store1. 方法定义2. 方法实现3. 优点4. 再看看self.new_vector_store 总结 前言 上一篇文章&#xff0c;我们追到了这里&#xff0c;了解了kb是通过KBServiceFactory产生的一个对象&#xff0c;而…

计算机网络-BGP路由优选原则八

一、优选到Next_Hop的IGP度量值最小的路由。 查看BGP路由详细信息&#xff1a; [AR1]dis bgp routing-table 192.168.1.0BGP local router ID : 1.1.1.1Local AS number : 100Paths: 2 available, 1 best, 1 selectBGP routing table entry information of 192.168.1.0/24:Fr…

ADOP带你了解:数据中心的高速互联解决方案

随着大语言模型和AIGC的飞速发展&#xff0c;数据中心对于高速、高可靠性的网络连接需求日益增长。ADOP系列产品正是在这样的背景下应运而生&#xff0c;为现代数据中心提供了全面的连接解决方案。 ADOP系列产品概览 ADOP系列产品旨在为云、高性能计算、Web 2.0、企业、电信、…

Python | Leetcode Python题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; class Solution:def twoSum(self, numbers: List[int], target: int) -> List[int]:low, high 0, len(numbers) - 1while low < high:total numbers[low] numbers[high]if total target:return [low 1, high 1]elif total <…

吴恩达机器学习 第二课 week4 决策树

目录 01 学习目标 02 实现工具 03 问题描述 04 构建决策树 05 总结 01 学习目标 &#xff08;1&#xff09;理解“熵”、“交叉熵&#xff08;信息增益&#xff09;”的概念 &#xff08;2&#xff09;掌握决策树的构建步骤与要点 02 实现工具 &#xff08;1&#xff09;…

格式化数据恢复,4个方法,恢复文件好帮手

“由于电脑病毒的原因&#xff0c;我不得已将磁盘格式化了&#xff0c;不知道大家有没有方法恢复格式化的数据呢&#xff1f;” 在数字时代的浪潮中&#xff0c;我们每个人的生活都如同被数据编织成的一幅幅绚丽画卷。然而&#xff0c;有时这幅画卷可能会因为一次意外的格式化操…

【科研基础】通感一体化讲座

通信和感知在硬件结构上相似&#xff0c;高效地利用资源&#xff0c;实现相互的增益&#xff1b; 感知是基于不同的任务&#xff0c;比如

Python联动Mysql

首先配置pip源(不然在安装库的时候会很慢!!!) pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/安装必要库: mysql.connector MySQL 连接器/ODBC 是 MySQL ODBC 驱动程序&#xff08;以前称为 MyODBC 驱动程序&#xff09;系列的名称&#xff0c;它使…

计算机网络:运输层 - TCP 流量控制 拥塞控制

计算机网络&#xff1a;运输层 - TCP 流量控制 & 拥塞控制 滑动窗口流量控制拥塞控制慢开始算法拥塞避免算法快重传算法快恢复算法 滑动窗口 如图所示&#xff1a; 在TCP首部中有一个窗口字段&#xff0c;该字段就基于滑动窗口来辅助流量控制和拥塞控制。所以我们先讲解滑…

kotlin集合框架

1、集合框架的接口类型对比 2、不可变和可变List fun main() {// 不可变List - 不能删除或添加元素val intList: List<Int> listOf(1,2,3)intList.forEach{println(it) // 1 2 3}println("")// 可变List - 可以删除或添加元素val mutableList mutableListO…