




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、軟件保護(hù)殼技術(shù)專題 - 變形引擎的構(gòu)建 <目錄>1.需要變形的部分22.花指令的構(gòu)建32.1產(chǎn)生隨機(jī)寄存器42.2產(chǎn)生隨機(jī)的清052.3產(chǎn)生隨機(jī)的JMP82.4產(chǎn)生異常代碼82.5利用MODRM/SIB143.構(gòu)建解密頭144.另一種變形(1)155.另一種變形(2)166.總結(jié)191.需要變形的部分 殼的變形技術(shù)主要來(lái)自于病毒。病毒變形主要目的為了躲避殺毒軟件的查殺,殼的變形也無(wú)非是這個(gè)。當(dāng)然還有目的是為了延長(zhǎng)破解時(shí)間,消耗Cracker的精力?,F(xiàn)在看一個(gè)經(jīng)典的變形結(jié)構(gòu),也確認(rèn)哪部分是用來(lái)變形的殼加載段-解密頭殼主體被加密的部分密鑰儲(chǔ)存- 大多數(shù)情況下,殼加載器的結(jié)構(gòu)就是這三個(gè)部
2、分。解密頭對(duì)殼主體進(jìn)行解密后再跳入到殼主體進(jìn)行運(yùn)行。這里就可以很明顯的看出 殼主體是很容易進(jìn)行變形的,只要每次加密的密鑰不一樣最后的隊(duì)列肯定不一樣?,F(xiàn)在解密頭是固定的,所以這里是最需要進(jìn)行變形的。以上這個(gè)結(jié)構(gòu)絕對(duì)是經(jīng)典多態(tài)的結(jié)構(gòu),再?gòu)?fù)雜的變形也是從以上這個(gè)簡(jiǎn)單的結(jié)構(gòu)開始的。下面看一段簡(jiǎn)單的CODE。代碼:call deltadelta:pop esiadd esi, offset Packet - offset deltamov edi, esimov ecx, o
3、ffset Decoder - offset Packetmov eax, esiadd eax, offset Decoder - offset Packetmov bl, byte ptr eax:lodsbxor al, blstosbloop B; 這里解密后直接進(jìn)去殼主體Packet:;.殼主體Decoder:db 099h 以上就是簡(jiǎn)單的ASM代碼。這里的算法是XOR當(dāng)然比較
4、簡(jiǎn)單,當(dāng)然在解密之前要首先保證代碼段是可寫屬性。現(xiàn)在開始變形解密頭要如何變形呢?這里可以看出其實(shí)總共解密頭也沒幾個(gè)字節(jié),提出兩種通用方式。一個(gè)就是添加花指令構(gòu)建將花指令丟到解密頭每條指令中間。一個(gè)就是等價(jià)的代碼替換,寄存器的替換??傊饷茴^是我們自己編寫的。我們可以精心的去構(gòu)建一段代碼,并將此按照我們自己的規(guī)則進(jìn)行模板化。 每當(dāng)生成新的殼解密頭時(shí)進(jìn)行填充。當(dāng)然也可以用一些復(fù)雜的規(guī)則去擴(kuò)大這個(gè)結(jié)構(gòu)。自定義的模板規(guī)則,復(fù)雜的花指令生成等等。產(chǎn)生解密模板的時(shí)候可以適當(dāng)?shù)倪\(yùn)用一些編譯原理的技術(shù)。首先產(chǎn)生一個(gè)自己可以理解的中間指令,然后再翻譯成X86代碼。這樣的好處是可以無(wú)限的擴(kuò)充模板的形勢(shì),變形力度很
5、大。在病毒上可能實(shí)現(xiàn)要麻煩些,畢竟病毒要考慮到自身體積的大小,但是殼卻不用考慮那么多。另外一點(diǎn)要說(shuō)明的是做變形的時(shí)候不要拘泥于此格式,可以盡量發(fā)揮想象來(lái)做。例如把解密分段,或者將解密先寫入到棧中在執(zhí)行??傊_(dá)到惡心Cracker的目的就成。2.花指令的構(gòu)建 花指令的構(gòu)建方法有很多種,但是原理都是相同的在不影響運(yùn)行上下文的情況下,產(chǎn)生一些無(wú)效的指令。同樣下文以例子展出,如果自己做的,盡量發(fā)揮想象力。不用拘泥于這篇文章或者某篇文章。2.1產(chǎn)生隨機(jī)寄存器 每條指令對(duì)寄存器的操作的編碼都有一些規(guī)則,具體是什么規(guī)則可以讀下INTEL的編碼規(guī)則。這個(gè)專題里也有一篇是講反匯編引擎的,不過(guò)為了不產(chǎn)生歧義還是推
6、薦去看INTEL的手冊(cè)。這里也不講IA32的編碼規(guī)則了。直接來(lái)看些具體的例子$R表示寄存器,IMM(X)表示立即數(shù),例如MOV $R, IMM32,形如類似的移動(dòng)語(yǔ)句。OPCODE是B8 IMM32 這樣的。B8表示MOV EAX, 可以在OD里查看B9為MOV ECX,這里有個(gè)排序:從EAX開始為EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI這樣的順序。如果翻看MODRM/SIB規(guī)則可以看到這個(gè)排序規(guī)則,至于為什么要這樣排。
7、只能去問(wèn)INTEL公司了。INTEL手冊(cè)里也沒說(shuō)明。 總之MOV $R, IMM32可以變成為B8 B9 BA BB . 按照以上那個(gè)排序選取寄存器。其他指令也一樣例如POP $R是從58開始的.所以每次選取之需要很簡(jiǎn)單的一個(gè)隨機(jī)模8就可以了。 但是這里要排除一個(gè)意外就是esp。ESP控制著堆棧指針稍微有些不細(xì)心就會(huì)造成程序運(yùn)行錯(cuò)誤。為了保險(xiǎn)還是把它T出去好了。不過(guò)不是非要排除ESP。如果你的花指令產(chǎn)生器構(gòu)建的夠精密,模板夠好。也可以把ESP的變換也加進(jìn)來(lái)。為了穩(wěn)定,按照我謹(jǐn)慎的性格還是將它排除在外。SH
8、OW段代碼。C+的。代碼:const DWORD Registry_Eax = 0x00;const DWORD Registry_Ecx = 0x01;const DWORD Registry_Edx = 0x02;const DWORD Registry_Ebx = 0x03;const DWORD Registry_Esp = 0x04;const DWORD Regis
9、try_Ebp = 0x05;const DWORD Registry_Esi = 0x06;const DWORD Registry_Edi = 0x07;const DWORD Registry_MaxCount = 0x08;while (bR0 = Registry_Esp) bR0 = (BYTE)(lrand() % Registry_MaxCount);/
10、0;bR0是選取的寄存器,lrand是隨機(jī)函數(shù)2.2產(chǎn)生隨機(jī)的清0 在編寫代碼過(guò)程中請(qǐng)0操作是常用操作。sub $R,$R . xor $R,$R等都是常用的清0方式。我們把這些方式記錄下來(lái)并保存為我們的模板,如果你不喜歡單指令的。也可以做一些復(fù)雜些的模板 mov $R, IMM32; sub $R, IMM32-1; dec $R;都是可以的。以下展示段簡(jiǎn)單的C+代碼。代碼:const DWORD Clr0_Mov = 0x00;co
11、nst DWORD Clr0_Xor = 0x01;const DWORD Clr0_Sub = 0x02;DWORD MakeClearZero(LPBYTE pClearZero, DWORD dwBufSize, BYTE bRegistry) / mov $R, 0 const BYTE MoveZeroBase = "xB8
12、x00x00x00x00" / xor $R, $R const BYTE XorZeroBase = "x33xC0" / sub $R, $R const BYTE SubZeroBase = "x2BxC0" int nRand = 0; i
13、f (dwBufSize >= 5) lsrand(unsigned)time(NULL); nRand = lrand() % 3; if (nRand = Clr0_Mov) memcpy(pClearZero
14、, MoveZeroBase, 0x05); while (bRegistry = Registry_Esp) bRegistry = (BYTE)(lrand() % Registry_MaxCount); bRegistry += 0xB8;
15、; *(BYTE *)pClearZero = bRegistry; return 0x05; else if (nRand = Clr0_Xor) memcpy(pClearZe
16、ro, XorZeroBase, 0x02); while (bRegistry = Registry_Esp) bRegistry = (BYTE)(lrand() % Registry_MaxCount); bRegistry *= 0x09;
17、0; bRegistry += 0xC0; *(BYTE *)(pClearZero + 1) = bRegistry; return 0x02; else
18、 memcpy(pClearZero, SubZeroBase, 0x02); while (bRegistry = Registry_Esp) bRegistry = (BYTE)(lrand() % Registry_MaxCount);
19、; bRegistry *= 0x09; bRegistry += 0xC0; *(BYTE *)(pClearZero + 1) = bRegistry; return 0x02; e
20、lse if (dwBufSize >= 2) lsrand(unsigned)time(NULL); if (nRand = Clr0_Xor) memcpy(pClearZero, XorZeroBase, 0x02);
21、; while (bRegistry = Registry_Esp) bRegistry = (BYTE)(lrand() % Registry_MaxCount); bRegistry *= 0x09; bRegistry += 0
22、xC0; *(BYTE *)(pClearZero + 1) = bRegistry; return 0x02; else memcpy(pClearZero, SubZeroB
23、ase, 0x02); while (bRegistry = Registry_Esp) bRegistry = (BYTE)(lrand() % Registry_MaxCount); bRegistry *= 0x09;
24、60; bRegistry += 0xC0; *(BYTE *)(pClearZero + 1) = bRegistry; return 0x02; return 0;2.3產(chǎn)生隨機(jī)的JMP有了上面的基礎(chǔ),直接看實(shí)例代碼。代碼:DWORD Ge
25、nerateDummyJmp(PJUNKCODE_BASE pJunkCodeBase, LPBYTE pStart, DWORD dwJunkCodeSize) const DWORD dwMinSize = 0x05; if (dwJunkCodeSize < dwMinSize) return 0; LPBYTE pEnd = pStart
26、;+ dwJunkCodeSize; / 只能產(chǎn)生向后跳的指令 BYTE JmpCodes = "xE9xFFxFFxFFxFF" DWORD dwOffset = pEnd - pStart - 0x05; *(DWORD *)&JmpCodes1 = dwOffset; memcpy(pStart,
27、0;JmpCodes, 0x05); / 生成花指令 DWORD dwRet = GenerateJunkCode(pJunkCodeBase, pStart + 0x05, dwOffset); return (dwRet + 0x05);/ pJunkCodeBase 是 垃圾指令庫(kù),GenerateJunkCode是產(chǎn)生垃圾指令。進(jìn)行填充可以自行構(gòu)建2.4產(chǎn)生異常代碼/
28、60;這個(gè)其中有些函數(shù)是產(chǎn)生push pop的原理都一樣.有興趣的自己動(dòng)手DIY就OK了。原理很簡(jiǎn)單沒什么好寫的了DWORD NaTaSha:GenerateDummySehJmp(PJUNKCODE_BASE pJunkCodeBase, LPBYTE pHeader, DWORD dwHeaderSize) / 基本型 / push $R0 1
29、byte / push $R1 1byte / call delta 5bytes / delta: / pop $R0 1byte
30、160;/ add $R0, dwOffset 6bytes / push $R0 1byte / xor $R1, $R1 2bytes / push fs:$R1
31、; 3bytes / mov fs:$R1, esp 3bytes / 觸發(fā)異常 / 垃圾代碼 / 執(zhí)行代碼 / pop fs:$R1 3bytes / add esp, 04h
32、60; 3bytes / pop $R1 1byte / pop $R0 1byte const DWORD dwSehTotal = 0x80; if (dwHeaderSize
33、0;< dwSehTotal) return 0; LPBYTE pHandler = NULL, pCurr = pHeader; / 模擬SEH跳轉(zhuǎn)的空間最小長(zhǎng)度為128個(gè)字節(jié) const DWORD dwResumeStack = 0x06;/恢復(fù)異常處理堆棧長(zhǎng)度 DWORD dwRemain = dwHeaderSize,
34、160;dwSize = 0; / 首先隨機(jī)選出兩個(gè)寄存器,為了避免意外,過(guò)濾掉esp寄存器 lsrand(unsigned)time(NULL); / R0作為重定位與觸發(fā)異常,R1作為清0 BYTE bR0 = (BYTE)(lrand() % Registry_MaxCount), bR1 = (BYTE)(lrand() % Registry_MaxCount)
35、; while (bR0 = Registry_Esp) bR0 = (BYTE)(lrand() % Registry_MaxCount); while (bR1 = Registry_Esp) bR1 = (BYTE)(lrand() % Registry_MaxCount); DWORD dwRet = 0;
36、160; / 保存寄存器 dwRet = MakePushValue(bR0); *pCurr = (BYTE)dwRet; dwSize+; dwRemain-; pCurr+; dwRet = MakePushValue(bR1); *pCurr = (BYTE)dwRet; dwSize+; d
37、wRemain-; pCurr+; / 重定位 LPBYTE pCall0 = pCurr; dwRet = MakeRelocateCode(pCurr, dwRemain, bR0, 0); dwSize += dwRet; dwRemain -= dwRet; pCurr += dwRet
38、; DWORD dwCall0Size = dwRet; / 壓入異常句柄 dwRet = MakePushValue(bR0); *pCurr = (BYTE)dwRet; dwSize+; dwRemain-; pCurr+; / 清0 dwRet = MakeClearZero(pCu
39、rr, dwRemain, bR1); dwSize += dwRet; dwRemain -= dwRet; pCurr += dwRet; / 建立異常堆棧 const BYTE PushFsR = "x64xFFx30"/3字節(jié) const BYTE MovEspR =
40、"x64x89x20"/3字節(jié) / push dword ptr fs:$R memcpy(pCurr, PushFsR, 0x03); *(pCurr + 0x02) = bR1 + 0x30; dwSize += 0x03; dwRemain -= 0x03; pCurr
41、+= 0x03; / mov dword ptr fs:$R, esp memcpy(pCurr, MovEspR, 0x03); *(pCurr + 0x02) = bR1 + 0x20; dwSize += 0x03; dwRemain -= 0x03; pCurr +=&
42、#160;0x03; / 觸發(fā)異常 dwRet = MakeExpCode(pCurr, dwRemain, bR1); dwSize += dwRet; dwRemain -= dwRet; pCurr += dwRet; / 確定是否產(chǎn)生垃圾代碼 lsrand(unsigned)time(NULL);
43、0;int nRand = lrand() % 2; if (nRand = 0)/ 不產(chǎn)生垃圾代碼 goto GenerateExpHandler; / 垃圾代碼 DWORD dwJunkCodeSize = dwRemain / 2; nRand = lrand() %&
44、#160;dwJunkCodeSize; dwJunkCodeSize = nRand + 1;/隨機(jī)長(zhǎng)度范圍在剩余長(zhǎng)度的一半之內(nèi) dwRet = GenerateJunkCode(pJunkCodeBase, pCurr, dwJunkCodeSize); dwSize += dwRet; dwRemain -= dwRet; pCurr +=
45、dwRet; / 異常執(zhí)行函數(shù)GenerateExpHandler: DWORD dwExpCodeSize = dwRemain - dwResumeStack; dwRet = GenerateJunkCode(pJunkCodeBase, pCurr, dwExpCodeSize); dwSize += dwRet; dwRemain -=
46、dwRet; DWORD dwOffset = (DWORD)(pCurr - pCall0); / 0x04為偏移長(zhǎng)度 *(DWORD *)(pCall0 + dwCall0Size - 0x04) = dwOffset; pCurr += dwRet; / 恢復(fù)異常堆棧 const BYTE&
47、#160;PopFsR = "x64x8Fx00" const BYTE AddEsp4 = "x83xC4x04" / pop dword ptr fs:$R memcpy(pCurr, PopFsR, 0x03); *(pCurr + 0x02) = bR1; dwSize
48、+= 0x03; dwRemain -= 0x03; pCurr += 0x03; / add esp, 04h memcpy(pCurr, AddEsp4, 0x03); dwSize += 0x03; dwRemain -= 0x03; pCurr += 0x03;
49、160;return dwSize;2.5利用MODRM/SIB如果你不知道什么是MODRM/SIB去看看那篇反匯編引擎的構(gòu)建吧或者直接去都INTEL手冊(cè)。TMD這個(gè)殼里運(yùn)用了很多M/S這個(gè)結(jié)構(gòu)構(gòu)造的花指令。這種構(gòu)造很惡心尤其是聯(lián)合上JMP指令。每次你要想在OD里瀏覽代碼整體樣子。都必須要去修復(fù)這段代碼。相比脫過(guò)殼的朋友都遇上過(guò)這種。現(xiàn)在看一個(gè)基本型.其余復(fù)雜的形式靠自己想象了。再次鄭重想做好殼。要時(shí)刻保持豐富的想象力還有一顆“邪惡”的心。所謂是人至*則無(wú)敵。殼至*則無(wú)Cracker.-00401010:JMP 004013E 這里就跳入到了 dword
50、 ptr 4 * ebx + 0xFFFFEEEE這部分其余指令004013Dmov eax, dword ptr 4 * ebx + 0xFFFFEEEE 這里發(fā)揮一下想象力吧。dword ptr 4 * ebx + 0xFFFFEEEE 這部分是可是有足足6個(gè)字節(jié)的空間可以發(fā)揮想象力,但是通常只能利用到SIB位。因?yàn)镸ODRM位產(chǎn)生不了。當(dāng)Mod = 00 01 10 RM = 100 時(shí),那么它的下一個(gè)字節(jié)就是SIB了。通常JMP指令是個(gè)不錯(cuò)的選擇。因?yàn)樽铋L(zhǎng)的JMP也就5個(gè)字節(jié)剛好滿足。既有了花指令的作用,又可以對(duì)抗反匯編。一個(gè)不錯(cuò)的想法
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 區(qū)域獨(dú)家經(jīng)銷合同樣本
- 小學(xué)生漫畫課件
- 農(nóng)用薄膜在不同作物上的應(yīng)用考核試卷
- 體育經(jīng)紀(jì)人運(yùn)動(dòng)員經(jīng)紀(jì)人職業(yè)發(fā)展與轉(zhuǎn)型路徑考核試卷
- 建筑物清潔服務(wù)中的物聯(lián)網(wǎng)技術(shù)應(yīng)用考核試卷
- 期貨市場(chǎng)交易技能培訓(xùn)與模擬交易考核試卷
- 人工智能在電力系統(tǒng)中的電網(wǎng)智能化運(yùn)維考核試卷
- 有線電視傳輸網(wǎng)絡(luò)無(wú)線覆蓋與接入技術(shù)考核試卷
- 服裝生命周期管理考核試卷
- 信托與G網(wǎng)絡(luò)頻譜規(guī)劃實(shí)施策略考核試卷
- 地下車庫(kù)螺旋汽車坡道施工
- 2023年山東鋁業(yè)職業(yè)學(xué)院?jiǎn)握芯C合素質(zhì)題庫(kù)及答案解析
- 【人教版二年級(jí)下冊(cè)數(shù)學(xué)】全冊(cè)課時(shí)鞏固提升練習(xí)和單元鞏固提升練習(xí)
- GB/T 2007.1-1987散裝礦產(chǎn)品取樣、制樣通則手工取樣方法
- 交流課:資本主義世界市場(chǎng)的形成
- 城市社會(huì)學(xué)(2015)課件
- 年產(chǎn)2萬(wàn)噸馬來(lái)酸二乙酯技改建設(shè)項(xiàng)目環(huán)評(píng)報(bào)告書
- 中國(guó)古代文論教程完整版課件
- 中班美工區(qū)角活動(dòng)教案10篇
- SJG 103-2021 無(wú)障礙設(shè)計(jì)標(biāo)準(zhǔn)-高清現(xiàn)行
- 皇冠假日酒店智能化系統(tǒng)安裝工程施工合同范本
評(píng)論
0/150
提交評(píng)論