• <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>
            posts - 94, comments - 250, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            探索NDIS HOOK新的實現方法(1)

            Posted on 2008-08-30 23:42 Condor 閱讀(1674) 評論(0)  編輯 收藏 引用

            NDIS HOOK是專業級防火墻使用的一種攔截技術,NDIS HOOK的重點是如何獲得特定協議對應NDIS_PROTOCOL_BLOCK指針,獲得了該指針,接下來就可以替換該協議所注冊的收發函數,而達到攔截網絡數據的目的。
                 獲 得NDIS_PROTOCOL_BLOCK指針的方法一般是用NdisRegisterProtocol注冊一個新的協議,所獲得的協議句柄實際上就是一 個NDIS_PROTOCOL_BLOCK指針,順著該指針遍歷NDIS_PROTOCOL_BLOCK鏈表,就可以找到你所要掛鉤的協議所對應的 NDIS_PROTOCOL_BLOCK.之所以可以這樣做,是因為每注冊一個協議,系統都會把該協議對應的NDIS_PROTOCOL_BLOCK放置 在協議鏈表的開頭,該協議鏈表每個元素都是NDIS_PROTOCOL_BLOCK類型,代表一個已經注冊的協議。
                 事 實上我們需要的只是TCPIP協議族的NDIS_PROTOCOL_BLOCK指針,畢竟TCP,IP,ARP,ICMP等等幾乎所有我們感興趣的協議, 都是在tcpip.sys協議驅動里面實現的。如果我們只需要TCPIP協議所對應的NDIS_PROTOCOL_BLOCK,那么上面的方法就有點繁瑣 了。我們可以試著尋找更簡便的方法來獲得TCPIP協議的NDIS_PROTOCOL_BLOCK.
            于 是我對tcpip.sys驅動進行了反匯編,發現NDIS_PROTOCOL_BLOCK指針存放在一個名為_ARPHandle的全局變量里面,所以如 果能找到_ARPHandle的地址,我們就成功了,我們完全可以把該全局變量的偏移量作為一個常量來使用,但這里純粹為了拓寬思路,我介紹另一種找到該 全局變量的方法。
                 Tcpip.sys有個導出函數叫IPDelayedNdisReEnumerateBindings,該函數內部曾經出現過_ARPHandle 的地址,為什么會出現它的地址呢,因為該函數內部調用過NdisReEnumerateProtocolBindings函數,懂得反匯編的應該知道,在 用call指令調用函數之前,必然會用到push指令將函數的參數壓到棧里面去,不巧的是, NdisReEnumerateProtocolBindings函數只有一個參數,而該參數恰恰是一個NDIS_PROTOCOL_BLOCK指針類 型,在這里,實際上就是把_ARPHandle當作參數傳給了
            NdisReEnumerateProtocolBindings,所以_ARPHandle的地址必然會出現在push指令的后面,說具體一點,緊跟push指令的四個字節就是_ARPHandle的地址。
                  所以具體的思路就是這樣,先找到IPDelayedNdisReEnumerateBindings函數的地址,然后從該函數的地址開始搜索push指令的特征碼,搜到了以后,把緊跟push指令的四個字節作為指向NDIS_PROTOCOL_BLOCK指針的指針返回。
                 也許有的人會問,如果IPDelayedNdisReEnumerateBindings函數體內部出現過多次push指令,豈不是會搜出不正確的地址,事實上,雖然都叫push指令,然而在機器碼級別是不同的,push指令的機器碼表示有十幾種之多,用來區別不同的尋址方式,調用NdisReEnumerateProtocolBindings 時用的push指令字節序列是0xff35,這個push指令表示后面緊跟的四個字節是一個內存地址,而不是一個立即數或者寄存器之類的。知道了這些,我 們就可以清楚,在一個有限的地址范圍,0xff35的唯一性是可以得到滿足的。根據我的觀察,在win2000,winxp,win2003上面,IPDelayedNdisReEnumerateBindings本身是一個很短的函數,0xff35指令確實只出現過一次,所以該方法是很可靠的。
            思路已經出來了,下面我把詳細的代碼給大家貼出來,理解這些代碼需要對windows Pe格式有所了解,如果你不想理解也行,代碼可以直接拿來用。
                   以下是我寫的一個 獲取內核模塊某個導出函數地址的 通用例程。這里主要是為了獲取tcpip.sys模塊的導出函數IPDelayedNdisReEnumerateBindings
               void* GetRoutineAddress(char* ModuleName,char* RoutineName)
            {
                   PIMAGE_DOS_HEADER dos_hdr;
                PIMAGE_NT_HEADERS nt_hdr;
                PIMAGE_EXPORT_DIRECTORY export_dir;
                ULONG *fn_name, *fn_addr, i;
                  char* base;
                  base=(char*)FindModule(ModuleName);//該函數用來獲得內核模塊的基地址
                if(!base)
                    return NULL;
                DbgPrint("tcpip address:%p",base);
                dos_hdr = (PIMAGE_DOS_HEADER)base;
                if (dos_hdr->e_magic != IMAGE_DOS_SIGNATURE)
                    return NULL;
                nt_hdr = (PIMAGE_NT_HEADERS)(base + dos_hdr->e_lfanew);
                export_dir = (PIMAGE_EXPORT_DIRECTORY)(base + nt_hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
                fn_name = (ULONG *)(base + export_dir->AddressOfNames);
                fn_addr = (ULONG *)(base + export_dir->AddressOfFunctions);
                for (i = 0; i < export_dir->NumberOfNames; i++, fn_name++, fn_addr++)
                {
                    if (strcmp(RoutineName, base + *fn_name) == 0)
                    {
                        return base + *fn_addr;
                    }
                }
                return NULL;
            }
            以下是FindModule函數的實現:
            void *
            FindModule(char *name)
            {
                ULONG i, n, *q;
                PSYSTEM_MODULE_INFORMATION p;
                void *base;
                ZwQuerySystemInformation(SystemModuleInformation, &n, 0, &n);
                q = (ULONG *)ExAllocatePool(PagedPool, n);
                ZwQuerySystemInformation(SystemModuleInformation, q, n * sizeof (*q), 0);
                p = (PSYSTEM_MODULE_INFORMATION)(q + 1);
                base = NULL;
                for (i = 0; i < *q; i++) {
                    if (_stricmp(p.ImageName + p.ModuleNameOffset, name) == 0) {
                        base = p.Base;
                        break;
                    }
                }
                ExFreePool(q);
                return base;
            }
            以下是獲取tcpip協議的NDIS_PROTOCOL_BLOCK指針的函數
               void* GetProtocolBlock()
            {
                char* base;
                char bytes[]={0xff,0x35};
                base=GetRoutineAddress("tcpip.sys","IPDelayedNdisReEnumerateBindings");
                 while(RtlCompareMemory(base,bytes,2)!=2)
                {
                   base++;
                }
                return **((void***)(base+2));
            }

            久久久国产精品网站| 久久久久久国产精品无码下载| 久久国产色AV免费看| 久久久久国产一级毛片高清版| 久久91精品综合国产首页| 日日狠狠久久偷偷色综合0| 一本色道久久88精品综合| 久久国产乱子精品免费女| 色诱久久av| 日韩精品国产自在久久现线拍| 亚洲v国产v天堂a无码久久| 久久久久无码精品国产不卡| 久久久中文字幕日本| 国产精品免费福利久久| 伊人久久大香线蕉AV一区二区| 精品一区二区久久久久久久网站| 蜜桃麻豆WWW久久囤产精品| 久久久91精品国产一区二区三区| 亚洲午夜久久久影院| 久久精品亚洲男人的天堂| 久久99精品综合国产首页| 精品伊人久久大线蕉色首页| 久久精品一区二区三区中文字幕| 精品久久久噜噜噜久久久| 久久精品国产2020| 亚洲人AV永久一区二区三区久久 | 久久精品国产亚洲av日韩| 欧美与黑人午夜性猛交久久久| 久久久久久免费一区二区三区| 老男人久久青草av高清| 亚洲精品99久久久久中文字幕| 亚洲国产精品久久66| 国产999精品久久久久久| 97久久超碰成人精品网站| 久久亚洲精品人成综合网| 国内精品久久久久久久久电影网| 亚洲色欲久久久久综合网| 亚洲中文字幕伊人久久无码 | 蜜桃麻豆www久久| 日本免费一区二区久久人人澡 | 亚洲女久久久噜噜噜熟女|