劉鍵林
(天津現(xiàn)代職業(yè)技術(shù)學(xué)院,天津 300350)
?
CrackMe調(diào)試及算法分析
劉鍵林
(天津現(xiàn)代職業(yè)技術(shù)學(xué)院,天津300350)
摘要:目前網(wǎng)絡(luò)上最便利于交流學(xué)習(xí)的CrackMe,已經(jīng)被程序人員與Cracker愛好者廣泛地流傳于相互學(xué)習(xí)交流的平臺(tái)上,便利大家共同研究、分析、切磋程序人員的最新思路,以及程序人員之間要準(zhǔn)備解決與需要攻克的問題。文本主要論述與分析CrackMe的調(diào)試及算法。
關(guān)鍵詞:CrackMe分析;脫殼分析;算法分析
一、CrackMe分析
首先分析一下CrackMe,主要條件是需要詳細(xì)觀察其運(yùn)行條件,是否有注冊(cè)窗口,是否有人機(jī)對(duì)話框提示,其次、是否加殼、加何種殼,如何脫殼。何種語言編寫等等,這些都是詳細(xì)分析之前需要掌握的信息。我們雙擊主程序使其運(yùn)行,隨即出現(xiàn)運(yùn)行后的主界面。主界面要求在注冊(cè)框輸入注冊(cè)碼。任意輸入了一些數(shù)字之后點(diǎn)擊注冊(cè)按鈕,隨即驚人的一幕發(fā)生了Windows操作系統(tǒng)被強(qiáng)制注銷了。
1.這種情況首先是CrackMe必須獲取權(quán)限,然后對(duì)輸入的任意數(shù)字“測(cè)試碼”進(jìn)行對(duì)比,正確即刻彈出現(xiàn)溫和的人機(jī)互動(dòng)對(duì)話框。反之此CrackMe將在不做任何提示的情況下一律按逆向分析者處理,繼而使用獲取到的權(quán)限調(diào)用Windows系統(tǒng)下的ExitWindowsEx函數(shù),此函數(shù)為重啟或注銷操作系統(tǒng)。這種函數(shù)調(diào)用僅此CrackMe如此使用而已,若為惡意軟件使用麻煩肯定是有的。
2.待計(jì)算機(jī)操作系統(tǒng)重新正常啟動(dòng)之后,注冊(cè)框內(nèi)我們什么也沒有輸入而再次點(diǎn)擊注冊(cè)按鈕時(shí)Windows系統(tǒng)再次被強(qiáng)制注銷。至此我們已經(jīng)大致清楚了CrackMe的作者為了防止逆向分析其注冊(cè)機(jī)制而設(shè)計(jì)的調(diào)取API來注銷系統(tǒng)繼而考驗(yàn)?zāi)托裕M(jìn)而阻止利用獲取內(nèi)存鏡像方法來獲取注冊(cè)比對(duì)信息。至此大致已經(jīng)清楚CrackMe作者的思路這是反內(nèi)存注冊(cè)算法。
二、脫殼分析
1.如果對(duì)任何一款軟件進(jìn)行分析,那么首先要利用一些工具軟件檢測(cè)一下該程序是被什么加殼工具加的殼,尤其是那些經(jīng)驗(yàn)豐富的Cracker在反匯編代碼里大致分析段首的特征碼即刻確定加的什么殼。然后將其外表的殼脫掉使其還原成未加殼的代碼原貌再進(jìn)行反匯編詳盡分析。對(duì)于此CrackMe所加殼的種類分析,本文在這里借助一款查殼專業(yè)很強(qiáng)的軟件PEID來對(duì)其進(jìn)行殼種類的檢測(cè)。通過PEID?檢測(cè)結(jié)果此CrackMe殼為ASPack?2.12?->?Alexey?Solodovnikov?所加殼,屬于比較溫和的一款加殼軟件。無論任何一款被加殼程序在逆向詳細(xì)分析前首先是需要脫掉其ASPack的外殼,脫殼的方法有很多、包括現(xiàn)成的效果很棒脫殼軟件?;蛘呃肙llyDbg調(diào)試器等。方式方法很多諸如OllyDbg軟件的脫殼腳本、ESP定律等等。這里將使用OllyDbg調(diào)試器插件當(dāng)中OllyDump來進(jìn)行手動(dòng)單步跟蹤,進(jìn)行脫殼過程以及分析ASPack外殼的加密方式。
2.進(jìn)行脫殼分析。OllyDbg調(diào)試器載入CrackMe脫殼過程以及反匯編源代碼如下:
004D3001>60pushad:程序入口 (F8)單步執(zhí)行。
004D3002E8 03000000call004D300A:此call(F7)跟進(jìn)里面。
004D3007- E9 EB045D45jmp45AA34F7:迷惑人的花指令。
004D300C55pushebp
004D300DC3retn
004D300E E8 01000000call004D3014 :巧妙利用花指令保護(hù)上面CALL地址。
(F7)跟進(jìn)004D3002的call之后來到這里反匯編代碼如下:
004D300A5Dpopebp:CrackMe.004D3007。
004D300B45incebp
004D300C55pushebp
004D300DC3retn:執(zhí)行返回到004D3008。
接上面執(zhí)行返回之后來到這里反匯編代碼如下:
004D3008/EB 04jmpshort 004D300E :無條件跳轉(zhuǎn)跳到004D300E處。
004D300A|5Dpopebp
004D300B|45incebp
004D300C|55pushebp
004D300D|C3retn
004D300E/E8 01000000call004D3014:此call(F7)跟進(jìn)去。
上面004D300E的call跟進(jìn)之后來到這里反匯編代碼如下:
004D30145Dpopebp CrackMe.004D3013:代碼重定位。彈出返回地址ebp=004D3013。
004D3015BB EDFFFFFFmovebx, -13:偏移量為13h字節(jié)。
004D301A03DDaddebx, ebp:004D3013-13=004D3000殼代碼段起始位置。
004D301C81EB 00300D00subebx, 0D3000:004d3000-3000=00400000(ImageBase)
映射地址。
004D302283BD 220400000>cmpdword ptr [ebp+422], 0
:[ebp+422]=[004D3435]=00000000。
004D3029899D 22040000movdword ptr [ebp+422], ebx
:[ebp+422]存入00400000(ImageBase)。
004D302F0F85 65030000jnz004D339A:初始化為0,進(jìn)行解壓縮、填充IAT表處理,完成后再回到這里判斷,如果是00400000就去OEP)jnz條件跳轉(zhuǎn),轉(zhuǎn)移指令。結(jié)果不為零(或不相等)則轉(zhuǎn)移。
004D30358D85 2E040000leaeax, dword ptr [ebp+42E]:然后繼續(xù)單步跟蹤。
004D303B50pusheax
004D303CFF95 4D0F0000calldword ptr[ebp+F4D]
004D30428985 26040000movdword ptr[ebp+426], eax
004D30488BF8movedi, eax
說明:其中這上、下代碼之間還有很多相關(guān)但是不太重要的代碼段在此處已經(jīng)被忽略若干條。
然后我們繼續(xù)單步跟蹤來到這里反匯編代碼如下:
004D30668985 51050000movdword ptr[ebp+551], eax :保存函數(shù)地址。
004D306C8D45 77leaeax, dword ptr[ebp+77]:地址=004D308A。
004D306FFFE0jmpeax:跳向目標(biāo)地址004D308A。
004D307156pushesi:
004D33A00385 22040000addeax, dword ptr[ebp+422]:CrackMe.00400000。
:RVA+ImageBase=OEP。
004D33A659popecx:彈出OEP的RVA。
004D33A70BC9orecx, ecx:OEP的RVA是否為0。
004D33A98985 A8030000movdword ptr [ebp+3A8], eax:修改程序代碼,將OEP寫入、壓棧指令。
004D33AF61popad:
004D33B075 08jnzshort CrackMe 004D33BA :OEP的RVA不為0則跳,否則程序已經(jīng)運(yùn)行。
004D33B2B8 01000000moveax, 1:
004D33B7C2 0C00retn0C:
004D33BA68 00000000push0:這里被修改成了push 004B0FE0。
004D33BFC3retn:利用執(zhí)行到返回前往OEP也就是程序的可以運(yùn)行的入口處。
承接上面的執(zhí)行到返回來到下面的反匯編代碼到達(dá)OEP 入口。匯編代碼如下:
004B0FE055pushebp:這里就是程序入口的OEP此處我們可以利用OllyDump進(jìn)行脫殼了。
004B0FE18BECmovebp, esp
004B0FE383C4 F0addesp, -10
004B0FE6B8 800D4B00moveax, 004B0D80
004B0FEBE8 D85AF5FFcall00406AC8
004B0FF06A 00push0
004B0FF268 58104B00push004B1058:ASCII “CrackMeDialTime”。
004B0FF7E8 9462F5FFcall00407290: jmp user32.FindWindowA。
通過上面詳盡的單步跟蹤我們順利的到達(dá)了OEP,到達(dá)之后本文將使用OllyDbg調(diào)試器內(nèi)的OllyDump功能插件進(jìn)行脫殼,程序脫殼順利完成。隨之我們雙擊運(yùn)行被脫殼后的程序,出現(xiàn)的運(yùn)行界面顯示本軟件完全可以正常運(yùn)行。
3.脫殼分析ASPack 2.12小結(jié)。根據(jù)ASPack 2.12的特點(diǎn)現(xiàn)作如下分析,該殼非常巧妙的利用了偽輸入表動(dòng)態(tài)的調(diào)入來滿足殼運(yùn)行時(shí)所需要的函數(shù)。然后將程序中的每一個(gè)段先解壓到緩沖區(qū)域之后,再進(jìn)行復(fù)制到目標(biāo)區(qū)域的段內(nèi),以達(dá)到對(duì)輸入表的保護(hù)。如果代碼在緩沖區(qū)內(nèi),可以將所有開頭為call和jmp指令的段先行解密到正確的目標(biāo)地址之后,再復(fù)制到目標(biāo)區(qū)域的段內(nèi)。但是對(duì)于我們分析的此CrackMe所加ASPack殼被完整的保留了輸入表,脫殼后輸入表不需要再行修復(fù)。因?yàn)樗妮斎氡硎抢脛?dòng)態(tài)函數(shù)獲取得到的。利用動(dòng)態(tài)獲取函數(shù)地址之后再填入IAT表,之后方利用執(zhí)行到返回的指令跳轉(zhuǎn)向OEP。此ASPack殼運(yùn)行中且自動(dòng)完成了修改代碼,最后以retn“執(zhí)行到返回 ”的方式返回到OEP。此殼采用了一些花指令干擾靜態(tài)調(diào)試。對(duì)部分的call和jmp的目標(biāo)地址好像是起到了加密的作用了,但是、不過是解壓后在緩沖區(qū)域內(nèi)又解密并復(fù)制到代碼段中。所以此處好像是略顯欠佳,作者在后面的ASPack高版本中已經(jīng)進(jìn)行了改變?cè)O(shè)計(jì)。
三、算法及注冊(cè)機(jī)制分析
1.脫殼成功且能夠運(yùn)行之后、首先發(fā)現(xiàn)一點(diǎn)既是CrackMe的文件大小發(fā)生了變化由脫殼前的305KB增大為脫殼后的864KB換句話說,也就是壓縮比還是可以的。但是ASPack 2.12這個(gè)版本對(duì)于輸入表的隱藏與加密還是欠佳的,因此后面高版本的ASPack作者對(duì)輸入表的隱藏功能改進(jìn)較大,另外還增加了許多加密功能。脫殼后需要輸入表的深入、細(xì)心的修復(fù),否則的話逆向分析將為之停止在這里。
2.完成脫殼之后對(duì)此CrackMe也有了一個(gè)詳盡的分析及了解,接下來就要按照輕重順序、來清除影響阻止我們分析的障礙。接下來需要我們解除CrackMe對(duì)調(diào)試機(jī)器操作系統(tǒng)的強(qiáng)制注銷,不然我們將被陷于操作系統(tǒng)往復(fù)重啟之麻煩當(dāng)中。也便利對(duì)其進(jìn)行深入細(xì)致的分析。當(dāng)我們運(yùn)行CrackMe出現(xiàn)主界面之后,在其注冊(cè)框內(nèi)輸入任意“測(cè)試碼”點(diǎn)擊注冊(cè)按鈕之后系統(tǒng)毫不客氣的被注銷,也就是所有潛伏的調(diào)試軟件一律被停止了。分析:首先CrackMe在運(yùn)行過程中其注冊(cè)框內(nèi)如果輸入的注冊(cè)碼正確將顯示注冊(cè)成功,解除一切功能限制。若發(fā)現(xiàn)注冊(cè)框內(nèi)注冊(cè)碼錯(cuò)誤首先利用AdjustTokenPrivileges函數(shù)獲取對(duì)操作系統(tǒng)的管理權(quán)限,繼而調(diào)用ExitWindowsEx函數(shù)使調(diào)試機(jī)器的操作系統(tǒng)重新啟動(dòng),以此達(dá)到阻止對(duì)其分析,至此我們已經(jīng)有了一個(gè)詳盡解除方案了。好了我們等待計(jì)算機(jī)的操作系統(tǒng)重新啟動(dòng)之后利用OllyDbg調(diào)試器載入CrackMe在命令窗口下斷點(diǎn)BP ExitWindowsEx過程以及反匯編源代碼如下:
命令窗口BP ExitWindowsEx斷在這里反匯編代碼顯示如下:
77D5A275>8BFFmov edi,edi
77D5A27755push ebp
77D5A2788BECmov ebp,esp
77D5A27A83EC 18sub esp,0x18
77D5A27D53push ebx
77D5A27E8B5D 08mov ebx,dword ptr ss:[ebp+0x8]。
分析堆棧匯反編代碼顯示如下:
0012FD54004AD87F/CALL 到 ExitWindowsEx 來自 CrackMe.004AD87A。
0012FD5800000004 |Options = EWX_FORCE。
0012FD5C00000000/Reserved = 0。
利用快捷鍵、Ctrl+G 前往004AD87A:
當(dāng)我們來到004AD87A仔細(xì)分析這些匯編代碼之后,發(fā)現(xiàn)跳轉(zhuǎn)已經(jīng)無條件實(shí)施了所以檢測(cè)和校驗(yàn)一定是在004AD87A之上這些匯編代碼之中。反匯編代碼分析顯示如下:
004AD860 |.50push eax: /pRetLen。
004AD861 |.6A 00push 0x0:|pPrevState = NULL。
004AD863 |.6A 10push 0x10:|PrevStateSize = 10 (16.)。
004AD865 |.8D4424 20lea eax,dword ptr ss:[esp+0x20] :|
004AD869 |.50push eax:|pNewState。
004AD86A|.6A 00push 0x0:|DisableAllPrivileges = FALSE。
004AD86C|.8B4424 14mov eax,dword ptr ss:[esp+0x14]:|
004AD870 |.50push eax:|hToken = 0000018C (window)。
004AD871E8 8A93F5FFcall CrackMe.00406C00: jmp 到 advapi32.AdjustTokenPrivileges。
004AD8766A 00push 0x0:這個(gè)入棧的推手NOP掉。
004AD8786A 04push 0x4:這個(gè)入棧的推手NOP掉。
004AD87AE8 019AF5FFcall CrackMe.00407280: jmp 到 user32.ExitWindowsEx。
修改其倆個(gè)指令之后,然后我們右鍵將對(duì)其重新修改指令之處復(fù)制到可執(zhí)行文件,保存。至此可以說我們已經(jīng)完全的解除了該CrackMe將自己提升的的注銷系統(tǒng)權(quán)限,之后再行測(cè)試一切安然。注:關(guān)于NOP在反匯編修改其內(nèi)容或改變其跳轉(zhuǎn)時(shí)一定要按照匯編指令規(guī)律操作,所以這里只有用NOP來填充其字節(jié)數(shù)保證CrackMe的完整不受影響。
3.解除注銷系統(tǒng)權(quán)限之后我們只是簡(jiǎn)略的分析其注冊(cè)算法:利用OllyDbg再次載入CrackMe利用ApiBreak插件內(nèi)的功能下斷?PointH這是一個(gè)萬能斷點(diǎn),點(diǎn)擊運(yùn)行,待CrackMe運(yùn)行起來我們輸入測(cè)試碼之后點(diǎn)擊注冊(cè)按鈕時(shí)CrackMe被攔截在這里。
萬能斷點(diǎn)攔截后反匯編源代碼如下:
004AD707 |.8B86 FC020000mov eax,dword ptr ds:[esi+0x2FC]
004AD70D |.E8 1260F9FFcall CrackMe.00443724:獲取“測(cè)試”碼的輸入位數(shù)。
004AD712|.837D FC 00cmp [local.1],0x0:注冊(cè)框內(nèi)是否“空”。
004AD7160F84 A3000000je CrackMe.004AD7BF:如果注冊(cè)框是空的就開始循環(huán),否則繼續(xù)。
004AD71C|.8D55 F8lea edx,[local.2]:動(dòng)態(tài)指向0012FDB0“測(cè)試碼”地址。
004AD71F|.8B86 FC020000mov eax,dword ptr ds:[esi+0x2FC]
:獲取的“測(cè)試碼”與“位數(shù)”存入EDX寄存器。
004AD725|.E8 FA5FF9FFcall CrackMe.00443724
004AD72A|.8B45 F8mov eax,[local.2]
004AD72D|.50push eax:測(cè)試碼入站。
004AD72E|.8D55 F0lea edx,[local.4]
004AD731|.8BC6mov eax,esi
004AD733|.E8 90FBFFFFcall CrackMe.004AD2C8:測(cè)試碼轉(zhuǎn)成16進(jìn)制乘:10加4減1重復(fù)測(cè)試碼位數(shù),然后獲取CPUID。
004AD738|.8B55 F0mov edx,[local.4]
004AD73B|.8D4D F4lea ecx,[local.3]
004AD73E|.A1 F8334B00mov eax,dword ptr ds:[0x4B33F8]
004AD743|.8B00mov eax,dword ptr ds:[eax]
004AD745|.E8 02A2FDFFcall CrackMe.0048794C
004AD74A|.8B55 F4mov edx,[local.3]
004AD74D|.58pop eax
004AD74E|.E8 5973F5FFcall CrackMe.00404AAC:測(cè)試碼與注冊(cè)碼對(duì)比。
004AD753|.74 14je XCrackMe.004AD769:對(duì)比結(jié)果相等跳向004AD769,否則將重啟機(jī)器。
綜上所述分析結(jié)果,如果根據(jù)上面所做的詳細(xì)分析要得到注冊(cè)算法已經(jīng)非常明朗,若利用我們自己編寫的程序提取注冊(cè)碼也是很輕松的事情。這里本文不在論述、如何編寫程序提取注冊(cè)碼,因?yàn)槿绻撌鼍帉懗绦蛱崛∽?cè)碼需要很長(zhǎng)的篇幅所以此文不在論述。但是我們可以利用一款現(xiàn)成的內(nèi)存注冊(cè)碼提取軟件來完成此CrackMe的內(nèi)存注冊(cè)碼的算法提取工作。
內(nèi)存注冊(cè)碼提取方法如下:
我們首先下載keymake內(nèi)存注冊(cè)碼算法提取軟件,這是一款功能非常強(qiáng)大的軟件。它的詳細(xì)功能我們不在復(fù)述,因?yàn)樽髡哔x予的功能是超出大家想象的之外。只有但我們親自試驗(yàn)之后方為得知。
下面首先運(yùn)行keymake待其正常運(yùn)行之后,開始填入我們上面詳細(xì)分析的相關(guān)的中斷地址、寄存器、中斷次數(shù)、攔截進(jìn)程、等。按軟件提示填入相關(guān)數(shù)據(jù)之后,該軟件將自動(dòng)生成內(nèi)存注冊(cè)碼提取軟件但是在使用時(shí)該軟件一定要和CrackMe保存在一個(gè)文件夾之下。
關(guān)鍵之處反匯編代碼如下:
004AD74A|.8B55 F4mov edx,[local.3]
004AD74D|.58pop eax
004AD74E|.E8 5973F5FFcall CrackMe.00404AAC:測(cè)試碼與注冊(cè)碼對(duì)比。
004AD753|.74 14je XCrackMe.004AD769:對(duì)比結(jié)果相等跳向004AD769,否則將重啟機(jī)器。
需要填寫代碼如下:
地址如下:
中斷地址004AD74E。
中斷次數(shù) :1。
中斷指令:E8。
指令長(zhǎng)度:5。
方式:
內(nèi)存方式:
寄存器:EDX
寬字節(jié):
地址指針:1
攔截所有進(jìn)程。
然后將指針指向CrackMe所在之處,接下來點(diǎn)擊生成。此時(shí)一款我們自己分析的內(nèi)存注冊(cè)碼提取軟件已經(jīng)生成。運(yùn)行之時(shí)內(nèi)存注冊(cè)碼提取軟件首先按我們的指針方向?qū)ふ褻rackMe,并將其激活。之后我們?cè)谧?cè)窗口輸入測(cè)試碼、點(diǎn)擊確定按鈕之關(guān)鍵之時(shí),我們的內(nèi)存注冊(cè)碼提取軟件將在內(nèi)存當(dāng)中獲取到正確的注冊(cè)碼,之后將注冊(cè)碼復(fù)制填入注冊(cè)窗口點(diǎn)擊確定按鈕,溫馨的人機(jī)對(duì)話欣然出現(xiàn)“注冊(cè)成功”。
再者將此CrackMe脫殼、解除ExitWindowsEx。的調(diào)用之后,將004AD753這個(gè)關(guān)鍵跳轉(zhuǎn)74若修改為75或者EB。將得到非常輕松的爆破結(jié)果,
通過對(duì)其CrackMe的脫殼、解除限制、算法分析之后。雖然花費(fèi)了一些時(shí)間,但是從中獲益匪淺深感益師無處不在,學(xué)無止境。若這種限制方法被惡意使用,解決的難度也是可想的、不過通過分析學(xué)習(xí)解決的方法也會(huì)更加進(jìn)步。
CrackMe Debugging and Algorithm Analysis
LIU Jian-lin
(TianjinModernVocationalTechnicalCollege,Tianjin, 300350)
Abstract:CrackMe which is most convenient for exchange and communication on the internet has been widely communicated by the programmers and Cracker fans on the platform of mutual learning and exchange, so that everyone can jointly research, analyze and discuss the latest thought of programmers and problems to be solved and tackled among the programmers.This paper mainly discusses and analyzes the debugging and algorithm of CrackMe.
Key words:CrackMe analysis; shell analysis; algorithm analysis
中圖分類號(hào):TP311
文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1673-582X(2016)04-0106-07
作者簡(jiǎn)介:劉鍵林(1959-),男,天津市人,天津現(xiàn)代職業(yè)技術(shù)學(xué)院計(jì)算機(jī)實(shí)驗(yàn)室管理員、工程師,從事計(jì)算機(jī)加密與解密教學(xué)與研究工作。
收稿日期:2015-12-29