1. 程式人生 > >病毒檢測與防毒技術大揭祕7

病毒檢測與防毒技術大揭祕7

3.3.升級實現方案及編碼實現

防毒軟體需要及時升級病毒庫,更新特徵碼,以保證能夠識別最新爆發的病毒。為了完成這個操作,需要用到升級伺服器(或者虛擬主機也可以滿足基本需要)。將要升級的檔案,連同新的版本號檔案放置在伺服器固定位置上。軟體中以IP地址或域名的方式訪問這個版本號檔案,獲取最新的版本號,然後跟儲存在使用者端本地的版本號進行對比。如果檢測到伺服器上的版本號更高,表明有新的檔案需要升級。 在這裡插入圖片描述 升級其實是一個很簡單的功能,主要實現的是檔案下載功能,為了能夠在程式中進行版本號判斷以及替換正在執行的檔案等操作,我們將此功能分為兩個部分,一部分寫在應用程式中,一部分寫做一個單獨的模組控制元件。模組中的編碼如下:

主動事件,用於向用戶顯示下載進度: Public Event DownloadProcess(lProgress As Long)

主動事件,下載完檔案後觸發此函式: Public Event DownLoadFinish()

主動事件,錯誤資訊輸出函式: Public Event ErrorMassage(sDescription As String)

控制元件初始化函式: Public Function Init() As Boolean bConnect = True

該函式是第一個由應用程式呼叫的 WinINet 函式。它告訴 Internet DLL 初始化內部資料結構並準備接收應用程式之後的其他呼叫。當應用程式結束使用Internet函式時,應呼叫 InternetCloseHandle 函式來釋放與之相關的資源: lOpen=InternetOpen(scUserAgent,INTERNET_OPEN_TYPE_PRECONFIG,vbNullString,vbNullString,0)

通過一個完整的FTP、Gopher或HTTP網址開啟一個資源: lFile=InternetOpenUrl(lOpen,sUrl,vbNullString,0, INTERNET_FLAG_RELOAD, 0) sBuffer = Space(1024) lBuffer = 1024

從伺服器獲取HTTP請求頭資訊: bRetQueryInfo = HttpQueryInfo(lFile, 21, sBuffer, lBuffer, 0) sBuffer = Mid(sBuffer, 1, lBuffer) End Function

開始下載檔案函式:

Public Function StartUpdate() As Boolean

Dim bBuffer(1 To 1024) As Byte Dim lRet As Long Dim lDownloadSize As Long Dim i As Long

Dim lFileNumber As Long lFileNumber = FreeFile()

下載儲存檔案方式:下載儲存為file.exe.bak下載完成後刪除file.exe,再重新命名 file.exe.bak 為file.exe,這是為了防止file.exe在下載時出現網路錯誤檔案只被寫入一部分資料而引起錯誤:

Dim sTempDownloadFile As String sTempDownloadFile = Trim(sSaveFile) & “.bak” If Dir(sTempDownloadFile) <> “” Then Call DeleteFile(sTempDownloadFile) End If

開啟檔案,儲存下載資料:

Open sTempDownloadFile For Binary Access Write As #lFileNumber Do

讀取被下載檔案內容:

InternetReadFile lFile, bBuffer(1), 1024, lRet If lRet = 1024 Then

將讀取到的資料寫入檔案:

Put #1, , bBuffer Else For i = 1 To lRet Put #1, , bBuffer(i) doEvents Next i end If lDownloadSize = lDownloadSize + lRet

引發下載進度事件,這是為了在下載檔案時讓使用者瞭解下載進展情況,防止使用者以為程式假死:

RaiseEvent DownloadProcess(lDownloadSize)

Loop Until lRet < 1024 Close #lFileNumber

檢查已下載位元組數與要下載檔案大小是否一至,一至說明下載完成了: If lDownloadSize = CLng(GetHeader(“Content-Length”)) Then

下載完成後,刪除原檔案,重新命名下載檔案為原檔名:

If Dir(Trim(sSaveFile)) <> “” Then Call DeleteFile(sSaveFile) End If Sleep 50 If Dir(sSaveFile) = “” Then

重新命名下載的檔案:

Name sTempDownloadFile As sSaveFile End If DoEvents End If

End Function

獲取要下載檔案的資訊: Public Function GetHeader(Optional hdrName As String) As String

Dim sTemp As Long Dim sTemp2 As String Select Case UCase(hdrName)

獲取要下載的檔案大小:

Case “CONTENT-LENGTH” sTemp = InStr(sBuffer, “Content-Length”) sTemp2 = Mid(sBuffer, sTemp + 16, Len(sBuffer)) sTemp = InStr(sTemp2, Chr(0)) GetHeader = CStr(Mid(sTemp2, 1, sTemp - 1)) End Select

End Function

設定屬性,即要下載的檔案的網路地址:

Public Property Let URL(ByVal sInUrl As String) sUrl = sInUrl End Property

以上是控制元件中的編碼,之所以使用控制元件,是為了能夠使用主動事件,方便的與介面互交,比如:即時的顯示下載進度,使使用者能看到下載進行了多少、下載完成後能做出相應的訊息提示。

在程式更新病毒庫或其它程式檔案時,首先會進行如下的方式進行呼叫,獲取網路伺服器檔案中的版本號,如果版本號高於本地版本號,則進行更新,如果與本地版本號一至,則說明本地已經是最新版本,無需更新:

Dim sUpdateFiles As String sUpdateFiles=DetectUpdateFile("http://xxx.cn/update/update.txt")

DetectUpdateFile函式的程式碼如下:

Public Function DetectUpdateFile(sUrl As String) As String

Dim lInternetOpenUrl As Long
Dim lInternetOpen As Long
Dim sTemp As String * 1024
Dim lInternetReadFile As Long
Dim lSize As Long
Dim sContent As String
sContent = vbNullString
lInternetOpen = InternetOpen("update", 1, vbNullString, vbNullString, 0)
lInternetOpenUrl=InternetOpenUrl(lInternetOpen, sUrl, vbNullString, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0)
Do
lInternetReadFile = InternetReadFile(lInternetOpenUrl, sTemp, 1024, lSize)
sContent = sContent & Mid(sTemp, 1, lSize)
Loop While (lSize <> 0)
lInternetReadFile = InternetCloseHandle(lInternetOpenUrl)

升級查詢返回以“Update”開始為標識
If UCase(Left(sContent, 6)) = UCase("Update") Then
DetectUpdateFile = Right(sContent, Len(sContent) - 6)
Else
DetectUpdateFile = ""
End If

End Function

這部分程式碼與上面檔案下載控制元件中的程式碼非常類似,都是用來下載檔案的,不同在於此處下載檔案後會讀取檔案內容。

檔案內容是我們預設好的,本地設定檔案中有版本號,升級時,從伺服器下載版本號檔案並從中讀取內容獲取最新整體版本號,與當前軟體中的整體版本號進行比對,如果網路中的版本號更高,則進行更新,呼叫升級控制元件下載升級檔案。每次升級把設定檔案同時也下載,以同步版本號。

我們設定網路中版本號檔案格式為:“Update”(6位,用於標識是升級校驗檔案)+版本號(6位)+待升級檔案+"$"(結束符)

獲取到檔案資訊後,然後對比版本號,如果伺服器中的版本號更高,則表示有檔案需要下載更新,那麼我們就需要下載檔案。編碼如下:

取得伺服器檔案中的版本號:

Dim lNewWholeVersion As Long lNewWholeVersion = Left(sUpdateFiles, 6) sUpdateFiles = Right(sUpdateFiles, Len(sUpdateFiles) - 6)

取得本地版本號,在這裡Version.ini檔案中存放著本地版本號:

Dim sVersionFile As String sVersionFile = App.Path & “\Version.ini” Dim lOldWholeVersion As Long lOldWholeVersion = ReadIni(sVersionFile, “Version”, “WholeVersion”)

判斷是否需要升級:

If lNewWholeVersion <= lOldWholeVersion Then MsgBox “已是最新版本,無需升級。” End If

如果有持更新內容,從返回內容中獲取要升級的檔案並下載:

Do While Not sUpdateFiles = “” sNewFile = Left(sUpdateFiles, InStr(1, sUpdateFiles, “&quot;)1)sUpdateFiles=Right(sUpdateFiles,Len(sUpdateFiles)InStr(1,sUpdateFiles,&quot;&quot;) - 1) sUpdateFiles = Right(sUpdateFiles, Len(sUpdateFiles) - InStr(1, sUpdateFiles, &quot;”))

如果是要下載exe檔案,先用MoveFileEx函式去掉它的執行保護,這樣就不會出現替換正在執行的檔案而產生錯誤的問題:

If InStr(1, LCase(sNewFile), LCase(".exe")) Then Call MoveFileEx(sNewFile, RndChr(6), 1) End If

使用上面寫好的升級控制元件下載檔案,假設控制元件名為UserControlUpdate1:

With UserControlUpdate1

構造檔案下載地址:

.URL = "http://xxx.cn/update/" & sNewFile 
.SaveFile = App.Path & "\" & sNewFile 
If .Init = True Then
lCurrentFileSize = .GetHeader("Content-Length")

開始下載檔案:

.StartUpdate End If End With

Loop

以上是升級功能的思現思路及編碼方法,在實際軟體的編碼中,除了實現檔案下載的功能,還需要考慮其它輔助因素,比如在下地時,要將檔案顯示在介面中,告訴使用者正在下載哪個檔案,以及顯示下載進度,以給使用者一個更為直觀和親切的使用感受。

注:作者:wing qq:6465660 本書理論及功能、程式碼源於防毒軟體:“Ty2y防毒軟體”,作者授意,文章可自由轉載,只需註明原出處即可,特此說明。