• <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 閱讀(1680) 評論(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));
            }

            91精品国产综合久久久久久| 久久精品国产99久久丝袜| 久久人人爽人人爽AV片| 久久精品亚洲日本波多野结衣 | 精品久久久久久无码中文野结衣| 亚洲人成无码www久久久| 精品一区二区久久久久久久网站| 77777亚洲午夜久久多人| 午夜精品久久久久9999高清| 久久青青草原国产精品免费| 亚洲AV无码久久精品色欲| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 国产香蕉97碰碰久久人人| 99久久国产综合精品女同图片| 国产精品久久国产精麻豆99网站| 一本综合久久国产二区| 国产精品gz久久久| 久久强奷乱码老熟女| 99久久国产热无码精品免费 | 91精品国产乱码久久久久久 | 97久久久久人妻精品专区| 午夜精品久久影院蜜桃| 国产精品免费久久久久电影网| 狠狠色婷婷久久一区二区三区| 久久精品中文无码资源站| 久久精品国产2020| 日韩精品久久久久久久电影| 日本五月天婷久久网站| 午夜天堂av天堂久久久| 久久笫一福利免费导航| 狠狠色丁香婷婷久久综合五月| 久久精品中文字幕有码| 久久久久国产亚洲AV麻豆| 97精品伊人久久久大香线蕉| 怡红院日本一道日本久久| 久久精品国产亚洲AV高清热| 久久妇女高潮几次MBA| 新狼窝色AV性久久久久久| 久久综合久久自在自线精品自| 一级做a爰片久久毛片16| 久久婷婷国产麻豆91天堂|