【JS 逆向学习】【笔记】03-油猴插件tampermonkey、常用hook脚本

本文用于接收油猴插件,收录常见的hook脚本

声明

本文章内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!


插件安装

方法1:将下载下来的压缩包解压出来,其中类型为CRX文件就是接下来需要用到的安装文件。

打开浏览器设置,打开扩展程序页面,或者直接搜索Chrome://extensions/进入。然后保持页面开发者模式的开启。找到被解压后的tampermonkey.crx文件,将其拖动到扩展程序页面,释放并同意完成安装。

方法2:直接百度手动搜索进入Tampermonkey官网

点击下载,并安装

下载插件

hook实例

下面介绍常用脚本,或下载常用脚本

常用脚本
实例1:hook cookie

chrome->工具栏->油猴图标->管理面板->新建脚本

进入管理面板


进入管理面板

编写hook代码,并保存

// ==UserScript==
// @name         Cookie Hook for aqy __dfp
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  爱奇艺Hook-Cookie 脚本示例
// @author       younghare
// @match        *
// @icon         http://wework.qpic.cn/bizmail/MRHcKwRohReU225xmwYk2qqQW6oHFzXdy105rFyic0JJgSq43QAWY2A/0
// @grant        none
// @run-at       document-start
// ==/UserScript==

(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;
    },
  });
})();

保持脚本


保持脚本

启用脚本

启用脚本

在chrome访问网页
成功hook到cookie,会自动产生断点,也打印出信息

hook-cookie
实例2:hook localStorage.getItem("某某参数");
// ==UserScript==
// @name         Hook localStorage.getItem
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  localStorage.getItem脚本示例  localStorage.getItem("某某参数");
// @author       younghare
// @match        *
// @icon         http://wework.qpic.cn/bizmail/MRHcKwRohReU225xmwYk2qqQW6oHFzXdy105rFyic0JJgSq43QAWY2A/0
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    var tmp_getItem = localStorage.getItem;
    localStorage.getItem = function(params) {
        console.log("Hook localStorage.getItem ——> ", params);
        debugger;
        return tmp_getItem(params);
    }
})();
hook-localStorage.getItem
实例3:hook URL open = function (method, url, async);

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

hook-UR-open
// ==UserScript==
// @name         Hook URL
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  用于定位请求 URL 中关键参数生成位置;
// @author       younghare
// @match        *
// @icon         http://wework.qpic.cn/bizmail/MRHcKwRohReU225xmwYk2qqQW6oHFzXdy105rFyic0JJgSq43QAWY2A/0
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    var open = window.XMLHttpRequest.prototype.open;
    window.XMLHttpRequest.prototype.open = function (method, url, async) {
        if (url.indexOf("videoTopResource") != -1) { //url中包含videoTopResource
            debugger;
        }
        return open.apply(this, arguments);
    };
})();
实例4:hook setRequestHeader(key, value);
(function () {
    var org = window.XMLHttpRequest.prototype.setRequestHeader;
    window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
        debugger;
        if (key == 'Accept') {
            debugger;
        }
        return org.apply(this, arguments);
    };
})();
实例5:Hook JSON.stringify(params)

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);
    }
})();
实例6:Hook JSON.parse(params)将一个 JSON 字符串转换为对象

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

(function() {
    var parse = JSON.parse;
    JSON.parse = function(params) {
        console.log("Hook JSON.parse ——> ", params);
        debugger;
        return parse(params);
    }
})();
实例7:Hook eval(src)动态执行 JS

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

Hook-eval
// ==UserScript==
// @name         Hook eval() 操作都会在控制台打印输出将要执行的 JS 源码
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Hook eval() 操作都会在控制台打印输出将要执行的 JS 源码;
// @author       younghare
// @match        *
// @icon         http://wework.qpic.cn/bizmail/MRHcKwRohReU225xmwYk2qqQW6oHFzXdy105rFyic0JJgSq43QAWY2A/0
// @grant        none
// @run-at       document-start
// ==/UserScript==

(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
    });
})();
实例8:Hook window.Function所有的函数操作都会在控制台打印输出将要执行的 JS 源码
// ==UserScript==
// @name         Hook window.Function
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Hook window.Function
// @author       younghare
// @match        *
// @icon         http://wework.qpic.cn/bizmail/MRHcKwRohReU225xmwYk2qqQW6oHFzXdy105rFyic0JJgSq43QAWY2A/0
// @grant        none
// @run-at       document-start
// ==/UserScript==
(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
    });
})();
实例9:Hook createElement查看创建了什么元素

document下的createElement()方法的hook,查看创建了什么元素

// ==UserScript==
// @name         Hook createElement查看创建了什么元素
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  查看创建了什么元素createElement
// @author       younghare
// @match        *
// @icon         http://wework.qpic.cn/bizmail/MRHcKwRohReU225xmwYk2qqQW6oHFzXdy105rFyic0JJgSq43QAWY2A/0
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict'
   var _createElement = document.createElement.bind(document);
   document.createElement = function(elm){
   // 这里做判断 是否创建了script这个元素
   debugger;
   if(elm == 'body'){
        debugger;
   }
    return _createElement(elm);
}
})();
Hook-createElement
实例10:websocket hook
// ==UserScript==
// @name         websocket hook
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  websocket hook
// @author       younghare
// @match        *
// @icon         http://wework.qpic.cn/bizmail/MRHcKwRohReU225xmwYk2qqQW6oHFzXdy105rFyic0JJgSq43QAWY2A/0
// @grant        none
// @run-at       document-start
// ==/UserScript==

 // 1、webcoket 一般都是json数据格式传输,那么发生之前需要JSON.stringify
var my_stringify = JSON.stringify;
JSON.stringify = function (params) {
    //这里可以添加其他逻辑比如 debugger
    console.log("json_stringify params:",params);
    return my_stringify(params);
};

var my_parse = JSON.parse;
JSON.parse = function (params) {
    //这里可以添加其他逻辑比如 debugger
    console.log("json_parse params:",params);
    return my_parse(params);
};

// 2  webScoket 绑定在windows对象,上,根据浏览器的不同,websokcet名字可能不一样
//chrome window.WebSocket  firfox window.MozWebSocket;
window._WebSocket = window.WebSocket;

// hook send
window._WebSocket.prototype.send = function (data) {
    console.info("Hook WebSocket data", data);
    return this.send(data)
}

Object.defineProperty(window, "WebSocket",{value: WebSocket})
实例11:js hook ajax 进一步分析
// ==UserScript==
// @name         js hook ajax 进一步分析
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  js hook ajax 进一步分析
// @author       younghare
// @match        *
// @icon         http://wework.qpic.cn/bizmail/MRHcKwRohReU225xmwYk2qqQW6oHFzXdy105rFyic0JJgSq43QAWY2A/0
// @grant        none
// @run-at       document-start
// ==/UserScript==

//将此代码粘贴到工具中
!function(t) {
    function n(e) {
        if (r[e]) return r[e].exports;
        var i = r[e] = {
            exports: {},
            id: e,
            loaded: !1
        };
        return t[e].call(i.exports, i, i.exports, n),
        i.loaded = !0,
        i.exports
    }
    var r = {};
    return n.m = t,
    n.c = r,
    n.p = "",
    n(0)
} ([function(t, n, r) {
    r(1)(window)
},
function(t, n) {
    t.exports = function(t) {
        var n = "RealXMLHttpRequest";
        t.hookAjax = function(t) {
            function r(n) {
                return function() {
                    var r = this.hasOwnProperty(n + "_") ? this[n + "_"] : this.xhr[n],
                    e = (t[n] || {}).getter;
                    return e && e(r, this) || r
                }
            }
            function e(n) {
                return function(r) {
                    var e = this.xhr,
                    i = this,
                    o = t[n];
                    if ("function" == typeof o) e[n] = function() {
                        t[n](i) || r.apply(e, arguments)
                    };
                    else {
                        var u = (o || {}).setter;
                        r = u && u(r, i) || r;
                        try {
                            e[n] = r
                        } catch(t) {
                            this[n + "_"] = r
                        }
                    }
                }
            }
            function i(n) {
                return function() {
                    var r = [].slice.call(arguments);
                    if (!t[n] || !t[n].call(this, r, this.xhr)) return this.xhr[n].apply(this.xhr, r)
                }
            }
            return window[n] = window[n] || XMLHttpRequest,
            XMLHttpRequest = function() {
                var t = new window[n];
                for (var o in t) {
                    var u = "";
                    try {
                        u = typeof t[o]
                    } catch(t) {}
                    "function" === u ? this[o] = i(o) : Object.defineProperty(this, o, {
                        get: r(o),
                        set: e(o),
                        enumerable: !0
                    })
                }
                this.xhr = t
            },
            window[n]
        },
        t.unHookAjax = function() {
            window[n] && (XMLHttpRequest = window[n]),
            window[n] = void 0
        },
        t.
    default = t
    }
}]);
hookAjax(
        // hook functions and callbacks of XMLHttpRequest object
        {
            onreadystatechange: function (xhr) {
                //console.log("onreadystatechange called: %O", xhr)

            },
            onload: function (xhr) {
                //console.log("onload called: %O", xhr)
                xhr.responseText = "hook" + xhr.responseText;

            },
            open: function (arg, xhr) {
                console.log("open called: method:%s,url:%s,async:%s", arg[0], arg[1], arg[2], xhr)
                arg[1] += "?hook_tag=1";
                //统一添加请求头
            },
            send: function (arg, xhr) {
                //console.log("send called: %O", arg[0])
                xhr.setRequestHeader("_custom_header_", "ajaxhook")
            },
            setRequestHeader: function (arg, xhr) {
                //console.log("setRequestHeader called!", arg)
            },
            // hook attributes of XMLHttpRequest object
            timeout: {
                setter: function (v, xhr) {
                    //timeout shouldn't exceed 10s
                    return Math.max(v, 1000);
                }
            }
        }
    );

更多插件脚本参考

油猴脚本市场
js的hook方法和技巧
githubGist插件

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容