[hook.js]通用Javascript函数钩子

来源:互联网 发布:搜索引擎优化 名词解释 编辑:程序博客网 时间:2024/06/04 19:40

最近看Dom Xss检测相关的Paper,涉及到Hook Javascript函数,网上翻了一下,貌似没有什么通用的函数钩子脚本,自己用就自己写一个吧。最后有代码地址,前面写下mind storm的过程。
最经典且简单的Javascript函数钩子的写法应该是下面这样了:

var _alert = alert;window.alert = function(s) {       console.log("Hooked!");        _alert(s);}

不过这种Hook方式跟闹着玩儿似的,用到实际生产上通用性不好,效率也不高。

国内比较早看到的介绍Javascript函数劫持的文章应该是安全焦点上luoluo写的《浅谈javascript函数劫持》,用Javascript函数钩子实现了一个简单的内联代码调试器。后来看到了大风在08年搞了一个anehta的攻击平台,其中有一段能够hook任意Javascript函数的代码,看了下感觉有一些问题。这里贴出部分代码,有兴趣可以到这里看完整版:

 hook: function(funcNameHooked, RealFuncAfterHooked, hookFunc){                try {                  setTimeout(function(){                           //alert("hook before: "+window[funcNameHooked]);                          // 保存原函数                          window[RealFuncAfterHooked] = window[funcNameHooked];                          //window[funcNameHooked] = window[hookFunc];                          // 参数个数可以根据需要进行调整                          window[funcNameHooked] = function (param1,param2,param3,param4,param5,param6,param7){                                // 劫持参数                                var newParam = new Array();                                  // 先执行注入的函数; 需要返回被劫持后的参数,作为新参数传入原函数                                  newParam = window[hookFunc](param1,param2, param3, param4, param5, param6, param7)                                   //alert("newParam= "+newParam);                                  // 再执行原函数                                  window[RealFuncAfterHooked](newParam[0], newParam[1], newParam[2], newParam[3],                                                               newParam[4], newParam[5], newParam[6]);                                                  // 不注入参数,直接执行原函数;                                                              //window[RealFuncAfterHooked](param1,param2,param3,param4,param5,param6,param7);                                    }                          //alert("hook after: "+window[funcNameHooked]);                          },                       10);                    return true;                  } catch (e){                          return false;                  }          },

这段代码固定了被Hook的函数所在对象是window,这样对于自定义对象中的函数及原型对象中的函数(String.prototype)就没办法进行Hook了。而且参数param[1-7]是写死在函数里的,通用性不太好,其实可以用arguments对象来实现变参。 
因为要做的是函数钩子,函数又都是Function对象的实例,那么直接给Function.prototype添加hook和unhook函数就可以了。
按照这个思路自己写了一个小脚本,简单封装了一下,能够对普通的全局函数(eg:alert),自定义类中的函数(eg:cat.Eat()),以及原型对象中的函数(eg:String.prototype.slice)进行hook。可以防止函数被二次hook而导致的callback in callback。代码不长这里就贴出来了,也可以到github上去看,有测试样例和参数说明。

function Hooks(){return {initEnv:function () {Function.prototype.hook = function (realFunc,hookFunc,context,funcName) {var _context = null; //函数上下文var _funcName = null; //函数名_context = context || window;_funcName = funcName || getFuncName(this);_context[realFunc] = this;if(_context[_funcName].prototype && _context[_funcName].prototype.isHooked){console.log("Already has been hooked,unhook first");return false;}function getFuncName (fn) {// 获取函数名var strFunc = fn.toString();var _regex = /function\s+(\w+)\s*\(/;var patten = strFunc.match(_regex);if (patten) {return patten[1];};return '';}try{eval('_context[_funcName] = function '+_funcName+'(){\n'+'var args = Array.prototype.slice.call(arguments,0);\n'+'var obj = this;\n'+'hookFunc.apply(obj,args)\n'+'return _context[realFunc].apply(obj,args);\n'+'};');_context[_funcName].prototype.isHooked = true;return true;}catch (e){console.log("Hook failed,check the params.");return false;}}Function.prototype.unhook = function (realFunc,funcName,context) {var _context = null;var _funcName = null;_context = context || window;_funcName = funcName;if (!_context[_funcName].prototype.isHooked){console.log("No function is hooked on");return false;}_context[_funcName] = _context[realFunc];delete _context[realFunc];return true;}},cleanEnv:function () {if(Function.prototype.hasOwnProperty("hook")){delete Function.prototype.hook;}if(Function.prototype.hasOwnProperty("unhook")){delete Function.prototype.unhook;}return true;}};}

hook.js

A hooks to any Javascript function.

Notice

[bool]hook:params{    realFunc[String|must]:用于保存原始函数的函数名称,用于unHook;    hookFunc[Function|must]:替换的hook函数;    context[Object|opt]:目标函数所在对象,用于hook非window对象下的函数,如String.protype.slice,carInstance1    methodName[String|opt]:匿名函数需显式传入目标函数名eg:this.Begin = function(){....};}[bool]unhook:params{    realFunc[String|must]:用于保存原始函数的函数名称,用于unHook;    funcName[String|must]:被Hook的函数名称    context[Object|opt]:目标函数所在对象,用于hook非window对象下的函数,如String.protype.slice,carInstance1}

0 0
原创粉丝点击