Chinaunix

标题: Apache Hook 结构分析(二) [打印本页]

作者: ftomorrow    时间: 2009-03-18 17:18
标题: Apache Hook 结构分析(二)
Apache Hook 结构分析(二)
                                          杨学刚
                                          2009-3-18
                                          xuegangyang@eyou.com


一、简介        1
二、Hook array结构分析        2
三、Hook 函数分析        3
3.1 hook函数实现        3
3.2 Run函数实现        4
3.2.1 FIRST处理流程对应的run函数定义        4
3.2.2 ALL处理流程对应的run函数定义        5
3.2.3 VOID处理流程对应的run函数定义        5
3.3 get_hook函数实现        6
四、HOOK宏分析        6
4.1 HOOK_STRUCT宏分析        6
4.2 EXTERNAL_HOOK宏分析        7
4.3 VOID宏分析        7
4.4 RUN_ALL宏分析        8
4.5 RUN_FIRST宏分析        9
4.6 使用宏定义HOOK        10
五、HOOK定义扩展        10
六、小结和思考        11

四、HOOK宏分析
        通过以上分析可以看出apache中HOOK实现需要编写一个Hook array和三个函数,为了简化实现hook的方法和提高代码开发效率,Apache定义了五个HOOK宏来实现HOOK:APR_HOOK_STRUCT、APR_DECLARE_EXTERNAL_HOOK、APR_IMPLEMENT_EXTERNAL_HOOK_VOID、APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL、APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST,为描述方便,以上五个宏按照其名字分别简称为:HOOK_STRUCT、EXTERNAL_HOOK、VOID、RUN_ALL和RUN_FIRST宏
4.1 HOOK_STRUCT宏分析
        APR_HOOK_STRUCT主要用于定义hook对应的_hooks变量,该宏的代码为:
#define APR_HOOK_STRUCT(members) \
static struct { members } _hooks;

但在apache源码中,该宏通常以以下形式使用:
APR_HOOK_STRUCT(
           APR_HOOK_LINK(header_parser)
)

        以上使用涉及到APR_HOOK_LINK宏,其定义非常简单:
#define APR_HOOK_LINK(name) \
apr_array_header_t *link_##name;

结合APR_HOOK_LINK和HOOK_STRUCT宏,便可以定义_hooks 变量。
4.2 EXTERNAL_HOOK宏分析
        EXTERNAL_HOOK宏主要用于声明Hook对应的hook、run和get_hook函数(注意:仅仅是声明而不是实现),声明了hook array中对应的element类型,其源码如下:
/** macro to declare the hook correctly */   
#define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
typedef ret ns##_HOOK_##name##_t args; \
link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
                                      const char * const *aszPre, \
                                      const char * const *aszSucc, int nOrder); \
link##_DECLARE(ret) ns##_run_##name args; \
APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \
typedef struct ns##_LINK_##name##_t \
    { \
    ns##_HOOK_##name##_t *pFunc; \
    const char *szName; \
    const char * const *aszPredecessors; \
    const char * const *aszSuccessors; \
    int nOrder; \
} ns##_LINK_##name##_t;


从以上源码中可以看到涉及APR_IMPLEMENT_HOOK_GET_PROTO宏,其功能是用于声明HOOK的get_hook函数,其源码如下:
/** macro to return the prototype of the hook function */   
#define APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \
link##_DECLARE(apr_array_header_t *) ns##_hook_get_##name(void)

4.3 VOID宏分析
        VOID 宏主要用于实现处理流程为VOID时的run函数,其源码如下:
#define APR_IMPLEMENT_EXTERNAL_HOOK_VOID(ns,link,name,args_decl,args_use) \
APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
link##_DECLARE(void) ns##_run_##name args_decl \
    { \
    ns##_LINK_##name##_t *pHook; \
    int n; \
\
    if(!_hooks.link_##name) \
    return; \
\
    pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \
&nbsp;&nbsp;&nbsp;&nbsp;for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \
&nbsp;&nbsp;&nbsp;&nbsp;pHook[n].pFunc args_use; \
}

源码中用到了APR_IMPLEMENT_EXTERNAL_HOOK_BASE宏,该宏用于实现HOOK对应的hook和get_hook函数,其源码如下:
#define APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf,const char * const *aszPre, \
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const char * const *aszSucc,int nOrder) \
&nbsp;&nbsp;&nbsp;&nbsp;{ \
&nbsp;&nbsp;&nbsp;&nbsp;ns##_LINK_##name##_t *pHook; \
&nbsp;&nbsp;&nbsp;&nbsp;if(!_hooks.link_##name) \
&nbsp;&nbsp;&nbsp;&nbsp;{ \
&nbsp;&nbsp;&nbsp;&nbsp;_hooks.link_##name=apr_array_make(apr_hook_global_pool,1,sizeof(ns##_LINK_##name##_t)); \
&nbsp;&nbsp;&nbsp;&nbsp;apr_hook_sort_register(#name,&_hooks.link_##name); \
&nbsp;&nbsp;&nbsp;&nbsp;} \
&nbsp;&nbsp;&nbsp;&nbsp;pHook=apr_array_push(_hooks.link_##name); \
&nbsp;&nbsp;&nbsp;&nbsp;pHook->pFunc=pf; \
&nbsp;&nbsp;&nbsp;&nbsp;pHook->aszPredecessors=aszPre; \
&nbsp;&nbsp;&nbsp;&nbsp;pHook->aszSuccessors=aszSucc; \
&nbsp;&nbsp;&nbsp;&nbsp;pHook->nOrder=nOrder; \
&nbsp;&nbsp;&nbsp;&nbsp;pHook->szName=apr_hook_debug_current; \
&nbsp;&nbsp;&nbsp;&nbsp;if(apr_hook_debug_enabled) \
&nbsp;&nbsp;&nbsp;&nbsp;apr_hook_debug_show(#name,aszPre,aszSucc); \
&nbsp;&nbsp;&nbsp;&nbsp;} \
&nbsp;&nbsp;&nbsp;&nbsp;APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \
&nbsp;&nbsp;&nbsp;&nbsp;{ \
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return _hooks.link_##name; \
}





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2