1. 在windows平台下的底層開發應該有什麼樣的學習路線
1.語言C/C++(參考書籍:<<C/C++ Primer>> ,<<C和指針>>,<<數據結構C語言描述>>)),匯編(王爽的匯編語言,作為入門,參考Intel手冊,之後參考看雪的<<加密與解密>>,了解PE文件的格式,加殼脫殼和病毒感染的手法,如果是開發的話,只需要了解即可,能用反匯編調試工具去做簡單的CrackMe即可),這個階段大約是大一大二的時間,除去老師上課教的C語言基礎,80x86匯編語言以為,很多知識都是自己去擴展。
2.windows api(win32sdk) 參考書籍(《Windows程序設計》,《Windows核心編程》,MFC之類的需要使用的時候在參考即可,不必花費太多精力,主要是去了解程序的消息機制,事件等等,應該把主要的精力比如線程注入,Ring3的各種HOOK等。這個階段是大二下學期的時間,說實話,我這個方面看的太少了,花了好多時間在一些沒有意義的事情上,導致到大三的時候參加信息安全比賽做驅動的時候經驗嚴重不足,所以基礎太重要了)
3.然後就是winows驅動內核的開發(參考書籍,寒江獨釣,張帆的Windows驅動開發技術詳解,WDK上的各種示例代碼) 熟悉各種過濾驅動框架(文件過濾驅動,文件微過濾驅動,tdi,ndis協議,ndis中間層,ndis小埠等等)。
然後就是各種系統底層的原理,進程創建的流程,文件創建的流程,進程間通信的過程,用各種調試,反匯編工具(od,ida,windbg)去跟蹤分析,可以寫一些Rootkit/Anti-Rootkit工具,比如對於進程隱藏和保護,有SSDT HOOK OpenProcess,摘除進程鏈表等等,這樣有助於對系統底層機制的理解
4.後期就是經驗和內功了,什麼《深入解析Windows操作系統》,《TCP/IP》卷123,《Windows內核原理與實現》等等,說白了,個人認為,底層開發對於調試的功力要求很高,能從藍屏的mp文件出有用的信息
2. 求個簡單的防火牆源代碼
防火牆源代碼網路上是有的,我也寫過一套,不過我寫的不是針對客戶端計算機的,是針對伺服器的, 目前客戶端防火牆開發上使用 大致分為3種技術 1、SPI 會話層過濾的,做行為控制比較好。2、TDI 傳輸層過濾驅動,性能要比SPI好。3、NDIS中間層過慮驅動,也是目前幾大防火牆廠家常用的計算機。 第一種防火牆 可以滿足你需要的功能,下載地址 http://down.cnzz.cn/info/6548.aspx 開發語言VC++6.0如果你想研究 第三種技術,並且也順帶 第一種技術的源代碼,目前沒有免費的。要通過付款購買的 http://www.filseclab.com/procts/source.htm
3. 個人防火牆的數據類型
用戶態(user-mode)和內核態(kernel-mode)。
1)用戶態(user-mode)。
在用戶態下進行網路數據包的攔截有三種方法:WinsockLayeredServiceProvider(LSP)、Windows2000包過濾介面、替換系統自帶的WINSOCK動態連接庫。在用戶態下
進行數據包攔截最致命的缺點就是只能在Winsock層次上進行,而對於網路協議棧中底層協議的數據包無法進行處理。因此,這些方法並不適合個人防火牆。
2)內核態(kernel-mode)。
a)TDI過濾驅動程序(TDIFilterDriver)。當應用程序要發送或接收網路數據包的時候,都是通過與協議驅動所提供的介面來進行的。協議驅動提供了一套系統預定義的標准介面來和應用程序之間進行交互。因此,只需要開發一個過濾驅動來截獲這些交互的介面,就可以實現網路數據包的攔截。在Windows2000/NT下,ip,tcp,udp是在一個驅動程序里實現的,叫做tcp.sys,這個驅動程序創建了5個設備:DeviceRawIp,DeviceUdp,DeviceTcp,DeviceIp,DeviceMULTICAST。應用程序所有的網路數據操作都是通過這些設備進行的。因此,我們只需要開發一個過濾驅動來截獲這些交互的介面,就可以實現網路數據包的攔截。另外,TDI層的網路數據攔截還可以得到操作網路數據包的進程詳細信息,這也是個人防火牆的一個重要功能。但是,TDI傳輸驅動程序有一個缺陷,TDIFilterdriver屬於Upperdriver,位於TcpIP.sys之上,這就意味著由TcpIP.sys接收並處理的數據包不會傳送到上層,從而無法過濾某些接收的數據包,例如ICMP包。ICMP的應答包直接由TcpIP.sys生成並回應,而上面的過濾驅動程序全然不知。另外,該方法需要在系統核心層編寫驅動程序,需要編寫人員對Windows操作核心層的工作機制非常熟悉,同時,驅動程序對代碼質量要求非常高,稍有不慎就會使系統崩潰,
b)Win2kFilter-HookDriver。這是從Windows2000開始系統所提供的一種驅動程序,該驅動程序主要是利用Ipfiltdrv.sys所提供的功能來攔截網路數據包。Filter-HookDriver的結構非常簡單,易於實現。但是正因為其結構過於簡單,並且依賴於Ipfiltdrv.sys,Microsoft並不推薦使用Filter-HookDriver。
c)NDISHookDriver。該方法在Windows2000/xp下是非公開的,因此這種方法對平台的依賴性比較大,需要在程序中判斷不同的操作系統版本而使用不同的方法。
d)NDIS中間層驅動程序(NDISIntermediateDriver)。NDIS()是Microsoft和3Com公司開發的網路驅動程序介面規范的簡稱,它支持如下三種類型的網路驅動程序:微埠驅動程序、中間層驅動程序(IntermediateDriver)和協議驅動程序。其中中間層驅動介於協議層驅動和小埠驅動之間,其功能非常強大,可以提供多種服務,能夠截獲所有的網路數據包(以太幀),過濾微埠驅動程序,實現特定的協議或其他諸如數據包加密、認證等功能。綜上所述,在NDIS中間層進行網路數據包截獲的方法結構規范,功能強大,該技術極其適合個人防火牆所採用。
中間層驅動程序(NDIS)的內部結構
NDIS支持3種驅動:微埠驅動,中間層驅動和協議驅動。
1) 微埠驅動。就是網卡驅動,它負責管理網卡,包括通
過網卡發送和接受數據,它也為上層驅動提供介面。
2) 中間層驅動。它通常位於微埠驅動和傳輸協議驅動之間,是基於鏈路層和網路層之間的驅動,由於中間層驅動在驅動層次中的中間層位置,它必須與其上層的協議和下層的微埠驅動通信,並且導出兩種協議的函數。雖然中間層驅動導出MINIPORTXX函數,但它並不真正的管理物理網卡,而是導出一個或者多個虛擬適配器,上層協議可以綁定到上面。對於協議驅動來說,中間層導出的虛擬適配器看起來像一個物理網卡,當它向這個虛擬適配器發送封包或者請求時,中間層驅動將這些封包和請求傳播到下層微埠驅動;當下層微埠驅動向上指示接收封包或者狀態時,中間層驅動向上到綁定虛擬適配器上的協議驅動。中間層驅動的主要作用就是過濾封包,其優點是能夠截獲所有的網路數據包。
3) 協議驅動,即網路協議。它位於NDIS體系的最高層,經常用作實現傳輸協議堆棧的傳輸驅動中的最底層驅動。傳輸協議驅動申請封包,從發送應用程序將數據復制到封包中,通過調用NDIS函數將這些封包發送到下層驅動。協議驅動也是提供了一個協議介面來接收來自下層驅動的封包。傳輸協議驅動將收到的封包傳遞給相應的客戶應用程序。在下層,協議驅動與中間層微埠驅動交互。協議驅動調用NDISXX函數發送封包,讀取和設置下層驅動維護的信息,使用操作系統服務。協議驅動也要導出一系列的入口點,NDIS調用它來指示封包的接受,指示下層驅動的狀態,或者是和其他協議驅動的通信。
中間層內部的工作流程
1) 中間層對數據包的管理
中間層驅動程序從高層驅動程序接收數據包描述符,並在網路上發送,該包描述符與一個或多個鏈式數據緩沖區相關聯。中間層驅動程序能夠對數據進行重新打包,並使用新的數據包描述符進行數據傳輸,也可以直接將數據包傳遞給低層驅動程序,如果驅動程序下邊界面向無連接,可調用NdisSend或NdisSendPackets函數完成該功能,如果驅動程序下邊界是面向連接的,可調用NdisCoSendPackets函數完成此項功能。中間層驅動程序也可以進行一些操作改變鏈式緩沖區的內容,或者調整內入數據包相對於其他發送任務的發送次序或發送定時。但是,即使中間層驅動程序只是向下層傳遞上層引入的數據報,例如,僅僅只是對數據包進行計數,也必須分配新的數據包描述符,並且要管理部分或者全部新的包結構。
每一個中間層驅動程序都必須分配自己的包描述符來代替高層的數據包描述符。如果中間層驅動程序要把數據包從一種格式轉化為另一種格式,也必須分配緩沖區描述符來映射用於復制轉配數據的緩沖區,該緩沖區由中間層驅動程序進行分配。如果有與復制的包描述符相關的OOB數據,那麼可以將這些數據復制到與包描述符(中間層驅動程序分配的)相關的新OOB數據塊,其過程是,首先,用NDIS_OOB_DATA_FROM_PACKET宏獲取OOB數據區的指針,然後,調用disMoveMemory將其內容移入與新包描述符相關的OOB數據區。該驅動程序也能夠用NDIS_GET_PACKET_XXX或NDIS_SET_PACKET_XXX宏從與老的包描述符相關的OOB數據區中,讀取相關的內容,並寫入與新包描述符相關的OOB數據區。
包描述符通過調用以下NDIS函數進行分配
a)調用NdisAllocatePacketPool或者NdisAllocatePacketPoolEx,為固定尺寸包描述符(由呼叫器指定數量)分配並初始化一組非可分頁池。
b)調用NdisAllocatePacket函數,從NdisAllocatePacketPool(Ex)已經分配的池中分配包描述符。根據中間層驅動程序目的的不同,驅動程序能夠對引入包描述符連接的緩沖區進行重新打包。例如,中間層驅動程序可以在接下來的情況下分配包緩沖池、對引入包數據重新打包.如果中間層驅動程序從高層協議驅動程序接收到的數據緩沖區,比低層介質能夠發送的單個緩沖區更大,那麼中間層驅動程序必須將引入的數據緩沖分割成更小的、滿足低層發送要求的數據緩沖。中間層驅動程序在將發送任務轉交低層驅動程序之前,可以通過壓縮或加密數據方式來改變內入數據包的長度。調用以下NDIS函數分配上面所要求的緩沖區:
NdisAllocateBufferPool獲取用於分配緩沖區描述符的句柄;
NdisAllocateMemory或NdisAllocateMemoryWithTag分配緩沖區;
c)調用NdisAllocateBuffer分配和設置緩沖區描述符,映射由NdisAllocateMemory(WithTag)分配的緩沖區,並鏈接到NdisAllocatePacket分配的包描述符上。驅動程序可以通過調用NdisChainBufferAtBack或NdisChainBufferAtFront函數,將緩沖區描述符和包描述符進行鏈接。調用NdisAllocateMemory(WithTag)返回的虛擬地址和緩沖區長度,將被傳遞給NdisAllocateBuffer函數來初始化其所映射的緩沖區描述符。符合典型要求的包描述符能夠在驅動程序初始化時根據要求進行分配,也可以通過ProtocolBindAdapter函數調用來實現。如果必要或者出於性能方面的考慮,中間層驅動程序開發者可以在初始化階段,分配一定數量的包描述符和由緩沖區描述符映射的緩沖區,這樣,就為ProtocolReceive復制內入數據(將向高層驅動程序指示)預先分配了資源,也為MiniportSend或MiniportSendPackets向相鄰低層驅動程序傳遞引入的發送數據包,准備了可用的描述符和緩沖區。如果在中間層驅動程序復制接收/發送數據到一個或多個緩沖區時,最末的一個緩沖的實際數據長度比緩沖區的長度小,那麼,中間層驅動程序將調用NdisAdjustBufferLength把該緩沖區描述符調節到數據的實際長度。當該包返回到中間層驅動程序時,應再次調用該函數將其長度調節到完整緩沖區的實際尺寸。
2)下邊界面向無連接的中間層驅動程序的工作流程
通過ProtocolReceivePacket函數,從低層NIC驅動程序以完整數據包形式接收內入數據,該數據包由NDIS_PACKET類型的包描述符指定,也能夠通過將內入數據指示給ProtocolReceive函數,並將數據復制到中間層驅動程序提供的數據包中。下邊界面向連接的中間層驅動程序總是用ProtocolCoReceivePacket函數,從低層NIC驅動程序接收數據作為一個完整的數據包。
在如下情況下,中間層驅動程序能夠保持對接收數據包的所有權:當下邊界面向無連接的中間層驅動程序向ProtocolReceivePacket函數指示完整數據包時,當下邊界面向連接的中間層驅動程序向ProtocolCoReceivePacket函數指示數據包時,其中DIS_PACKET_OOB_DATA的Status成員設置為除NDIS_STATUS_RESOURCES以外的任何值。在這些情況下,中間層驅動程序能夠保持對該包描述符和其所描述的資源的所有權,直到所接收數據處理完畢,並調用NdisReturnPackets函數將這些資源返還給低層驅動程序為止。如果ProtocolReceivePacket向高層驅動程序傳遞其所接收的資源,那麼至少應該用中間層驅動程序已經分配的包描述符替代引入包描述符。根據中間層驅動程序目的的不同,當其從低層驅動程序接收完整數據包時,將有幾種不同的包管理策略。例如,以下是幾種可能的包管理策略:復制緩沖區內容到中間層驅動程序分配的緩沖區中,該緩沖區被映射並鏈接到一個新的包描述符,向低層驅動程序返回該輸入包描述符,然後可以向高層驅動程序指示新的數據包;創建新的包描述符,將緩沖區(與被指示包描述符相關聯)鏈接到新的包描述符,然後將新的包描述符指示給高層驅動程序。當高層驅動程序返回包描述符時,中間層驅動程序必須拆除緩沖區與包描述符間的鏈接,並將這些緩沖區鏈接到最初從低層驅動程序接收到的包描述符,最後向低層驅動程序返還最初的包描述符及其所描述的資源。即使下邊界面向無連接的中間層驅動程序支持ProtocolReceivePacket函數,它也提供ProtocolReceive函數。當低層驅動程序不釋放包描述符所指示資源的所有權時,NDIS將調用ProtocolReceive函數,當這類情況出現時,中間層驅動程序必須復制所接收的數據到它自己的緩沖區中。對於下邊界面向連接的中間層驅動程序,當低層驅動程序不釋放包描述符所指示資源的所有權時,則將數據包的NDIS_PACKET_OOB_DATA的Status成員設為NDIS_STATUS_RESOURCES,然後驅動程序的ProtocolCoReceivePacket函數必須將接收到數據復制到自己的緩沖區中
5) 中間層驅動過濾數據包的原理
NDIS中間層驅動程序在NDIS中起著轉發上層驅動程序送來的數據包,並將其向下層驅動程序發送的介面功能。當中間層驅動程序從下層驅動程序接收到數據包時,它要麼調用NdisMXxxIndicateReceive函數,要麼調用NdisMindicateReceivePacket函數向上層指示該數據包中間層驅動程序通過調用NDIS打開和建立一個對低層NIC驅動程序或者NDIS中間層驅動程序的綁定。中間層驅動程序提供MiniportSetInformation和MiniportQueryInformation函數來處理高層驅動程序的設置和查詢請求,某些情況下,可能還要將這些請求向低層NDIS驅動程序進行傳遞,如果其下邊界是面向無連接的可通過調用NidsRequest實現這一功能,如果其下邊界是面向連接的則通過調用NidsCoRequest實現該功能。中間層驅動程序通過調用NDIS提供的函數向網路低層NDIS驅動程序發送數據包。例如,下邊界面向無連接的中間層驅動程序必須調用NdisSend或NdisSendPackets來發送數據包或者包數組,而在下邊界面向連接的情況下就必須調用NdisCoSendPackets來發送包數組數據包。如果中間層驅動程序是基於非NDISNIC驅動程序的,那麼在調用中間層驅動程序的MiniportSend或Miniport(Co)SendPackets函數之後,發送介面對NDIS將是不透明的。NDIS提供了一組隱藏低層操作系統細節的NdisXxx函數和宏。例如,中間層驅動程序可以調用NdisMInitializeTimer來創建同步時鍾,可以調用NdisInitializeListHead創建鏈表。中間層驅動程序使用符合NDIS標準的函數,來提高其在支持Win32介面的微軟操作系統上的可移植性。
在防火牆的設計中,最核心的部分應該是數據包的過濾。
其他的功能都是建立在數據包過濾的基礎之上,如:入侵檢測功能和郵件檢測功能都是建立在數據包過濾的基礎之上。數據包過濾中主要是IP包頭的分析,例如:在乙太網中,得到的數據報大致是如下結構,以太幀頭14個位元組,放在PUCHAR結構數組的第0個元素到第13個元素中,其中前六個位元組是目的MAC地址,然後六個位元組源MAC地址,然後兩個位元組是協議類型,通常的協議類型有0x080x00->IP,0x080x06->ARP,0x080x35->RARP,所以,可以通過數組的第12個元素和第13個元素來判斷協議類型。過濾規則就是在這個基礎之上建立。如果要過濾特定協議,只要在相應的位元組讀取數據,判斷是否符合要過濾的規則就可以了,當然實際的過濾規則要復雜的多的多,比如對指定的埠指定的IP的過濾。
4. 殺毒軟體與防火牆
請樓主看看這個帖子吧。真的很有用,一般我不會轉帖的,這個真的很好。
流氓軟體和木馬在各種防火牆和殺毒軟體的「打壓」之下已經開始逐步向內核「退縮」,傳統的依靠查看本地打開的埠與進程的關系的方法檢查非法網路訪問已經不再適用,個人防火牆已經成為裝機必備的軟體。目前主流的個人防火牆軟體都是構建在Windows內核之上的,但是Windows的內核驅動是分層的,防火牆工作在哪一層實際上就決定了防火牆的性能,工作在TDI層的防火牆是無論如何也不能知道NDIS層的數據收發情況的,因為TDI驅動層在內核中是高於NDIS驅動層的。過去的木馬(上個世紀九十年代以前)都是構建在Windows應用層上的普通程序,工作在TDI層的防火牆可以輕易地覺察並阻斷它們非法的網路訪問,但是對付縮進內核的木馬和流氓軟體,單純的依靠TDI層攔截已經顯得力不從心。內核木馬的特點是不依賴句柄,不綁定埠(NDIS)
),可以工作在TDI層,甚至在NDIS層,所以,真正可靠的防火牆應該在NDIS層建立防線。
雖然真正可靠的防火牆應該工作在NDIS層,但是,個人防火牆和用於伺服器的防火牆畢竟還是有一些不同之處,工作在伺服器端的防火牆只需要根據協議、地址和埠判斷是轉發還是丟棄就行了,高級一點還可以分析包內容,根據預設的專家系統判斷是正常的數據包還是非法攻擊數據包,這樣的防火牆還可以用硬體實現。但是個人防火牆的特別之處就是需要與用戶交互,用戶數據多是基於IP協議的,並且用戶並不關心協議的細節(掌握這些對大多數用戶來說有點難度),所以個人防火牆除了通過IP層的協議進行過濾之外,更主要的手段是根據用戶的意願允許還是阻止某個進程(程序)訪問網路,在這個粒度上用戶比較容易理解和控制。從這一點上講,工作在TDI層的防火牆的優勢就是能夠在網路訪問發生的時候追蹤到發起訪問的進程名稱,從而給用戶一個提示,而工作在NDIS層的防火牆則不容易做到這一點。因為發送數據時上層驅動將數據包提交到NDIS的發送隊列中後就返回了,當數據包被真正投遞的時候已經無從確定是哪個程序(進程)發送的了,對於收到的數據包需要根據埠號判斷是哪個程序的,但是在NDIS層並不知道埠號和進程的對應關系,所以無論數據發送還是接收都無法有效地確定是屬於哪個進程的數據。如果不能確定哪個進程訪問網路,只是根據地址、埠和協議進行過濾對(大多數)用戶來說是很不友好的,所以最好的個人防火牆(不一定是最安全的)應該是TDI+NDIS雙保險:TDI層根據進程級訪問過濾,NDIS層根據地址、埠和協議過濾。
前幾天,一個朋友要我給他推薦一款比較好的防火牆軟體,說實話,我也不知道哪個好,因為我沒有比較過。沒有調查就沒有發言權,隨便應付也不是本人的風格,加上本人最近正在驗證一個在內核構建TCP/IP協議繞過防火牆的概念的可行性,需要對當前主流防火牆的能力有所了解,所以就把當前比較流行的防火牆都弄來研究了一下,沒想到真是大開眼界,不看不知道,一看嚇一跳。先上網搜了一下個人防火牆,沒想到有這么多種,沒時間全搞一遍,只能對用的最多的幾個下手了,它們是「天網防火牆個人版」,「金山網鏢」,「瑞星個人防火牆」,「卡巴斯基」,「冰盾」和「風雲防火牆」,有幾個防火牆軟體不僅提供網路防火牆功能,還提供諸如文件訪問控制,進程創建保護等功能,不過本文只是比較它們的網路防範功能。
首先是天網防火牆,這可是本人上學的時候最喜歡的防火牆了,簡單好用。這次使用的是天網防火牆個人版(Trial_Release_v3.0_Build1213),結果卻令人失望,天網是一個單純的TDI防火牆。下圖天網啟動後的設備驅動載入情況:
圖 1 天網防火牆設備驅動載入情況
工作在TDI層的防火牆有兩種方式,一種是做成過濾驅動掛接到支持TCP/IP協議的設備上,簡單地講,就是發送給TCP/IP協議驅動的請求會先發送給它過濾,另一種是使用Hook的方式直接HookTCP/IP協議的驅動分派函數,相比較而言,第一種比較容易bypass,驅動層的木馬或流氓軟體通過設備直接找到TCP/IP的驅動發送請求,就可以避開Attach在其上的過濾驅動,從上圖看,天網的驅動是一個Filter驅動,除了直接向TCP/IP的驅動發送請求可以避開天網之外,還有一種方法可以讓它完全失效,就是直接摘除掛接的Filter驅動,看看下面的代碼:
void ByPassAttachDevice(PDEVICE_OBJECT DeviceObject)
{
PDEVICE_OBJECT CurDevObj = DeviceObject;
while(CurDevObj != NULL )
{
CurDevObj->AttachedDevice = NULL;
CurDevObj = CurDevObj->NextDevice;
}
}
運行在驅動層的木馬只要對設備驅動運行一下ByPassAttachDevice()函數就可以讓天網和所有使用這種技術的防火牆形同虛設。口說無評,本人專門寫了一個驅動來驗證,首先在天網的設置中禁止IE訪問網路,此時IE的網路訪問會被禁止:
圖 2 天網防火牆組織IE訪問網路
然後用驅動載入測試工具載入本人編寫的驅動程序(文後附有載入工具和驅動程序,以及使用說明,可以用來測試一下你用的防火牆是否安全),假設這是一個運行在內核的木馬或流氓軟體:
圖 3 載入Bypass驅動程序
運行後天網就失效了,看看IE可以訪問網路了,不僅IE,所有被禁止的程序都可以訪問網路了:
圖 4 天網防火牆失效了
結論,就不說了,真的很失望。
下面看看金山網鏢,這個是我的朋友很喜歡用的,一直說它好用,本次比較用的是金山安全套件2008中附帶的金山網鏢,先看看它的驅動載入情況:
圖 5 金山網鏢驅動載入情況
這也是一個TDI Filter,沒有在NDIS層做工作,使用前面的工具可以輕松bypass,不說了,下一個。
接下來是瑞星個人防火牆,使用的版本是瑞星個人防火牆2008。瑞星的驅動在TDI層使用了不容易bypass的TDI hook,除此之外,在NDIS層也使用了Hook,先看看TDI層的情況:
圖 6 瑞星驅動的TDI Hook情況
再看看在NDIS層的Hook情況:
圖 7 瑞星驅動的NDIS Hook情況
從驅動上看瑞星防火牆要比前兩個強很多,本人曾試著手工恢復被hook的函數,雖然恢復後不再彈出「某某程序要訪問網路」的提示,但是實際上還是不能訪問網路,不知為何,有興趣的朋友可以研究一下。
再來看看卡巴斯基,這次使用的是卡巴斯基的互聯網安全套裝6.0個人版,從驅動上看卡巴斯基採用的是用TDI Filter驅動+NDIS Hook:
圖 8 卡達斯基的驅動載入情況
但是可能卡巴斯基的NDIS Hook只是用來分析可以的數據才使用的,也或者是為實現其它功能設置的Hook,總之,使用本文的程序可以bypass卡巴斯基的防火牆功能。
再看看冰盾防火牆,冰盾是一個伺服器防火牆,這次使用的是冰盾8.1 Build60214,從驅動載入情況看,冰盾使用了一個NDIS中間層驅動,沒有Hook,也沒有處理TDI層的事務,畢竟它不是個人防火牆,沒必要處理TDI層的事情(這只是本人的看法的)。工作在NDIS層的好處是可以探測工作在TDI層的rootkit木馬,但是對於個人計算機用戶來說,冰盾的設計不太好用(或者說比較難理解,相對於其它幾種防火牆軟體),另外,中間層驅動還容易被Hook,rootkit木馬可以Hook它的處理函數,比如指向一個空函數,就可以癱瘓中間層驅動。
最後一個是風雲防火牆,這個是從網上搜到的,以前沒聽說過,使用的版本是V1.26 正式版。這個軟體除了防火牆功能之外,還有很多附加功能,比如文件訪問監控,注冊表訪問監控等等,不過其網路防火牆這塊使用的策略和卡巴斯基一樣,可以被本文的工具bypass
從分析的結果來看,這幾款防火牆軟體對於應用程序的訪問控制都是沒有問題的,但是對於同樣工作在內核級別上的木馬和流氓軟體則問題很多,只有瑞星防火牆結果好一點,其它的幾款防火牆軟體都挺令人失望,特別是天網防火牆。最後需要強調一點的是即使是瑞星這樣使用TDI Hook + NDISHook的方式也不一定就是安全的,因為在應用程序級別上進行網路訪問控制還是粒度太粗,如果使用rootkit工具將木馬注入到防火牆允許訪問網路的程序的進程中,就可以在防火牆眼皮底下堂而皇之地訪問網路了,比如IE的一些BHO插件就是這么幹得。
驅動載入測試工具以及bypass驅動下載
附錄: 驅動載入測試工具以及bypass驅動的使用方法
首先將hook_test.sys復制到windows的系統驅動程序目錄中(如果是windowsxp的系統,這個目錄可能是c:\windows\system32\drivers),然後運行drv_test.exe,在驅動文件位置中填入驅動文件hook_test.sys的完整路徑名,在驅動名稱中填入驅動名稱,這個比較重要,因為後面的啟動、停止和卸載驅動都需要這個驅動名稱,不過不一定是「hook_test」,顯示名稱隨便填寫就行了。輸入完成後首先點擊「安裝驅動」按鈕安裝驅動,如果沒有錯誤再點擊「啟動驅動」按鈕啟動這個驅動程序,然後就可以測試你的防火牆軟體了。測試的方法很簡單,就是運行一個訪問網路的程序,如果防火牆有效,會提示是否阻止程序訪問網路,如果防火牆失效,則沒有任何提示,卸載驅動先點擊「停止驅動」按鈕,然後點擊「卸載驅動」按鈕就可以了。
5. 誰英語好幫忙翻譯一段英語,是一個論文的概述,有點長,謝謝啦
With the rapid development of computer networks, network security issues are increasingly attracted our attention. Firewall as an effective security measure is widely used in various types of networks. Firewall technology has experienced a number of improvements and development stage. However, whether the traditional firewall or currently popular distributed firewall all have their own weaknesses, making their use in practice many restrictions.
This design has implemented a firewall adopting the NDIS driver technology. It』s driven through the kernel mode, the NDIS callback function has been implemented and the filter-hook driver is registered by the NDIS which is provided by system. The IP filter driver uses the filter-hook to handle the data packets in and out. The firewall is composed of the following moles: adding filter rules mole, display filter rules mole storage filter rules mole, storage file mole, installation unloading rules mole and IP packet driver mole. Users can finish the operation of firewall by using main menu and button to protect the system effectively.
The program is a traditional firewall technology and distributed firewall technology combined. The firewall can overcome the internal insecurity and other issues. And also can avoid too much focus on the distributed firewall management problems. In this paper a decision tree based on packet classification algorithms. The main idea is the pre-treatment rules to build the decision-making tree of structural characteristics.
6. 網路監控軟體的網路監控軟體工作原理
企業里涉及到兩部分的網路管理,一部分是監視上INTERNET的行為和內容,也就是大家說的上網監控或外網監控;另一部分就是如果這個電腦不上 INTERNET但又在內部區域網上(比如列印個文件什麼的),一般被大家叫成內網監控或本網監控;上網監控管理的是上網的內容監視和上網行為監視(比如發了什麼郵件,是否限制流量,是否允許QQ,或監視用戶頁面瀏覽);而內網監視管理的是本地網路的活動過程(比如有沒有COPY東西到U盤、是否在玩單機 游戲、使用電腦做了什麼等等)。
外網監控軟體模式基本可以分為兩類:有客戶端的和沒有客戶端的(內網安全都需要客戶端,上面沒有客戶端的都不能實現內網安全管理)。
擁有內網管理功能的:網眼監控軟體、Anyview(網路警)網路監控軟體、網路崗區域網管理軟體、網貓網路監控軟體實現需要客戶端支持。這幾種軟體都有專門的客戶端軟體提供。
沒有內網管理功能的:百絡網警區域網管理、聚生網管系統、超級嗅探狗上網監控系統。二、有客戶端的外網監控
信安上網行為管理系統和Phantom系統(外網管理和內網管理功能都提供)。
不牽涉部署模式,因為他們的實現原理都是在C/S模式,通過部署在被監控計算機上的客戶端來實現各種功能,在這種模式下,伺服器的安裝部署對網路環境就沒有特別的要求,網路內隨意找一個電腦就可以做伺服器,而且功能、網路速度、效率都不受影響,不需要對原有網路架構、環境進行改動。
唯一的缺點就是需要安裝客戶端。 大概分為四種安裝模式:旁路、旁聽(共享式HUB、埠鏡像)、網關、網橋。
(1)旁路模式:
基本採用ARP欺騙方式虛擬網關,讓其他計算機將數據發送到監控計算機。
(2)網關模式:
是把本機作為其他電腦的網關(設置被監視電腦的默認網關指向本機),常用的是NAT存儲轉發的方式;簡單說有點像個路由器工作的方式;因此控制力極強,但由於存儲轉發的方式,性能多少有點損失;不過效率已經比較好了。但維護和安裝比較麻煩;無法跨越VLAN和VPN;假如網關死了,全網就癱瘓了。此類軟體有 ISA、anyrouter軟網關等,這里沒有引用,ISA在一些銀行金融機構仍在使用,海天上網監控軟體是專門針對ISA而開發的。
(3)網橋模式:
支持網橋模式的軟體比較少。 除了模式,我們講一下獲取數據包的技術,大概有兩種方式:
1) 採用操作系統核心NDIS中間層驅動模式,
2) 公開免費介面WINPCAP協議層驅動。
由於WINPCAP本身設計的天生弱點,所以在流量限制方面無法實現、阻斷UDP也將導致網路中斷、無法支持千M網路和無線網路、性能也必然很低;也無法實現NAT等更多的擴展功能,由於在協議層運行會被火牆禁止;而NDIS中間層驅動模式由於在NDIS層位置驅動,因此性能效率將非常高,更多功能也將成為可能;能夠克服WINPCAP所有的弱點,因此成為主流技術;但實現起來很大難度需要很強的開發實力;
4, 結論:
按照部署模式分:通過對比我們可以知道,網橋模式是最理想的一種模式,這種模式唯一的缺點就是額外開支,需要購買一台足夠網路處理能力伺服器,而且還要連接在交換機和路由器之間的網路上。
5, 總結
如果需要內網管理與外網管理都需要,那麼所有軟體都需要客戶端,顯然Phantom和網眼監控軟體是最好的選擇。
如果只需要外網監控,那末就需要選擇了,這時不需要部署客戶端,但需要買一台伺服器,部署在交換機和路由器之間。而網眼網路監控軟體和Phantom則可以任選一台電腦做伺服器;缺點是要安裝客戶端,優點是:實現的功能強大,支持拓展功能性強。 1) 免費開放的國外代碼,因此安全性欠缺;原理上是採用旁聽模式,所以無法阻斷UDP應用,無法流量限制,並容易數據丟包;阻斷規則有可能引起網路中斷或無效;
2) 原理上決定不適合超過100個電腦的網路環境,如採用老式共享式HUB速度限制在10M帶寬損失嚴重;如採用交換機鏡像是共享100M方式,由於一些交換機本身的缺陷,採用鏡像後會導致交換機阻塞現象的可能,因此網路帶寬會大約損失40%;
3) 由於是免費介面只提供匯流排抓包功能,所以不支持集群環境也不支持任何內網監控功能;
4) 由於是高層協議介面同時未提供適合監控的加密壓縮資料庫;所以不支持即時大規模數據存儲,不適合大用戶網路;不包含千M、無線網;如需支持多 VLAN或VPN應採用鏡像技術,需額外投資支持雙向鏡像技術的交換機並正確設置和維護;
5) 由於提供的介面都是通用的有限代碼,缺乏良好的可控性,所以很多功能無法實現;
7, Arp欺騙
欺騙區域網內計算機,使其他計算機誤認為監控計算機為網關計算機,將所有數據發送到監控計算機,只能適合於小型的網路,且環境中不能有限制旁路模式;路由或防火牆的限制或被監視電腦安裝了ARP防火牆都會導致無法旁路成功,因為你一邊在禁止旁路一邊卻正在旁路,所以自相矛盾;同時如網內同時多個旁路將會導致混亂而中斷網路。
7. 中間層的程序開發
1、設備資料庫所在的注冊表健值為: ENUM子項中是一個設備資料庫,在資料庫存放計算機中所有安裝的,並且被系統認識到的設備。 所有的用戶(包括管理員)都不能更改ENUM項的內容。這是為了保護操作系統和安裝的設備的完整性。為了更改設備的設置,應該使用「設備管理器」。 為了在設備管理器中現實隱藏的,非即插即用的,以及沒有連接到計算機上的所有設備,你應該首先在命令解釋器中敲入命令set DEVMGR_SHOW_NONPRESENT_DEVICES=1,然後啟動設備管理器,就可以在設備管理器中刪除和重新配置這些設備了。
2、硬體設備類所在ntControlSetControlClass Class項下存放硬體設備類的配置信息。在Class項下的每個子項都代表一個設備類,子項的名稱使用「唯一全局標識符(GUI)」,這些標識符存放該設備類的配置信息。在每個類標識符下,還會有以4位數命名的子項,他們代表該設備類里的具體設備,其他的配置數據只應用於該具體設備。 如網卡的設備類是{4D36E972-E325-11CE-BFC1-08002BE10318},並假定我們網卡對應的4為數命名子項名為0005。 其中{4D36E972-E325-11CE-BFC1-08002BE10318}5Linkage 中:Export:代表該設備在設備名字空間輸出的設備名字。RootDevice:代表當前設備的GUID。中間層驅動這里有兩個GUID,第一個是自己的GUID,第二個是該中間層驅動綁定的下層MINIPORT的GUID。UpperBind:代表上層綁定它的NDIS協議驅動或NDIS中間層驅動。當某個協議驅動綁定該MINIPORT設備時,則這個協議驅動的名字必須出現在UpperBind健值的字元串中,否則不能進行綁定。也就是說,UpperBind健值的字元串決定了那個協議驅動(當然也包括中間層驅動注冊的協議)和當前的MINIPORT設備綁定,即,它決定了NDIS的上下層綁定關系。
註:一般添加中間層驅動後,中間層驅動只插入到真是網卡和相應協議中間,不會插入到虛擬網卡(如安裝虛擬機後虛擬出來的網卡設備)和相應協議中間。
3、驅動程序所在的注冊表健值為: 子項 通常如果某個服務下存在ENUM子項,表明該服務是用來控制某個設備或者設備交互的,它的下面存放該設備的實例。用戶不要去試圖修改該子項的內容,因為每次系統啟動時,都會重寫該子項的內容。LINKAGE子項 值項Bind 存放該協議所在綁定棧的最低層小埠設備實例(即MINIPORT)。 值項Export 存放該服務必須訪問的對象,該對象必須已經安裝在系統中,並且該服務能夠使用。 值項Route 指定子項Linkage從那裡獲取綁定數據。Parameters Adapters子項 這里,我們只解釋中間層驅動中該子項的意義。為此,我們假設當前我們討論的中的XXXX為中間層驅動。 對於中間層驅動,該子項下含有一個子項,是以我們當前中間層驅動綁定的下層MINIPORT設備的GUID命名的,在我的系統中,健值如下:{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子項有個健,名稱為UpperBindings,該健的健值是當前中間層驅動的MINIPORT設備名稱,在我的系統中為如下健值:Device {5BF5A311-13E4-4746-8865-339DDD6C73AF} 在我們的函數NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()中,會調用一系列函數(如NdisOpenProtocolConfiguration、NdisReadConfiguration)來訪問注冊表,其實都是訪問ParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子項。 注意,函數NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()的倒數第二個參數是SystemSpecific1,如果我們安裝的是XPASSTHRU,則其具體指的是如下字元串: xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0} 其中xfilter 是XPASSTHRU的,而{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系統中不同。 函數NdisOpenProtocolConfiguration()其實只是構造一個查詢注冊表的RTL_QUERY_REGISTRY_TABLE結構(該結構在利用函數RtlQueryRegistryValues()查詢注冊表是使用)。並將這個結構封裝到NDIS_WRAPPER_CONFIGURATION_HANDLE結構中,然後作為NdisOpenProtocolConfiguration()的第二個參數返回。 其實NdisOpenProtocolConfiguration()構造的RTL_QUERY_REGISTRY_TABLE結構的含義也就是查詢 xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}下的健值(xfilter 會隨著安裝不同的中間層驅動而不同,{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系統中不同,下面均省略這些注釋)。 函數NdisReadConfiguration()有兩個作用,它首先修改在函數NdisOpenProtocolConfiguration()構造的RTL_QUERY_REGISTRY_TABLE結構。也就是在查詢 xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}的基礎上加上了一個健,將其變成 xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}UpperBindings。然後函數NdisReadConfiguration()會調用函數RtlQueryRegistryValues()查詢新構造的這個注冊表,並將結果存儲在調用函數NdisReadConfiguration()時的第二個參數中。在我的系統中,RtlQueryRegistryValues()讀出的這個新構造的這個注冊表的健值是:Device {5BF5A311-13E4-4746-8865-339DDD6C73AF}(後面我們稱為RESULT1),它其實是我們注冊的中間層驅動(XPASSTHRU)的設備輸出(其構造是Device+GUID)。 其實我們讀出的這個中間層驅動(XPASSTHRU)的設備(即我們剛才讀出的那個健值RESULT1)只在後面的函數()中才用得著,並且RESULT1是作為函數()的第二個參BindAdapterHandler()我們一旦調用了函數NdisOpenAdapter()綁定了一個下層的MINIPORT,為什麼還要調用函數()初始化我們中間層驅動自己的MINIPORT(因為函數()的參數是RESULT1,而RESULT1代表我們中間層驅動的MINIPORT)。為了解釋這個原因,我們先做如下假設。
我們假設我們系統安裝了一個中間層驅動(假設為XPASSTRHU),在上圖中,PROT-IM和MINIPORT-IM分別代表我們中間層驅動的協議驅動程序和小埠驅動程序,PROT-TCPIP代表真正的協議驅動程序,MINIPORT-NIC代表真是網卡的小埠驅動程序。 當PROT-TCPIP需要發送數據時,會調用函數NdisSend(),其實它會調用MINIPORT-IM中的發送數據函數,但是MINIPORT-IM和MINIPORT-NIC沒聯系,按照常規是不能發送數據到MINIPORT-NIC的。但是我們可以看到PROT-IM是可以和MINIPORT-NIC互相發送數據的,所以我們必須將MINIPORT-IM和PROT-IM聯系起來。 另外當MINIPORT-NIC需要將數據提交給PROT-TCPIP時,只能首先將數據提交給PROT-IM,PROT-IM也只能通過MINIPORT-IM才能和PROT-TCPIP聯系起來。 所以必須將PROT-IM和MINIPORT-IM聯系起來。有人說這兩個東西都是我們中間層驅動注冊得,難道還聯系不起來嗎?不錯,但是不管怎樣你都得通過你得代碼才能將他們聯系起來呀!下面我們就介紹聯系得方法。 我們以XPASSTHRU為例,在其函數ProtocolBindAdapter()中,先分配了一個ADAPT結構(這個結構是自己定義的,可根據用戶的需要定義)。當調用函數ProtocolBindAdapter()調用函數NdisOpenAdapter()進行綁定時,是以&Adapt->BindingHandle作為函數NdisOpenAdapter()的第三個參數的,這樣Adapt->BindingHandle就指向了NDIS_OPEN_BLOCK1(注意,調用函數NdisOpenAdapter()時的第三個參數會返回指向綁定以後的NDIS_OPEN_BLOCK指針)。然後函數ProtocolBindAdapter()會調用函數(),該函數會進一步調用XPASSTHRU的NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函數。上面我們討論過,()中的第二個參數就是XPASSTHRU注冊的小埠驅動的設備實例(即上面的RESULT1)。在函數()中會根據設備名稱(RESULT1),找到對應的MINIPORT結構,並將其指針作為參數傳遞給NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函數(以後簡稱InitializeHandler()函數)。在InitializeHandler()函數中,會進一步將MINIPORT結構指針賦值給ADAPT->MiniportHandle(ADAPT就是上面在函數ProtocolBindAdapter()中分配的那個結構)。 這樣數據結構ADAPT中就含有了兩個指針,一個指向NDIS_OPEN_BLOCK1,另一個指向MINIPORT-IM,而NDIS_OPEN_BLOCK1和PROT-IM是密切聯系的,所以ADAPT就將PROT-IM和MINIPORT-IM緊密的聯系起來了。 另外注意,NDIS_MINIPORT_BLOCK->DeviceContext是指向我們的ADAPT結構的,這個賦值在函數()中完成。上面談到了也是在函數()中完成了從ADAPT-> MiniportHandle到MINIPORT的綁定,所以在函數()中完成了ADAPT和MINIPORT的互相連接(即指針互相指向)。函數InitializeHandler()中可以利用句柄MINIPORT的句柄得到我們的ADAPT結構,具體實現這個功能的函數是NdisIMGetDeviceContext(),這個函數的參數是個NDIS_HANDLE類型,但是在該函數內部,會將這個參數轉換成NDIS_MINIPORT_BLOCK結構,並返回NDIS_MINIPORT_BLOCK->DeviceContext。在函數NdisOpenAdapter()中,除了上面提到的完成了由Adapt->BindingHandle到NDIS_OPEN_BLOCK1的指向外,還完成了我們沒有提到的由NDIS_OPEN_BLOCK1-> ProtocolBindingContext到ADAPT的指向,所以函數NdisOpenAdapter()完成了ADAPT和NDIS_OPEN_BLOCK1的互相連接(即指針互相指向)。 講到這里,我們上圖完善為下圖。
8. 學習windows驅動編程有什麼用
驅動程序(Device Driver)全稱為「設備驅動程序」,是一種可以使計算機和設備通信的特殊程序。可以說相當於硬體的介面,操作系統只能通過這個介面,才能控制硬體設備的工作,假如某設備的驅動程序未能正確安裝,便不能正常工作。驅動程序在系統中所佔的地位十分重要, 驅動程序給我的首先印象應該是面對設備與操作系統的,但是並不一定每一個驅動程序都是與硬體相關聯的.在實際的驅動程序開發中不要狹義的理解為硬體,應該理解為設備,硬體也可以叫做設備,在計算機系統中虛擬的也可以是設備,比如 磁碟卷,分區、網路協議、以及其他的設備驅動程序都是設備,那麼與硬體無關的驅動程序,比如NDIS驅動,文件過濾系統驅動、磁碟過濾系統驅動程序、文件透明加密驅動... 他們所面對的設備不一樣而已 我們形象的理解為NDIS是與網路中間層通訊協議(設備)驅動,卷(設備)過濾驅動,文件系統(設備)過濾驅動。驅動程序的強大之處就是因為他在OS核心層(Ring0)運行,在RING0層運行有什麼強大的呢,因為操作系統的保護模式限制,在RING3層很多操作受到限制,比如 直接IO硬體、開啟/關閉中斷等等特權指令必須在RING0層才能執行、如果你在RING3層執行此類代碼就會收到一個類似於 【應用程序指令錯誤】的消息提示,而相關的應用程序也會被WINDOWS終止,在CPU的所有指令中,有一些指令是非常危險的,如果錯用,將導致整個系統崩潰,所以在RING3受到限制.必須在RING0下運行. 如何理解驅動程序的重要性與強大之處,再看看我們在操作計算機的內部流程,我們簡單的理解為 輸入-應用程序--內核-設備,在這里在最後有個『設備』但是某些操作的流程並不是一定是與設備有關的,可能僅僅是一系列的簡單的操作僅僅是與API有關的.比如OpenProcess、 NtTerminateProcess 在應用程序調用的時候,在RING3的最後一步是在NTDLL 最終由NTDLL進入內核 ,基本上可以這樣概括一下,就是所有的操作在進入計算機底層以後都要進過相關驅動程序,在這些功能調用上用個形象的說法 應用層是『標』,那麼驅動層就是『本』,還有就是驅動層作為操作系統與設備(不一定是硬體)的中間橋梁,有著一夫當關的重大作用,哈哈.... 太多說不完,LZ自己找資料看看..
9. 如何把ndis filter框架利用到日膚indows驅動開發工作中
NDIS Filter NET_BUFFER_LIST NET_BUFFER MDL
1
網路數據結構如下圖:
5
第二種方法:
/*******************************************************************GetNetBufferData函數的功能:從1個NET_BUFFER裡面獲取數據。1個NET_BUFFER裡面含有1個或者多個的MDL*******************************************************************/VOIDGetNetBufferData(PNET_BUFFERNetBuffer,PUCHAROutputBuffer,ULONGOutputBufferSize,PULONGOutputBytesCopied){PMDLMdl=NetBuffer->CurrentMdl;*OutputBytesCopied=0;if(NetBuffer->DataLength>OutputBufferSize){#ifDBGDbgPrint("Notenoughoutputbufferspace,in:%d,out:%d ",NetBuffer->DataLength,OutputBufferSize);#endifreturn;}NdisMoveMemory(OutputBuffer,(PUCHAR)MmGetSystemAddressForMdlSafe(Mdl,LowPagePriority)+NetBuffer->CurrentMdlOffset,Mdl->ByteCount-NetBuffer->CurrentMdlOffset);OutputBuffer+=Mdl->ByteCount-NetBuffer->CurrentMdlOffset;*OutputBytesCopied+=Mdl->ByteCount-NetBuffer->CurrentMdlOffset;////循環MDL鏈表,獲取每一個結點的數據,數據被保存到OutputBuffer裡面//OutputBuffer的空間不斷地擴大。//當鏈表不為空,並且OutputBuffer的長度<1個NET_BUFFER的總長度while(((Mdl=Mdl->Next)!=NULL)&&(*OutputBytesCopied<NetBuffer->DataLength)){NdisMoveMemory(OutputBuffer,MmGetSystemAddressForMdlSafe(Mdl,LowPagePriority),Mdl->ByteCount);OutputBuffer+=Mdl->ByteCount;//數據被保存到OutputBuffer裡面*OutputBytesCopied+=Mdl->ByteCount;//OutputBuffer的空間不斷地擴大}if(Mdl!=NULL){NdisMoveMemory(OutputBuffer,MmGetSystemAddressForMdlSafe(Mdl,LowPagePriority),NetBuffer->DataLength);OutputBuffer+=Mdl->ByteCount;*OutputBytesCopied+=Mdl->ByteCount;}#ifDBGDbgPrint("buffercopied:%dbytes ",*OutputBytesCopied);#endif}
6
上面的2種方法,只是獲取數據。而原本NDISFilter框架提供的這4個函數默認的代碼,都沒有做任何操作,沒有實質性質的功能,這4個函數原本默認的代碼,我們都不需要,因為我們的驅動程序需要處理網路數據包。這4個函數分別是:
7
在我們的NDISFilter工程裡面,我們需要修改掉這4個函數的功能,把它們替換成我們所想要的功能。比如,你在發送數據包或者接收數據包的時候,需要實現自己的一些業務邏輯,而不是去使用MicrosoftNDISFilter提供的原始代碼的功能。
8
函數的功能:NDIS調用把發送的結構和數據返還給FilterDriver。NDIS可以收集多次NdisFSendNetBufferLists發送的結構和數據形成一個單鏈表傳遞給。除非到NDIS調用,否則一個發送請求的當前狀態總是未知的。一個過濾驅動是不能在NDIS調用返回結構之前對NET_BUFFER_LIST和其關聯的數據做檢查的。要完成一個發送請求完成後的任何必要的後繼處理。當NDIS調用時,FilterDriver就重新獲地對結構及結構相關資源的所有權。可以在中釋放相關的資源和准備下一個NdisFSendNetBufferLists調用。NDIS總是按照過濾驅動調用NdisFSendNetBufferLists提交的順序傳遞給下層驅動,但是回返的順序則是任意的。FilterDriver可以請求一個回環發送請求,只要把NdisFSendNetBufferLists的SendFlags設置成NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK就行了。NDIS會引發一個包含發送數據的接收包指示。
9
一個FilterDriver應該對自己引發的發送請求保持跟蹤並確保在完成時不調用NdisFSendNetBufferComplete常式。
步驟閱讀
10
FilterSendNetBufferLists函數的功能:NDIS調用一個FilterDriver的FilterSendNetBufferLists常式來過濾上層驅動的發送請求。FilterDriver不能改變其它驅動傳來的NET_BUFFER_LIST結構中的SourceHandle成員的值。它可以過濾數據並發送過濾的數據到下層驅動。
11
對每一個提交到FilterSendNetBufferLists的NDIS_BUFFER_LIST,我們可做下面的操作:
1)可以把緩沖區通過NdisFSendBufferLists傳遞給下層驅動,NDIS保證上下文空間對FilterDriver的有效性。過濾驅動可以在發送前修改緩沖區的內容。可以像處理自己引發的發送請求的緩沖區一樣處理這個緩沖區。2)可以調用拒絕傳遞這個包3)排隊緩沖區內容到本地的供以後處理。例如要在一定超時後處理或要接收到特定包後才處理等。如果支持這種處理方式就要支持取消請求的操作。4)可以拷貝緩沖區並引發一個發送請求。它類似自己引發一個發送請求,但必須先調用NdisFSendNetBufferComplete返回上層驅動的緩沖區。
12
發送請求在驅動棧繼續完成,當一個微埠驅動調用完成一個發送請求時,NDIS會調用微埠
13
在一個發送操作完成後,FilterDriver可以做在FilterSendNetBufferLists中所有修改的相反操作。返回一個NET_BUFFER_LIST結構的單鏈表和發送請求的最終狀態給上層的驅動。當最頂層的FilterMole的被調用完成後NDIS會調用引發發送請求的協議驅動的。如果FilterDriver不提供FilterSendNetBufferLists它還是可以引發一個發送操作的,但它必須提供一個並且不能在這個常式里把這個事件傳遞給上層驅動。
14
一個FilterDriver可以傳遞或過濾一個上層驅動的回環請求,要傳遞一個回環請求,NDIS會設置FilterSendNetBufferLists的SendFlags參數為NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK,FilterDriver在調用NdisFSendNetBufferLists時把這個標記傳給它即可。在回環請求的情況下NDIS會指示一個包含發送數據的接收包。
15
如果一個FilterDriver修改的任何行為不是NDIS提供的標准服務,那麼它應該當自己為NDIS提供相應的服務。例如,如果一個FilterDriver修改了一個硬體地址請求,就必須處理直接到這個新地址回環包。在這種情況下,因為FilterDriver已經更改了地址NDIS是不能提供一個回環服務的。
16
_Use_decl_annotations_VOIDFilterSendNetBufferLists(NDIS_HANDLEFilterMoleContext,PNET_BUFFER_LISTNetBufferLists,NDIS_PORT_NUMBERPortNumber,ULONGSendFlags){PMS_FILTERpFilter=(PMS_FILTER)FilterMoleContext;PNET_BUFFERNetBuffer;UCHARTempBuffer[MAX_BUFFER_SIZE];ULONGBytesCopied;pEthHdrEthernetHeader;pIPHdrIpHeader;#ifDBGDbgPrint(">>>FilterSendNetBufferLists:%p ",NetBufferLists);#endiffor(NetBuffer=NetBufferLists->FirstNetBuffer;NetBuffer!=NULL;NetBuffer=NetBuffer->Next){GetNetBufferData(NetBuffer,TempBuffer,MAX_BUFFER_SIZE,&BytesCopied);if(BytesCopied==0){#ifDBGDbgPrint("Netbuffercatcherror ");#endif}else{EthernetHeader=TempBuffer;if(EthernetHeader->Type==0x0800)//乙太網類型{IpHeader=EthernetHeader+sizeof(EthHdr);//去掉乙太網頭,抓出IP頭#ifDBGDbgPrint("Getippacket ");#endif}}}NdisFSendNetBufferLists(pFilter->FilterHandle,NetBufferLists,PortNumber,SendFlags);}
17
FilterReturnNetBufferLists函數的功能:如果FilterDriver設置了的狀態為NDIS_STATUS_SUCCESS,NDIS通過驅動的FilterReturnNetBufferLists返回指示數據。在這種情況下FilterDriver失去了對NET_BUFFER_LIST的所有權,直到FilterReturnNetBufferLists被調用。FilterDriver調用NdisFIndicateNetBufferLists傳遞接收指示給驅動棧上的上層驅動,如果上層驅動保留了對緩沖區(NET_BUFFER_LIST)的所有權,NDIS會調用FilterDriver的FilterReturnNetBufferLists常式。在FilterReturnNetBufferLists中應該撤消在接收路徑上(如在FilterReciveNetBufferLists中做的一些處理)的操作。當最底層的FilterMole完成對緩沖區(NET_BUFFER_LIST)的處理後,NDIS把緩沖區返回給微埠驅動。如果FilterReceiveNetBufferLists的ReceiveFlags沒有設置NDIS_RECEIVE_FLAGS_RESOURCES標記,FilterDriver調用NdisFReturnNetBufferList返回這個緩沖區數據,如果設置了FilterReceiveNetBufferLists直接返回時就把緩沖區返還給了下層微埠驅動。
步驟閱讀
18
FilterReceiveNetBufferLists函數的功能:FilterDriver調用來指示發送數據。這個函數通過NET_BUFFER_LIST結構給上層驅動指示數據。FilterDriver可以從池中分配這個結構。如果FilterDriver設置了的狀態為NDIS_STATUS_SUCCESS,NDIS通過驅動的FilterReturnNetBufferLists返回指示數據。在這種情況下FilterDriver失去了對NET_BUFFER_LIST的所有權直到FilterReturnNetBufferLists被調用。如果FilterDriver在調用時設置ReceiveFlags為NDIS_RECEIVE_FLAGS_RESOURCES,在函數返回後FilterDriver會立即恢復對NET_BUFFER_LIST的所有權,這時FilterDriver必須立即處理這個NET_BUFFER_LIST的返回,因為NDIS在這種情況下是不會調用FilterReturnNetBufferLists返回NET_BUFFER_LIST結構的。注意:一個FilterDriver應該跟蹤自己引發的接收指示確保它在FilterReturnNetBufferLists中不調用NdisFReturnNetBufferLists。
19
_Use_decl_annotations_(NDIS_HANDLEFilterMoleContext,PNET_BUFFER_LISTNetBufferLists,NDIS_PORT_NUMBERPortNumber,ULONGNumberOfNetBufferLists,ULONGReceiveFlags){PMS_FILTERpFilter=(PMS_FILTER)FilterMoleContext;PNET_BUFFERNetBuffer;UCHARTempBuffer[MAX_BUFFER_SIZE];ULONGBytesCopied;pEthHdrEthernetHeader;pIPHdrIpHeader;#ifDBGDbgPrint(">>>FilterReceiveNetBufferLists:%p ",NetBufferLists,ReceiveFlags,NumberOfNetBufferLists);#endifdo{for(NetBuffer=NetBufferLists->FirstNetBuffer;NetBuffer!=NULL;NetBuffer=NetBuffer->Next){GetNetBufferData(NetBuffer,TempBuffer,MAX_BUFFER_SIZE,&BytesCopied);if(BytesCopied==0){#ifDBGDbgPrint("Netbuffercatcherror ");#endif}else{EthernetHeader=TempBuffer;if(EthernetHeader->Type==0x0800){IpHeader=EthernetHeader+sizeof(EthHdr);#ifDBGDbgPrint("IPpacketexist ");#endif}}}}while(FALSE);
20
調用來指示發送數據。如果FilterDriver設置了的狀態為NDIS_STATUS_SUCCESS,NDIS通過驅動的FilterReturnNetBufferLists返回指示數據。如果FilterDriver設置了的ReceiveFlags值為NDIS_RECEIVE_FLAGS_RESOURCES,那麼在函數返回後FilterDriver會立即恢復對NET_BUFFER_LIST的所有權,這時FilterDriver必須立即處理這個NET_BUFFER_LIST的返回。在這種情況下是不會調用FilterReturnNetBufferLists返回NET_BUFFER_LIST結構的。