TLS实现代码段加密
? ? 剛開始見到這個(gè)思路是看到周大師用這個(gè)東西做的免殺,當(dāng)時(shí)感覺這個(gè)想法很好,但是由于當(dāng)時(shí)對(duì)PE結(jié)構(gòu)了解的少,看到二進(jìn)制的東西就打怵,所以當(dāng)時(shí)也沒能成功的去實(shí)現(xiàn)這個(gè)思路,只是簡(jiǎn)單的記錄了一下TLS的特性,直到最近在看核心編程的某一章,里面又提到了TLS,讓我想起了當(dāng)時(shí)沒有成功實(shí)現(xiàn)的那個(gè)思路,所以就又嘗試了一次,用了一下午實(shí)現(xiàn)了這個(gè)TEXT代碼段加密的思路。
? ? 功能就是把PE文件的TEXT段進(jìn)行加密,隱藏他的靜態(tài)代碼段特性,在運(yùn)行的時(shí)候搶在main函數(shù)執(zhí)行之前把代碼段直接在內(nèi)存里面解密(不然就崩潰了),從而達(dá)到靜態(tài)代碼隱藏功能。
? ? 先說下TLS(線程本地存儲(chǔ)),這個(gè)東西平時(shí)用的并不多,分為靜態(tài)TLS和動(dòng)態(tài)TLS,主要是為了給程序做預(yù)處理以及實(shí)現(xiàn)存儲(chǔ)隔離的思路,就是比如一個(gè)全局變量,N個(gè)線程同時(shí)訪問,可以不上鎖,大家通過TLS自己每人有一個(gè)自己的備份等等.然而今天用的不是這方面,今天要用的是靜態(tài)TLS,靜態(tài)TLS也有很多特性和功能,這里不廢話,需要的可以自行搜索,就用到一點(diǎn),TLS可以在main函數(shù)執(zhí)行之前加載并且調(diào)用,也就是在干活之前先執(zhí)行TLS然后在進(jìn)入main函數(shù)做事情,這個(gè)就是重點(diǎn),這樣的話就可以通過先按代碼段加密,然后在TLS部分進(jìn)行代碼解密,這樣靜態(tài)PE文件看上去就是一個(gè)text段被加密的了。
說下實(shí)現(xiàn)思路(細(xì)節(jié)并不固定,很多地方可以DIY).
(1)首先找到一個(gè)位置存自己的密碼(用于加解密代碼),再找一個(gè)地方存一個(gè)key,這個(gè)key用來標(biāo)記這個(gè)PE文件是不是已經(jīng)被我們加密過了,防止二次加密。
我是直接在DOS頭里面存的,在1的位置存的一個(gè)KEY用于標(biāo)記這個(gè)東西是不是被自己處理過了,這個(gè)地方并沒有寫成一個(gè)固定的值,不然感覺很容易暴露,寫的是一個(gè)隨機(jī)計(jì)算出來的值,最后我會(huì)根據(jù)這個(gè)地方的值是否滿足自己的公式來確定這個(gè)文件是不是自己處理過的,當(dāng)然這個(gè)地方默認(rèn)是0x90這么寫也容易暴露,后續(xù)可以換位置寫。2的位置是用來存密碼的,用于加解密代碼段內(nèi)容。
(2)然后就是在自己的代碼段里面留一個(gè)用于確定TLS代碼大體位置的值:
?
? ? 注意這個(gè)地方是用匯編寫的,不要用變量或者其他,匯編寫的目的是防止數(shù)據(jù)被編譯到數(shù)據(jù)段里面去,這樣寫直接在TEXT段里面找這個(gè)序列,然后根據(jù)這個(gè)序列的位置大體確定TLS函數(shù)的位置,然后在向兩邊擴(kuò)展一個(gè)長(zhǎng)度,用于猜測(cè)TLS函數(shù)代碼部分,防止加密的時(shí)候誤傷了這部分代碼。還有就是一定要注意一個(gè)問題:
?上面兩個(gè)是對(duì)應(yīng)的,但是仔細(xì)觀察里面的序列對(duì)應(yīng)關(guān)系,...表示今天下午被這個(gè)地方坑了好一會(huì)。
????當(dāng)然這個(gè)key的序列可以不寫死,畢竟寫死之后也會(huì)留下特征,由于時(shí)間原因我是臨時(shí)寫死了,其實(shí)可以這樣,自己寫一個(gè)遞增的式子,然后每次隨機(jī)生成一個(gè)滿足式子的序列,在校驗(yàn)的時(shí)候我們每次固定取出來長(zhǎng)度,然后依次校驗(yàn)這段長(zhǎng)度是否全部滿足地推公式,這樣來判斷key的位置,之前我這么干過,當(dāng)時(shí)因?yàn)閷懙氖沁f減的式子,吃了不少虧,記住要遞增,原因是?5?/?2?=?2??這種情況下在結(jié)合概率,很容易出現(xiàn)誤判。
這樣的話,我們把key序列寫到TLS代碼里之后整個(gè)代碼段大體是這樣樣子:
? ? 紅色的部分,標(biāo)記的位置是通過key序列找到的TLS代碼定位坐標(biāo),然后前面擴(kuò)展0x200,后面擴(kuò)展0x1000這樣得到的區(qū)域是自己估算的TLS函數(shù)區(qū)域,這個(gè)部分是處于代碼段里但是不能進(jìn)行加解密的部分(0x200和0x1000這個(gè)可以自己根據(jù)實(shí)際情況定義),然后兩端的部分可以通過XOR或者其他方式直接處理,在編譯完成之后,通過輔助程序把編譯好的PE文件加載到內(nèi)存里,然后找到代碼段,然后找到key序列坐標(biāo)計(jì)算出保護(hù)區(qū)域,然后把這個(gè)代碼段除了保護(hù)區(qū)域的其他部分全都加密,最后再把相關(guān)信息,比如加密的密碼以及標(biāo)記等填充在相關(guān)位置上(這里我是填在DOS頭里面了),這樣加密部分就搞定了(通過輔助程序),解密的話代碼是直接寫在TLS里面的,同樣的思路,只不過的是自己所在的進(jìn)程空間的地址而已。
然后看一個(gè)處理過和處理前的PE文件的大體區(qū)別:
存儲(chǔ)標(biāo)記和加密key
修改代碼段讀寫權(quán)限
加密代碼段
受保護(hù)的TLS函數(shù)段:
? ? 最終達(dá)到PE文件的代碼段記性加密的思路,用在靜態(tài)免殺和夾克程序里。
大體思路就是上面那些,很多細(xì)節(jié)和坑點(diǎn)都沒有寫,太多了不寫了,對(duì)于這樣的東西提示一個(gè)大家容易犯的通病,就是忽略:
1.了解思路
2.親自實(shí)現(xiàn)出來
3.產(chǎn)品化,發(fā)版出去
這三個(gè)的區(qū)別,很多人以為一看,嗯,這個(gè)思路可以了。然后就拉倒了,其實(shí)你不一定能寫出來,就算你寫出來了,也不一定能達(dá)到穩(wěn)定發(fā)版的水平,這個(gè)是平時(shí)最容易犯的錯(cuò)誤(包括我),當(dāng)然至于做到什么程度,要看小伙伴們的初衷及其需求,上面做的那些就是為了讓小伙伴達(dá)到1的目的,至于2和3大家就自己實(shí)現(xiàn)把,只有去嘗試寫才能理解和發(fā)現(xiàn)這里面到底有啥坑點(diǎn),總之我不會(huì)告訴別人?今天被一個(gè)SB錯(cuò)誤坑了好幾個(gè)小時(shí),一直誤以為是內(nèi)存加密有問題。
傳了一下下午寫的一個(gè)實(shí)現(xiàn)代碼,沒有經(jīng)過強(qiáng)測(cè)試,自己在家寫著玩的。僅供大家思路參考:
?http://download.csdn.net/detail/u013761036/9726645
總結(jié)
以上是生活随笔為你收集整理的TLS实现代码段加密的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows PE导出表编程4(重构导
- 下一篇: Windows PE第6章 栈与重定位表