多年來,臺(tái)式計(jì)算機(jī)的安全性一直是人們關(guān)注的問題。一旦機(jī)器連接到互聯(lián)網(wǎng),本質(zhì)上就有可能受到某種攻擊。這種滲透可能是為了竊取數(shù)據(jù)、破壞系統(tǒng)或以某種方式改變其操作。保護(hù)手段是眾所周知的并且被廣泛應(yīng)用。嵌入式系統(tǒng)似乎總是不受這些問題的影響,因?yàn)樗鼈兒苌俾?lián)網(wǎng),而且它們的代碼通常在某種 ROM 中。事情變了。大部分現(xiàn)代系統(tǒng)都連接到 Internet,將代碼復(fù)制到 RAM 并從那里執(zhí)行是常見的做法。這意味著安全性現(xiàn)在是一個(gè)重要的嵌入式軟件設(shè)計(jì)考慮因素。
英語是一種很好的交流工具。它是一種極具表現(xiàn)力的語言,能夠以非常精確和微妙的方式進(jìn)行交流。然而,在日常講話中,我們大多數(shù)人都很懶惰,經(jīng)常使用沒有 100% 準(zhǔn)確度的單詞。我在這里想到的例子是安全和安保幾乎可以互換使用的方式,就好像它們是同義詞一樣。我認(rèn)為我聽到的最好的定義是這樣的:安全是保護(hù)世界免受設(shè)備影響的過程;安全性正在保護(hù)設(shè)備免受外界侵害。安全是我今天的主題。
如果一個(gè)系統(tǒng)真的需要完全防彈,則需要工業(yè)級(jí)加密。這通常需要特定的硬件支持,雖然很容易獲得,但對(duì)于不需要如此高安全性的應(yīng)用程序來說,這可能被認(rèn)為是多余的。在這種情況下,還有其他選擇,這就是我想探索的。
如果黑客可以訪問設(shè)備的內(nèi)存內(nèi)容,他們就可以開始弄清楚它做了什么以及它是如何做的。這是改變其運(yùn)作的第一階段。代碼可以被反匯編,因此可以揭示邏輯。如果沒有加密,就幾乎無法防止這種情況發(fā)生。黑客可能做的下一件事是查看數(shù)據(jù)的十六進(jìn)制/ASCII 轉(zhuǎn)儲(chǔ),看看他們能在那里找到有意義的東西。他們正在尋找模式和可識(shí)別的結(jié)構(gòu)。這是可以采取一些預(yù)防措施的地方。雖然加密可能不是一種選擇,但混淆是可能的。
數(shù)據(jù)混淆的目的是通過簡(jiǎn)單地降低數(shù)據(jù)的可識(shí)別性來延遲或阻止黑客。通過內(nèi)存轉(zhuǎn)儲(chǔ)掃描,最容易發(fā)現(xiàn)的事情之一是文本字符串。所以,這就是我將在這里重點(diǎn)介紹的內(nèi)容。
在 C/C++ 代碼中,文本字符串通常只是包含以空字節(jié)結(jié)尾的 ASCII 代碼的字節(jié)序列。這很容易發(fā)現(xiàn),所以我會(huì)改變它。首先,每個(gè)字符串的第一個(gè)字節(jié)將是一個(gè)長(zhǎng)度說明符,而不是空終止符。字符串的字符會(huì)稍微打亂它們的數(shù)據(jù),讓它們看起來不那么熟悉——我要做的就是交換每個(gè)字節(jié)的兩個(gè)半字節(jié)。我需要一個(gè)實(shí)用程序,將純文本字符串輸入其中,并生成具有適當(dāng)初始化的數(shù)組的聲明。這是該實(shí)用程序的核心功能:
void scramble(int index, unsigned char *input) { ??? unsigned char *charpointer, 字符; ??? printf("unsigned char string%d[%d] = {0x%02x,", index, ?????????? strlen(輸入)+1,strlen(輸入)); ??? 字符指針 = 輸入; ??? 而(*字符指針) ??? { ??????? 字符= *字符指針++; ??????? 字符 = ((字符 & 0x0f) << 4) | ??????????????????? ((字符 & 0xf0) >> 4); ??????? printf("0x%02x", 字符); ??????? if (*字符指針) ??????????? printf(","); ??? } ??? printf("}; // "%s"\n", 輸入); }
如果我向這個(gè)函數(shù)傳遞一個(gè)索引 4 和一個(gè)字符串“Hello world”(原來的嗯?),輸出將是:
unsigned char string4[12] = {0x0b, 0x84, 0x56, 0xc6, 0xc6, 0xf6, 0x02, 0x77, 0xf6, 0x27, 0xc6, 0x46};// “你好世界”
我可以將其復(fù)制并粘貼到我的代碼中,然后我需要做的就是編寫一個(gè)函數(shù)來在需要顯示文本時(shí)對(duì)其進(jìn)行解讀。我可以通過將index參數(shù)替換為字符串來給它一個(gè)任意名稱,而不是給每個(gè)字符串一個(gè)索引號(hào)。請(qǐng)注意,生成的代碼在某種程度上是自記錄的,因?yàn)樽⑨屢钥勺x的形式顯示了字符串,但是,當(dāng)然,這只出現(xiàn)在源代碼中。如果黑客可以訪問您的源代碼,那么您就有足夠的麻煩,我無法提供進(jìn)一步的幫助!
下面是一些代碼來說明解擾過程:
無效的主要() { ??? 無符號(hào)字符臨時(shí),緩沖區(qū)[50]; ??? 整數(shù)計(jì)數(shù) = string4[0],索引 = 0; ??? 而(計(jì)數(shù)--) ??? { ??????? temp = string4[index+1]; ??????? 溫度 = ((溫度 & 0x0f) << 4) | ((溫度 & 0xf0) >> 4); ??????? 緩沖區(qū)[索引] = 溫度; ??????? 索引++; ??? } ??? 緩沖區(qū)[索引] = 0; ??? printf("-%s-\n", 緩沖區(qū)); }
每個(gè)字節(jié)中半字節(jié)的交換是可以完成加擾的許多不同方式之一。另一種可能性是,比如說,將每個(gè)字符左旋轉(zhuǎn)三位。這里有一些代碼可以做到這一點(diǎn):
unsigned char leftrotate3(unsigned char c) { ??? c = (c << 3) | (c >> 5); ??? 返回 c; }
我概述的混淆技術(shù)會(huì)逐個(gè)字符地打亂字符串。可以改為對(duì)整個(gè)字符串執(zhí)行操作。例如,將字符串視為一長(zhǎng)串位并將其向左旋轉(zhuǎn)任意數(shù)字。我將把這個(gè)算法的編碼留給更熱心的讀者。
值得注意的是,本地化所有文本字符串的一個(gè)副作用是,為其他語言制作不同版本的軟件非常簡(jiǎn)單。
我必須重申并強(qiáng)調(diào),數(shù)據(jù)混淆遠(yuǎn)不是防彈的,充其量只能減緩黑客的攻擊速度。如果沒有其他情況,解讀代碼可能會(huì)被分解。這種技術(shù)的訣竅是使模糊處理成為難以遵循的軌跡。如果你真的需要更高的安全性,你必須考慮完全加密。
評(píng)論