• <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++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

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


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            伊人久久大香线焦AV综合影院| 99久久做夜夜爱天天做精品| 好属妞这里只有精品久久| 国产Av激情久久无码天堂| 久久亚洲精品视频| 欧美午夜A∨大片久久| 久久发布国产伦子伦精品| 国产亚洲精久久久久久无码AV| 久久亚洲AV无码精品色午夜麻豆| 99久久精品午夜一区二区| 伊人久久国产免费观看视频 | 精品无码久久久久久久动漫| 亚洲精品99久久久久中文字幕| 韩国免费A级毛片久久| 亚洲伊人久久综合影院| 成人精品一区二区久久久| 亚洲色欲久久久综合网| 久久精品三级视频| 天天爽天天爽天天片a久久网| 久久国产劲爆AV内射—百度| 久久国产乱子伦精品免费午夜| 激情伊人五月天久久综合| 久久伊人精品一区二区三区| 欧美与黑人午夜性猛交久久久| 久久精品不卡| 国产69精品久久久久99| 国产精品久久久久久福利69堂| 亚洲国产精品无码久久久不卡| 午夜精品久久久久9999高清| 欧美日韩中文字幕久久久不卡| 久久亚洲天堂| 久久亚洲高清综合| 亚洲AV伊人久久青青草原| www亚洲欲色成人久久精品| 久久www免费人成看国产片| 91精品免费久久久久久久久| 伊人久久大香线蕉影院95| 99热都是精品久久久久久| 国内精品久久久久久久亚洲| 精品久久综合1区2区3区激情 | 综合久久国产九一剧情麻豆|