這篇文章是我十年前寫的第二篇在雜志上發(fā)表的文章。發(fā)表在微電腦世界1997年的第三期上。
那個(gè)年代我對(duì)計(jì)算機(jī)病毒也非常感興趣。在九二年我剛上大學(xué)時(shí)候,對(duì)計(jì)算機(jī)病毒其實(shí)一點(diǎn)概念也沒有,只是感覺計(jì)算機(jī)病毒是很神秘很高深的東西。對(duì)于病毒程序能夠在不同電腦之間傳播,那時(shí)感覺很不可思議。
那的確是個(gè)很古老的時(shí)代,我們用的操作系統(tǒng)是DOS 3.31,學(xué)的是TRUEBASIC,電腦是33M主頻的PC/AT,286是當(dāng)時(shí)最先進(jìn)的機(jī)器。那時(shí)候的電腦病毒也很有意思,比如小球病毒,就是一個(gè)活蹦亂跳的小圓點(diǎn),不停地運(yùn)動(dòng),當(dāng)碰到屏幕邊沿就立刻反彈。雨點(diǎn)病毒則是一些下落的雨點(diǎn)或字符。64/Bloody病毒則是在屏幕上顯示血紅的Bloody文字。
計(jì)算機(jī)系的大學(xué)老師們對(duì)病毒其實(shí)也很感興趣,記得一個(gè)老師曾經(jīng)指著小球病毒的匯編代碼跟我們說:整個(gè)中國會(huì)編這個(gè)病毒的人不超過10個(gè)。
最開始的病毒破壞力都很小,在現(xiàn)在看來,甚至有些可愛。我估計(jì)都是一些高手在編寫病毒,寫病毒的目的大概是為了炫耀自己的編程能力。DOS病毒幾乎全是用匯編寫的代碼,匯編語言其實(shí)和二進(jìn)制機(jī)器語言差不多,用那個(gè)東西寫程序可真是一場(chǎng)噩夢(mèng)啊,我曾經(jīng)寫過一個(gè)八百多行的匯編程序,寫的我頭暈?zāi)X漲,我知道,用匯編來寫一個(gè)病毒的確不是一件容易的事情,特別是一些病毒甚至還有自身加密、變種的功能,因此,那些人也的確值得炫耀一下的。不過現(xiàn)在,匯編語言我都快忘光了,原因很簡單,用機(jī)器代碼寫程序的可維護(hù)性很差,自然用的人也肯定會(huì)越來越少。
大學(xué)畢業(yè)后的幾年,我逐漸對(duì)這些失去了興趣,主要因?yàn)橐恍┯?jì)算機(jī)業(yè)的害群之馬影響了我的心情,CIH病毒開了一個(gè)惡劣的開頭,對(duì)電腦用戶的資料信息甚至硬件進(jìn)行惡性破壞,而后的病毒似乎在比誰更不要臉,現(xiàn)在互聯(lián)網(wǎng)的普及,以及一些腳本語言的流行,編寫木馬病毒門檻非常低了,菜鳥都可以寫木馬病毒了,而現(xiàn)在的木馬病毒清一色全是惡性病毒,不是偷密碼、彈廣告就是改IE,甚至還出了HAO123這樣依靠木馬病毒發(fā)家的“成功案例”,但這些病毒的編寫目的都令我感到惡心,對(duì)于那些低劣的病毒編寫者,我只覺得他們可憐,讓他們繼續(xù)為了他們那低劣的理想和愿望而編寫病毒吧,我還有更重要的事情要做呢。
下面是我寫的論文,其目前已經(jīng)沒有實(shí)際意義,因?yàn)橥獠凯h(huán)境發(fā)生了巨大變化,我寫那篇論文的前提是“計(jì)算機(jī)病毒大部分不是惡性病毒”的基礎(chǔ)上,甚至執(zhí)行病毒代碼來還原恢復(fù)原始程序,現(xiàn)在的環(huán)境下這已經(jīng)不可能了,現(xiàn)在是什么世道?誰敢運(yùn)行病毒啊!
計(jì)算機(jī)病毒的通用清除技術(shù)
摘要 本文就當(dāng)前流行的文件型病毒出發(fā),分析介紹了從文件結(jié)構(gòu)特性入手清除計(jì)算機(jī)病毒的一種技術(shù).
關(guān)鍵字 病毒 傳染 加載執(zhí)行(EXEC) 文件前綴段(PSP) 進(jìn)程
計(jì)算機(jī)病毒的發(fā)展歷史悠久,從80年代中后期廣泛傳播開來.時(shí)至今日,據(jù)統(tǒng)計(jì)世界上已存在的計(jì)算機(jī)病毒有5000余種,并且每月以平均幾十種的速度增加.計(jì)算機(jī)病毒的發(fā)展一定程度上影響了反病毒產(chǎn)品的發(fā)展,原有的反病毒技術(shù)在新型病毒面前顯得陳舊而無能為力.病毒檢測(cè)產(chǎn)品是以病毒的特征碼為基礎(chǔ)的針對(duì)具體病毒的判斷技術(shù),因此,病毒的變種以及未知病毒給檢測(cè)軟件帶來較大的困難.病毒的清除是建立在病毒檢測(cè)的基礎(chǔ)上,目前病毒的清除實(shí)際上是針對(duì)已知病毒.這種被動(dòng)式的方法使反病毒技術(shù)總是落后于病毒技術(shù),雖然這類反病毒產(chǎn)品對(duì)病毒的抑制是不容忽視的,但它所暴露出來的漏洞卻越來越多.新一代的開放式反病毒技術(shù)應(yīng)運(yùn)而生,這種開放式反病毒技術(shù)將病毒的結(jié)構(gòu)用一個(gè)統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)加以描述,用戶可以根據(jù)自身對(duì)病毒進(jìn)行分析,并具有更加靈活的升級(jí)優(yōu)勢(shì),對(duì)于新一代具有反跟蹤,加密技術(shù)的多維變異病毒,這種方法顯示出其靈活及高效的特色,這種廣譜型的查毒殺毒系統(tǒng)將逐漸成為反病毒產(chǎn)品的發(fā)展趨勢(shì).
下面,本文將介紹一種基于可執(zhí)行文件結(jié)構(gòu)特性的通用殺毒技術(shù).
首先,我們先了解一下計(jì)算機(jī)病毒的結(jié)構(gòu)特點(diǎn)以及其工作原理.
計(jì)算機(jī)病毒的結(jié)構(gòu)決定了計(jì)算機(jī)病毒的特點(diǎn),大致歸納如下:
(1) 計(jì)算機(jī)病毒是一段可執(zhí)行的程序
計(jì)算機(jī)病毒和其它合法程序一樣,是一種可存儲(chǔ)可執(zhí)行的非法程序,它可以直接或間接地運(yùn)行,可以隱蔽在可執(zhí)行程序和數(shù)據(jù)文件中而不易被人們察覺和發(fā)現(xiàn).在病毒程序運(yùn)行時(shí),其與合法程序爭(zhēng)奪系統(tǒng)的控制權(quán).
(2) 計(jì)算機(jī)病毒的廣泛傳染性
由于病毒一詞來源于“生物學(xué)”,傳染也相應(yīng)成為計(jì)算機(jī)病毒的一個(gè)重要特性.傳染性是衡量一種程序是否為病毒的首要條件.計(jì)算機(jī)病毒的傳染性是計(jì)算機(jī)病毒的再生機(jī)制,病毒程序一旦進(jìn)入系統(tǒng)與系統(tǒng)中的程序接在一起,它就會(huì)在運(yùn)行這一被傳染的程序之后開始傳染其它程序.這樣一來,病毒就會(huì)很快地傳染到整個(gè)計(jì)算機(jī)系統(tǒng).
(3) 計(jì)算機(jī)病毒的潛伏性
計(jì)算機(jī)病毒的潛伏性是具有依附于其它媒體而寄生的能力.一個(gè)編制巧妙的計(jì)算機(jī)病毒程序,可以在幾周或者幾個(gè)月甚至幾年內(nèi)隱藏在合法文件之中,對(duì)其它系統(tǒng)進(jìn)行傳染,而不被人們發(fā)現(xiàn).計(jì)算機(jī)病毒的潛伏性于傳染性相輔相成,潛伏性越好,其在系統(tǒng)中存在的時(shí)間就會(huì)越長,病毒的傳染范圍也就會(huì)越大.
(4) 計(jì)算機(jī)病毒的可觸發(fā)性
計(jì)算機(jī)病毒一般都有一個(gè)觸發(fā)條件:或者觸發(fā)其傳染,或者在一定條件下激活計(jì)算機(jī)病毒的表現(xiàn)部分或破壞部分.觸發(fā)實(shí)質(zhì)上是一種條件控制,一個(gè)病毒程序可以按照設(shè)計(jì)者的要求,在某個(gè)點(diǎn)上激活并對(duì)系統(tǒng)發(fā)起攻擊.
(5) 計(jì)算機(jī)病毒的針對(duì)性
現(xiàn)在世界上出現(xiàn)的計(jì)算機(jī)病毒,并不是對(duì)所有計(jì)算機(jī)系統(tǒng)都進(jìn)行傳染的.例如,有針對(duì)IBMPC及其兼容機(jī)的,有針對(duì)APPLE公司的Macintosh的以及針對(duì)Unix操作系統(tǒng)的.現(xiàn)在流行的絕大多數(shù)計(jì)算機(jī)病毒都是針對(duì)基于MSDOS系統(tǒng)的IBM PC及其兼容機(jī)的.
(6) 計(jì)算機(jī)病毒的衍生性
由于計(jì)算機(jī)病毒本身是一段計(jì)算機(jī)系統(tǒng)可執(zhí)行的文件(程序),所以這種程序反映了設(shè)計(jì)者的一種設(shè)計(jì)思想.同時(shí),又由于計(jì)算機(jī)病毒本身也是由幾部分組成的,如安裝部分,傳染部分和破壞部分等,因此這些模塊很容易被病毒本身或其它模仿者所修改,使之成為一種不同于原病毒的計(jì)算機(jī)病毒.[1]
計(jì)算機(jī)病毒按鏈接方式可分為以下幾類:
(1)源碼型病毒 (Source Code Virus) (2)入侵型病毒 (Intrusive Virus) (3)操作系統(tǒng)病毒 (Operating System Virus) (4)外殼型病毒 (Shell Virus).
(1)(2)攻擊的是高級(jí)語言編寫的源文件及目標(biāo)文件,在微機(jī)上很少見,(3)即引導(dǎo)區(qū)病毒,主要攻擊計(jì)算機(jī)的Boot區(qū),其診治方法較為簡單,一般用DEBUG或NU等工具就能方便地清除.本文所提的病毒專指目前在PC在機(jī)上流行最廣的攻擊可執(zhí)行文件的外殼型病毒.
計(jì)算機(jī)外殼型病毒是將其自己包圍在主程序的四周,對(duì)原來的程序不作修改.外殼型病毒易于編寫,也較為常見,但診治卻較為麻煩.
外殼型病毒具有以下特點(diǎn):
自身復(fù)制在目標(biāo)文件外圍(即文件尾部);不修改原來正常文件[2];運(yùn)行時(shí)病毒搶先進(jìn)入內(nèi)存.病毒執(zhí)行完后,轉(zhuǎn)回原文件入口運(yùn)行(隱蔽性).
在基于DOS操作系統(tǒng)PC機(jī)上,外殼型病毒主要攻擊的目標(biāo)是兩類可執(zhí)行文件:COM文件與EXE文件.COM文件結(jié)構(gòu)比較簡單,解毒比較容易.而廣泛流行的EXE文件相對(duì)復(fù)雜,但操作卻更靈活,適合于超過64K的程序,更易與將來的操作系統(tǒng)兼容,因此得到廣泛的使用.
COM文件是DOS的一種二進(jìn)制代碼的可執(zhí)行文件,COM文件結(jié)構(gòu)比較簡單,加載過程十分迅速.整個(gè)程序只有一個(gè)段.因此全部代碼長度必須小于64K,其入口代碼地址是CS:100H.DOS裝入COM文件時(shí),先在內(nèi)存建立一個(gè)長度為100H的程序前綴段(PSP,由DOS建立,是DOS用戶程序和命令行之間的接口),然后將整個(gè)文件裝載于PSP上端,不進(jìn)行重定位操作,接著將四個(gè)段地址寄存器DS(Data Segment),CS(Code Segment),SS(StackSegment),ES(Extra Segment)初始化為程序前綴段(PSP)的段地址,最后將程序的控制權(quán)交于CS:100H處.如表1所示.
表1: COM文件的裝入執(zhí)行
地址 | 內(nèi)容 | |
XXXX:0000 | PSP | ← CS,DS,ES,SS |
XXXX:0100 | 程序代碼 | ← IP |
數(shù)據(jù) | ||
堆棧 | ← SP |
寄生于COM文件的病毒,大部分是采用保存文件頭若干字節(jié),并將第一條指令改為”JMP病毒入口”,以確保病毒最先執(zhí)行,也有部分病毒附加在文件首部,病毒執(zhí)行完后恢復(fù)寄生程序原先的狀態(tài),并用JMPFAR等指令使程序再次回到CS:100H處,以確保寄生程序與PSP的一致.
可見,病毒執(zhí)行完后,必將會(huì)恢復(fù)并運(yùn)行原文件,以便傳播,當(dāng)其將原文件參數(shù)全部恢復(fù)后,會(huì)將控制權(quán)交于CS:100H處.因此,判別COM文件的真正入口的標(biāo)準(zhǔn)是:最后一次在CS:100H處執(zhí)行的程序段(CS=當(dāng)前PSP段地址,IP=100H).
于是,可以設(shè)想出這樣一種跟蹤器,每執(zhí)行一條指令,便判斷上述條件是否滿足,如果滿足,則此時(shí)CS:100H處的代碼便是原文件的影像,由于COM文件只有一個(gè)段,因此此時(shí)內(nèi)存的影像既是磁盤文件的內(nèi)容.將CS:100H處的代碼寫回原文件,此病毒即被消除了,如果知道病毒的長度,還可將文件尾的無用代碼去掉,這樣病毒就物理上消除了.
設(shè)想的跟蹤器的實(shí)現(xiàn)是核心問題,也是主要的難點(diǎn).事實(shí)上單步陷阱中斷(INT 1)完全符合跟蹤器的條件,但由于目前的計(jì)算機(jī)病毒廣泛采取破壞單步斷點(diǎn)的技術(shù),因此這種跟蹤器在具體實(shí)現(xiàn)上還有一定難度.
目前有一種比較方便的替代方法,即DOS的EXEC(INT21H的功能4BH,加載執(zhí)行)功能,此功能有一個(gè)有趣的現(xiàn)象,即執(zhí)行完加載程序后,它會(huì)將所有寄存器恢復(fù)到執(zhí)行前的狀態(tài),并且它不清除內(nèi)存,此方法易于實(shí)現(xiàn),操作簡便,但對(duì)所處理的文件有一定的要求及限制.
具體實(shí)現(xiàn)是,先保存中斷向量表,然后在分配一塊內(nèi)存,調(diào)用DOS的EXEC功能執(zhí)行被感染的COM文件.執(zhí)行結(jié)束后,重寫中斷向量表以清除內(nèi)存中的病毒,然后將內(nèi)存偏移100H上的代碼寫入文件,文件長度為原文件長度,最后,在知曉病毒長度的情況下去掉文件尾的病毒代碼,清除工作結(jié)束.
這種技術(shù)可以對(duì)付任何一種文件型病毒,但對(duì)于COM文件卻有一定的要求:即文件在執(zhí)行過程中不可以修改代碼段的內(nèi)容,未被加密或壓縮的文件一般均可滿足此條件.
四 使用調(diào)試器DEBUG.COM的EXEC功能
更簡單的方法是用DEBUG來實(shí)現(xiàn),先用L命令裝入一個(gè)文件,再用G命令運(yùn)行,EXEC功能結(jié)束后,返回寄存器與運(yùn)行前完全一樣,此時(shí)用W命令存盤,這時(shí)病毒便被清除了.(全過程只用了三條命令)
EXE文件是DOS系統(tǒng)最為常見且靈活的可執(zhí)行文件,其應(yīng)用十分廣泛.但EXE文件的結(jié)構(gòu)要比COM文件復(fù)雜得多.EXE文件由文件頭(Header)和裝入模塊(Load Module)兩大部分組成.文件頭由格式化區(qū)(Format Area)和重定位表(RelocationTable)組成.裝入模塊為程序代碼部分,從位移量100H字節(jié)開始.DOS系統(tǒng)在調(diào)用EXE文件時(shí),先在內(nèi)存塊底部建立一個(gè)程序前綴段(PSP),再將裝入模塊讀入內(nèi)存指定區(qū)域(PSP上方),DS和ES初始化為PSP段地址,CS,IP,SS,SP由文件頭格式化區(qū)確定,并通過重定位參數(shù)調(diào)整.然后根據(jù)重定位項(xiàng)修改代碼數(shù)據(jù),最后將程序的控制權(quán)由CS:IP傳遞給目標(biāo)程序. (如表2所示)
表2: EXE文件的裝入執(zhí)行
地址 | 內(nèi)容 | |
XXXX:0000 | PSP | ← DS,ES |
XXXX:0100 | 數(shù)據(jù) | |
程序代碼 | ← CS:IP | |
堆棧 | ← SS:SP |
對(duì)于EXE文件而言,計(jì)算機(jī)病毒主要是附著于宿主文件的尾部,由于它必須首先獲得程序的控制權(quán),因此它必須對(duì)文件頭進(jìn)行修改.一般來說,只要恢復(fù)了正確的文件頭,便可達(dá)到殺毒的目的.
EXE文件被加載時(shí),系統(tǒng)根據(jù)EXE文件頭的CS:IP參數(shù)確定第一條執(zhí)行語句,因此病毒只需將CS:IP地址指針修改,便可首先執(zhí)行,事實(shí)上,大多數(shù)病毒僅僅只修改了文件頭,而未修改原文件內(nèi)容.這便為完整地恢復(fù)原程序代碼提供了條件.
從上面的分析可知,感染病毒的EXE文件尾部形成明顯的層次,CS:IP指向病毒體,不管病毒采取什么樣的措施,它最終必定會(huì)在內(nèi)存中恢復(fù)宿主程序所有的真實(shí)參數(shù),并且用一條長跳轉(zhuǎn)指令返回原程序.這時(shí),我們便可直接提取出正確的CS:IP和SS:SP參數(shù)指針,用它修改文件頭后,再將外層病毒代碼去掉,這便徹底地恢復(fù)了原EXE文件.
問題在于如何找到EXE文件的正確入口.判斷EXE文件的真正入口是十分復(fù)雜的,但對(duì)于基于DOS系統(tǒng)的病毒來說,其編寫語種基本上是匯編語言,因此便具有一些獨(dú)特的特點(diǎn).經(jīng)過大量分析看出,一般情況下,當(dāng)EXE病毒執(zhí)行到真正的文件開頭時(shí),其CS和DS均要改變,并且DS內(nèi)容必定是PSP段地址,SS:SP指針被初始化,對(duì)于不修改重定位表的病毒來說,CS:IP指針應(yīng)處于重定位區(qū)域內(nèi).
于是,可以再設(shè)想出這樣一種跟蹤器,每執(zhí)行一條指令,便判斷上述條件是否滿足,如果滿足,則此時(shí)CS:IP處的代碼便是原文件的影像,根據(jù)CPU各個(gè)寄存器的內(nèi)容便可正確地恢復(fù)EXE文件頭,以達(dá)到殺毒的目的.
同COM文件殺毒一樣,這種理論上的跟蹤器實(shí)際上是很難奏效的.因此,我們又要求助于我們的老朋友--EXEX功能.
MS DOS的功能4B有兩個(gè)重要的子功能:4B00為裝入并執(zhí)行,4B01為裝入不執(zhí)行(未公開的文檔功能),4B00用于執(zhí)行所有的可執(zhí)行程序,4B01則用于DEBUG調(diào)試器中的裝入功能.(關(guān)于4B01功能的具體參數(shù)見附錄1).
由于問題的關(guān)鍵在于如何找到原程序的第一條指令,也就是說在執(zhí)行到原程序的第一條指令時(shí)發(fā)生中斷,因此我們可以人為地將第一條指令改為中斷指令.為了完成這種功能,只需用4B01功能來仿真4B00功能.
具體是這樣做的,當(dāng)系統(tǒng)調(diào)用加載執(zhí)行功能4B00時(shí),先用功能4B01加載,并初試化所有參數(shù),這時(shí)內(nèi)存的影像應(yīng)如表3所示.
表3: EXE 染毒程序內(nèi)存影像
地址 | 內(nèi)容 |
原程序代碼區(qū) | |
CS:IP→ | 病毒代碼區(qū) |
假定病毒的第一條指令處于病毒代碼的最前端,原程序的內(nèi)存影像應(yīng)為PSP:100~CS:IP(病毒的第一條指令),將這部分區(qū)域全部用ASCII碼CD填充.這樣,原程序的每一條指令都變成了中斷指令I(lǐng)NT CD(不用INT3斷點(diǎn)中斷是因?yàn)榇蟛糠植《径季哂衅茐膯尾綌帱c(diǎn)中斷的功能),也就是說,無論從原程序的任何地址開始運(yùn)行,所執(zhí)行的第一條指令都是INTCD.這樣,一旦病毒代碼執(zhí)行完畢,打算用長跳轉(zhuǎn)指令返回原程序執(zhí)行時(shí),都會(huì)觸發(fā)軟中斷INT CD,而通過INTCD的中斷服務(wù)程序便可取得EXE文件頭真正的初始化CS:IP和SS:SP指針.
另外值得注意的是,修改后的INT 21必須是可遞歸的,因?yàn)橛行┎《?如新世紀(jì)病毒)是通過第二次加載原程序來返回的,因此,內(nèi)存填充要進(jìn)行兩次.4B01也被調(diào)用了兩次.
此方法的效率和準(zhǔn)確度要遠(yuǎn)遠(yuǎn)高于用DEBUG等工具逐步跟蹤分析的手工殺毒法.可以為各種染上已知或未知病毒的文件去除病毒外殼.與RCOPY等去殼程序不同的是,這種方法對(duì)EXE程序的恢復(fù)是全真的恢復(fù),它并不改變?cè)璄XE文件的任何內(nèi)容.它所恢復(fù)的EXE程序代碼應(yīng)與原EXE程序代碼完全一樣.另外,此法由于采用了剝殼還原法,因此還可以用來清除交叉感染的病毒,方法是從外到內(nèi)逐層脫殼,最后徹底恢復(fù)最內(nèi)層的宿主文件.
本文所論述的這種清除病毒的方法的實(shí)現(xiàn)原理是非常獨(dú)特的.當(dāng)然,文中所給出的實(shí)現(xiàn)方案并不能清除所有的計(jì)算機(jī)病毒,但它卻給出了一種思想,即拋棄以前那種一個(gè)殺毒算法只能殺一個(gè)病毒,而是一個(gè)算法可以殺一類病毒.根據(jù)這種思想,筆者已用C語言和匯編語言編寫出這個(gè)通用殺病毒程序,并且用大量的病毒對(duì)它進(jìn)行了測(cè)試,效果良好.當(dāng)然,病毒是五花八門的,因此一個(gè)統(tǒng)一的病毒對(duì)抗軟件應(yīng)接受廣泛的考驗(yàn).其具體的功效還需要多方面的驗(yàn)證,筆者也僅僅希望這種思想能夠在反病毒領(lǐng)域發(fā)揮出積極的作用.
參考文獻(xiàn)
1. 李向宇 著 <<計(jì)算機(jī)病毒概論>> IDG國際數(shù)據(jù)集團(tuán) 1990
2. Ray Dancan <<高水平MS DOS程序設(shè)計(jì)>> 電子工業(yè)出版社 1988
Ray Dancan Advanced MS-DOS Programing Microsoft Press 1988
3 . Ray Dancan <<MS DOS百科全書>> 電子工業(yè)出版社 1990
Ray Duncan the MS-DOS Encyclopedia Microsoft Press 1990
附錄:MS-DOS EXEC功能詳解
翻譯人:William Long 于1996年 譯自:MS DOS百科全書(Ray Duncan: the MS-DOS Encyclopedia)
MS-DOS系統(tǒng)的加載,即把磁盤上的COM及EXE文件裝入內(nèi)存并執(zhí)行,可以被任何程序使用MS-DOS功能(功能4BH,加載執(zhí)行)產(chǎn)生.DOS的命令解釋程序COMMAND.COM使用EXEC裝入它的外部命令,如CHKDSK,或其它應(yīng)用程序.許多流行的商業(yè)軟件,例如數(shù)據(jù)庫和字處理,都使用EXEC執(zhí)行輔助程序(例如拼寫檢查),或是裝入COMMAND.COM的另一個(gè)副本,這就允許用戶在不失去當(dāng)前工作上下文時(shí)運(yùn)行一個(gè)輔助程序或打入MS-DOS命令.
當(dāng)EXEC被一個(gè)程序(父進(jìn)程)調(diào)用并加載另一個(gè)程序(子進(jìn)程),父進(jìn)程可以通過一串字符即環(huán)境塊,命令行及兩個(gè)文件控制塊,來傳輸一定的信息給子進(jìn)程.子進(jìn)程同樣繼承了父進(jìn)程的MSDOS標(biāo)準(zhǔn)設(shè)備及其它父進(jìn)程打開的設(shè)備的句柄(除非打開的操作有"非繼承性"的選擇).任何操作都可被子進(jìn)程的繼承句柄執(zhí)行,例如定位或文件輸入輸出,而且還影響著與父進(jìn)程句柄聯(lián)系著的文件指針.子進(jìn)程也可裝入另一程序,如此循環(huán)直至系統(tǒng)內(nèi)存溢出.
因?yàn)镸SDOS并非一個(gè)多任務(wù)的操作系統(tǒng),子進(jìn)程直到運(yùn)行結(jié)束才交出系統(tǒng)控制權(quán),父進(jìn)程此時(shí)被掛起,這種進(jìn)程操作有時(shí)也叫做同步執(zhí)行.當(dāng)子進(jìn)程中止,父進(jìn)程得到控制權(quán)并可用另一個(gè)系統(tǒng)功能調(diào)用(INT21H功能4DH)取回子進(jìn)程的返回碼并檢查子進(jìn)程的中止是否正常,或是一個(gè)重大的硬件錯(cuò)誤,比如用戶按了Ctrl-C.
除了裝入子進(jìn)程外,EXEC還可以被用來裝入由于用匯編或高級(jí)語言寫成而不能包含在其庫文件中的子程序或應(yīng)用程序的覆蓋文件,這種類型的覆蓋文件不能單獨(dú)運(yùn)行,多數(shù)需要主程序的段內(nèi)的"幫助"工作或數(shù)據(jù).
EXEC功能僅存在MSDOS 2.0版以上,在MSDOS 1.X版中,父進(jìn)程可以用INT 21H的功能26H建立一個(gè)子進(jìn)程的程序前綴段,但必須自己完成裝載,重定位,執(zhí)行代碼的過程,而不是依靠操作系統(tǒng)的幫助.
EXEC是怎樣工作的
當(dāng)EXEC功能接到一個(gè)執(zhí)行程序的請(qǐng)求時(shí),它首先試圖打開并定位指定的程序文件.如果文件沒有找到,EXEC立刻失敗并返回調(diào)用者一個(gè)錯(cuò)誤碼.
如果文件存在,EXEC打開此文件,確定它的大小,并檢查文件的首塊.如果塊的頭兩個(gè)字節(jié)是ASCII碼MZ,文件便設(shè)定為一個(gè)EXE裝入模式.程序代碼段,數(shù)據(jù)段,堆棧段的大小可以從文件頭獲得.否則,整個(gè)文件便設(shè)定為一個(gè)決對(duì)裝入影像(COM程序).實(shí)際的文件名后綴(COM或EXE)在這個(gè)測(cè)試中被忽略.
此時(shí),內(nèi)存所需要裝入程序的大小是知道的,假如有足夠的空間裝入程序,EXEC便在內(nèi)存分配兩個(gè)塊:一個(gè)包括新程序的環(huán)境塊,另一個(gè)包括程序的代碼段,數(shù)據(jù)段和堆棧段.不同類型的程序?qū)嶋H分配的大小不同.COM程序得到系統(tǒng)中全部的空余內(nèi)存(除非內(nèi)存空間過早形成碎塊),而分配給EXE程序的空間大小是由文件頭的兩個(gè)字段控制,MINALLOC和MAXALLOC,它是由LINK設(shè)置的.
EXEC接著將父進(jìn)程的環(huán)境塊拷入子進(jìn)程的環(huán)境塊,在子進(jìn)程內(nèi)存塊的底部建立一個(gè)程序前綴段(PSP).并將命令行及缺省文件控制塊拷入PSP.以前的終止地址(INT 22H),Ctrl-C(INT 23H)
及嚴(yán)重錯(cuò)誤(INT 24H)中斷向量的目錄存入新的PSP,終止地址向量被更新,以便子進(jìn)程終止或失敗時(shí)控制能夠返回到父進(jìn)程.
接著子進(jìn)程的實(shí)際代碼和部分?jǐn)?shù)據(jù)便由磁盤文件讀到新PSP結(jié)構(gòu)上方的程序內(nèi)存塊.如果子程序是一個(gè)EXE文件,文件頭的重定位表常用于在程序里定位參考段以便反映出它實(shí)際的裝入地址.
最后,EXEC功能建立為程序的CPU寄存器和堆棧并將控制傳給程序.COM文件的入口指針常是程序內(nèi)存塊中偏移100H(PSP后第一個(gè)字節(jié)).而EXE文件的入口地址由文件頭指定,可以在程序中任何位置.
當(dāng)EXEC用于裝入并執(zhí)行一個(gè)覆蓋文件而不是子程序時(shí),它的操作會(huì)比上述更為簡單.對(duì)于覆蓋文件,EXEC并不試圖分配內(nèi)存或建立PSP及環(huán)境塊,它只簡單地將文件的內(nèi)容裝入調(diào)用文件所指定的地址,并執(zhí)行一些必要的重定位(如果覆蓋文件有一個(gè)EXE文件頭).使用的段值也是由調(diào)用者提供.EXEX接著并不是將控制傳給最新裝入文件的代碼,而是返回所產(chǎn)生的程序,請(qǐng)求程序負(fù)責(zé)在適當(dāng)?shù)奈恢谜{(diào)用覆蓋.
使用EXEC裝入程序
當(dāng)一個(gè)程序裝入并執(zhí)行另一個(gè)程序時(shí),它必須執(zhí)行以下幾步:
1.確認(rèn)有足夠的空閑內(nèi)存來裝入子進(jìn)程的代碼,數(shù)據(jù)和堆棧.
2.建立EXEC和子進(jìn)程所需要的信息.
3.調(diào)用MSDOS的EXEC功能運(yùn)行子進(jìn)程.
4.恢復(fù)并測(cè)試子進(jìn)程的結(jié)束及返回碼.
分配內(nèi)存
MSDOS典型地分配給被加載的COM或EXE文件所有可用的內(nèi)存.一個(gè)不常見的例外是當(dāng)一個(gè)由/CPARMAXALLOC開關(guān)聯(lián)接或被EXEMOD修改的EXE程序會(huì)由它先前駐留的數(shù)據(jù)或代碼分裂一個(gè)短小的程序塊.所以,當(dāng)一個(gè)程序要裝入另一個(gè)程序之前,它必須釋放所有它本身代碼數(shù)據(jù)堆棧所不用的內(nèi)存.
釋放多余的內(nèi)存是調(diào)用MSDOS的重分配內(nèi)存塊功能(INT21H,功能4AH).此時(shí),ES寄存器置父進(jìn)程的PSP段地址,BX寄存器置程序自身必須使用的內(nèi)存塊數(shù),如預(yù)期的父進(jìn)程是COM程序,且它減少它的內(nèi)存分配數(shù)低于64K時(shí),它必須移動(dòng)它的堆棧到一個(gè)安全的空間.
準(zhǔn)備EXEC的參數(shù)
當(dāng)使用裝入和執(zhí)行一程序時(shí),必須提供EXEC功能兩條參數(shù):
1.子程序路徑名的地址.
2.參數(shù)塊地址.
參數(shù)塊依次包括子程序所需信息的地址.
程序名
子程序的路徑名必需是明確的,零結(jié)尾(ASCIIZ),規(guī)定文件名(沒有非識(shí)別字符).如果沒有包含路徑,便在當(dāng)前目錄下尋找程序,如果無驅(qū)動(dòng)器名,則使用默認(rèn)驅(qū)動(dòng)器.
參數(shù)塊
參數(shù)塊包括四個(gè)數(shù)據(jù)項(xiàng)地址:
1. 環(huán)境塊
2. 命令行
3. 二個(gè)缺省文件控制塊(FCBs)
在參數(shù)塊中為環(huán)境塊指針準(zhǔn)備的空間只有兩個(gè)字節(jié),包括一個(gè)段地址.這是因?yàn)榄h(huán)境塊總是排在段落上(它的地址總可以被16整除).值0000H表示子進(jìn)程的環(huán)境應(yīng)被毫不改變地繼承.余下的三個(gè)地址全是雙字節(jié)地址,是標(biāo)準(zhǔn)的Intel格式,一個(gè)低字的段偏移,一個(gè)高字的段地址.
環(huán)境塊
一個(gè)環(huán)境塊總是從一個(gè)邊界段開始,包含一系列的以0結(jié)尾的字符串(ASCIIZ),形式如下:
name = variable 全部字符串的結(jié)尾以一個(gè)附加的0表示.
如果在參數(shù)塊中的環(huán)境塊指針提供給一個(gè)EXEC的調(diào)用包含0,那么子進(jìn)程只需簡單地拷貝父進(jìn)程的環(huán)境塊.父進(jìn)程能夠提供一個(gè)不同或是增長一組字符串的段指針.另一方面,在MSDOS 3.0
以后的版本里,EXEC使子程序的環(huán)境塊具有完整的路徑名.環(huán)境塊最大為32字節(jié).通過這種途徑,這么大的信息也可被程序識(shí)別.
最初的(或主控的)系統(tǒng)環(huán)境塊屬于系統(tǒng)接通或重新啟動(dòng)后的命令處理程序(通常是COMMAND.COM)所裝入的.COMMAND.COM將字符串PATH,SHELL,PROMPT和SET命令的結(jié)果寫入系統(tǒng)的主環(huán)境塊.前兩個(gè)通常使用的是默認(rèn)值.例如,一個(gè)MSDOS3.2版的系統(tǒng)從C驅(qū)啟動(dòng),在AUTOEXEC.BAT文件中無PATH命令,CONFIG.SYS文件中也無SHELL命令,則主環(huán)境塊將下面兩行字符串寫入:
PATH =
COMSPEC = C: \COMMAND.COM
COMMAND.COM為運(yùn)行"外部"命令而尋找這些說明清單,同時(shí)也為了找到自身在磁盤上的可執(zhí)行文件以便它能在必要的時(shí)候重新裝入它的暫態(tài)部分.當(dāng)PROMPT字串存在時(shí)(先前的PROMPT或SET PROMPT命令產(chǎn)生的結(jié)果),COMMAND.COM它來修訂用戶的提示顯示.
環(huán)境塊中的其它字符串僅僅為了特殊程序提供信息,它不影響操作系統(tǒng)的操作.例如,Microsoft C 編譯器和 MicrosoftObject連接器在環(huán)境塊中尋找INCLUDE,LIB和TMP字符串,以確定頭文件,庫文件,臨時(shí)文件的指定位置.圖2給出了一個(gè)典型的環(huán)境塊的十六進(jìn)制顯示圖.
命令行
命令行是傳給子進(jìn)程的,它包括一字節(jié)指明余下命令行的長度,緊接著的ASCII字符串是以ASCII碼回車(0DH)為結(jié)束的.回車碼并不包含在長度值里.命令行可包括子進(jìn)程可以檢查到的所有開關(guān),文件名,以及其它參數(shù),用以影響程序的操作.命令行被拷貝到子進(jìn)程PSP偏移80H處.
當(dāng)COMMAND.COM使用EXEC運(yùn)行一個(gè)程序時(shí),它的命令行包括除程序名或重定向參數(shù)外所有用戶打下的命令.I/O的重定向是在COMMAND.COM內(nèi)部處理的,它表明子進(jìn)程繼承了標(biāo)準(zhǔn)設(shè)備句柄的活動(dòng).其它程序使用EXEC來運(yùn)行子進(jìn)程必須自己做一些必要的重定向而且必須提供一個(gè)合適的命令行,以便子進(jìn)程表現(xiàn)得如同被COMMAND.COM裝入一樣.
確省的文件控制塊
EXEC參數(shù)塊的二個(gè)確省的FCBs指向拷貝到子進(jìn)程PSP的偏移5CH和6CH.
當(dāng)前只有極少數(shù)應(yīng)用程序使用FCB作為文件和記錄的I/O.這是因?yàn)镕CBs不支持目錄樹結(jié)構(gòu).但有些程序檢查確省的文件控制塊作為分離前二個(gè)開關(guān)或其它命令行參數(shù)的快速的方法.然而,使它自己本身對(duì)子進(jìn)程透明,父進(jìn)程應(yīng)該仿效COMMAND.COM那樣把命令行前二個(gè)參數(shù)裝入確省的文件控制塊.這能使MSDOS的分析文件名功能(INT 21H,功能29H)能方便地使用.
如果子進(jìn)程不需要這二個(gè)確省的文件控制塊,應(yīng)用程序內(nèi)存中的參數(shù)塊中正確的地址會(huì)初始化指向二個(gè)空FCBs,這些空FCBs是由1字節(jié)0和11字節(jié)ASCII碼空格(20H)組成.
運(yùn)行子進(jìn)程
當(dāng)父進(jìn)程構(gòu)造完所必要的參數(shù)后,它就可以通過中斷21H來調(diào)用EXEC,各寄存器設(shè)置如下:
AH = 4BH
AL = 00H (EXEC子功能,裝入并執(zhí)行程序)
DS:DX = 程序路徑名的段地址:偏移址
ES:BX = 參數(shù)塊的段地址:偏移址
從以上軟件中斷返回后,父進(jìn)程必須要測(cè)試一下進(jìn)位標(biāo)志,以此來檢測(cè)子進(jìn)程是否實(shí)際運(yùn)行過.如果進(jìn)位清楚,則成功裝入并控制了子進(jìn)程.如果進(jìn)位置位,則EXEC功能失敗,錯(cuò)誤碼返回在AX中,可檢測(cè)原因.通常的原因是:
指定文件沒有找到
文件找到,但沒有足夠的內(nèi)存裝入
其它不常見的服務(wù)錯(cuò)誤可以從整個(gè)系統(tǒng)感到其特征(如磁盤文件或內(nèi)存中的MSDOS被損壞),使用MSDOS 3.0以后的版本,可以通過調(diào)用INT 21H功能59(取擴(kuò)展錯(cuò)誤信息)來獲得EXEC更詳細(xì)的失敗原因.
總的來說,提供給EXEC參數(shù)塊一個(gè)無效地址或參數(shù)塊本身地址無效并不會(huì)引起EXEC錯(cuò)誤,但這將使子進(jìn)程產(chǎn)生一些不可的后果.
聯(lián)系客服