破解过程明天补上。
- 标 题:2008看雪论坛读书月第二题 KeyGen
- 作 者:沙金
- 时 间:2008-07-26 00:38
- 链 接:http://bbs.pediy.com/showthread.php?t=69321
破解过程明天补上。
【文章标题】: 【原创】【看雪读书月】《2008看雪论坛读书月第二题crackMe02》KeyGen
【文章作者】: 沙金
【软件名称】: 2008看雪论坛读书月第二题crackMe02
【软件大小】: 49.2 KB
【下载地址】: http://bbs.pediy.com/showthread.php?t=68795
【软件作者】: MegaX
【编写语言】: Microsoft Visual C++ 2008 (.net)
【使用工具】: OD
【操作平台】: WINDOWS2003
【软件介绍】: 2008看雪论坛读书月第二题
--------------------------------------------------------------------------------
【详细过程】
一、测试篇
拿到题以后,首先用OD载入,直接报错(我的系统是winxp)。
启动VM,把题拷入2003系统下,运行,OK了。
随便输入用户名和key,提示重启应用程序,查看没有生成文件,于是在注册表里查找刚才输入的用户名,果然在 HKEY_CURRENT_USER\Software\MegaX 找到。
二、反编译篇
由于从来没有调试过.net程序,所以,在google一下,才知道.net可以反编译,于是,开始下载工具。
首先是Reflector 下载了最新版,结果反编译失败。
然后使用ildasm 可以读出部分结构,但很多类名乱码,没有得到可用信息。
本想试试PEBrowse ,在google里发现,在使用PEBrowse前,要用ildasm反编译后,生成带debug信息的exe才有效果。只能放弃。
仔细想想,如果可以这么简单,那就不是看雪的风格了。应该是加了壳,所以一般的反编译工具没有办法。只能动态调试了。
三、OD篇
用OD载入,程序直接自动启动,OD的ICE区一片空白。
想到有注册表的操作,于是 bp RegOpenKeyExA 和 bp RegOpenKeyExW ,重新载入,在RegOpenKeyExW处断下。可以判断是UNICODE码。
断了70次左右,总算看到了"MegaX" 字符串,记录下当前寄存器变量发现esi值可以利用,于是,
在 77F57AAB > 81FE 04000080 cmp esi, 80000004 下esi == 1DC 的条件断点,再次重启程序,果然断下。(ESI和不同的系统,值不一样,而且,也不是每次都可以成功断下)
接下来的工作非常郁闷,一直没法到“程序领域”,经过N次尝试后发现,程序代码在堆空间里,而且,边执行边解压,难怪反编译不成功。
而且,更郁闷的是,由于在堆空间里,所以,没办法保存断点,只要跑飞了,就得从头再来。代码里,很多暗桩,稍不注意就飞了,大大增加了分析难度。
废话了这么多,现在开始
00F19A43 8B8F 60010000 mov ecx, dword ptr [edi+160] 00F19A49 8B97 58010000 mov edx, dword ptr [edi+158] ; name 00F19A4F FFB7 5C010000 push dword ptr [edi+15C] ; key 00F19A55 FF15 90659A00 call dword ptr [9A6590] ; 比较函数
00F1B7C0 8B8D 0CFFFFFF mov ecx, dword ptr [ebp-F4] 00F1B7C6 FF15 9C659A00 call dword ptr [9A659C] 00F1B7CC 83F8 05 cmp eax, 5
00F1B90A 50 push eax 00F1B90B FFB5 24FFFFFF push dword ptr [ebp-DC] 00F1B911 8B95 1CFFFFFF mov edx, dword ptr [ebp-E4] 00F1B917 8B8D 20FFFFFF mov ecx, dword ptr [ebp-E0] 00F1B91D FF15 AC659A00 call dword ptr [9A65AC]
00F1B923 8BC8 mov ecx, eax 00F1B925 8B95 18FFFFFF mov edx, dword ptr [ebp-E8] 00F1B92B FF15 B0659A00 call dword ptr [9A65B0] 00F1B931 8985 08FFFFFF mov dword ptr [ebp-F8], eax 00F1B937 BF 58000000 mov edi, 58
00F1CDA1 8BF0 mov esi, eax 00F1CDA3 8BD3 mov edx, ebx 00F1CDA5 8BCE mov ecx, esi 00F1CDA7 FF15 B87A9A00 call dword ptr [9A7AB8]
00F1D160 8BD0 mov edx, eax 00F1D162 8BCE mov ecx, esi 00F1D164 FF15 BC7A9A00 call dword ptr [9A7ABC]
CString StrToMd5Hash(char *pCharDate,int nOutSize) { HCRYPTPROV hProv = 0; HCRYPTHASH hHash; byte hash[MAXBYTE]; DWORD nLen = strlen(pCharDate), nSize = nOutSize; CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0); CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash); CryptHashData(hHash,(const byte *) pCharDate, nLen, 0); CryptGetHashParam(hHash, HP_HASHVAL, (byte *)hash, &nSize, 0); CString OutBuff = pByteToAscStr(hash); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return OutBuff; } CString pByteToAscStr(byte *pByteDate) { CString str1; CString OutBuff = ""; for (int i=0;i<16;i++) { str1.Format("%d",pByteDate[i]); OutBuff += str1; } return OutBuff; }
CString str = "CrackMe" + keyArray[0] + keyArray[1] + "MegaX" + strUser + "MegaX"; //构成 strBuff CString strmd5 = StrToMd5Hash((LPSTR)(LPCTSTR)str,16); //构成 strMd5 int j=0; CString strout = ""; for (int i=0;i<5;i++) { int nIndex = keyStrArray[0].Find((LPSTR)(LPCTSTR)keyArray[2].Mid(i,1),0); //keyArray[2] 表示key的第三部分 CString strIndex = strmd5.Mid(i,1); j=0; while (strcmp((LPSTR)(LPCTSTR)keyStrArray[j].Mid(nIndex,1),(LPSTR)(LPCTSTR)strIndex) != 0) { j++; if (j>=keyStrArray.GetSize()) { j=0; } } if (j>0) { strout += keyStrArray[j-1].Mid(1,1); } else { strout += keyStrArray[j].Mid(1,1); } } strout.MakeUpper(); //转成大写
794F955A 8B80 18010000 mov eax, dword ptr [eax+118] 794F9560 FF70 04 push dword ptr [eax+4] 794F9563 8D4C24 10 lea ecx, dword ptr [esp+10] 794F9567 33D2 xor edx, edx 794F9569 E8 06AFEAFF call 793A4474
CString GetKey4(CString &strKey) { CString str1 = ""; CString str2 = "MegaX"; CString str3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; for (int i=0;i<5;i++) { char cTemp1 = strKey.GetAt(i); char cTemp2 = str2.GetAt(i); int nIndex = (cTemp1 + cTemp2 - 1) % str3.GetLength(); str1 += str3.Mid(nIndex,1); } return str1; }