我在驅壇生涯的回憶(包含NDIS架構簡述)

我在驅壇生涯的回憶(包含NDIS架構簡述)

by monkeyy 2003-11-29深夜
這篇文章是因爲花貓所寫的《病毒的本質》這篇文章的觸動,讓我有了寫下自己在驅壇所有感悟的衝動,但是又願意在那兒做一個荒唐的獨白或者是弱智般的宣讀教義,所以就寫下了自己關於NDIS結構的理解。也包含一點Windows網絡組件的結構,但是不多,這個東西太龐大了,就是寫一本書也不足爲過。爲防止有的人覺得很無聊和浪費時間,我告訴大家下面的文字大約有5000字左右。不過關於NDIS架構的描述還是值得你去看看,至少到今天我還沒有看到任何關於NDIS架構的文章,如果你有自己的心得,我們的交流將會讓我們彼此有所進步,何樂而不爲呢?下面就是我寫下的文字:

都說人能記得住第一次,並且是一生難忘。我卻忘了自己寫的第一個程序,寫的第一個NDIS驅動,甚至第一次與別人合作別人研究技術。大學四年在我的身上本來有太多的第一次,可是我都忘了,忘的乾乾淨淨,記住這些第一次有什麼意義呢?人總會去踏出第一步,這一步並不是成功,而是你爲了實現成功的第一步。人總是需要去超越自己的環境,自己的背景,不然怎麼能算成功呢?或者這就是所謂的酸葡萄效應,我自身的弱智讓我難以達到真正的成功,於是我開始這樣阿Q起來。這樣去講又有什麼意義呢,在乎別人的看法是重要的,但是用別人的觀點來約束自己卻是不可饒恕的!

驅壇的人也都匆匆的來去,已經不記得誰第一個走,只知道突然有一天胡老大很少露面了,GJP也很少露面了,NDIS版的斑竹只剩下了mikeluo。在驅壇註冊是個偶然的機會,可這個機會卻改變了我太多,而今我的頭兒就是我在驅壇認識的一個網友。還記得那個時候爲了查找在Windows下截獲數據包的辦法,看到很多的RAW Socket,終於在驅壇看到了NDIS這個名詞,終於開始了自己的NDIS之旅。我2001年6月在驅壇註冊的,那個時候的驅壇可以說代表了我國Windows驅動界的最高水平,Huyuguang、Lu0、GJP等等這些高人幾乎天天出沒其間。從我第一次登陸驅壇到今天已經3個年頭了,在驅壇的日子我一直很少說話,因爲知道自己的實力,我一向厭惡誤導別人,如果你沒有十足的把握,那麼你就應該標上討論的字樣,這樣總不會有太多的貽害;所以自己一向很少開口。上大學的時候私下裏和別人合作研究過技術,最後終於成爲了不錯的朋友,我仍然喜歡這種人與人的交往,哪怕從來沒有見過面,只是在電話的這頭聽到過他的聲音,哪怕自己做的一切都是沒有報酬的,哪怕別人只是在電話那頭說了一句“來北京,我一定好好請你吃頓飯”,這都無關緊要,我需要的僅僅是技術,而不是報酬。但是我仍然喜歡不多說話,可能有人要說是保守,實際上在Winsdows下進行NDIS驅動開發只要不使用微軟反對的方法,一般沒有什麼高深的。如果你要研究一些Native的話,確實需要很高的技術,我想這個也就是GJP、Lu0、胡老大這些高人可以做了,所以自己也從來不去試圖這樣的研究。我同意花貓的話,編程需要的是資料和耐性。

我一直以爲個人防火牆的檢測技術急需更新,現今的個人防火牆檢測技術已經無法應對個人網絡安全了,怎麼去更好的保密數據和系統的完整性已經是最重要的問題了。可是到今天我仍然沒有看到天網、諾頓等等這些個人防火牆有什麼舉措,可能有人要說我狂妄。那麼問問在NDIS版兄弟們,做一個天網需要的是什麼,除了時間還有別的嗎?無論它用NDIS還是TDI甚至是SPI,早就沒有什麼技術可言了,需要的僅僅是怎麼去組合他們。軟件只是一種工具,好的軟件技術無法替代劣質的軟件思想。象天網這樣的防火牆縱然是使用TDI與NDIS的雙層過濾,縱然是使用我們至今未能知道的NDIS HOOK技術又能怎麼樣呢?它能彌補它在檢測模式上的弱智嗎?不能,永遠不能。可惜人們已經放棄了在個人防火牆上進行一次檢測模式更新,完全放棄了。我仍然同意老莫的話,在網絡安全中驅動開發是必須和很小的一部分,加、解密、認證、入侵檢測等等纔是真正需要掌握的!

說了這麼多我並不是要評判什麼,我也沒有任何權利去幹涉別人的工作和生活,就算是對現在纔來到NDIS版的朋友們的一點意見吧,希望不會給你們造成太多的誤導。

現在來寫點東西吧,在網上關於NDIS的文章確實很多了,但是直到今天我還沒有在國內的什麼地方看到過關於NDIS架構的文章或者是Windows網絡組件架構的文章(國外的很久沒有去了,以前也沒有看到過)。要寫點東西還是寫點不曾見到的吧,衆所周知的文字翻來覆去的描寫,除了助長自己囂張的氣焰和滿足自己的虛榮可能就沒有別的用處。

Windows網絡組件的架構確實比較複雜,尤其是在應用太和核心太的交界處,爲了實現Sokcet操作的接口統一、減少核心太與應用交互的麻煩與在文件系統中支持網絡操作,這個接口做了很多複雜的處理,說起來真的是很繁,再加上在這個交界處我寫過的測試程序很少,所以也就不再多言了,只是在下面給出一張Windows網絡組件的結構圖,這個圖當初費了很大的工夫才畫出來,畫出來後的不久就在PCAUSA看到了,雖然有些出入,但是我相信自己在架構上的理解是沒有錯誤的,那些測試程序給了我信心。

Windows網絡組件體系結構
對於NDIS結構我覺得已經沒有任何必要去談Miniport或者是Protocol了,如果有疑問的話,就應用自己去找資料或者是看看DDK、MSDN的文檔了,在網上關於這個的文字已經很多了。我個人認爲對於NDIS結構的理解千萬不要過於相信微軟的文檔,這就是我直到今天一個最大的心得,可以說微軟關於NDIS架構的描述有誤導的嫌疑。相反,當你自己搞清楚了WDM驅動,更確切的說是微軟的驅動模型之後你就會發現,NDIS並不是一個和其它驅動不同的驅動,相反它們的本質結構是一致,不同之處只是因爲網絡驅動所需特性讓微軟在原來的驅動模型上做了一些修改,這就是NDIS架構的本質。下面就讓我們從微軟的誤導開始來看NDIS的架構,其中也許存在着謬論,但是我想這樣的謬論也還是值得一寫的!J

1、關於IMD中Protocol與Miniport的關係,微軟說他們是上下層次關係,初一看這明顯是錯誤。從邏輯的角度看他們應該是並行關係,一個爲TCP/IP協議送出數據,一個爲TCP/IP協議接收數據。如果是上下關係,那這個數據怎麼能夠順利的發送、接收呢?實際上在這裏微軟已經隱約的道出了NDIS架構的實質,但是由於缺乏足夠的解釋,在這裏通常會給Developer們造成一種誤導,覺得這個存在矛盾。

2、實際上微軟說的並沒有錯,確實是上下結構,並且就是我們在Device Attach中看到的上下結構。但是在軟件的數據流程上,它確實是並行的結構,它只是將原本一條數據通道根據方向的不同改成了兩個通道。

3、最有意思的東西就要開始,NDIS同分層驅動模型沒有任何的差別,而微軟似乎一直在掩蓋的東西,它的文檔中沒有任何關於這個的說明,除了上面提到的那個隱約的說法。以前大家常說的在IMD中存在反向綁定就是一個例子,實際上並不存在反向綁定,那個所謂的反向綁定是對Device Attach的另一種說法。
要說清楚這個東西,我們就需要來說說真正的虛擬網卡與IMD中Miniport驅動的區別。在IMD中,當Protocol綁定到真正的網卡後會初始化一張虛擬的網卡讓TCP/IP協議來綁定,可是我們都知道這個虛擬的網卡並不能在設備管理器中顯示出來,我們並不能爲它設置IP等等信息,而使用NdisIMRegisterLayeredMiniport這個東西就可以虛擬一張真正的網卡!爲什麼呢?因爲在IMD中並沒有建立什麼真正的網卡設備,而只是爲已經存在的網卡設備建立了一個設備實例,然後將這個實例Attach到真正的網卡設備實例上,這就是典型的Windows下的分層驅動模型。那麼我們就應該想到爲什麼微軟要這麼做呢,爲什麼不象TDI或者是其它分層驅動那麼直接Attach Device還有搞個Protocol這個東西。我想原因有二,一是爲了不破壞NDIS架構的完整性,因爲NDIS最基本的架構就是協議和小端口;二是爲了保持網絡驅動的特性。現在我們來看看網絡驅動的特性,網卡設備不是簡單的Device Object,因爲Device Object是對設備的通用抽象,它無法表示網卡驅動特性。對一個網卡來說最重要的就是Interface概念,在應用程序中,通常不會去指定本地IP地址,比如你用JAVA或者.NET去連接某個主機,這個動作最終轉化成Socket動作,Socket根據協議族類型來挑選WSH DLL,然後由WSH DLL負責和協議驅動進行交互,實際上解析Socket的動作是在WSH DLL中進行的。但是在多網卡、多IP的環境中,應用程序無法去選擇使用哪個IP作爲本地IP,因爲它不知道任何的路由信息,所以它只能向協議驅動傳送一個通配符地址,然後由協議驅動來選擇本地IP和網卡。我想大家都知道了網卡驅動的特性了,那就是路由中關於Interface的問題。如果微軟同意我們隨意在網卡設備上的Attach Object,同時保持路由,那麼整個路由部分將是十分的混亂,所以要開發可以配置IP等網絡信息的虛擬網卡需要微軟做特殊的處理。我以爲這就是微軟的工程師們爲什麼在IMD中並不實現真正的虛擬網卡的原因;主要是路由信息的混亂,IMD中Miniport本身只是一個網卡設備的實例,我們爲它添加路由信息是不符合邏輯和無法想象。我們不得不承認微軟的工程師在軟件結構的設計上確實很厲害,在我看來Linux就要差許多了,至少我沒有在Linux中看到任何這樣的東西。

上面只是說了TCP/IP協議和網卡在NDIS中的問題,這也是目前我們開發中最常用到的地方,說到這裏我突然想起了另一個問題。ATM承載IP網卡的驅動,現在世面上已經存在ATM承載IP的網卡了,它的技術難點又在哪兒呢?我曾經有幸膚淺地做過這樣的事情,但不是很深入,只是略知一點點。他們的技術難點主要在於網卡設備類型的轉換和具體協議相關動作解析上。ATM和Eternet是不同的網絡類型,在數據鏈路層是完全不同的,那麼我們如何將下端的ATM類型的網卡設備轉化爲以太網卡設備讓TCP/IP來綁定,這個實現我一直沒有機會去實驗,因爲沒有ATM的網卡,但我覺得應該不是太難,不過這話仍然值得商榷。協議相關動作解析是比較困難和繁瑣的事情,比如在ATM中沒有MTU的問題,然而在TCP/IP中會向網卡查詢MTU,那麼這個ATM承載IP的網卡該如何回答TCP/IP協議的查詢呢?當然這個例子是比較簡單的,比較複雜的應該是ATM中所有信令的模擬,這將消耗Developer許多的精力。

實在話,我很久就不再去崇尚程序設計技術;相反,那麼優秀的軟件架構更容易引起我的興趣。所以當我搞清楚Windows網絡組件的結構時,真的很驚訝,尤其是從Winsock SPI到WSH DLL這一段結構上的處理,可以說是應用太和核心太交互同時支持多接口的典範。原來我一直在想,在已經存在了Base SPI這個東西之後爲什麼微軟的工程師還要設計出WSH DLL這個東西,在Base SPI中就已經將Socket中的協議族解析結束了,也就是說已經確定了應用程序使用的是TCP/IP協議還是IPX/SPX協議還是NetBEUI協議,他們爲什麼還有加一個WSH DLL這一層來具體的根據協議類型來解析Socket的動作。後來才發現是爲了文件系統直接操作網絡的支持和科學的細分模塊的需要,在這個中間我確實第一次感到了微軟的工程師們在設計上的精湛。關於文件系統支持網絡操作,我在做網絡組件的探討時,只是爲了找到在Windows中嵌入一個讓Winsock支持的全新的協議,並沒有說到一定要文件系統也支持該協議,所以沒有詳細的分析過文件系統對網絡支持的具體模型,在這裏也就不再多言,所以在上面的圖中我也未曾畫出來,因爲對於這個東西我基本沒有寫過什麼真正的測試代碼。

NDIS是一個設計很優秀的接口模塊,同時在Windows網絡組件中這樣的接口至少還有TDI、SPI,但是他們都是各有區別,在細節上都有一些不同。我真的很佩服微軟的工程師在軟件架構上的設計,所以我覺得我們不應該只去研究他們的實現以後的東西、怎麼去找到一個undocument函數、怎麼去突破一種限制,我們應該去研究一些他們實現的架構,這些架構真的是很精湛。或許是我的弱智才認爲這個東西很神奇,但是你還是應該去嘗試一下,這會給你帶來很多的驚喜!

實際上Windows網絡組件是一個很龐大的結構,我真的很難去了解太多,我僅僅是一個比較能吃苦的程序員而已。同時由於內容很多,很繁雜,所以很難用文字的方式將它表述的很清楚,所以我覺得自己不可能去寫書,呵呵!

希望能有高手來講解一下Windows網絡組件中優秀的架構設計!這裏面真地有許多值得我們學習和借鑑的!

這篇文章是爲了回花貓的,他寫了一個《病毒的本質》,希望大家不要迷信病毒編寫是多麼的神奇。我是寫這個東西,想告訴大家我的一點看法。對於Windows下的NDIS驅動開發是很簡單的,不要去迷信神話,但是對NDIS架構的掌握是不容易的,所以胡老大是我一直很尊敬的人。同時,我們不應該只去研究微軟已經實現的東西,應該也抽點時間去看看他們的總體結構,看看他們的軟件架構,這同樣是我們應該學習的!

如果有什麼意見和建議,或者是想要討論些什麼東西,請使用
發佈了61 篇原創文章 · 獲贊 12 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章