Pages

Showing posts with label Protocol. Show all posts
Showing posts with label Protocol. Show all posts

2015-07-29

軟件授權序號發行

以前覺得軟件授權用序號方式很容易被破解,因此就實作硬體ID+網路啟動的方式,但站在User的角度其實輸入註冊序號是比較簡單的,至少不需要連網。一般簡單註冊序號的實作方式,就是將用戶資訊+到期時間加密寫成二進位檔。

加密內容方式應該能隨DateTime變化而內容不同,以防止被推算竄改,加密方式可以加上隨機byte陣列Salt(鹽)混淆即可。

License KeyGen

關於License授權物件的寫作,多數人大概會優先使用.NET二進化序列化技術,不過我不喜歡這類帶有強型別的序列化行為(因為序列化的前面Bytes都是描述類別不會變化,很好推算加密私鑰),最主要也因為別的程式語言不容易針對檔案作反序列化。

因此我使用「Packet封包結構與解析」文件的格式來包裝License物件,因為它有很好的擴充性,也是C/C++很好理解處理的模式。

當然,.NET軟件上的檢查註冊機制,很容易被反組譯給註解掉IL執行指令,這部分可以在程式裏加上很多空的函式來混淆別人的分析,授權檢查不要只回傳Boolean值就了事,而是在多處關鍵處去授權物件內的值作簡易計算比對,即使發現授權檢查被竄改也不要立即彈視窗警告,使用一個%機率出現怪現象即可。

最後,防守到一個程度被破解就算了,千萬不要為了授權檢查而混淆程式執行效能,做出本末倒置的事才好。畢竟,軟體上的授權檢查,都是防君子不防小人的。

2011-10-24

Packet封包結構與解析

兩年前寫的封包資料驗證文章主要應用在網路封包或RS232資料,後來從事嵌入式與單晶片程式工作,發現TI德州儀器的ZigBee通訊資料結構也差不多如此,只不過為了快速辨別封包類型,把Data欄位的前兩個bytes拉出來作為CMD0, CMD1兩個欄位.

SOF

LEN0長度

LEN1長度

CMD0

CMD1

DATA資料

FCS檢查碼

長度

1

1

1

1

1

N

1

SOF (Start of Frame)就是每個封包Packet的起始辨別字元,TI的資料長度只有1個byte,我將其擴充為2bytes。
FCS (Frame Check Sequence)即是針對LEN0至DATA這部分的陣列作xor運算之值。

網路Socket傳輸,這樣的格式也是一個很不錯的bytes陣列包裝方式,透過PacketFrame這樣的Helper Class,可以快速得到這樣的資料結構。
image 
我們可以快速建立一個符合結構的pkt[] array, 而其封包有效的資料長度即為pktLen值.
為什麼這函式不直接傳回新陣列呢? 因為重複使用buffer位址來存寫資料,可大大增加效能。

建立該結構的陣列,並沒有什麼困難,比較有門檻的是如何在陸續進來的封包緩衝區(Buffer)裏,解析(Parsing)出一個個完整的Packet結構。
image

為單一封包準備一個足夠大的Packet Buffer及SOF辨識字元,透過Parse(queue, startIndex, length)函式即可觸發事件。
事件參數為:
image
以上的Event Arguments資訊,就足夠判斷進來的封包資料所為何事了!

2009-09-17

封包資料驗證

無論是網路UDP封包或RS232的串列資料,它們的傳輸不保證內容順序及資料是正確的,
因此若要實作資料驗證機制的話,最基本的封包(Package或Frame)結構定義如下表:

起始字

資料長度

資料

檢查碼

1 byte

2 bytes

N bytes

1 bytes

1. 起始字: 如固定以0xAB開頭
2. 資料長度: 代表後面資料的陣列長度,通常low byte在前,high byte在後地組成2個bytes。
3. 資料: 一個符合前面長度的byte[]陣列,有可能是0長度。
4. 檢查碼: 通常是從資料長度byte至資料陣列的最後一個byte作xor sum。

由於接收資料的socket或rs232 reader,每次事件觸發可能只收到破碎的片段資料
因此必須準備一個自訂Queue來累績存放讀取buffer進來的raw data,
當Queue的長度大於一個封包定義的最小長度時,即進行Queue的Parsing工作。

從Queue映射出一個Shadow Array(固定長度),然後使用一個loop來比對起始字
接著取得其資料長度(Data Length)。這兩個代表資料長度的bytes可能是錯誤的值,
因此要檢查其宣稱的長度值,是否在封包定義最小長度與整個映射array長度之間。

若是,則依Data Length值跳至該封包最後一個byte作checksum驗證,若正確則是有效封包區段,
直接作長度跳躍去驗證下一個封包片段起始字。
反之,若Data Length及checksum檢查失敗,則array position加1繼續比對起始字。

當中值得注意的是,當checksum失敗的話代表其區域內的bytes值都不可靠,
因此即使Data Length所宣稱值符合在Array範圍內,亦不可直接作整個長度的跳躍
只能postition + 1,繼續比對下一個起始字byte。

另外,需要設定一個queue已讀取位置的read position變數,記錄checksum失敗時的讀取位置,
避免重複再對這些不可靠的區段作parsing。等到遇到一個有效封包結構進來時,
再一次回收這些空間,該read position變數再設為0。

SNAGHTMLb1a0d4

以上是業界作資料驗證的邏輯原則,筆者經過千錘百鍊的資料傳輸驗證及效能除錯
基於智慧財產保障,僅提供流程邏輯,並不提供源碼分享,尚請見諒。