0x00 前言
缘起是我前两天看了一篇逆向文章,里面用到了一段hook脚本,在这之前我是不理解hook是什么东西,看了那段脚本后我突然就悟了,遂写下这篇文章分享一下个人心得。
注:本文不会太深入js hook。
0x01 Intro
首先我需要明确一点,我们在浏览网站时,由于js是在客户端上执行的,所以我们有最高的权限,这也就方便我们去对js进行一些操作,例如hook。我个人认为的js hook技术就是我们去修改函数或方法内部的实现过程,也就是重写方法,以便我们去利用它去实现一些我们想要的效果。
接下来我会通过一个小demo简单演示一下js hook脚本该如何编写。
0x02 Demo
console.log = function (message) {
alert(message);
}
效果:
console是内置对象,不需要实例化即可使用,所以我们可以直接修改它的方法,例如log方法。代码中我将log方法的内部实现过程改成了将传入的参数进行alert。不过这个脚本其实还是有缺陷的,一般情况下我们改写某个函数或方法的内部实现过程后,我们还需要将它原本的功能实现了,否则可能会造成意想不到的后果。
改写后的脚本:
var test = console.log;
console.log = function (message) {
alert(message);
test(message);
}
将log方法赋值给test,代码执行完我们想要的效果后就完成它本来的工作,也就是最后执行test函数,相当于执行了log方法。
效果:
现在就是一个比较完善的hook脚本了。
0x03 个人脚本分享
我在看完上文提到的那篇逆向文后,立马就去写了我的第一个hook脚本(注:后文会发全部代码以及讲解如何使用):
就拿上期自动化加解密的案例进行测试:
通过控制台输出的堆栈信息直接定位到解密位置。
我先说明一下我为什么要重写JSON.parse和JSON.stringify这两个方法,可能有看过我的逆向文章或者看过其他js逆向文章的朋友们会发现,这两个方法在加解密操作中出场率极高。一般情况下密文解密后开发可能会选择将json转为object,那么就会用到JSON.parse,JSON.stringify可能就会在加密时用到。
代码的话通过上文的讲解读者应该能看懂大部分,我觉得唯一需要讲的就是new Error().stack
,Error是构造函数,需要实例化才能用,以下是MDN介绍的stack方法:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error/stack
简单来说就是它可以直接输出调用的堆栈,也就是上文演示的效果:
不过我这里还需要提的一点的就是这个方法需要不断的实例化调用,如果只实例化一个对象然后反复调用这个实例的stack方法,只会输出实例化时的那个调用堆栈,例如:
0x04 如何使用js hook脚本
当我们要hook时,一般来说这个脚本一定要是文档中第一个加载执行的js,这样就能拿到函数或方法的控制权,所以我们就需要插件进行帮助。
这里我推荐大家使用油猴插件,直接在google应用商店搜篡改猴即可:
安装后固定到chrome后点击添加新脚本:
将代码写到注释部分即可:
另外我需要提一点,我这个hook脚本一定要是文档中第一个加载的js,所以要修改一下脚本的运行时期。保存代码后点击设置:
修改运行时期即可,document-start是我们需要设置的:
具体为什么可查看油猴中文文档(https://www.cnblogs.com/grubber/p/12560522.html
):
hook_JSON:
// ==UserScript==
// @name hook_JSON
// @namespace http://tampermonkey.net/
// @version 2024-10-29
// @description try to take over the world!
// @author 0xsdeo
// @match http://*/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=csdn.net
// @grant none
// ==/UserScript==
(function() {
'use strict';
var json_p = JSON.parse;
JSON.parse = function(str){
console.log(str);
console.log(new Error().stack);
console.log("-----------------------------------------------------------------------------------------------------")
return json_p(str);
}
var json_s = JSON.stringify;
JSON.stringify = function(obj){
console.log(obj);
console.log(new Error().stack);
console.log("-----------------------------------------------------------------------------------------------------")
return json_s(obj);
}
})();
最后提一点,脚本需要指定一下要执行脚本的网站,匹配到的网站才会执行脚本,也是在设置里改:
这里我设置的*,意为所有网站都执行该脚本。