[注]本文為作者原創文章,轉載請注明出處。謝謝。
問題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);
}
}}
