文章目录

  • 一、了解什么是hook?
  • 二、fiddler插件
  • 三、常见的hook代码总结
  • 1.Hook Cookie
  • 2.Hook Header
  • 3.Hook URL
  • 4.Hook JSON.stringify
  • 5.Hook JSON.parse
  • 6.Hook eval
  • 7.Hook Function


一、了解什么是hook?

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

Object.defineProperty(obj, prop, descriptor)
  • obj:对象;
  • prop:对象的属性名;
  • descriptor:属性描述符;

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

属性名

默认值

含义

get

undefined

存取描述符,目标属性获取值的方法

set

undefined

存取描述符,目标属性设置值的方法

value

undefined

数据描述符,设置属性的值

writable

false

数据描述符,目标属性的值是否可以被重写

enumerable

false

目标属性是否可以被枚举

configurable

false

目标属性是否可以被删除或是否可以再次修改特性

我们一般hook使用的是get和set方法,下边简单演示一下

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);

结果:

JavaScript代码的逆向工程 js逆向教程_前端


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

二、fiddler插件

有时候我们在注入hook代码时候,需要在代码运行开始就执行代码,那么这个时候我们需要借助插件,这里我使用的是编程猫的fiddler插件。

JavaScript代码的逆向工程 js逆向教程_javascript_02

资源下载地址:

三、常见的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
    });
})();