前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅谈Javascript中的Hook技术

浅谈Javascript中的Hook技术

作者头像
drunkdream
发布2020-06-07 11:02:03
8.3K0
发布2020-06-07 11:02:03
举报
文章被收录于专栏:醉梦轩

0x00 前言

Hook是一种动态修改函数执行流程或返回结果的方法,在实际应用中非常广泛。Javascript作为一种动态语言,也可以进行Hook操作。随着Javascript语言的发展,Hook的方法也越来越多,本文介绍了常见的几种Hook方法。

0x01 最简单的Hook方法

Javascript中的函数可以直接被覆盖,因此,这也是最简单的一种Hook方法。

代码语言:javascript
复制
window.alert = function(s){
    console.log('Alert: ' + s);
}
代码语言:javascript
复制
> alert('Hello!')
  Alert: Hello!

这种方法简单粗暴,但是只能覆盖具体变量的成员函数。

0x02 Hook类方法

考虑以下这种情况:希望Hook所有元素的setAttribute方法。

方案一:遍历获取所有元素,并Hook每个元素的setAttribute方法。

首先,页面中的元素数量非常多,而且不断有新元素动态创建出来,如果要监控新元素创建,还得Hook document.createElement等函数,甚至还需要考虑通过其它方式动态创建出来的函数。因此,这种方案不是最佳方案。

方案二:直接Hook类方法

代码语言:javascript
复制
Element.prototype.setAttribute = function(attr, value){
    console.log('setAttribute ' + attr + ' ' + value);
}
代码语言:javascript
复制
> document.body.setAttribute('xx', 123)
  setAttribute xx 123

这里利用了原型链来进行类方法的Hook。

0x03 利用Getter/Setter进行Hook

document.domain是一个只读对象,正常是不允许乱修改的。

代码语言:javascript
复制
> document.domain = 'test.com'
  Uncaught DOMException: Failed to set the 'domain' property on 'Document': 'test.com' is not a suffix of 'www.baidu.com'.
    at <anonymous>:1:16

乱修改这个值的话,浏览器会直接报错。

但是下面这段代码却可以将document.domain改成可修改的对象。

代码语言:javascript
复制
Object.defineProperty(document, 'domain', {
    configurable: true,
    enumerable: true,
    get: function() {
        return this._domain || location.host;
    },
    set: function(value) {
        this._domain = value;
    }
});
代码语言:javascript
复制
> document.domain = 'test.com'
  "test.com"
> document.domain
  "test.com"

如果将configurable属性设为falsedocument.domain就可以避免被其他人使用Object.defineProperty来修改了。

代码语言:javascript
复制
> Object.defineProperty(document, 'domain', {value: 'xxx'});
  Uncaught TypeError: Cannot redefine property: domain
    at Function.defineProperty (<anonymous>)
    at <anonymous>:1:8

同样的方法还可以用来修改:navigator.userAgent等属性。

代码语言:javascript
复制
Object.defineProperty(navigator, 'userAgent', {
    configurable: true,
    enumerable: true,
    value: 'MyBrowser 1.0.0'
});
代码语言:javascript
复制
> navigator.userAgent
  "MyBrowser 1.0.0"

不过这种方法只影响使用Javascript获取的数据,不会影响浏览器发送请求时带上的浏览器标识。

事实上,有多很多系统对象都是不允许使用Object.defineProperty修改的,例如:window.location等。

0x04 使用Proxy

Proxy是Chrome 49开始支持的一项新特性,具有拦截函数执行功能,可以用于运算符重载、对象模拟等功能。

代码语言:javascript
复制
window.screen = new Proxy(window.screen, {
    get: function (target, key) {
        console.log('get', key);
        return target[key];
    }});
代码语言:javascript
复制
> screen.availHeight
  get availHeight
  864

这里通过创建screen对象的代理,然后赋值给window.screen,可以实现对属性、函数访问的拦截。这种方法比较适合需要Hook某个对象中大部分属性、函数的场景。

不过,有很多对象是不能被替换的,例如:windowdocumentnavigatorlocation等。

0x05 总结

Javascript是一门非常灵活的语言,并且新的接口和规范不断出现,以后还会出现更多的可以用作Hook的方法。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-06-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x00 前言
  • 0x01 最简单的Hook方法
    • 0x02 Hook类方法
      • 0x03 利用Getter/Setter进行Hook
        • 0x04 使用Proxy
          • 0x05 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档