免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1812 | 回复: 1
打印 上一主题 下一主题

[Web] Apache Hook 结构分析(三) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-18 17:19 |只看该作者 |倒序浏览
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

4.4 RUN_ALL宏分析
RUN_ALL宏用于实现处理流程为ALL时的run函数,其源码如下:
#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ns,link,ret,name,args_decl,args_use,ok,decline) \
APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
link##_DECLARE(ret) ns##_run_##name args_decl \
    { \
    ns##_LINK_##name##_t *pHook; \
    int n; \
    ret rv; \
\
    if(!_hooks.link_##name) \
    return ok; \
\
    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;{ \
&nbsp;&nbsp;&nbsp;&nbsp;rv=pHook[n].pFunc args_use; \
\
&nbsp;&nbsp;&nbsp;&nbsp;if(rv != ok && rv != decline) \
&nbsp;&nbsp;&nbsp;&nbsp;    return rv; \
&nbsp;&nbsp;&nbsp;&nbsp;} \
&nbsp;&nbsp;&nbsp;&nbsp;return ok; \
&nbsp;&nbsp;&nbsp;&nbsp;}

        以上用到的APR_IMPLEMENT_EXTERNAL_HOOK_BASE宏和在VOID中用到一样功能。
4.5 RUN_FIRST宏分析
RUN_ALL宏用于实现处理流程为FIRST时的run函数,其源码如下:
#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ns,link,ret,name,args_decl,args_use,decline) \
APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
link##_DECLARE(ret) ns##_run_##name args_decl \
&nbsp;&nbsp;&nbsp;&nbsp;{ \
&nbsp;&nbsp;&nbsp;&nbsp;ns##_LINK_##name##_t *pHook; \
&nbsp;&nbsp;&nbsp;&nbsp;int n; \
&nbsp;&nbsp;&nbsp;&nbsp;ret rv; \
\
&nbsp;&nbsp;&nbsp;&nbsp;if(!_hooks.link_##name) \
&nbsp;&nbsp;&nbsp;&nbsp;return decline; \
\
&nbsp;&nbsp;&nbsp;&nbsp;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;{ \
&nbsp;&nbsp;&nbsp;&nbsp;rv=pHook[n].pFunc args_use; \
\
&nbsp;&nbsp;&nbsp;&nbsp;if(rv != decline) \
&nbsp;&nbsp;&nbsp;&nbsp;    return rv; \
&nbsp;&nbsp;&nbsp;&nbsp;} \
&nbsp;&nbsp;&nbsp;&nbsp;return decline; \
&nbsp;&nbsp;&nbsp;&nbsp;}

以上用到的APR_IMPLEMENT_EXTERNAL_HOOK_BASE宏和在VOID中用到一样功能。
4.6 使用宏定义HOOK
        经过以上分析的以后,如果要实现HOOK将会变得比较简单,只需按照顺序依次调用三个宏即可完成HOOK的定义,与上文相同,假设要实现example HOOK,其定义源码如下:
APR_HOOK_STRUCT(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;APR_HOOK_LINK(example)
)

APR_DECLARE_EXTERNAL_HOOK(ap,AP,int,example,(apr_pool_t *pconf,apr_pool_t *plog,
&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;apr_pool_t *ptemp,server_rec *s))
// 假设对应的处理方式为 ALL

APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap,AP,int, example,
&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;(apr_pool_t *pconf, apr_pool_t *plog,
&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;apr_pool_t *ptemp, server_rec *s),
&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;(pconf, plog, ptemp, s), OK, DECLINED)


五、HOOK定义扩展
        在以上分析中说过每一个HOOK都对应一个_hooks变量,如果在同一个编译单元里我们两次使用HOOK_STRUCT宏定义example1和example2 HOOK,岂不是会存在两个_hooks变量,这将导致编译错误,如果在同一编译单元中需要定义两个HOOK,就需要用到HOOK的扩展定义方式。假如要定义example1和example2 HOOK,可以按照以下方式进行定义:
APR_HOOK_STRUCT(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;APR_HOOK_LINK(example1)
APR_HOOK_LINK(example2)
)

以上宏定义展开后的源码如下:
static struct {
apr_array_header_t * link_example1;
apr_array_header_t * link_example2;
} _hooks;

如此就在一个_hooks变量中定义了两个HOOK array,其中一个用于example1 HOOK,另外一个用于example2,之后需要使用两次
APR_DECLARE_EXTERNAL_HOOK宏来分别定义example1和example的hook函数和element类型,同样也需要使用两次APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL宏来定义run函数,其源码如下:
APR_DECLARE_EXTERNAL_HOOK(ap,AP,int,example1,(apr_pool_t *pconf,apr_pool_t *plog,
&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;apr_pool_t *ptemp,server_rec *s))
// 假设对应的处理方式为 ALL

APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap,AP,int, example2,
&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;(apr_pool_t *pconf, apr_pool_t *plog,
&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;apr_pool_t *ptemp, server_rec *s),
&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;(pconf, plog, ptemp, s), OK, DECLINED)
APR_DECLARE_EXTERNAL_HOOK(ap,AP,int,example2,(apr_pool_t *pconf,apr_pool_t *plog,
&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;apr_pool_t *ptemp,server_rec *s))
// 假设对应的处理方式为 ALL

APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap,AP,int, example2,
&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;(apr_pool_t *pconf, apr_pool_t *plog,
&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;apr_pool_t *ptemp, server_rec *s),
&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;(pconf, plog, ptemp, s), OK, DECLINED)

至此便解决了同一编译单元定义多个HOOK的问题,笔者称此方法为HOOK扩展(也许不恰当,但没有想到更好方法)。虽然如此,疑惑也随之而来,这样定义的HOOK是一个HOOK还是两个HOOK?我想暂且称之为HOOK组吧,虽然他们由同一个HOOK_STRUCT定义,并且通过同一个_hooks 变量管理。
六、小结和思考
        Apache HOOK目的是为了能让用户开发的模块注入到apache处理流程中,其核心在于函数指针的应用,笔者也接触过C++中的多态开发,通过使用多态可以避免函数指针的使用,而且可以使系统结构更加简单,但我想可能是C++多态开销太高,开发人员没有采用吧。
以前只学过C++,没有太多接触过C 语言,虽然二者相通,可在看源代码中发现,二者对程序的组织以及语言的应用完全不一样,apache中的HOOK 宏就耗去了我一个周的时间,而且在VC中宏是没有办法debug调试执行的,只好手工把宏进行替换,之后用自己替换后的函数进行debug才弄懂程序执行流程,不经感慨要是有一个宏替换的小软件该多好啊!
我研究生导师有一句诗:“才别夕阳又见朝阳”,感觉刚刚开了电脑写文档,倏忽已是日别西山,手中方才调整好本文格式,不经感慨古人写书之艰辛与执着,批阅十载,增删五次,方成红楼,而我辈电脑词霸一应俱全,google搜索时刻相随,却提笔踌躇,不知所书。虽如此,我辈阅大牛之源码,亦应有所得,有所得便应有所录,有所录方能河海不择细流 故能就其深。

论坛徽章:
0
2 [报告]
发表于 2009-03-27 16:01 |只看该作者
好文 顶 清晰 清晰
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP