Javascript-Hook-基础

本文最后更新于:2020年9月27日 晚上

Hook原理

假设我们现在有这样一个JS代码

1
2
3
4
5
function test(aa,bb){
cc = aa + bb;
return cc;
}
test(100,200);

我们在console中可以修改这个函数,比还有其它的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var _setInterval=setInterval;
setInterval=function(a,b){
if(a.toString().indexOf("debugger")!=-1{
return null;
}
_setInterval(a,b);
}
~~~如让它打印各个参数的输出结果,这就是一个JS Hook
~~~javascript
var _test=test;
test=function(aa,bb){
console.log(aa);
console.log(bb);
var result=_test(aa,bb);
console(result);

这个函数的注入时机是在函数调用之后,页面加载完毕才注入。但实际上可以在调用地方下断点,在它运行的时候注入JS Hook,在函数被调用之前就进行修改,这也是可以的。

JS Hook看起来是很简单的,不过我们能够用它来实现很强大的功能,比如修改一些系统函数,如debugger,Function,eval等,这些都是和反调试相关的。

我们日常拿到的许多数据都是JSON,所以也可以HookJSON.stringfy进行一些操作,这样一来我们就可以在Hook后直接从堆栈中找到调用函数了。

读者应该已经发现,无论如何Hook,我们总是要把自己的代码注入到网页的环境里边,这个注入的时机选择很重要。
可以选择下断点的方式注入,但是有一种更为优雅的方法,那就是编写Chrome拓展插件,插件可以在网页运行之前就对系统函数进行Hook,一些网页的反调试就可以直接步过了

Hook简单案例

JS Hook是比较容易实现的,但是对网站的破坏性却比较大
所以有些网站会有JS Hook的检测,最常见的就是比对关键函数前后的JS文本,如果不一致就进入循环debugger

1
2
3
4
function test(x,y){z=x+y;return z;}
setInterval(function(){test+""=="function test(x,y){z=x+y;return z;}" ? console.log("未修改") :setInterval(function(){eval("debugger")},1000);},1000);
test(100,200);
// 这里得到的结果会是 300

将函数与””相加会使得函数调用toString方法,返回函数自身的字符串类型代码,在通过预设的校验代码就能知道函数是否被修改过。

想要过掉这种Hook检测,可以修改函数返回的字符串,就能使得检验通过

1
2
3
4
5
6
7
8
function test(x,y){z=x+y;return z;}
// 注入
function test(x,y){return "Hello world";}
// 修改toString使得转字符串与原来的结果相同,避免被反调试
test.toString=function(){return "function test(x,y){z=x+y;return z;}";};
setInterval(function(){test+""=="function test(x,y){z=x+y;return z;}" ? console.log("未修改") :setInterval(function(){eval("debugger")},1000);},1000);
test(100,200);
// 这里得到的结果会是 Hello world

当然,还有其它的方法可以解决

1
2
3
4
5
6
7
var _setInterval=setInterval;
setInterval=function(a,b){
if(a.toString().indexOf("debugger")!=-1{
return null;
}
_setInterval(a,b);
}

这样做相当于在执行setInterval函数前检查了函数是否有debugger;有就不执行setInterval函数

Hook对象属性

我们要想Hook对象属性,需要用到Object.defineProperties或者Object.defineProperty方法,它可以直接在一个对象上修改原有属性或者定义新的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
var obj = new Object();
Object.defineProperties(obj, {
name: {
value: 'JS Hook',
configurable: false,
},
age: {
value: 18,
}
})
Object.defineProperty(obj, 'name', {
value: 'hello'
})

obj对象定义了name属性和age属性,其中name属性定义了不能修改
在下面尝试去修改name属性的时候,会报错

只要对象生成之后,我们就可以Hook
比如下边的Hook,会在每次设置对象参数的时候debugger(虽然这样做完以后,这个值就不会赋成功了)

1
2
3
4
var obj = new Object();
Object.defineProperty(obj, 'name', {
set:function(x){debugger;return x;}//被赋值后断下来
})

对于内置对象属性的Hook,需要在文档加载之前Hook,这时候就需要用到Chrome拓展插件了。
比如document.cookie中的各种cookies,
要想知道cookies是从哪里生成的,使用Chrome拓展是很方便的,如果要使用断点调试可能比较麻烦一点,我们可以在JS文件头部下断点,在console里边输入如下代码

1
Object.defineProperty(document,"cookie",{set:function(x){console.log(x);return x;}})

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!