标题:一个vb.net crackme分析
链接:http://www.unpack.cn/viewthread.php?tid=20746&extra=page%3D1
贴者:noirlucifer
日期:2007-12-25 19:39
今天又去crackmes.de逛了逛发现了个新的crackme,于是就有了下文.
拿到手peid查壳:Microsoft Visual C# / Basic .NET,立即ildasm一下.然后找到ok_click事件,代码如下:
.method private instance void OK_Click(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 279 (0x117)
.maxstack 4
.locals init (string V_0,
string V_1,
string V_2,
string V_3,
string V_4,
string V_5,
string V_6,
string V_7,
string V_8,
string V_9,
string V_10,
string V_11,
string V_12,
string V_13)
IL_0000: ldarg.0
IL_0001: callvirt instance void Crackme3.LoginForm1::chkdbg()
IL_0006: ldstr "6AE199A93C381BF6D5DE27491139D3F9"
IL_000b: stloc.s V_11 //v11= 6AE199A93C381BF6D5DE27491139D3F9
IL_000d: ldstr "9F6CF82DEB99289E14AEA9DCC24E54CB"
IL_0012: stloc.s V_9 //v9=9F6CF82DEB99289E14AEA9DCC24E54CB
IL_0014: ldstr "ABDF74354GFDDF344HJ4667HVHJVDGG"
//v12=ABDF74354GFDDF344HJ4667HVHJVDGG(这个v12起到key的作用,后面的encode,decode都要用到它)
IL_001b: ldloc.s V_11
IL_001d: ldloc.s V_12
IL_001f: call string Crackme3.Crypto::StringEncrypt(string,
string)
IL_0024: stloc.s V_6 //v6=encrypt(v11,v12)
IL_0026: ldloc.s V_11
IL_0028: ldloc.s V_12
IL_002a: call string Crackme3.Crypto::StringEncrypt(string,
string)
IL_002f: stloc.s V_4 //v4=encrypt(v11,v12)
IL_0031: ldstr "1p9vPg/XReKyDADJx7O1juK6KwsNneaLV+iztkVVjptfLHbxO+" //这是个经过encrypt的值记为s1
+ "suSRX8V/lZ+ZJ3"
IL_0036: ldloc.s V_12
IL_0038: call string Crackme3.Crypto::StringDecrypt(string,
string)
IL_003d: stloc.2 //l2=decrypt(s1,v12)
IL_003e: ldstr "8+k/OamDIWXKRS7UrbAfiizNVwtnb3+WNSzdENYNaWNQp4uCP1" //这也是个经过encrypt的值记为s2
+ "NbjLAzIAf2eKJq"
IL_0043: ldloc.s V_12
IL_0045: call string Crackme3.Crypto::StringDecrypt(string,
string)
IL_004a: stloc.0 //l0=decrypt(s2,v12)
IL_004b: ldarg.0
IL_004c: callvirt instance void Crackme3.LoginForm1::chkdbg() //检查调试器,用的isdebuggerpresent.
IL_0051: ldarg.0
IL_0052: callvirt instance class [System.Windows.Forms]System.Windows.Forms.TextBox Crackme3.LoginForm1::get_UsernameTextBox()
IL_0057: callvirt instance string [System.Windows.Forms]System.Windows.Forms.TextBox::get_Text() //获取用户名
IL_005c: call string Crackme3.Crypto::GetHash(string) //计算用户名的md5值
IL_0061: stloc.s V_10 //v10=md5(用户名)
IL_0063: ldarg.0
IL_0064: callvirt instance void Crackme3.LoginForm1::chkdbg() //检查调试器
IL_0069: ldarg.0
IL_006a: callvirt instance class [System.Windows.Forms]System.Windows.Forms.TextBox Crackme3.LoginForm1::get_PasswordTextBox()
IL_006f: callvirt instance string [System.Windows.Forms]System.Windows.Forms.TextBox::get_Text() //获取注册码
IL_0074: call string Crackme3.Crypto::GetHash(string) //计算注册码的md5值
IL_0079: stloc.s V_8 //v8=md5(注册码)
IL_007b: ldarg.0
IL_007c: callvirt instance void Crackme3.LoginForm1::chkdbg() //检查调试器
IL_0081: ldloc.s V_10
IL_0083: ldloc.s V_12
IL_0085: call string Crackme3.Crypto::StringEncrypt(string,
string)
IL_008a: stloc.s V_7 //v7=encrypt(v10,v12)
IL_008c: ldarg.0
IL_008d: callvirt instance void Crackme3.LoginForm1::chkdbg() //检查调试器
IL_0092: ldloc.s V_8
IL_0094: ldloc.s V_12
IL_0096: call string Crackme3.Crypto::StringEncrypt(string,
string)
IL_009b: stloc.s V_5 //v5=encrypt(v8,v12)
IL_009d: ldarg.0
IL_009e: callvirt instance void Crackme3.LoginForm1::chkdbg()
IL_00a3: ldloc.s V_7
IL_00a5: ldloc.s V_12
IL_00a7: call string Crackme3.Crypto::StringDecrypt(string,
string)
IL_00ac: stloc.3 //l3=decrypt(v7,v12)
IL_00ad: ldarg.0
IL_00ae: callvirt instance void Crackme3.LoginForm1::chkdbg() //检查调试器
IL_00b3: ldloc.s V_5
IL_00b5: ldloc.s V_12
IL_00b7: call string Crackme3.Crypto::StringDecrypt(string,
string)
IL_00bc: stloc.1 // l1=decrypt(v5,v12)
IL_00bd: ldarg.0
IL_00be: callvirt instance void Crackme3.LoginForm1::chkdbg() //检查调试器
IL_00c3: ldloc.2
IL_00c4: ldloc.3
IL_00c5: ldc.i4.0
IL_00c6: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Operators::CompareString(string, //比较l2和l3
string,
bool)
IL_00cb: ldc.i4.0
IL_00cc: bne.un.s IL_00d9
IL_00ce: ldloc.0
IL_00cf: ldloc.1
IL_00d0: ldc.i4.0
IL_00d1: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Operators::CompareString(string, //比较l0和l1
string,
bool)
IL_00d6: ldc.i4.0
IL_00d7: beq.s IL_00dc
IL_00d9: ldc.i4.0
IL_00da: br.s IL_00dd
IL_00dc: ldc.i4.1
IL_00dd: ldloc.s V_11
IL_00df: ldloc.3
IL_00e0: ldc.i4.0
IL_00e1: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Operators::CompareString(string, //比较v11和l3
string,
bool)
IL_00e6: ldc.i4.0
IL_00e7: bne.un.s IL_00f5
IL_00e9: ldloc.s V_9
IL_00eb: ldloc.1
IL_00ec: ldc.i4.0
IL_00ed: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Operators::CompareString(string, //比较v9和l1
string,
bool)
IL_00f2: ldc.i4.0
IL_00f3: beq.s IL_00f8
IL_00f5: ldc.i4.0
IL_00f6: br.s IL_00f9
IL_00f8: ldc.i4.1
IL_00f9: or
IL_00fa: brfalse.s IL_0105
IL_00fc: ldstr "Yes, you found the secret username & password! Wel"
+ "l Done!"
IL_0101: stloc.s V_13
IL_0103: br.s IL_010c
IL_0105: ldstr "I'm sorry, please try again."
IL_010a: stloc.s V_13
IL_010c: ldloc.s V_13
IL_010e: ldc.i4.0
IL_010f: ldnull
IL_0110: call valuetype [Microsoft.VisualBasic]Microsoft.VisualBasic.MsgBoxResult [Microsoft.VisualBasic......]
IL_0115: pop
IL_0116: ret
} // end of method LoginForm1::OK_Click
总结以下算法
l0=decrypt(s2,v12)
l1=decrypt(v5,v12)
l2=decrypt(s1,v12)
l3=decrypt(v7,v12)
v4 =encrypt(v11,v12)
v5=encrypt(v8,v12)
v6 =encrypt(v11,v12)
v8=md5(注册码)
v7=encrypt(v10,v12)
v9 =9F6CF82DEB99289E14AEA9DCC24E54CB
v10=md5(用户名)
v11=6AE199A93C381BF6D5DE27491139D3F9
v12=ABDF74354GFDDF344HJ4667HVHJVDGG
注册成功的条件为(l2=l3并且l0=l1)或者(l1=v9并且l3=v11)
1.先来分析后一种情况:
l1=decrypt(v5,v12) 1'
v5=encrypt(v8,v12) 2'
v8=md5(注册码) 3'
现在只要求出v8就可以求出注册码了
由1'和2'可知
v8=decrypt(v5,v12)=decrypt(encrypt(l1,v12),v12)=l1=v9=9F6CF82DEB99289E14AEA9DCC24E54CB
用户名=richerd
同理
v7=v11=6AE199A93C381BF6D5DE27491139D3F9
注册码=peugeot
至此得到了一组固定的注册码
以上md5破解均在http://www.cmd5.com/上面完成
2.现在来分析第1种情况即l2=l3并且l0=l1
l0=decrypt(s2,v12) 1'
l1=decrypt(v5,v12) 2'
l0=l1 3'
v5=encrypt(v8,v12) 4'
v8=md5(注册码) 5'
l0是固定的因为s2,v12是固定的,所以由1,2,3可得v5=s2
再由4得v8=decrypt(v5,v12)=decrypt(s2,v12)=l0,所以求出lo就乐意求出注册码了,但是怎么求出l0呢.
首先我用ildasm反编译,然后转存,然后用ilasm编译但出现错误.我手上也没有.vs.net,想想算了用程序本身吧!
先运行程序,然后启动od然后附加进程,不知为什么直接用od加载后运行会卡死.然后在code段下f2断点(直接下断
ShowWindow不行,哪位解释下),断下后再下ShowWindow断点,输入用户名和注册码按ok,此时断下,返回后往上找到过
程首部如下:
00EA11E2 53 push ebx
00EA11E3 55 push ebp
00EA11E4 83EC 18 sub esp, 18
00EA11E7 8BF1 mov esi, ecx
00EA11E9 8BCE mov ecx, esi
00EA11EB 3909 cmp dword ptr [ecx], ecx
00EA11ED E8 7670BEFF call 00A88268 //检测调试器
00EA11F2 8B1D 006C3C02 mov ebx, dword ptr [23C6C00]
00EA11F8 8B05 046C3C02 mov eax, dword ptr [23C6C04]
00EA11FE 894424 14 mov dword ptr [esp+14], eax
00EA1202 8B3D 086C3C02 mov edi, dword ptr [23C6C08]
00EA1208 8BD7 mov edx, edi
00EA120A 8BCB mov ecx, ebx
00EA120C FF15 2482A800 call dword ptr [A88224] //encrypt
00EA1212 8BD7 mov edx, edi
00EA1214 8BCB mov ecx, ebx
00EA1216 FF15 2482A800 call dword ptr [A88224]
00EA121C 8B0D 0C6C3C02 mov ecx, dword ptr [23C6C0C] //这个就是s1
00EA1222 8BD7 mov edx, edi //这个就是v12
00EA1224 FF15 2882A800 call dword ptr [A88228] //decrypt
00EA122A 894424 08 mov dword ptr [esp+8], eax //eax地址保存的就是decrypt的结果
00EA122E 8B0D 106C3C02 mov ecx, dword ptr [23C6C10] 也就是我们要找的
00EA1234 8BD7 mov edx, edi l2=67F3A873D1F7CECA8C3C4C1211AE2355
00EA1236 FF15 2882A800 call dword ptr [A88228] //这个decrypt能算出
00EA123C 894424 04 mov dword ptr [esp+4], eax l0=23EB5D0DDB99AF268BC17C9A63D32AD5
00EA1240 8BCE mov ecx, esi
00EA1242 3909 cmp dword ptr [ecx], ecx
00EA1244 E8 1F70BEFF call 00A88268
00EA1249 8BCE mov ecx, esi
00EA124B 8B01 mov eax, dword ptr [ecx]
00EA124D FF90 10060000 call dword ptr [eax+610]
00EA1253 8BC8 mov ecx, eax
00EA1255 8B01 mov eax, dword ptr [ecx]
00EA1257 FF90 64010000 call dword ptr [eax+164] //GetText
00EA125D 8BC8 mov ecx, eax
00EA125F FF15 2082A800 call dword ptr [A88220] //md5
00EA1265 8BE8 mov ebp, eax
00EA1267 8BCE mov ecx, esi
00EA1269 3909 cmp dword ptr [ecx], ecx
00EA126B E8 F86FBEFF call 00A88268
00EA1270 8BCE mov ecx, esi
00EA1272 8B01 mov eax, dword ptr [ecx]
00EA1274 FF90 18060000 call dword ptr [eax+618]
00EA127A 8BC8 mov ecx, eax
00EA127C 8B01 mov eax, dword ptr [ecx]
00EA127E FF90 64010000 call dword ptr [eax+164] //GetText
00EA1284 8BC8 mov ecx, eax
00EA1286 FF15 2082A800 call dword ptr [A88220] //md5
00EA128C 894424 10 mov dword ptr [esp+10], eax
00EA1290 8BCE mov ecx, esi
00EA1292 3909 cmp dword ptr [ecx], ecx
00EA1294 E8 CF6FBEFF call 00A88268
00EA1299 8BD7 mov edx, edi
00EA129B 8BCD mov ecx, ebp
00EA129D FF15 2482A800 call dword ptr [A88224] //encrypt
00EA12A3 8BE8 mov ebp, eax
00EA12A5 8BCE mov ecx, esi
00EA12A7 3909 cmp dword ptr [ecx], ecx
00EA12A9 E8 BA6FBEFF call 00A88268
00EA12AE 8BD7 mov edx, edi
00EA12B0 8B4C24 10 mov ecx, dword ptr [esp+10]
00EA12B4 FF15 2482A800 call dword ptr [A88224] //encrypt
00EA12BA 894424 0C mov dword ptr [esp+C], eax
00EA12BE 8BCE mov ecx, esi
00EA12C0 3909 cmp dword ptr [ecx], ecx
00EA12C2 E8 A16FBEFF call 00A88268
00EA12C7 8BD7 mov edx, edi
00EA12C9 8BCD mov ecx, ebp
00EA12CB FF15 2882A800 call dword ptr [A88228] //decrypt
00EA12D1 8BE8 mov ebp, eax
00EA12D3 8BCE mov ecx, esi
00EA12D5 3909 cmp dword ptr [ecx], ecx
00EA12D7 E8 8C6FBEFF call 00A88268
00EA12DC 8BD7 mov edx, edi
00EA12DE 8B4C24 0C mov ecx, dword ptr [esp+C]
00EA12E2 FF15 2882A800 call dword ptr [A88228] //decrypt
00EA12E8 8BF8 mov edi, eax
00EA12EA 8BCE mov ecx, esi
00EA12EC 3909 cmp dword ptr [ecx], ecx
00EA12EE E8 756FBEFF call 00A88268
00EA12F3 6A 00 push 0
00EA12F5 8BD5 mov edx, ebp
00EA12F7 8B4C24 0C mov ecx, dword ptr [esp+C]
00EA12FB E8 D0375C5D call Microsof.5E464AD0 //StirngCompare
00EA1300 85C0 test eax, eax
00EA1302 75 11 jnz short 00EA1315
00EA1304 6A 00 push 0
00EA1306 8BD7 mov edx, edi
00EA1308 8B4C24 08 mov ecx, dword ptr [esp+8]
00EA130C E8 BF375C5D call Microsof.5E464AD0 //StirngCompare
00EA1311 85C0 test eax, eax
00EA1313 74 04 je short 00EA1319
00EA1315 33F6 xor esi, esi
00EA1317 EB 05 jmp short 00EA131E
00EA1319 BE 01000000 mov esi, 1
00EA131E 893424 mov dword ptr [esp], esi
00EA1321 6A 00 push 0
00EA1323 8BD5 mov edx, ebp
00EA1325 8BCB mov ecx, ebx
00EA1327 E8 A4375C5D call Microsof.5E464AD0 //StirngCompare
00EA132C 85C0 test eax, eax
00EA132E 75 14 jnz short 00EA1344
00EA1330 893424 mov dword ptr [esp], esi
00EA1333 6A 00 push 0
00EA1335 8BD7 mov edx, edi
00EA1337 8B4C24 18 mov ecx, dword ptr [esp+18]
00EA133B E8 90375C5D call Microsof.5E464AD0 //StirngCompare
00EA1340 85C0 test eax, eax
00EA1342 74 04 je short 00EA1348
00EA1344 33D2 xor edx, edx
00EA1346 EB 05 jmp short 00EA134D
00EA1348 BA 01000000 mov edx, 1
00EA134D 8B0424 mov eax, dword ptr [esp]
00EA1350 0BC2 or eax, edx
00EA1352 74 08 je short 00EA135C
00EA1354 8B0D 146C3C02 mov ecx, dword ptr [23C6C14]
00EA135A EB 06 jmp short 00EA1362
00EA135C 8B0D 186C3C02 mov ecx, dword ptr [23C6C18]
00EA1362 6A 00 push 0
00EA1364 33D2 xor edx, edx
00EA1366 E8 0D10655D call Microsof.5E4F2378 //MessageBox
现在得到了l0=23EB5D0DDB99AF268BC17C9A63D32AD5,l2=67F3A873D1F7CECA8C3C4C1211AE2355
但这两个md5码都找不到对应的值或许是作者的一个陷阱吧!
所以这个Crackme的用户名和注册码为固定的 richard(用户名)和peugeot(注册码)
谢谢看完本文,如有错误,请不吝指教!
|