新160個(gè)CrackMe分析-第1組:1-10(上)

作者:selph
目錄:
?001-前言1
?002-abexcm52
?003-CrueheadCM33
?004-AcidBytes.24
?005-Andrénalin.15
?006-ArturDents-CrackMe26
?007-reg7
?008-Afkayas.18
?009-Boonz-KeygenMe1
?010-ceycey10
6-10(關(guān)注下期文章)
1.001-前言
新160個(gè)CM來(lái)自:新160個(gè)CrackMe算法分析-001-簡(jiǎn)介_(kāi)嗶哩嗶哩_bilibili
?視頻課件下載,百度網(wǎng)盤(pán):https://pan.baidu.com/s/1BaROP5e9UbJMSN1sgOOKbA?提取碼:z2i6
前言
這位師傅整理了新160個(gè)CrackMe和配套的逆向視頻來(lái)幫助新手練習(xí)逆向技能,逆向的基礎(chǔ)便是閱讀反匯編的能力,這正是本練習(xí)的核心所在??????????以前我想過(guò)去堅(jiān)持把160個(gè)做完,但沒(méi)堅(jiān)持下來(lái),近期總想著每天多多少少做點(diǎn)逆向練習(xí),于是我打算去再次挑戰(zhàn),本次以這個(gè)師傅整理的為準(zhǔn)進(jìn)行逆向的練習(xí),去扎實(shí)自己的逆向功底?????????這個(gè)師傅提供了逆向的講解視頻,主要是基于OD動(dòng)態(tài)調(diào)試分析的以及VB版本的注冊(cè)機(jī)編寫(xiě)??????????這里我從另一個(gè)視角去完成本系列文章:以IDA靜態(tài)分析為主,x86dbg動(dòng)態(tài)分析為輔,完成程序的調(diào)試和分析,使用C++/C#?編寫(xiě)注冊(cè)機(jī)??????????歡迎有興趣的童鞋來(lái)探討交流~
?本系列難度星級(jí):
??????????CM難度評(píng)星標(biāo)準(zhǔn)按視頻里的走:
算法:–?:明文字符串操作–??:很容易看懂的算法–???:算法復(fù)雜但容易看懂,or?算法簡(jiǎn)單但不容易看懂–????:算法難,看懂難–?????:分析不出來(lái),以后回來(lái)做??????????爆破:–?:靜態(tài)分析就能找到關(guān)鍵跳–??:回追一層,或修改2個(gè)點(diǎn)的–???:回追二層以上,或修改超過(guò)2個(gè)點(diǎn)的–????:回追多層,修改點(diǎn)難找且多–?????:暫時(shí)無(wú)法破解,以后回來(lái)做
2.?????002-abexcm5
爆破難度:?
算法難度:?
信息收集
運(yùn)行情況:輸入序列號(hào),輸入錯(cuò)誤會(huì)提示錯(cuò)誤并退出程序,這是個(gè)驗(yàn)證序列號(hào)的程序
? ? ? ?查殼:無(wú)殼

? ? ? ? ??查字符串:有提示語(yǔ),疑似硬編碼的字符串

? ? ? ? ??查導(dǎo)入表:使用了字符串操作類(lèi)的函數(shù),以及GetVolumeInformationA函數(shù),不知道序列號(hào)生成跟這個(gè)有無(wú)關(guān)系??????????

到現(xiàn)在已經(jīng)知道了軟件大概的運(yùn)行流程:獲取用戶(hù)輸入,對(duì)用戶(hù)輸入進(jìn)行一些處理,然后彈框提示
逆向分析
IDA里選擇MessageBoxA函數(shù)查交叉引用,跟蹤到函數(shù)sub_401056中,這是CM的校驗(yàn)邏輯所在:首先先獲取用戶(hù)輸入,然后生成兩個(gè)字符串:(注釋寫(xiě)錯(cuò)了,應(yīng)該是do-while循環(huán)而不是while循環(huán))

? ? ? ? ?然后把剛剛生成的兩個(gè)字符串拼接到一起,生成序列號(hào),與用戶(hù)輸入進(jìn)行比對(duì),序列號(hào)幾乎是硬編碼

??????????
暴力破解
驗(yàn)證邏輯是:生成序列號(hào),通過(guò)與用戶(hù)輸入的比對(duì)來(lái)進(jìn)行驗(yàn)證
暴力破解的思路是:修改跳轉(zhuǎn)條件即可,把jz改成jmp即可:

? ? ? ? ??算法分析注冊(cè)碼生成算法:????#include
#include
int main()
{
????char VolumeNameBuffer[MAX_PATH] = { 0 };
????DWORD VolumeSerialNumber = 0;
????DWORD MaximumComponentLength = 0;
????DWORD FileSystemFlags = 0;
????int i = 2;
????char Series[MAX_PATH] = { 0 };
?????
????GetVolumeInformationA(
????????0,
????????VolumeNameBuffer,
????????0x32u,
????????&VolumeSerialNumber,
????????&MaximumComponentLength,
????????&FileSystemFlags,
????????0,
????????0);
????lstrcatA(VolumeNameBuffer, "4562-ABEX");
??????
????do{
????????VolumeNameBuffer[0]++;
????????VolumeNameBuffer[1]++;
????????VolumeNameBuffer[2]++;
????????VolumeNameBuffer[3]++;
????} while (--i);
????lstrcatA(Series, "L2C-5781");
????lstrcatA(Series, VolumeNameBuffer);
????std::cout << Series << std::endl;
????system("pause");
????return 0;
}效果:

? ? ? ? ??總結(jié)字符串拼接生成序列號(hào),通過(guò)判斷+跳轉(zhuǎn)進(jìn)行校驗(yàn),很簡(jiǎn)單,沒(méi)啥好說(shuō)的
參考資料
–[1]?GetVolumeInformationA獲取磁盤(pán)卷標(biāo)、文件系統(tǒng),_上善若水pjf的博客-CSDN博客_getvolumeinformationa
3.?????003-CrueheadCM3
爆破難度:??算法難度:??
信息收集
運(yùn)行情況:是一個(gè)空白界面,可能要經(jīng)過(guò)某些操作才能讓內(nèi)容顯示出來(lái)??????????

查殼:無(wú)殼

查字符串:看到了一些提示語(yǔ)

??????????查導(dǎo)入表:除去窗口繪制,消息循環(huán)用到的函數(shù),這里還出現(xiàn)了文件操作相關(guān)函數(shù),可能跟文件有關(guān),結(jié)合上面的字符串搜索信息,應(yīng)該需要一個(gè)CRACKME3.KEY的文件

??????????
逆向分析
根據(jù)之前對(duì)文件進(jìn)行靜態(tài)的信息收集之后,這個(gè)文件操作很可疑,就從文件操作函數(shù)CreateFileA去搜索交叉引用看看這里在干嘛首先打開(kāi)名為CRACKME3.KEY的文件,然后讀取其中的內(nèi)容保存到緩沖區(qū)

??????????然后判斷讀取的字節(jié)數(shù)如果是0x12就往下走,對(duì)讀取到的內(nèi)容進(jìn)行一頓操作,然后通過(guò)某種計(jì)算方法進(jìn)行校驗(yàn),然后把校驗(yàn)結(jié)果保存在al里入棧了

??????????然后經(jīng)過(guò)一段窗口創(chuàng)建的操作之后,在進(jìn)入消息循環(huán)之前,做了這樣一個(gè)校驗(yàn),校驗(yàn)文件內(nèi)容是否正確,正確就彈框提示,正是通過(guò)剛剛push的al進(jìn)行校驗(yàn)的

暴力破解整個(gè)校驗(yàn)流程最后還是通過(guò)判斷+跳轉(zhuǎn)進(jìn)行執(zhí)行的,暴力破解老樣子,直接修改跳轉(zhuǎn)條件即可:

前面還有個(gè)判斷讀取到的內(nèi)容是否為0x12字節(jié),把那個(gè)跳轉(zhuǎn)也nop改掉即可,這里就不演示了
算法分析
這里的校驗(yàn)算法主要是這幾行:

??????????這里調(diào)用了兩個(gè)自寫(xiě)的函數(shù),首先是sub_401311:這里計(jì)算一個(gè)前14字節(jié)的校驗(yàn)和,然后對(duì)前14字節(jié)依次與ABCD...進(jìn)行異或操作,將異或的結(jié)果保存起來(lái),校驗(yàn)和也保存起來(lái)

??????????然后是下一個(gè)函數(shù)sub_40133C:就是取后4字節(jié)出來(lái)

??????????現(xiàn)在這個(gè)校驗(yàn)算法已經(jīng)清晰了起來(lái):–計(jì)算一個(gè)校驗(yàn)和,校驗(yàn)和與0x12345678進(jìn)行異或,得到的結(jié)果與輸入里的最后4字節(jié)進(jìn)行比較–對(duì)輸入的前14字節(jié)進(jìn)行異或操作,異或后的結(jié)果作為參數(shù)去調(diào)用顯示驗(yàn)證成功提示框
那么序列號(hào)的生成就是:a.隨便輸入一個(gè)14字節(jié)的字符串作為用戶(hù)名b.對(duì)這14字節(jié)依次異或ABCD...,保存起來(lái)c.對(duì)校驗(yàn)和異或0x12345678,然后拼接到異或結(jié)果后面,即可完成生成
注冊(cè)碼生成算法:????#include
#include
void generateSeriesFile(const char* in_pwd) {
????char pwd[0x13] = { 0 };
????int i;
????char var_bl = 'A';
????unsigned int sum = 0;
????memcpy(pwd, in_pwd, 0x13);
????i = 0;
????do {
????????sum += pwd[i];
????????pwd[i] ^= var_bl;
????????i++;
????????var_bl++;
????????if (!pwd[i])break;
????} while (var_bl != 'O');
????sum ^= 0x12345678;
????*(unsigned int *)&pwd[0xE] = sum;
????for (int k = 0; k < 18; k++)
????{
????????unsigned char* tmp = (unsigned char*) & pwd;
????????printf("%02x ",tmp[k]);
????}
????HANDLE hFile = CreateFileA("CRACKME3.KEY", GENERIC_ALL, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
????DWORD retNum = 0;
????WriteFile(hFile, pwd, sizeof(pwd), &retNum, NULL);
????CloseHandle(hFile);
}
int main()
{
????const char *pwd= "helloworld@qqq.com";
????generateSeriesFile(pwd);
????system("pause");
????return 0;
}效果:

? ? ? ? ??
總結(jié)
序列號(hào)算法和校驗(yàn)依然很簡(jiǎn)單,這里有意思的是:這個(gè)程序的校驗(yàn)邏輯位于窗口進(jìn)入消息循環(huán)之前,校驗(yàn)行為發(fā)生在了軟件正常運(yùn)行之前,根據(jù)校驗(yàn)結(jié)果再選擇是否正常運(yùn)行程序
參考資料
–[1]?ASCII碼一覽表,ASCII碼對(duì)照表?(biancheng.net)–[2]?setz_ccboby的博客-CSDN博客_setz指令
4.?????004-AcidBytes.2
算法難度:?爆破難度:?脫殼難度:?
信息收集
運(yùn)行情況:
依然是序列號(hào)驗(yàn)證,輸入序列號(hào)點(diǎn)擊Check,會(huì)顯示提示信息?
?????????
查殼與脫殼:
出現(xiàn)殼了,Die查出來(lái)是Upx壓縮殼??????????
對(duì)于Upx殼使用ESP定律即可完成脫殼,過(guò)程相當(dāng)簡(jiǎn)單,這里簡(jiǎn)述一下就不截圖演示了:a.運(yùn)行到OEP,運(yùn)行到pushad的下一行(執(zhí)行這個(gè)指令只有esp的值會(huì)被修改)
b.在內(nèi)存中查看esp指向的地址,對(duì)該地址下訪問(wèn)硬件斷點(diǎn),然后運(yùn)行,此時(shí)會(huì)運(yùn)行到popad指令的下一行,是跳轉(zhuǎn)到真正OEP的jmp,跳轉(zhuǎn)過(guò)去
c.使用Scylla進(jìn)行Dump和修復(fù)PE,得到脫殼后的程序再次查殼驗(yàn)證:
? ? ? ?
?查字符串:
有點(diǎn)幫助的字符串是這些,是驗(yàn)證提示信息
??????????
查導(dǎo)入表:
沒(méi)有什么特別的點(diǎn),看起來(lái)都是圖形界面相關(guān)的內(nèi)容,程序使用MessageBoxA彈窗提示
調(diào)試分析
這個(gè)程序的傳參方式比較特別,根據(jù)查閱資料[1],前三個(gè)數(shù)據(jù)保存在eax,edx,ecx寄存器里,超過(guò)三個(gè)參數(shù)部分放在堆棧傳遞這里以字符串作為入口進(jìn)行突破,搜索字符串Congrats!...的交叉引用,找到按鈕控件的處理例程:首先是注冊(cè)了SEH異常鏈,然后獲取用戶(hù)輸入
??????????接下來(lái)就是比較+彈窗三連:輸入字符串和硬編碼字符串進(jìn)行對(duì)比,如果相同,就彈窗提示成果如果不相同,就判斷是否輸入的有內(nèi)容,如果無(wú)內(nèi)容,提示輸入為空,否則提示輸入錯(cuò)誤
???? ? ?
暴力破解
直接Nop掉關(guān)鍵跳即可:
??????????
算法分析
硬編碼密碼,無(wú)算法效果:
??????????
總結(jié)
處理該CM的要點(diǎn)就是脫殼,脫殼之后就是硬編碼判斷跳轉(zhuǎn),算是個(gè)入門(mén)級(jí)脫殼練習(xí)
參考資料
–[1]?Delphi的參數(shù)傳遞約定以及動(dòng)態(tài)參數(shù)個(gè)數(shù)(轉(zhuǎn)載筆記) -?不得閑?-?博客園?(cnblogs.com)
5.?????005-Andrénalin.1
算法難度:?爆破難度:?
信息收集
運(yùn)行情況:
功能就是輸入密碼,然后驗(yàn)證??????????
查殼與脫殼:
無(wú)殼,是?VB?編寫(xiě)的?GUI?程序,需要使用?VB?反編譯工具進(jìn)行逆向分析
?? ? ? ?
調(diào)試分析
對(duì)于?VB?程序,可以使用?VB Decompiler?進(jìn)行逆向,本例驗(yàn)證邏輯較為簡(jiǎn)單,估計(jì)主要是練習(xí)
??????????
破解
硬編碼校驗(yàn)密碼,直接輸入即可效果:
??????????
總結(jié)
本例沒(méi)什么難度,主要是告訴初學(xué)者,對(duì)于?VB,CSharp?這類(lèi)的托管程序,可以使用專(zhuān)門(mén)的反編譯軟件進(jìn)行代碼還原分析邏輯