[注]本文為作者原創文章,轉載請注明出處。謝謝。
問題1,什么是特征
這個人長個馬臉,那個妹子胸大,這都是特征。顯然,特征越明顯,我們越容易對其進行辨識。
問題2,什么是數據特征
數據特征,就是說,某段數據具有的特征。
比如,通迅的雙方(A <-> B ),在建立連接后,A發給B的第一個包,長度總是固定的,有時候甚至值都是固定的(在協議握手階段尤其如此)。
問題3,為什么要去掉這些特征
我們在講網絡安全的時候,絕大部分的人能想到數據加密,然而僅僅加密還不足於保護我們的。下面我舉幾個例子。
1,某FW在對數據包進行檢測的時候,可以通過特征的學習及辨識去決定要不要reset這個連接。
2,瀏覽網站時產生的流量數據,帶有明顯的網頁字節數特征,通過對這個特征的學習,第三方可以大概知道瀏覽網站的人都訪問過哪些網站,甚至知道訪問了哪些頁面。
問題4,怎么去數據特征
通過粗略的分析,我們至少有兩個辦法可以使數據特征不明顯。
1,改變數據長度。主要通過在數據流中加入一些隨機長度的隨機值。
2,通過增加冗余位,增加數據中具體位的隨機性。
一種冗余位Obfuscate方案
我們知道一個字節通常由8個bit組成。確定的值,它的bit平面(低位到高位所呈現的0101序列)總是確定的。如果我們讓這個確定變成不確定,我們的目的就達成了。
下面,我介紹一個簡單的通過冗余位達到混擾的目的。
以uint8_t -> uint32_t 為實例進行一個大概的算法描述
uint8_t 占8bit
uint32_t 占32bit
uint8_t中
01位置於uint32_t 第一個byte,
23位置於uint32_t第二個byte,
45位置於uint32_t第三個byte,
67位置於uint32_t第四byte
具體的算法:
取uint32_t中每個byte的高3位,得到一個數值p, p mod 5 = z, z就是這個byte中起始有效bit位,從這個位開始,順序存儲(從底位到高位)2個uint8_t中的位 (見下圖)
C代碼實現
//UINT_X's width must be less than sizeof(uint32_t), it can be uint8_t or , uint16_t template <typename UINT_X> inline static uint32_t obfuscate(UINT_X const& val, uint32_t const& r_u32) { if (sizeof(uint32_t) <= sizeof(UINT_X)) return val; uint32_t rr = 0; uint8_t b[sizeof(UINT_X) * 8]; uint8_t bii[sizeof(UINT_X) * 8]; //per bytes contain bit count uint8_t pbcbc = (sizeof(UINT_X) * 8) / (sizeof(uint32_t) / sizeof(uint8_t)); for (int i = 0; i < (sizeof(UINT_X) * 8); i++) { if ((i%pbcbc) == 0) { b[i] = ((r_u32 >> ((5 + ((i / pbcbc) << 3))) & 0x7) % 5) & 0xFF; bii[i] = b[i]; } else { b[i] = ((b[i - 1] + 1) % 5); bii[i] = bii[i - 1]; } uint8_t bi = 0; if (val&(0x01 << i)) { bi |= (0x01 << b[i]); } bi |= ((0x7 & bii[i]) << 5); rr |= ((0xFFFFFFFF & bi) << ((i / pbcbc) << 3)); } return rr; } template <typename UINT_X> inline static UINT_X deobfuscate(uint32_t const& val) { UINT_X r = 0; uint8_t pbcbc = (sizeof(UINT_X) * 8) / (sizeof(uint32_t) / sizeof(uint8_t)); UINT_X b[sizeof(UINT_X) * 8]; for (int i = 0; i < (sizeof(UINT_X) * 8); i++) { if ((i%pbcbc) == 0) { b[i] = ((val >> ((5 + ((i / pbcbc) << 3))) & 0x7) % 5) & 0xFF; } else { b[i] = ((b[i - 1] + 1) % 5); } r |= (((val >> (b[i] + ((i / pbcbc) << 3))) & 0x1) << i); } return r; } namespace wawo { namespace security { inline static uint32_t u8_obfuscate(uint8_t const& val, uint32_t const& r_u32) { return obfuscate<uint8_t>(val,r_u32); } inline static uint32_t u16_obfuscate(uint16_t const& val, uint32_t const& r_u32) { return obfuscate<uint16_t>(val, r_u32); } inline static uint8_t u8_deobfuscate(uint32_t const& val) { return deobfuscate<uint8_t>(val); } inline static uint16_t u16_deobfuscate(uint32_t const& val) { return deobfuscate<uint16_t>(val); } }}