VNC協議分析

VNC協議分析 數組

 

 

 

摘自:緩存

http://blog.csdn.net/forever_feng/article/details/4703088安全

 

 

 

簡介

VNC(Virtual Network Computing)是基於RFB(Remote Frame Buffer)協議進行通訊的,是一個基於平臺無關的簡單顯示協議的超級瘦客戶系統,服務器

由Cambridge的AT&T實驗室設計開發的。網絡

vnc的缺省端口是main:5900(C/S)和http:5800(B/S)端口。tcp

RFB (遠程幀緩存) 是一個遠程圖形用戶的簡單協議,由於它工做在幀緩存級別上,因此它能夠應用於全部的窗口系統,例如:X11,Windows和Mac系統。性能

遠程終端用戶使用機器(好比顯示器、鍵盤、鼠標)的叫作RFB客戶端,提供幀緩存變化的被稱爲RFB服務器。優化

RFB是基於tcp的一個應用層協議。編碼

clip_image002

RFB 是真正意義上的「瘦客機」協議。RFB協議設計的重點在於減小對客戶端的硬件需求。這樣客戶端就能夠運行在許多不一樣的硬件上,客戶機的任務實現上就會盡可能的簡單。加密

RFB協議對於客戶端是無狀態的。也就是說:若是客戶端從服務器端斷開,那麼若是它從新鏈接相同的服務器,客戶端的狀態會被保存。甚至,一個不一樣的客戶端能夠用來鏈接相同的RFB服務器。而在新的客戶端已經可以得到與前一個客戶端相同的用戶狀態。所以,用戶的應用接口變的很是便捷。

只要合適的網絡鏈接存在,那麼用戶就可使用本身的應用程序,而且這些應用會一直保存,即便在不一樣的接入點也不會變化。這樣不管在哪,系統都會給用戶提供一個熟悉、獨特的計算環境。

顯示協議

顯示協議是創建在「把像素數據放在一個由x,y 定位的方框內」這單一圖形基礎之上的。

乍一看上去,把這麼多的用戶接口組件繪製出來是很是低效的方法。可是,容許不一樣的像素數據編碼方式,使得咱們在處理不一樣的參數(如:網絡帶寬,客戶端的繪製速度,服務器處理速度)有了很大程度的靈活性。

經過矩形的序列來完成幀緩存的更新。一次更新表明着從一個可用幀緩存狀態轉換到另外一個可用,所以有點和視頻的楨相似。儘管矩形的更新通常是分開的,可是並非必須的。

顯示協議的更新部分是由客戶端經過命令驅動的。也就是說,更新只是在服務器端響應客戶端的請求時發生的。這樣就讓協議更新質量是可變的。客戶端/網絡越慢,更新速度也就越慢。對於一些應用來講,相同區域的更新是接二連三的。若是用一個慢的客戶端,那麼幀緩存的緩存狀態是能夠被忽略的。這樣也能夠減小對客戶端網絡速度和繪製速度的要求。

輸入協議

輸入協議是基於標準工做站的鍵盤和鼠標等設備的鏈接協議。

輸入事件就是經過把客戶端的輸入發送到服務器端。

這些輸入事件也能夠經過非標準的I /O 設備來綜合。

例如,手寫筆引擎可能產生一個鍵盤事件。

像素數據的表示

初始的交互涉及到RFB客戶端和服務器之間傳輸像素數據格式和編碼方式的協調。這種協調被設計的讓客戶端的工做盡可能簡單。而設計的底線是:服務器必須按照客戶端的要求格式來提供像素數據。若是客戶端能夠一樣的處理多種數據格式或編碼格式,那麼通常會選擇服務器端易於生成的格式。

像素格式涉及如何經過像素值來實現不一樣顏色的重現。最經常使用的通常像素格式是24 位或16 位的「真彩色」,它經過位來直接實現像素值到紅、綠、藍亮度的轉換。8 位「顏色映射」能夠任意映射像素值到RGB亮度的轉換。

編碼指一個矩形的像素數據如何經過網線傳輸。每一個像素數據的矩形都加上了一個頭,給定矩形在屏幕上的X、Y座標、矩形的寬和高,以及指定的編碼類型。然後數據自己就是採用這種特定的編碼方式。

數據自己遵循特定的編碼。目前的編碼方式主要有Raw、CopyRect、RRE、Hextile 和ZRLE.在實際應用中咱們通常使用ZRLE、Hextile 和CopyRect,由於它們提供了典型桌面的最好壓縮。其餘可能的編碼方式還包括,用於靜態圖片的JPEG和用於動態圖像有效傳輸的MPEG。

協議能夠經過增長新的編碼方式來進行擴展。

協議擴展

協議能夠經過如下方式進行擴展:

新的編碼方式

一種新的協議能夠經過與現存的客戶端和服務端進行相關兼容的添加。由於現存的服務器將會忽略它們所不支持的新編碼方式。因此客戶端經過新的編碼方式進行請求也就不會有結果返回。

僞編碼方式

除了真正的編碼方式,客戶端也能夠請求「僞編碼」通告服務器,它支持某一協議的擴展。服務器若是不支持這種擴展,那麼它將忽略。值得注意的是:客戶端必須先假設服務器端不支持這種擴展,直到它得到服務器端支持的確認。

新的安全方式

添加一個新型的安全方式會帶來無限的靈活性,它經過修改協議的一些行爲,可是並無犧牲現存客戶端和服務器端的兼容性。客戶端和服務器端能夠經過協議好的安全方式進行交流,固然並不必定與RFB協議相似。

不管如何你都不該使用不一樣的版本號。

RFB協議的版本是由RealVNC公司來制定的。若是你使用一個不一樣的協議版本可能與RFB/VNC不兼容,要保證協議的兼容性,請聯繫RealVNC公司。這樣會減小在編碼方式和安全類型上的衝突。

協議消息

RFB協議能夠進行可靠的傳輸,如字節流或基於消息的。和大多數協議同樣,它也是經過TCP /IP協議簇鏈接。協議由三步完成鏈接。首先是握手報文,目的是對協議版本和加密方式進行協商。第二步是初始化報文,主要用於客戶和服務器的初始化消息。最後就是正常協議的交互,客戶端能夠按需發送消息,而後能夠得到服務器的回覆。

全部的消息以消息類型開始,接下來是特定的消息數據。

協議消息描述的基本類型有:U八、U1六、U3二、S八、S1六、S32。

U表示無符號整數,S表示有符號整數。

全部字節整數(除了像素值自己)聽從big endian順序。

big endian或者little endian跟cpu有關,從而影響整數在內存中的排列順序。big endian是高字節在前,little endian是低字節在前,網絡字節序通常是big-endian。

PIXEL表明一個像素值bytesPerPixel字節,8XbytesPerPixel = bits-per-pixel。

協議流程

clip_image004

消息說明

握手消息

一、vnc服務器發送所可以支持的最高RFB協議版本號給客戶端,好比:「RFB 003.006/n」,即版本號爲3.6,版本號固定格式爲×××.×××,不足部分前面補零。

clip_image006

二、客戶端回覆將要使用的版本號,格式如上。客戶端的版本號必須小於或等於服務器版本號。這樣服務器能夠實現向後兼容。

三、目前發佈的協議版本主要有3.三、3.七、3.8(3.5版本被報告存在問題),最高版本號爲4.0。

協商安全類型

(一)v3.7以上版本安全類型

服務器發送所支持的安全類型列表

若是客戶端能支持服務器的某一安全類型,那麼客戶端就會發送一個字節來確認鏈接clip_image008

的安全類型:

clip_image010

若是安全類型數是0,那麼鏈接失敗(例如服務器不支持客戶請求版本號),這樣就

會有字符串來描述失敗緣由:

clip_image012

服務器在發送緣由字串後,就會關閉鏈接。

(二)3.7如下版本(以vnc認證爲例)

一、服務器發送一個無符號的32位整數標識一個安全類型(與認證有關)。

clip_image014

安全類型:

clip_image016

其餘認證類型:

clip_image018

說明:

①0,鏈接失敗(例如服務器不支持客戶請求版本號),這樣就會有字符串來描述失敗緣由:

clip_image012[1]

服務器發送完reason-string就關閉鏈接。

②NONE,不須要認證(不要輸密碼),協議數據將被使用明文發送。

V3.8 以上版本, 還會帶有安全結果的消息。

V3.3 和 3.7 協議直接進入初始報文.

③VNC認證,協議數據將採用明文發送,服務器發送一個16 字節的隨機數。

clip_image020

客戶端使用DES對驗證進行加密,使用用戶密碼做爲密鑰,把16 字節的回覆返回到服務器。

clip_image022

隨之而來的就是安全結果消息。

二、服務器發送16位隨機數。

三、客戶端使用DES對驗證進行加密,使用用戶密碼做爲密鑰,把加密後的16字節返回給服務器。

四、服務器對安全認證進行確認,返回值爲無符號32位整數,若是爲0則表示成功,1表示失敗。若是不成功,服務器直接關閉鏈接。

clip_image024

V3.8 以上版本 若是不成功,就會有字符串來描述失敗緣由,並關閉鏈接。clip_image026

對於V3.8如下,若是不成功,服務器直接關閉鏈接。

初始化消息

一、客戶端發送一個字節的初始化消息。

clip_image028

若是容許服務器其餘客戶繼續鏈接,那麼共享標誌應該是非零(真)。不然,服務器將

斷開其餘客戶的鏈接。

二、服務器發送初始化消息,主要告知客戶端服務器的幀緩存的高、寬、象素格式和桌面相關的名稱。

clip_image030

這個跟實現有關,有些實現是先發送24個字節,而後再發送桌面名字字符串。名稱字符串格式如:sh-yinghua -1 ( 192.168.70.69 )。

幀緩存寬度通常爲水平分辨率的大小,幀緩存高度通常是垂直分辨率的大小,好比1024×768等。

象素格式主要包括如下段:

clip_image032

服務器象素定義服務器原本的象素格式,這種象素格式會被一直使用,除非客戶端使

用設置象素格式消息來請求另外一種象素格式。bits-per-pixel是表示每一個像素值須要的位數。這個數字必須大於等於depth,而depth用來表示像素值中有用的位數。目前位每象素必須是8,16 或32——小於8 位象素不被支持。若是多字節象素被看作big-endian,那麼Big-endian 標誌非零。固然了,這對8 位每象素沒有任何意義。

若是真彩標誌非零,那麼最後6 項規定如何按照象素值來肯定紅、綠、藍的亮度。紅的最

大值是紅色的最大值(=2 ^n - 1, n 表示用在紅色上的位數)。注意這個值通常在big endian

的順序中。紅色-替換表示要獲得最低明顯bit 所須要的替換個數。綠色最大值、綠色-替換和藍色最大值、藍色-替換和紅色相似。要在0—紅色最大值之間找一個紅色值,按照如下步驟進行:

• 遵循big-endian 標誌進行象素值。(例如:若是big-endian 標誌爲0,主機的字節順序是big endian,而後交換)。

• 使用紅色—替換將右邊替換。

• 和紅色最大值進行邏輯與(按照主機字節順序)。

若是真彩標誌是零,那麼服務器使用的象素值不是直接由紅、綠、藍的亮度組成,可是

服務爲索引到顏色圖中去。顏色圖中的項目是由服務器使用「設置顏色面板條目」 (FixColourMapEntries)消息進行設置的。

說明:位/象素通常爲顯示設置的顏色質量位數。

目前的任何服務器都還不能支持FixColourMapEntries消息,只有基於X的服務器才能支持顏色映射。實際上,爲了可以徹底支持顏色映射,客戶端大概須要可以指定特殊的、服務器不會使用的像素值。這可能會加在將來的協議版本里。

客戶端到服務器的消息

全部客戶端到服務器的消息第一個字節都爲消息類型,數據類型U8。

客戶到服務器的消息在本文中有以下定義:

clip_image034

其他的註冊消息類型有:

clip_image036

值得注意的是:若是要發送未在本文中定義的消息,那麼必須獲得服務器端的消息確認。

設置象素格式消息

「幀緩存更新」消息中設置什麼格式的象素值如何設置。

若是客戶端沒有發送「設置象素格式」消息,那麼服務器發送的象素值將遵循在服務器初始化消息中所包括的象素格式。

若是真彩標誌是零,那麼意味着使用「顏色面板」,只要客戶端發送顏色面板空的消息,或者是面板項被服務器端重設,服務器可使用設置顏色面板項目進行顏色面板的設置。

clip_image038

注:其中的象素格式如在上文中的描述。

設置編碼格式

設置編碼方式能夠來肯定服務器發送象素數據的類型。消息中編碼方式的順序是客戶端

按照優先級來排列(第一個擁有最高的優先級)。服務器可能選擇這種順序,也可能不選擇。

象素數據也可使用「原始編碼」若是沒有具體說明。

除了基本的編碼方式,客戶端也能夠請求「僞編碼」通告服務器它支持某一種擴展協議。若是服務器不支持這種擴展,它就會忽略這種僞編碼。注意:這意味着客戶端在獲得服務器的確認以前都要假設服務器並不支持它的擴展。

clip_image040

接下來就是編碼數目個編碼類型的重複

clip_image042

由編碼類型決定編碼格式。

請求幀緩存更新

通知服務器,客戶對幀緩衝區中的某個區域感興趣,這個區域由x座標、y座標、寬度和高度幾個參數限定。

服務器一般對FramebufferUpdateRequest消息的響應,是發送一條FramebufferUpdate消息。

注意,能夠發送一條FramebufferUpdate消息用來回復幾條FramebufferUpdateRequest消息。

服務器假定客戶保留了幀服務器中它感興趣的全部部分的副本。這意味着,服務器一般只須要向客戶發送增量部分的更新。

可是,若是因爲某種緣由,客戶丟失了它所須要的一個特定區域的內容,就發送一條FramebufferUpdateRequest消息,把消息中的incremental置爲0(false)。這要求服務器把指定區域的所有內容儘量快地發送過來。這個區域的更新不會使用copy rectangle編碼方式。

若是客戶沒有丟失它感興趣區域的任何內容,就發送一條FramebufferUpdateRequest消息,把消息中的incremental設爲非零(true)。當幀緩衝區中的指定區域發生變化時,服務器會發送一條FramebufferUpdate消息。

注意,在FramebufferUpdateRequest和FramebufferUpdate之間可能會有一段不肯定長的間隔。

對於速度快的客戶,它可能但願以固定頻率發送增量的FramebufferUpdateRequests消息,以免佔用網絡資源。

clip_image044

增量標誌爲0時,表示必須發送完整內容過來。

按鍵事件

某一個鍵的按下與釋放。若是某一個鍵被按下,那麼按下標誌非零。釋放的時候變爲零。

在X Window 系統中鍵自己被賦值爲「keysym」。

clip_image046

對於大多數鍵來講,「keysym」與ASCII碼相對應,具體參考《The Xlib ReferenceManual》或者參考。在Linux上爲/usr/include/X11/keysymdef.h。

對於大多數普通鍵,「keysym」和ASCII碼的值是一致的(前面3個字節爲0,最後一個字節爲ASCII碼)。其餘的命令鍵爲:

clip_image048

鼠標(指針)事件

檢測指針移動或者某一個鍵的按下或釋放。指針目前在(x座標、y 座標),鼠標按鈕的各鍵採用1到8位掩碼標識,0 表示鬆開,1 表示按下。

拿普通鼠標來講,全零表示鼠標移動,第1,2,3 分別對應左、中、右鍵。對於滑輪鼠標來講,滾輪向上對應第4位,滾輪向下對應第5位。

拖動操做是不斷的發送左鍵按下的消息,並變換鼠標的座標。

clip_image050

客戶端文本剪切

客戶端有新的ISO8859 - 1(Latin - 1) 文本在它的剪切緩存裏,行的末尾經過新行字符(值爲10)來表示。 須要無回車(值爲13)。目前尚未找到傳輸非Latin - 1 字符集的方法。

clip_image052

服務器到客戶消息

服務器到客戶消息在本文中定義以下:

clip_image054

其他註冊的消息類型:

clip_image056

注意在服務器發送消息以前必須確認客戶端支持相關擴展,一般在請求「僞編碼」的

時候使用。

幀緩存更新

幀緩存更新是由一系列像素數據矩形而組成,這些矩形會被客戶端送入它的幀緩存中。

它是對客戶端幀緩存更新請求的響應。而在請求和響應之間有可能存在不肯定時期。

clip_image058

隨着像素數據矩形的個數,每一個矩形包括如下內容:

clip_image060

後面就是特定編碼的數據。

設置顏色面板條目

當像素格式使用「顏色面板」時,消息告訴客戶端對應像素值如何映射爲RGB亮度。

clip_image062

下面就是重複具體的色彩

clip_image064

目前對顏色映射的支持還不多甚至沒有。這方面已經作了一些初步的工做,可是尚未完成。

目前,只有基於X 的服務器可以徹底支持顏色映射。

響鈴

若是有響鈴事件,就在客戶端上響鈴。

clip_image066

服務器剪切文本

若是服務器的剪切板有新內容,服務器主動發送該消息給客戶端

clip_image068

編碼格式

本文的編碼類型

clip_image070

其餘編碼類型

clip_image072

原始編碼( Raw 編碼)

即採用原始的像素數據,而不進行任何的加工處理。在這種狀況下,對於一個寬度乘以高度(即面積)爲N的矩形,數據就由N個像素值組成,這些值表示按照掃描線順序從左到右排列的每一個像素。很明顯,這種編碼方式是最簡單的,也是效率最低的。

RFB要求全部的客戶都必須可以處理這種原始編碼的數據,而且在客戶沒有特別指定須要某種編碼方式的時候,RFB服務器就默認生成原始編碼。

clip_image074

複製矩形編碼( CopyRect編碼)

CopyRect 編碼方式對於客戶端在某些已經有了相同的象素數據的時候是很是簡單和有效的。這種編碼方式在網絡中表現爲x,y 座標。讓客戶端知道去拷貝那一個矩形的象素數據。它能夠應用於不少種狀況。最明顯的就是當用戶在屏幕上移動某一個窗口的時候,還有在窗口內容滾動的時候。在優化畫的時候不是很明顯,一個比較智能的服務器可能只會發送一次,由於它知道在客戶端的幀緩存裏已經存在了。

複製矩形編碼並非徹底獨立地發送全部的數據矩形,而是對於像素值徹底相同的一組矩形,只發送第一個矩形所有數據,隨後的矩形則只須要發送左上角X、Y座標。實際上,複製矩形編碼主要指的就是隨後的這一系列X、Y座標,而對於第一個矩形具體採用何種編碼類型並無限制,僅僅須要知道第一個矩形在幀緩衝區中的位置,以便於完成複製操做。所以,每每是把複製矩形編碼和其它針對某一個矩形的編碼類型結合使用。

接下來使用CopyRect 編碼方式發送相同的式樣。

clip_image076

二維行程編碼( rise-and-run-length,RRE)

RRE表示提高和運行長度,正如它名字暗示的那樣,它實質上表示二維向量的運行長度編碼。RRE把矩形編碼成能夠被客戶機的圖形引擎翻譯的格式。RRE不適合複雜的桌面,但在一些狀況下比較有用。

RRE的思想就是把像素矩形的數據分紅一些子區域,和一些壓縮原始區域的單元。最近最佳的分區方式通常是比較容易計算的。

編碼是由像素值組成的,Vb(基本上是在矩形中最經常使用的像素值)和一個計數N,緊接着是N的子矩形列表,這些裏面由數組組成,(x,y)是對應子矩形的座標,表示子矩形上-左的座標值,(w,h) 則表示子矩形的寬高。客戶端能夠經過繪製使用背景像素數據值,而後再根據子矩形來繪製原始矩形。

二維行程編碼本質上是對行程編碼的一個二維模擬,而其壓縮度能夠保證與行程編碼相同甚至更好。並且更重要的是,採用RRE編碼的矩形被傳送到客戶端之後,能夠當即有效地被最簡單的圖形引擎所還原。

在傳輸中,數據如下面的頭開始描述:

clip_image078

後面跟隨重複的子矩形結構:

clip_image080

CoRRE 編碼

CoRRE是RRE的變體,它把發送的最大矩形限制在255×255個像素之內,用一個字節就能表示子矩形的維度。若是服務器想要發送一個超出限制的矩形,則只要把它劃分紅幾個更小的RFB矩形便可。「對於一般的桌面,這樣的方式具備比RRE更好的壓縮度」。

實際上,若是進一步限制矩形的大小,就可以得到最好的壓縮度。「矩形的最大值越小,決策的尺度就越好」。可是,若是把矩形的最大值限制得過小,就增長了矩形的數量,而因爲每一個RFB矩形都會有必定的開銷,結果反而會使壓縮度變差。因此應該選擇一個比較恰當的數字。在目前的實現中,採用的最大值爲48×48。

Hextile 編碼

Hextile 是RRE編碼的變種,矩形被分割成16×16 小片,容許每一個小片的維數爲4位,

總共16 位。

把原始矩形劃分紅小塊是預約義的,這意味着每一個塊的位置與大小不須要明確地指定。

矩形被分割的小片從上開始,遵照自左到右,自頂向下的順序。小片的編碼內容按照預約的順序進行編碼。若是整個矩形的寬度不是16 的整數倍,那麼每行最後的小片也相應減小。高度也相似。

每一個小片可使用raw 編碼,也能夠是RRE編碼的變種,用一個類型字節來進行說明便可。每一個小片有一個背景像素值。可是,若是小片的背景像素值和前一個小片相同,那麼就不須要明肯定義。若是小片的子矩形有相同的像素值,那麼前景像素值就能夠只定義一次。和背景像素值同樣,前景像素值也能夠經過前一個小片得到。

所以由小片組成的數據是按照順序進行編碼的。每個小片以子編碼類型的字節開始。它是位數的掩碼組成。

clip_image082

若是Raw 位被設置,那麼其他的位就無效;接着是寬X高像素值(寬和高是小片的寬

高)。不然其餘的位就有效。

背景定義-若是設置,那麼像素值就會跟着小片的背景色:

clip_image084

在矩形中的第一片非Raw 小片必須設置這一位,若是不設置,那麼它的背景就會和上

一片相同。

前景定義-若是設置,那麼像素值就會定義小片中全部子矩形的前景色。

clip_image086

若是這一位被設置,那麼子矩形着色位必須爲0。

任意子矩形-若是設置,那麼一個字節包含着子矩形的個數。

clip_image088

若是這一位不設置,那麼就不會有子矩形。(例如,整個小片就是背景顏色)

子矩形着色-若是設置,那麼任意子矩形的像素值的優先級都高於子矩形的顏色定義,

所以子矩形是:

clip_image090

若是不設置,全部子矩形都是前景色的顏色,若是前景定義沒有設置,那麼前景色和

前一個片的相同。子矩形就是:

clip_image092

每個子矩形的位置和大小都是使用兩位進行定義,x - and - y - position 和width -

And - height。最重要的四位x - an d - y - posi tion 定義X的位置,不重要的定義Y位置。最

重要的四位width - and - height 定義寬度- 1,不重要的定義高度- 1。

ZRLE 編碼

ZRLE(Zlib Run - Length Encoding),它結合了zlib 壓縮,片技術、調色板和運行長度

編碼。在傳輸中,矩形以4 字節長度區域開始,緊接着是zlib 壓縮的數據,一個單一的

zlib「流」對象被用在RFB協議的鏈接上,所以ZRLE矩形必須嚴格的按照順序進行編碼和

譯碼。

clip_image094

zlibData 在沒有壓縮以前,表明了由64x64 像素組成的從左到右,從高到低的順序

的片,和hextile 編碼有點相似。若是整個矩形的寬度不是64 的整數倍,那麼每行最後的

小片也相應減小。高度也相似。

ZRLE編碼利用了一種新的壓縮像素CPIXEL(Compres se d PIXEL)。這個和PIXEL有着

相同的像素格式,除了真彩標誌是非零,位每像素是32,色深不大於24。全部的位組成紅,

綠和藍的亮度填充最不重要的或最重要的三字節。若是CPIXEL只有3 字節長,而且包含有

合適的最不重要或最重要3 字節。那麼bytesPerCPixel 就是CPIXEL的字節數。

每片都是以子編碼類型字節開始,若是片被使用運行長度編碼,那麼本字節的最高位

就會被設置。其他7 位表示繪圖樣式-零表示沒有樣式,1 表示片爲單色,2 - 127 表示對應

的樣式。可能的子編碼值以下:

0 - Raw 像素數據 寬X高像素值(寬和高爲對應片的寬和高,對應像素值以下:

clip_image096

2 - 16 -打包的樣式類型。對應像素值是由palet teSize(=子編碼)像素值,打包像素值組

成,每一個打包像素值表示爲一位區域服從樣式索引(0 表示第一個條目),對應

palet teSize 2,1 位被使用,palet teSize 3,4 有兩位被使用,從5 - 16 均有4 位區域被

使用。位的區域被打包成字節,最重要的位表示最左邊像素。由於片並非8,4,2 像素寬的

乘積,因此填充位被用來按照字節數排列每個行。

clip_image098

m 表示打包像素的字節數。對於palet teSize 2 就是floor((width + 7) / 8) x height,

相應3,4 就是floor((width + 3) / 4) x height,而5 - 16 就是floor((width + 1) / 2)x

height。

17 - 127 未使用(對於palet te RLE並無什麼優點)。

128 -簡單RLE 它由一些不斷重複的執行組成,一直到片結束。執行可能從一行的結束到另外一行的開始。每一次運行是經過一個像素值和像素值長度來表示的。長度通常爲1 個或多個字節。通過計算多於全部字節總和+ 1 做爲長度。除了255 任何字節值都隱含最後的字節。例如長度1 表示爲[0],255 表示爲[254],256 表示爲[255,0],257 表示爲[255,1],510 表示爲[255,254],511 表示爲[255,255,0]等等。

clip_image100

129 -未使用

130 - 255 調色RLE。調色緊跟其後,由palet teSize = (subencoding - 128) 像素值組成:

clip_image102

接下來就合簡單RLE類似,一些不斷重複的執行組成,一直到片結束。執行長度經過

調色板索引來表示。

clip_image104

若是執行長度使用多於一位來表示調色板索引,而且最高位被設置。那麼就會帶有執行長度。

clip_image106

僞編碼
指針/鼠標僞編碼

若是客戶端請求指針/鼠標僞編碼,那麼就是說它有能力進行本地繪製鼠標。這樣就能夠明顯改善傳輸性能。服務器經過發送帶有僞鼠標編碼的僞矩形來設置鼠標的形狀做爲更新的一部分。僞矩形的x 和y 表示鼠標的熱點,寬和高表示用像素來表示鼠標的寬和高。包含寬X高像素值的數據帶有位掩碼。位掩碼是由從左到右,從上到下的掃描線組成,而每一掃描線被填充爲floor((width +7) / 8)。對應每一字節最重要的位表示最左邊像素,對應1 位表示相應指針的像素是正確的。

clip_image108

桌面大小僞編碼

若是客戶端請求桌面大小僞編碼,那麼就是說它能處理幀緩存寬/高的改變。服務器經過發送帶有桌面大小僞編碼的僞矩形做爲上一個矩形來完成一次更新。僞矩形的x 和y 被忽略,而寬和高表示幀緩存新的寬和高。沒有其餘的數據與僞矩形有關。

協議漏洞及解決方法

RealVNC VNC Server採用的RFB(遠程幀緩衝區)協議容許客戶端與服務端協商合適的認證方法,協議的實現上存在設計錯誤,遠程攻擊者能夠繞過認證無需口令實現對服務器的訪問。

具體操做細節以下:

1) 服務端發送其版本「RFB 003.008/n」

2) 客戶端回覆其版本「RFB 003.008/n」

3) 服務端發送1個字節,等於所提供安全類型的數量

3a) 服務端發送字節數組說明所提供的安全類型

4) 客戶端回覆1個字節,從3a的數組中選擇安全類型

5) 若是須要的話執行握手,而後是服務端的「0000」

RealVNC 4.1.1或以前版本在實現RFB 003.008協議時沒有檢查判斷在上面第4步中客戶端所發送的字節是否爲服務器在3a步中所提供的,所以認證就從服務端轉移到了客戶端。攻擊者能夠強制客戶端請求「Type 1 - None」爲安全類型,無需口令字段即可以訪問服務器。

危害:遠程攻擊者能夠繞過認證無需口令實現對服務器的訪問。

解決方法:檢查客戶端請求的安全類型是否爲服務器支持的類型之一,不然斷開鏈接,或者禁止無認證的安全類型。

相關文章
相關標籤/搜索