混淆字串
基礎知識
物極必反。我們已經研究了閱讀windows核心的方法,現在開始討論在我們自己的驅動編碼中採用特殊的編碼方法,來簡單地防止反彙編閱讀。這是有趣的一種事態:一方面我們研究如何閱讀別人的(尤其是ms的)**;另一方面,我們不得不採取措施保護自己的技術不被他人簡單地竊取。
我這裡要用到的這種方法不同於加殼或者加密。加殼和加密的方法比較單一,從而容易被人以同樣單一的方法整體解密,同時核心驅動中進行加密稍顯複雜,難以做得穩定,而且我手頭沒有成熟的整體加密的**。實際上**如果在執行,則一定必須被解密,因此從記憶體中得到解密的**並不困難。所以我並不太傾向於使用加殼或者加密的方案。
劉濤濤的「扭曲變換」是根本的防止逆向解決方案,但是需要付出巨大的努力才得以實現。
下面的一些方法是比較簡單的。這樣的做法顯然不能完全防止逆向,但是能起到一定的「遮掩」作用。好處是隨時可以做,而且可以個人根據**的重要程度,決定哪些部位做,哪些部位不做。無論有多簡陋,有勝於無。
劉濤濤的扭曲變換
由於破解技術的發展,實際上大部分商業軟體的合法性驗證機制都變成了僅具有裝飾性,而且一些難以開發的底層軟體的技術細節,往往在發行不久就被人理解並發表在網上。這成為許多開發者厭惡的事(當然另一些開發者則樂於此道)。
於是如何讓編譯後的機器**更難以理解就成為乙個切實有用的研究方向。編譯器有效地優化了**,但這僅僅是將**變得更簡單。一般地說,簡單的東西總是比複雜的要容易理解,雖然和源**的關係變得模糊了。
國內著名技術牛人劉濤濤在網上發表「扭曲變換」的思想。這個思想和「優化」完全相反,主旨不是讓**更簡單、效率更高,而是讓**更加複雜——毫無疑問效率也更低。但是相比技術秘密的洩露,效率的損失其實並不那麼重要了。
這種複雜性有著無限的潛力。比如,讀者計畫一次從北京到上海的旅行,最近的直線航行路線當然只有一條。但是如果想要路線更長更複雜的話,則完全有無限種可能:你可以先從北京抵達紐約,在紐約休息後前往南極,然後北上到達撒哈拉沙漠,最後再前往上海。複雜的**使破解者無法找到驗證相關**的所在,也使試圖竊取技術的讀者一無所獲。
劉濤濤的工具可以將編譯後的obj檔案進行扭曲,鏈結後生成的可執行檔案變得極難閱讀,而且可以反覆地執行下去:一段**可以無限地變大變長——功能卻是和原來等價的。這真是不可思議的技術。
技術細節
在**中,出現了直接字串是非常不妥的一件事。往往這些常數字串在反彙編的時候會直接被人看見,對反工程者是最好的引導。
以下的**都會暴露我們的字串:
char *str = "mystr";
wchar_t buffer[2] = ;
unicode_string my_str;
rtlinitunicodestring(&my_str,l"hello,world");
隱藏這些常數字串並不能完全防止逆向工程,但是毫無疑問的是,會給逆向工程增加很多麻煩。
隱藏這些字串的手法是:在寫**的時候並不寫字串的明文,而是書寫密文,總是在使用之前解密。這樣的手法的後果是,在靜態反彙編的時候,反工程者是看不見字串的。但是,反彙編者顯然會在除錯的時候看見字串。
在除錯的時候才看見合法的字串比靜態反彙編的時候看見字串要麻煩許多,因為一般只有對一段**有興趣才去除錯它。而之所以對那段**有興趣,有些時候是因為看見了感興趣的字串。全部跟蹤除錯所有的**,是艱鉅的任務,只有具有重大價值的目標才值得那樣去做。
想保護**,請首先保密常數字串。
不過有點要注意的是,你不能把所有的字串都用同樣的一招進行加密,至少不能用相同的金鑰;否則,也許乙個簡單的解密程式就把你所有的字串恢復為明文了。
考慮:char *str = "mystr";
改為:char str =
如果認為異或是最簡單的加密方法,那麼0x12就是這裡的金鑰。現在編譯出來的字串已經面目全非了,當然,要解密這個字串需要乙個函式。
char *dazeestr(char *str, char key)
return str;
}你可以試試靜態反彙編下面的**:
char *str = ;
dazeestr(str,0x12);
printf(str);
當然你通過分析一定會知道printf的結果。除錯也可以知道結論,但是比直接用眼睛可以看見可是麻煩多了。當然這樣寫**也有些讓人抓狂,但是,你總是可以先按自己的本來的習慣寫完**,然後把關鍵的字串這樣處理。
下面是乙個寬字元的處理方法。
wchar_t *dazeestrw(wchar_t *str, wchar_t key)
return str;
}下面的**:
unicode_string my_str;
rtlinitunicodestring(&my_str,l"hello,world");
其實總是可以改為:
wchar_t buffer = ;
unicode_string my_str;
rtlinitunicodestring(&my_str,buffer);
那麼加密的寫法是:
wchar_t buffer = ;
unicode_string my_str;
rtlinitunicodestring(&my_str,dazeestrw(buffer,0x3a));
比較明顯的缺陷是書寫常數字串的時候變得麻煩。我一直在追尋更簡單的寫法,但是遺憾的是,我還沒有找到。怎麼說呢?如果你覺得隱蔽是值得的,那就這樣做。你甚至可以用更複雜的加密演算法,只要你能算出密文,然後填寫在**常數中,不過那樣修改**變得太困難了。如果你能寫乙個預編譯工具自動修改**,確實是乙個好辦法,不過對於一種僅僅防止肉眼直**到字串的方式,更複雜的加密方法往往沒必要,因為無論多複雜的演算法,解密演算法都很容易在你自己的**裡找到。
本文節選自電子工業出版社2023年10月出版的《天書夜讀——從組合語言到windows核心程式設計》。
混淆字串
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!物極必反。我們已經研究了閱讀windows核心的方法,現在開始討論在我們自己的驅動編碼中採用特殊的編碼方法,來簡單地防止反彙編閱讀。這是有趣的一種事態 一方面我們研究如何閱讀別人的 尤其是ms的 另一方面,我們不得不採取措施保護自己的技術不被他人簡...
易混淆陣列和字串api
split 將字串安裝指定字元切割,然後拼接成陣列。返回新陣列。如 var a jack,jetty,tom var arr a.split console.log arr jack jerry tom 陣列 join 將陣列安裝指定字元拼接為字串。var news arr.join console...
MFC中易混淆的字串指標
這是在我學習mfc時曾遇到的比較麻煩的東西 lpstr,lpcstr,lptstr,lpctstr,lpwstr,lpcwstr。初次看到時確實很不適應,不過現在說來也很簡單了。在 字元編碼篇 中提到windows下程式設計需要注意編碼轉換特別是ascii碼和unicode碼。windows已經提供...