• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            統(tǒng)計(jì)

            • 隨筆 - 50
            • 文章 - 42
            • 評(píng)論 - 147
            • 引用 - 0

            留言簿(6)

            隨筆分類

            文章分類

            Link

            搜索

            •  

            積分與排名

            • 積分 - 166406
            • 排名 - 159

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            API Hook基本原理和實(shí)現(xiàn)[圖文]
            hook是什么?
                windows系統(tǒng)下的編程,消息message的傳遞是貫穿其始終的。這個(gè)消息我們可以簡(jiǎn)單理解為一個(gè)有特定意義的整數(shù),正如我們看過(guò)的老故事片中的“長(zhǎng)江長(zhǎng)江,我是黃河”一個(gè)含義。windows中定義的消息給初學(xué)者的印象似乎是“不計(jì)其數(shù)”的,常見(jiàn)的一部分消息在winuser.h頭文件中定義。hook與消息有著非常密切的聯(lián)系,它的中文含義是“鉤子”,這樣理解起來(lái)我們不難得出“hook是消息處理中的一個(gè)環(huán)節(jié),用于監(jiān)控消息在系統(tǒng)中的傳遞,并在這些消息到達(dá)最終的消息處理過(guò)程前,處 理某些特定的消息”。這也是hook分為不同種類的原因。
                hook的這個(gè)本領(lǐng),使它能夠?qū)⒆陨淼拇a“融入”被hook住的程序的進(jìn)程中,成為目標(biāo)進(jìn)程的一個(gè)部分。我們也知道,在windows2000以后的系統(tǒng)中,普通用戶程序的進(jìn)程空間都是獨(dú)立的,程序的運(yùn)行彼此間都不受干擾。這就使我們希望通過(guò)一個(gè)程序改變其他程序的某些行為的想法不能直接實(shí)現(xiàn),但是hook的出現(xiàn)給我們開(kāi)拓了解決此類問(wèn)題的道路。

            api hook是什么?
                在windows系統(tǒng)下編程,應(yīng)該會(huì)接觸到api函數(shù)的使用,常用的api函數(shù)大概有2000個(gè)左右。今天隨著控件,stl等高效編程技術(shù)的出現(xiàn),api的使用概率在普通的用戶程序上就變得越來(lái)越小了。當(dāng)諸如控件這些現(xiàn)成的手段不能實(shí)現(xiàn)的功能時(shí),我們還需要借助api。最初有些人對(duì)某些api函數(shù)的功能不太滿意,就產(chǎn)生了如何修改這些api,使之更好的服務(wù)于程序的想法,這樣api hook就自然而然的出現(xiàn)了。我們可以通過(guò)api hook,改變一個(gè)系統(tǒng)api的原有功能。基本的方法就是通過(guò)hook“接觸”到需要修改的api函數(shù)入口點(diǎn),改變它的地址指向新的自定義的函數(shù)。api hook并不屬于msdn上介紹的13類hook中的任何一種。所以說(shuō),api hook并不是什么特別不同的hook,它也需要通過(guò)基本的hook提高自己的權(quán)限,跨越不同進(jìn)程間訪問(wèn)的限制,達(dá)到修改api函數(shù)地址的目的。對(duì)于自身進(jìn)程空間下使用到的api函數(shù)地址的修改,是不需要用到api hook技術(shù)就可以實(shí)現(xiàn)的。

            api hook和pe格式的關(guān)系
            api hook技術(shù)的難點(diǎn),并不在于hook技術(shù),初學(xué)者借助于資料“照葫蘆畫(huà)瓢”能夠很容易就掌握hook的基本使用技術(shù)。但是如何修改api函數(shù)的入口地址?這就需要學(xué)習(xí)pe可執(zhí)行文件(.exe,.dll等)如何被系統(tǒng)映射到進(jìn)程空間中,這就需要學(xué)習(xí)pe格式的基本知識(shí)。windows已經(jīng)提供了很多數(shù)據(jù)結(jié)構(gòu)struct幫助我們?cè)L問(wèn)pe格式,借助它們,我們就不要自己計(jì)算格式的具體字節(jié)位置這些繁瑣的細(xì)節(jié)。但是從api hook的實(shí)現(xiàn)來(lái)看,pe格式的訪問(wèn)部分仍然是整個(gè)編程實(shí)現(xiàn)中最復(fù)雜的一部分,對(duì)于經(jīng)常crack的朋友不在此列。
            假設(shè)我們已經(jīng)了解了pe格式,那么我們?cè)谀睦镄薷腶pi的函數(shù)入口點(diǎn)比較合適呢?這個(gè)就是輸入符號(hào)表imported symbols table(間接)指向的輸入符號(hào)地址。
               下面對(duì)于pe格式的介紹這一部分,對(duì)于沒(méi)有接觸過(guò)pe格式學(xué)習(xí)的朋友應(yīng)該是看不太明白的,但我已經(jīng)把精華部分提取出來(lái)了,學(xué)習(xí)了pe格式后再看這些就很容易了。

            pe格式的基本組成
            +-------------------+
                | DOS-stub          |    --DOS-頭
                +-------------------+
                | file-header       |    --文件頭
                +-------------------+
                | optional header   |    --可選頭
                |- - - - - - - - - -|
                |                   |
                | data directories |    --(可選頭尾的)數(shù)據(jù)目錄
                |                   |
                +-------------------+
                |                   |
                | section headers   |     --節(jié)頭
                |                   |
                +-------------------+
                |                   |
                | section 1        |     --節(jié)1
                |                   |
                +-------------------+
                |                   |
                | section 2        |     --節(jié)2
                |                   |
                +-------------------+
                |                   |
                | ...               |
                |                   |
                +-------------------+
                |                   |
                | section n        |     --節(jié)n
                |                   |
                +-------------------+
                在上圖中,我們需要從“可選頭”尾的“數(shù)據(jù)目錄”數(shù)組中的第二個(gè)元素——輸入符號(hào)表的位置,它是一個(gè)IMAGE_DATA_DIRECTORY結(jié)構(gòu),從它中的VirtualAddress地址,“順藤摸瓜”找到api函數(shù)的入口地點(diǎn)。
                下圖的簡(jiǎn)單說(shuō)明如下:
            OriginalFirstThunk 指向IMAGE_THUNK_DATA結(jié)構(gòu)數(shù)組,為方便只畫(huà)了數(shù)組的一個(gè)元素,AddressOfData 指向IMAGE_IMPORT_BY_NAME結(jié)構(gòu)。
            IMAGE_IMPORT_DESCRIPTOR數(shù)組:每個(gè)引入的dll文件都對(duì)應(yīng)數(shù)組中的一個(gè)元素,以全0的元素(20個(gè)bytes的0)表示數(shù)組的結(jié)束
            IMAGE_THUNK_DATA32數(shù)組:同一組的以全0的元素(4個(gè)bytes的0)表示數(shù)組的結(jié)束,每個(gè)元素對(duì)應(yīng)一個(gè)IMAGE_IMPORT_BY_NAME結(jié)構(gòu)
            IMAGE_IMPORT_BY_NAME:如..@Consts@initialization$qqrv. 表示
            Unmangled Borland C++ Function: qualified function __fastcall Consts::initialization()

                為了減少這個(gè)圖的大小,不得已將匯編和c++的結(jié)構(gòu)都用上了。這個(gè)圖是輸入符號(hào)表初始化的情形,此時(shí)兩個(gè)IMAGE_THUNK_DATA結(jié)構(gòu)數(shù)組的對(duì)應(yīng)元素都指向同一個(gè)IMAGE_IMPORT_BY_NAME結(jié)構(gòu)。
                程序加載到進(jìn)程空間后,兩個(gè)IMAGE_THUNK_DATA結(jié)構(gòu)數(shù)組指向有所不同了??聪聢D:


            // 本文轉(zhuǎn)自 C++Builder研究 - http://www.ccrun.com/article.asp?i=1036&d=cf6de2
            始化的,“兩個(gè)結(jié)構(gòu)都指向同一個(gè)IMAGE_IMPORT_BY_NAME”,此時(shí)還沒(méi)有api函數(shù)地址


            當(dāng)PE文件準(zhǔn)備執(zhí)行時(shí),前圖已轉(zhuǎn)換成上圖。一個(gè)結(jié)構(gòu)指向不變,另一個(gè)出現(xiàn)api函數(shù)地址

                如果PE文件從kernel32.dll中引入10個(gè)函數(shù),那么IMAGE_IMPORT_DESCRIPTOR 結(jié)構(gòu)的 Name1域包含指向字符串"kernel32.dll"的RVA,同時(shí)每個(gè)IMAGE_THUNK_DATA 數(shù)組有10個(gè)元素。(RVA是指相對(duì)地址,每一個(gè)可執(zhí)行文件在加載到內(nèi)存空間前,都以一個(gè)基址作為起點(diǎn),其他地址以基址為準(zhǔn),均以相對(duì)地址表示。這樣系統(tǒng)加載程序到不同的內(nèi)存空間時(shí),都可以方便的算出地址)
                上述這些結(jié)構(gòu)可以在winnt.h頭文件里查到。

            具體編程實(shí)現(xiàn)
                我將手上的vc示例代碼進(jìn)行了適當(dāng)修正,修改了一些資源泄漏的小問(wèn)題,移植到c++builder6 & update4上,經(jīng)過(guò)測(cè)試已經(jīng)可以完成基本的api hook功能。有幾個(gè)知識(shí)點(diǎn)說(shuō)明一下:
            1、    dll中共享內(nèi)存變量的實(shí)現(xiàn)
            正常編譯下的dll,它的變量使用到的內(nèi)存是獨(dú)立的。比如你同時(shí)運(yùn)行兩個(gè)調(diào)用了某個(gè)dll的用戶程序,試圖對(duì)某一個(gè)在dll中定義的全局變量修改賦值的時(shí)候,兩個(gè)程序里的變量值仍然是不同的。
            共享的方法為:在.cpp文件(.h文件里如此設(shè)置會(huì)提示編譯錯(cuò)誤)的頭部寫(xiě)上如上兩行:
            #pragma option -zRSHSEG           // 改變?nèi)笔?shù)據(jù)段名
            #pragma option -zTSHCLASS        // 改變?nèi)笔?shù)據(jù)類名

            HINSTANCE hdll = NULL;                  // 用來(lái)保存該動(dòng)態(tài)連接庫(kù)的句柄
            HHOOK hApiHook = NULL;                  // 鉤子句柄
            HHOOK hWndProc = NULL;                  // 窗口過(guò)程鉤子用來(lái)攔截SendMessage
            int threadId = 0;

                另外建立一個(gè)與dll同名,不同后綴的def文件,如HookDll.def文件,寫(xiě)上:
            LIBRARY HookDll.dll
            EXPORTS
            ;...
            SEGMENTS
                SHSEG CLASS 'SHCLASS' SHARED
            ;end

                這樣設(shè)置后在.cpp文件中定義的變量,如果進(jìn)行了初始化,將進(jìn)入“SHCLASS”共享內(nèi)存段(如果不初始化,將不改變其默認(rèn)段屬性)。

                上述的共享對(duì)于本示例代碼并不是必須的,只是稍微演示了一下。

            2、    api hook修改api函數(shù)入口點(diǎn)地址的時(shí)機(jī)
                很顯然,我們必須通過(guò)hook進(jìn)入目標(biāo)進(jìn)程的地址空間后,再在位于該地址空間里的hook消息處理過(guò)程里修改輸入符號(hào)表“指向”的api函數(shù)入口點(diǎn)地址,退出hook前也必須在這個(gè)消息處理過(guò)程里恢復(fù)原來(lái)的地址。只要我們牢記修改的過(guò)程發(fā)生在目標(biāo)進(jìn)程的地址空間中,就不會(huì)發(fā)生訪問(wèn)違例的錯(cuò)誤了。
                示例代碼使用了WH_GETMESSAGE、WH_CALLWNDPROC兩中hook來(lái)演示如何hook api,但WH_GETMESSAGE實(shí)際上并沒(méi)有完成具體的功能。
                為了讓初學(xué)者盡快的掌握重點(diǎn),我將代碼進(jìn)行了簡(jiǎn)化,是一個(gè)不健壯、不靈活的演示示例。

            3、    函數(shù)的內(nèi)外部表現(xiàn)形式
                例如api函數(shù)MessageBox,這個(gè)形式是我們通常用到的,但到了dll里,它的名字很可能出現(xiàn)了兩個(gè)形式,一個(gè)是MessageBoxA,另一個(gè)是MessageBoxW,這是因?yàn)橄到y(tǒng)需要適應(yīng)Ansi和Unicode編碼的兩種形式,我們不在函數(shù)尾端添加“A”或“W”,是不能hook到需要的函數(shù)的。

            4、    輔助pe格式查看工具
                PE Explorer是一個(gè)非常好的查看pe資源的工具,通過(guò)它可以驗(yàn)證自己手工計(jì)算的pe地址,可以更快的掌握pe格式。
                調(diào)試器ollydbg也是非常好的輔助工具,例如查看輸入符號(hào)表中的api函數(shù)。

            5、    程序文件列表
            dll基本文件:Hook.h,Hook.cpp,HookDll.def
            client驗(yàn)證方基本文件:HookTest.h,HookTest.cpp,ApiHookTest.cpp
               


            6、    實(shí)現(xiàn)的功能
                對(duì)記事本的MessageBoxW函數(shù)進(jìn)行了hook,先執(zhí)行自定義的
            int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR M1, LPCWSTR M2, UINT M3)
            {
                return oldMessageBoxW(hWnd, M1, L"my api hook", M3);
            }
                從這里可以看到,由于目標(biāo)進(jìn)程空間中的執(zhí)行線程并不知道你已經(jīng)改變了api函數(shù)的實(shí)際入口地址,它在調(diào)用時(shí)仍舊將參數(shù)一成不變的壓入堆棧(這個(gè)說(shuō)法是匯編代碼時(shí)看到的等價(jià)情形),事實(shí)上你已經(jīng)提前接收到了函數(shù)調(diào)用的所有參數(shù)。這里就是篇首帖子的回復(fù)了。

               
            hook之前

               
            hook以后

            示例代碼
            1、client驗(yàn)證方的代碼非常簡(jiǎn)單。建立一個(gè)Application工程,在窗體上放一個(gè)memo(提示信息),兩個(gè)button(一個(gè)SetHook,另一個(gè)RemoveHook)。
            void __fastcall TForm1::Button1Click(TObject *Sender)
            {
                DWORD dwProcessId, dwThreadID;

                HWND hWnd = FindWindow("Notepad", NULL);
                if (!hWnd)
                {
                    Memo1->Lines->Add("Nodepad is not found");
                }
                else
                {
                    dwThreadID = GetWindowThreadProcessId(hWnd, &dwProcessId);
                    Memo1->Lines->Add(dwThreadID);
                    SetHook(dwThreadID);
                }
            }
            //---------------------------------------------------------------------------
            void __fastcall TForm1::Button2Click(TObject *Sender)
            {
                RemoveHook();
            }
            //---------------------------------------------------------------------------

            2、api hook dll稍微復(fù)雜些,建立一個(gè)dll工程之后,修改之。代碼中有一些函數(shù)并未用上,ReplaceApiAddress是核心函數(shù),完整代碼提供下載:
            ApiHook.rar

            參考文獻(xiàn)
            1、《iczelion匯編程序設(shè)計(jì)教程》pe專題部分
            2、《WINDOWS核心編程》第22章
            3、《PE文件格式 1.9版》漢譯版,原著B(niǎo). Luevelsmeyer
            4、《跨進(jìn)程API Hook》,出自http://blog.csdn.net/detrox/archive/2004/01/29/17511.aspx,作者detrox
            5、《DLL木馬注入程序》,出自http://www.mydown.com/code/245/245731.html
            6、另有兩vc6下的源代碼包,APIHOOK與pw,因時(shí)間久遠(yuǎn),出處不明。在此對(duì)原作者的辛勤工作表示真摯的謝意。

            posted on 2009-08-14 18:28 pear_li 閱讀(819) 評(píng)論(0)  編輯 收藏 引用 所屬分類: windows kernel

            99热精品久久只有精品| 国产精品九九久久精品女同亚洲欧美日韩综合区| 国产精品激情综合久久| 久久久久久无码国产精品中文字幕| 很黄很污的网站久久mimi色 | 中文字幕久久精品无码| 久久人人爽人人爽人人片av高请 | 国产偷久久久精品专区| 精品综合久久久久久97超人| 日韩久久久久中文字幕人妻 | 97久久国产亚洲精品超碰热| 国产精品日韩深夜福利久久| 久久香综合精品久久伊人| 久久久精品日本一区二区三区 | 国产成人精品综合久久久| 久久精品国产亚洲AV影院| 精品久久久无码中文字幕| 精品一区二区久久| 婷婷伊人久久大香线蕉AV | 99久久99这里只有免费费精品| 久久婷婷五月综合色99啪ak| jizzjizz国产精品久久| 久久久亚洲裙底偷窥综合| 久久性生大片免费观看性| 久久久久亚洲AV无码网站| 99久久国产宗和精品1上映| 色综合久久天天综线观看| 国产福利电影一区二区三区,免费久久久久久久精 | 久久久久人妻精品一区| 伊人久久大香线焦AV综合影院| 无码精品久久一区二区三区| 91超碰碰碰碰久久久久久综合| 狠狠色丁香婷婷久久综合不卡| 91精品国产乱码久久久久久| 日韩乱码人妻无码中文字幕久久 | 99久久精品毛片免费播放| 亚洲国产精品无码久久久不卡| 久久久久久精品免费免费自慰| 一级做a爰片久久毛片看看| 色综合久久夜色精品国产| 亚洲va久久久久|