【软件名称】:Crackme 2005 #3 - KuNgBiM 【软件大小】: KB 【下载地址】:Crackme区 【软件简介】: 【软件限制】: 【破解声明】:初学Crack,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教! 【破解工具】:flyodbg,peid
——————————————————————————————————————————— 【破解过程】:
我学crack只是个人爱好,没事时爆破一下,找点快乐,真没想到跟出了这东东的注册码,一激动,我就十分详细地整理了下记录,把我的失败和高兴同大家一起分享。我们只要细心、耐心、认真思考、多向前辈大虾们学学会很快进步的---象我这样的莱鸟也能跟出注册码了。程式虽然简单,但还是给了我不少快乐!
它是用aspr(ASPack 2.12 -> Alexey Solodovnikov [Overlay])加壳的,用AspackDie1.41脱之。
用OD 载入,F9直接运行,在注册画面中仍意输入,我的:ghgh----78787878.先不点"注册",在OD中下断点 rtcMsgBox ,点"注册".有关VB中的函数问题,精华5中有几篇详细的介绍,去看看啊.
bp MSVBVM60.rtcMsgBox:
73522F26 56 push esi 73522F27 ^ EB D5 jmp short MSVBVM60.73522EFE 73522F29 M> 55 push ebp <<<<<<<<<<<<<<<<中断于此! 73522F2A 8BEC mov ebp,esp 73522F2C 83EC 4C sub esp,4C 73522F2F 8B4D 14 mov ecx,dword ptr ss:[ebp+14]
ctrl+f9,crackme 2005-3诰诉我们"key is not valid! please try again!",点"确定"到这:
7352303A 5E pop esi 7352303B 5B pop ebx 7352303C C9 leave 7352303D C2 1400 retn 14 <<<<<<<<<<<< 在这!要返回了.
f7,返回这:
00420E0E . 52 push edx 00420E0F . FF15 70104000 call dword ptr ds:[<&MSVBVM60.#595>] ; MSVBVM60.rtcMsgBox 00420E15 . 8D85 20FEFFFF lea eax,dword ptr ss:[ebp-1E0] <<<<<<<<<<<<是这!看见了啊,是crackme的空间,如果爆破,就可以找关键点了. 00420E1B . 50 push eax
让我们看看它在这以前都做了什么:
00420D7D . /7D 18 jge short unpacked.00420D97 00420D7F . |8B8D BCF7FFFF mov ecx,dword ptr ss:[ebp-844] 00420D85 . |68 A0000000 push 0A0 00420D8A . |68 8C5E4000 push unpacked.00405E8C 00420D8F . |51 push ecx 00420D90 . |50 push eax 00420D91 . |FF15 5C104000 call dword ptr ds:[<&MSVBVM60.__vbaH>; MSVBVM60.__vbaHresultCheckObj 00420D97 > /8B95 48FEFFFF mov edx,dword ptr ss:[ebp-1B8] <<<---(注册码 "7878787878787878787878787878")Jump from
00420D7D 00420D9D . 52 push edx 00420D9E . FF15 24104000 call dword ptr ds:[<&MSVBVM60.__vbaL>; MSVBVM60.__vbaLenBstr//取注册码长度!跟入后可以看见结果在eax中. 00420DA4 . 33C9 xor ecx,ecx 00420DA6 . 83F8 1C cmp eax,1C <<<-----先把ecx置0才比较,1Ch='28',注册码要28位! 00420DA9 . 0F95C1 setne cl <<<-----28位,cl=0,否则cl=1; 00420DAC . F7D9 neg ecx <<<-----28位,ecx=0,否则ecx=FFFF; 00420DAE . 66:898D B4F7F>mov word ptr ss:[ebp-84C],cx <<<-----所以,正确与否的值(ecx的值),传入word ptr ss:[ebp-84C]供比较; 00420DB5 . 8D8D 48FEFFFF lea ecx,dword ptr ss:[ebp-1B8] 00420DBB . FF15 DC114000 call dword ptr ds:[<&MSVBVM60.__vbaF>; MSVBVM60.__vbaFreeStr <<<--释放字串 00420DC1 . 8D8D 40FEFFFF lea ecx,dword ptr ss:[ebp-1C0] 00420DC7 . FF15 E0114000 call dword ptr ds:[<&MSVBVM60.__vbaF>; MSVBVM60.__vbaFreeObj <<<--释放对象 00420DCD . 66:399D B4F7F>cmp word ptr ss:[ebp-84C],bx <<<<软件把“00”和“FF”当作是注册码正确与否的标志,00就正确! 00420DD4 . 74 63 je short unpacked.00420E39 <<<<---F2重新在入,输入28位注册码,这里跳了. 00420DD6 . B8 0A000000 mov eax,0A 00420DDB . B9 04000280 mov ecx,80020004 00420DE0 . 8D95 20FEFFFF lea edx,dword ptr ss:[ebp-1E0] 00420DE6 . 52 push edx 00420DE7 . 8985 20FEFFFF mov dword ptr ss:[ebp-1E0],eax 00420DED . 8985 30FEFFFF mov dword ptr ss:[ebp-1D0],eax 00420DF3 . 8D85 30FEFFFF lea eax,dword ptr ss:[ebp-1D0] 00420DF9 . 50 push eax 00420DFA . 898D 28FEFFFF mov dword ptr ss:[ebp-1D8],ecx 00420E00 . 898D 38FEFFFF mov dword ptr ss:[ebp-1C8],ecx 00420E06 . 8D4D BC lea ecx,dword ptr ss:[ebp-44] 00420E09 . 51 push ecx 00420E0A . 53 push ebx 00420E0B . 8D55 8C lea edx,dword ptr ss:[ebp-74] 00420E0E . 52 push edx 00420E0F . FF15 70104000 call dword ptr ds:[<&MSVBVM60.#595>] ; MSVBVM60.rtcMsgBox <<--看见这个东东了?我们的断点啊, 00420E15 . 8D85 20FEFFFF lea eax,dword ptr ss:[ebp-1E0] <<<---我们返回到这的. 00420E1B . 50 push eax 00420E1C . 8D8D 30FEFFFF lea ecx,dword ptr ss:[ebp-1D0]
注册码的精点比较:call XXXXXX 关键过程,计算; cmp XXXXXX 比较计算结果, 有的用test; je XXXXXX 正确或不正确就跳, 可以是仍意跳转指令,跳向正确或不正确处; 所以我们向上找最近的跳,在 00420DD4 处就是,它跳向正确处,它的上一句是cmp,而cmp上面就是call,但是各们注意了,这一句call的是 MSVBVM60.__vbaFreeObj,就看它的名字也知晓它不是用来计算的,它是用来释放一个内存对象,同样,在上面一句:call MSVBVM60.__vbaFreeStr 也不是关键call,关键call的结果一定能影响到下一句cmp,从而控制程序跳的方向。在向上又有一个call,直得我们注意了,因为它叫“MSVBVM60.__vbaLenBstr”,用来计算字串的长度!它就是关键call!,它下面也有一个cmp:cmp eax,1C . 如果你还怀疑eax里是否是注册码的长度,跟入看看就知道了。为什么这里会有二个cmp?我认为是一种灵活运用,扰乱crack,不要固守什么句法就是。 F2重新在入,输入28位注册码(7878787878787878787878787878),跳到这里:
00420E39 > 8B45 08 mov eax,dword ptr ss:[ebp+8] <<<<<<<-----跳到这!看见了,己跳过了上面的rtcMsgBox!我们成功一点点了,加油啊! 00420E3C . 8B10 mov edx,dword ptr ds:[eax] <<<--F7走吧. 00420E3E . 50 push eax 00420E3F . FF92 14030000 call dword ptr ds:[edx+314] 00420E45 . 50 push eax 00420E46 . 8D85 40FEFFFF lea eax,dword ptr ss:[ebp-1C0] 00420E4C . 50 push eax 00420E4D . FF15 6C104000 call dword ptr ds:[<&MSVBVM60.__vbaO>; MSVBVM60.__vbaObjSet 00420E53 . 8B08 mov ecx,dword ptr ds:[eax] 00420E55 . 8D95 48FEFFFF lea edx,dword ptr ss:[ebp-1B8] 00420E5B . 52 push edx 00420E5C . 50 push eax 00420E5D . 8985 BCF7FFFF mov dword ptr ss:[ebp-844],eax 00420E63 . FF91 A0000000 call dword ptr ds:[ecx+A0] 00420E69 . DBE2 fclex 00420E6B . 3BC3 cmp eax,ebx 00420E6D / . 7D 18 jge short unpacked.00420E87 <<<<<---------F7走到这,跳了 00420E6F | . 8B8D BCF7FFFF mov ecx,dword ptr ss:[ebp-844] 00420E75 | . 68 A0000000 push 0A0 00420E7A | . 68 8C5E4000 push unpacked.00405E8C 00420E7F | . 51 push ecx 00420E80 | . 50 push eax 00420E81 | . FF15 5C104000 call dword ptr ds:[<&MSVBVM60.__vbaH>; MSVBVM60.__vbaHresultCheckObj 00420E87 / > B8 02000000 mov eax,2 <<<<----跳到这,大概是要取2个字吧 00420E8C . 8985 28FEFFFF mov dword ptr ss:[ebp-1D8],eax 00420E92 . 8985 20FEFFFF mov dword ptr ss:[ebp-1E0],eax 00420E98 . 8B85 48FEFFFF mov eax,dword ptr ss:[ebp-1B8] 00420E9E . 8D95 20FEFFFF lea edx,dword ptr ss:[ebp-1E0] 00420EA4 . 52 push edx 00420EA5 . 8985 38FEFFFF mov dword ptr ss:[ebp-1C8],eax 00420EAB . 6A 09 push 9 <<<-------------------------从第9位取子串9-10位! 00420EAD . 8D85 30FEFFFF lea eax,dword ptr ss:[ebp-1D0] 00420EB3 . 50 push eax 00420EB4 . 8D8D 10FEFFFF lea ecx,dword ptr ss:[ebp-1F0] 00420EBA . 51 push ecx 00420EBB . 899D 48FEFFFF mov dword ptr ss:[ebp-1B8],ebx 00420EC1 . C785 30FEFFFF>mov dword ptr ss:[ebp-1D0],8 00420ECB . FF15 94104000 call dword ptr ds:[<&MSVBVM60.#632>] ; MSVBVM60.rtcMidCharVar <<-----取子串,F8过 00420ED1 . 8D95 10FEFFFF lea edx,dword ptr ss:[ebp-1F0] 00420ED7 . 52 push edx 00420ED8 . 8D85 28FFFFFF lea eax,dword ptr ss:[ebp-D8] 00420EDE . 50 push eax 00420EDF . FF15 88114000 call dword ptr ds:[<&MSVBVM60.__vbaV>; MSVBVM60.__vbaVarTstNe <<---Tst是否是test之意?应有cmp的功用吧,F7进入!
其实很多vb函数都可以这样去猜测一下,跟入到这:
73540FFE M> FF7424 >push dword ptr ss:[esp+8] <<<-----在这 73541002 FF7424 >push dword ptr ss:[esp+8] 73541006 6A 00 push 0 73541008 E8 0A00>call MSVBVM60.73541017 <<<----只一个call,别多想,F7进入 7354100D 8B0485 >mov eax,dword ptr ds:[eax*4+7346F8F8] 73541014 C2 0800 retn 8
只有一个call,不进就出了,进入到这:
73541017 55 push ebp <<<<--------这! 73541018 8BEC mov ebp,esp 7354101A 83EC 38 sub esp,38
向下看看有什么:
......... 73541053 51 push ecx 73541054 52 push edx 73541055 FF15 70>call dword ptr ds:[73550E70] ; OLEAUT32.VarCmp <<<-----这个,你喜欢吧!F4到这,F7进! 7354105B 8945 08 mov dword ptr ss:[ebp+8],eax
进入到这: 7713A939 O> 55 push ebp <<<<---在这以下,我没看见有价值的东东了 7713A93A 8BEC mov ebp,esp 7713A93C 83EC 38 sub esp,38
但是上面有一个:
7713A91A FF75 0C push dword ptr ss:[ebp+C] 7713A91D FF75 08 push dword ptr ss:[ebp+8] 7713A920 FF77 08 push dword ptr ds:[edi+8] 7713A923 FF75 F8 push dword ptr ss:[ebp-8] 7713A926 E8 8EFD>call OLEAUT32.VarBstrCmp <<<----我很感兴趣的东东! 7713A92B FF75 F8 push dword ptr ss:[ebp-8]
路十分陌生,小心点,F7单步向下,慢慢的到这:
7713A97A FF2495 D9B01377 jmp dword ptr ds:[edx*4+7713B0D9]
它要跳了,ENTER跟随去看看:
7713AFA7 FF75 14 push dword ptr ss:[ebp+14] 7713AFAA FF75 10 push dword ptr ss:[ebp+10] 7713AFAD FF73 08 push dword ptr ds:[ebx+8] 7713AFB0 FF76 08 push dword ptr ds:[esi+8] 7713AFB3 E8 01F7FFFF call OLEAUT32.VarBstrCmp <<<---我太高兴了,F7让它来吧.
注意----不要F4(如果你在这点了鼠标的话),F7到这:
7713AFA7 FF75 14 push dword ptr ss:[ebp+14] <<<---这! 7713AFAA FF75 10 push dword ptr ss:[ebp+10] 7713AFAD FF73 08 push dword ptr ds:[ebx+8] <<<---注意看CPU窗口下面! 7713AFB0 FF76 08 push dword ptr ds:[esi+8] <<<---注意看CPU窗口下面! 7713AFB3 E8 01F7FFFF call OLEAUT32.VarBstrCmp
--堆栈---/// 7713AFAD处 堆栈 ds:[0012F454]=001630E4, (UNICODE "71") 7713AFB0处 堆栈 ds:[0012F33C]=0016480C, (UNICODE "78")
如果71你不知是何物,那么78呢?亲手输入的东东不会忘了吧!让我们在7713AFAD处下个断,看看它会不会在次到这!现在 call OLEAUT32.VarBstrCmp已没有必要进去了,F8走!当回到这留意一下:
73541008 E8 0A000000 call MSVBVM60.73541017 7354100D 8B0485 F8F84673 mov eax,dword ptr ds:[eax*4+7346F8F8] <<<-----eax置FFFF! 是注册码正确与否的标志? 73541014 C2 0800 retn 8 <<<----返回到 00420EE5 (unpacked.00420EE5)
/// ds:[7346F8FC]=FFFFFFFF eax=00000001 ///
继续返:
00420EE5 . 8D8D 40FEFFFF lea ecx,dword ptr ss:[ebp-1C0] 00420EEB . 66:8985 B4F7F>mov word ptr ss:[ebp-84C],ax <<<<-------ax=FFFF; 00420EF2 . FF15 E0114000 call dword ptr ds:[<&MSVBVM60.__vbaF>; MSVBVM60.__vbaFreeObj 00420EF8 . 8D8D 10FEFFFF lea ecx,dword ptr ss:[ebp-1F0] 00420EFE . 51 push ecx 00420EFF . 8D95 20FEFFFF lea edx,dword ptr ss:[ebp-1E0] 00420F05 . 52 push edx 00420F06 . 8D85 30FEFFFF lea eax,dword ptr ss:[ebp-1D0] 00420F0C . 50 push eax 00420F0D . 6A 03 push 3 00420F0F . FF15 28104000 call dword ptr ds:[<&MSVBVM60.__vbaF>; MSVBVM60.__vbaFreeVarList 00420F15 . 83C4 10 add esp,10 00420F18 . 66:399D B4F7F>cmp word ptr ss:[ebp-84C],bx <<<--------检查注册码比较结果! 00420F1F . 74 27 je short unpacked.00420F48 <<<--------正确就跳,否则死! 00420F21 > B9 04000280 mov ecx,80020004 00420F26 . B8 0A000000 mov eax,0A 00420F2B . 898D 28FEFFFF mov dword ptr ss:[ebp-1D8],ecx 00420F31 . 8985 20FEFFFF mov dword ptr ss:[ebp-1E0],eax 00420F37 . 898D 38FEFFFF mov dword ptr ss:[ebp-1C8],ecx 00420F3D . 8985 30FEFFFF mov dword ptr ss:[ebp-1D0],eax 00420F43 . E9 170C0000 jmp unpacked.00421B5F <<<<-------死亡之路!
00420F18处: bx=0000 堆栈 ss:[0012ECD8]=FFFF
我第一次跟时,全用F8,就在这玩完的.后来想了想,只要找出eax在何处被写入FFFF的,也许就能找到关键点了.于是用F8在跟了一次,看见只要过了00420EDF这个call,eax就为FFFFFFF;所以才跟入了call dword ptr ds:<&MSVBVM60.__vbaVarTstNe>],找到了关键点.我们在命令行中输入D 0012ECD8 把FFFF改为0000,跳过到这:
00420F48 > 8B45 08 mov eax,dword ptr ss:[ebp+8] 00420F4B . 8B08 mov ecx,dword ptr ds:[eax] 00420F4D . 50 push eax 00420F4E . FF91 14030000 call dword ptr ds:[ecx+314] 00420F54 . 50 push eax 00420F55 . 8D95 40FEFFFF lea edx,dword ptr ss:[ebp-1C0] 00420F5B . 52 push edx 00420F5C . FF15 6C104000 call dword ptr ds:[<&MSVBVM60.__vbaO>; MSVBVM60.__vbaObjSet 00420F62 . 8B08 mov ecx,dword ptr ds:[eax] 00420F64 . 8D95 48FEFFFF lea edx,dword ptr ss:[ebp-1B8] 00420F6A . 52 push edx 00420F6B . 50 push eax 00420F6C . 8985 BCF7FFFF mov dword ptr ss:[ebp-844],eax 00420F72 . FF91 A0000000 call dword ptr ds:[ecx+A0] 00420F78 . DBE2 fclex 00420F7A . 3BC3 cmp eax,ebx 00420F7C . 7D 18 jge short unpacked.00420F96 00420F7E . 8B8D BCF7FFFF mov ecx,dword ptr ss:[ebp-844] 00420F84 . 68 A0000000 push 0A0 00420F89 . 68 8C5E4000 push unpacked.00405E8C 00420F8E . 51 push ecx 00420F8F . 50 push eax 00420F90 . FF15 5C104000 call dword ptr ds:[<&MSVBVM60.__vbaH>; MSVBVM60.__vbaHresultCheckObj 00420F96 > B8 02000000 mov eax,2 00420F9B . 8985 28FEFFFF mov dword ptr ss:[ebp-1D8],eax 00420FA1 . 8985 20FEFFFF mov dword ptr ss:[ebp-1E0],eax 00420FA7 . 8B85 48FEFFFF mov eax,dword ptr ss:[ebp-1B8] 00420FAD . 8D95 20FEFFFF lea edx,dword ptr ss:[ebp-1E0] 00420FB3 . 52 push edx 00420FB4 . 8985 38FEFFFF mov dword ptr ss:[ebp-1C8],eax 00420FBA . 6A 03 push 3 <<--------------------取子串3-4位! 00420FBC . 8D85 30FEFFFF lea eax,dword ptr ss:[ebp-1D0] 00420FC2 . 50 push eax 00420FC3 . 8D8D 10FEFFFF lea ecx,dword ptr ss:[ebp-1F0] 00420FC9 . 51 push ecx 00420FCA . 899D 48FEFFFF mov dword ptr ss:[ebp-1B8],ebx 00420FD0 . C785 30FEFFFF>mov dword ptr ss:[ebp-1D0],8 00420FDA . FF15 94104000 call dword ptr ds:[<&MSVBVM60.#632>] ; MSVBVM60.rtcMidCharVar 00420FE0 . 8D95 10FEFFFF lea edx,dword ptr ss:[ebp-1F0] 00420FE6 . 52 push edx 00420FE7 . 8D85 14FFFFFF lea eax,dword ptr ss:[ebp-EC] 00420FED . 50 push eax 00420FEE . FF15 88114000 call dword ptr ds:[<&MSVBVM60.__vbaV>; MSVBVM60.__vbaVarTstNe <<--F8一路到这
你是否注意到了本程式的规律性: 1-> MSVBVM60.__vbaObjSet 2-> MSVBVM60.rtcMidCharVar 3-> MSVBVM60.__vbaVarTstNe <--** mov word ptr ss:[ebp-84C],ax 4-> MSVBVM60.__vbaFreeObj 5-> MSVBVM60.__vbaFreeVarList 6-> cmp word ptr ss:[ebp-84C],bx <--** 7-> jnz XXXXXXX <--** 它就这样循规蹈矩的进行!所以这时我大胆给它了一个F9(如果飞了,大不了重来),它又中断在:
7713AFA7 FF75 14 push dword ptr ss:[ebp+14] 7713AFAA FF75 10 push dword ptr ss:[ebp+10] 7713AFAD FF73 08 push dword ptr ds:[ebx+8] <<<---注意看CPU窗口下面!<<<<-----这就是我上一步下的断啊 7713AFB0 FF76 08 push dword ptr ds:[esi+8] <<<---注意看CPU窗口下面! 7713AFB3 E8 01F7FFFF call OLEAUT32.VarBstrCmp
/ 7713AFAD: 堆栈 ds:[0012F440]=0015BEFC, (UNICODE "41") 7713AFB0: 堆栈 ds:[0012F33C]=00165AB4, (UNICODE "78") //
现在,我们清除所有断点,重新载入程式,在00420D7D(第一次调用vbaVarTstNe之前均可) 处下断,运行它,输入ghgh和112233445566778899aabbccddee,注册.中断后在7713AFAD处下断,并改7354100D(7354100D :mov eax,dword ptr ds:[eax*4+7346F8F8])处为mov eax,00 .之所以注册码选"112233..."的形式,是因为它是每两位进行比较,我们可以不去管它是比较第几位;改7354100D处是为免除每次比较出来都修改"cmp word ptr ss:[ebp-84C],bx"处的"FFFF".
现在请准备好纸和笔,写上你的注册码112233.....,一切准备就绪后,运行程序F9!中断后记住数字"71""41".....,F7单走一下,是不是出现了"55""22"...?在它的下面写下上一行你记下的数字: 11 22 33 44 55 66 77 88 99...... 41 71
这样重复14次,你就有了一个可用的注册码了. 我的是: 用户名:ghgh 注册码:e741214771ff46fff5fe5162e771
【异想天开】:
大虾们可以截获狗中的数据,是否也可以有这样一个东东:它截获MSVBVM60.__vbaVarTstNe--也可是仍意想截获函数的结果,如果返回一个特定的值(如FF),我们可把它修改成我们想要的数返回给程式?如果可以,那这个crackme就可以完美爆破了----只修改__vbaVarTstNe的返回结果.因为按我上面方法破它时,它没有怪我qj它的.我是只很莱的鸟,这个东东有耐各位大虾了!
【算法分析】:
程式的算法,大致是KuNgBiMg+用户名+机器码+Crackme 2005 #3组成一个字串,然后做Md5运算,在用rtcMidCharVar取子串,它一共取了14次,我太莱了,无法进一步分析出其算法了~~~~~~,望大虾指点!
我在前面看到了这些:
/// 0041F277 . 68 8C624000 push unpacked.0040628C ; UNICODE "Md5_String_Calc"
735498F5 8B47 08 mov eax,dword ptr ds:[edi> 堆栈 ds:[0012F31C]=00162FFC, (UNICODE "7C88551464771E7FE21FFF6241357B0B") <<---这个与我的注册码有几分象. eax=00000008
【事后之言】:
vb的函数MSVBVM60.__vbaVarTstNe我是第一次接触(有可能是我没看见),它的用法不太了解,它前面有两个push可能是参数,用它作cmp时是否都会在 7713AFA7 FF75 14 push dword ptr ss:[ebp+14] 7713AFAA FF75 10 push dword ptr ss:[ebp+10] 7713AFAD FF73 08 push dword ptr ds:[ebx+8] 7713AFB0 FF76 08 push dword ptr ds:[esi+8] 7713AFB3 E8 01F7FFFF call OLEAUT32.VarBstrCmp 出现明码?它的返回值是否都是比较后正确与否的标志?我就不知了.如果你有了结果,请诰诉我一下 ^o^ ! @to:scxttb@126.comhttp://bbs.pediy.com/showthread.php?threadid=15331 |