Apache Hook 結構分析(三)

←手機掃碼閱讀     火星人 @ 2014-03-04 , reply:0

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

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搜索時刻相隨,卻提筆躊躇,不知所書。雖如此,我輩閱大牛之源碼,亦應有所得,有所得便應有所錄,有所錄方能河海不擇細流 故能就其深。
《解決方案》

好文 頂 清晰 清晰




[火星人 ] Apache Hook 結構分析(三)已經有457次圍觀

http://coctec.com/docs/service/show-post-23631.html