【文章标题】: [破]CrackMe.cyberbob.VC.3
【文章作者】: HappyTown
【作者主页】: www.pediy.com
【软件名称】: ppg_crackme
【软件大小】: 75.5KB(zip)
【下载地址】: 附件内
【加壳方式】: ASPack
【保护方式】: 灰色按钮,Math knowledge
【使用工具】: OD,IDA,BigCalc
【操作平台】: WinXP
【软件介绍】: 一个很有意思的CrackMe
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
1. 用PEiD的插件居然未脱掉ASPack的壳,害我手动脱之,而后却不用修复IAT即可直接运行;
2. PEiD得知CRC32、Miracl、RC2、Tiger、SHA1 inside,呵呵,我喜欢;
3. IDA分析,居然只是识别出了mirkill函数,很是扫兴,只好手动定位;
4. 运行程序,Name、Company和OK按钮不可用,直接用eXeScope修改其属性;
我在程序中手动定位找到了RC2和Tiger,但在注册的验证算法中却没有用到,难道有暗桩?
直接查找出错信息,我们把断点下在405B75处。
输入试炼码:
happy
pediy
11111111-22222222-33333333
为了下面解释方便,我们把sn分为3部分:sn_1-sn_2-sn_3
00405B66 >push 0040EBA0 ; /lParam = 40EBA0
00405B6B >push 0FF ; |wParam = FF
00405B70 >push 0D ; |Message = WM_GETTEXT
00405B72 >push 66 ; |ControlID = 66 (102.)
00405B74 >push edi ; |hWnd
00405B75 >call [<&user32.SendDlgItemMessageA>] ; \SendDlgItemMessageA
00405B7B >test eax, eax
00405B7D >mov [40EDCC], eax
00405B82 >je 00405C6E
00405B88 >xor esi, esi
00405B8A >xor edx, edx
00405B8C >test eax, eax
00405B8E >mov [40EE48], esi
00405B94 >mov [40EE44], edx
00405B9A >jbe 00405C6E
00405BA0 >mov cl, [edx+40EBA0]
00405BA6 >cmp cl, 30 ; //sn只接受1~9,A~F
00405BA9 >jb short 00405BB0
00405BAB >cmp cl, 39
00405BAE >jbe short 00405BC0
00405BB0 >cmp cl, 41
00405BB3 >jb short 00405BBA
00405BB5 >cmp cl, 46
00405BB8 >jbe short 00405BC0
00405BBA >cmp cl, 2D ; '-'
00405BBD >jnz short 00405C20 ; \\
00405BBF >inc esi
00405BC0 >inc edx
00405BC1 >cmp edx, eax
00405BC3 >jb short 00405BA0
00405BC5 >cmp esi, 2 ; 所以sn应该有2个'-'
00405BC8 >mov [40EE44], edx
00405BCE >mov [40EE48], esi
00405BD4 >jnz 00405C6E
00405BDA >push 8
00405BDC >push 0040EB10
00405BE1 >call 00403F71
00405BE6 >push 0040EDA8
00405BEB >push 0040EB10
00405BF0 >push 0040EBA0
00405BF5 >call 00408230
00405BFA >add esp, 14
00405BFD >mov [40EDCC], eax
00405C02 >test eax, eax
00405C04 >jnz short 00405C33
00405C06 >push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00405C08 >push <Caption> ; |Title = "The PowerPuff Girls"
00405C0D >push <Text> ; |Text = "Registration code is incorrect"
00405C12 >push edi ; |hOwner
00405C13 >call [<&user32.MessageBoxA>] ; \MessageBoxA
跟进405BF5的call:
00408230 />sub esp, 18
00408233 |>push ebx
00408234 |>push ebp
00408235 |>push esi
00408236 |>push edi
00408237 |>push 0
00408239 |>push 0C8 ; 200
0040823E |>call <mirsys>
00408243 |>push 0
00408245 |>mov dword ptr [eax+238], 10 ; mip->IOBASE = 16
0040824F |>call <mirvar>
00408254 |>push 0
00408256 |>mov [esp+24], eax
0040825A |>call <mirvar>
0040825F |>push 0
00408261 |>mov [esp+24], eax
00408265 |>call <mirvar>
0040826A |>push 0
0040826C |>mov [esp+30], eax
00408270 |>call <mirvar>
00408275 |>push 0
00408277 |>mov ebx, eax
00408279 |>call <mirvar>
0040827E |>push 0
00408280 |>mov ebp, eax
00408282 |>call <mirvar>
00408287 |>push 0
00408289 |>mov [esp+40], eax
0040828D |>call <mirvar>
00408292 |>push 0
00408294 |>mov [esp+48], eax
00408298 |>call <mirvar>
0040829D |>mov edi, [esp+58]
004082A1 |>mov [esp+4C], eax
004082A5 |>mov eax, [esp+54] ; sn
004082A9 |>mov ecx, edi
004082AB |>add esp, 28
004082AE |>xor esi, esi
004082B0 |>sub ecx, eax
004082B2 |>/mov dl, [eax]
004082B4 |>|cmp dl, 2D
004082B7 |>|je short 004082C3
004082B9 |>|mov [ecx+eax], dl
004082BC |>|inc esi
004082BD |>|inc eax
004082BE |>|cmp esi, 18 ; 24:在伽罗瓦域p内运算,因为p也只有22个字符长,所以,sn_1/sn_2长度必小于24
004082C1 |>\jl short 004082B2
004082C3 |>cmp esi, 18
004082C6 |>jnz short 004082D3
004082C8 |>mov edi, [esp+10]
004082CC |>xor esi, esi
004082CE |>jmp 004083AC
004082D3 |>push edi ; sn_1
004082D4 |>push ebp
004082D5 |>call <cinstr>
004082DA |>push 8 ; 8个DWORD
004082DC |>push edi ; sn_1
004082DD |>call 00403F71
004082E2 |>add esp, 10
004082E5 |>inc esi
004082E6 |>xor eax, eax
004082E8 |>/mov ecx, [esp+2C]
004082EC |>|mov cl, [esi+ecx]
004082EF |>|cmp cl, 2D
004082F2 |>|je short 004082FE
004082F4 |>|mov [eax+edi], cl
004082F7 |>|inc eax
004082F8 |>|inc esi
004082F9 |>|cmp eax, 18
004082FC |>\jl short 004082E8
004082FE |>cmp eax, 18
00408301 |>jnz short 0040830E
00408303 |>mov edi, [esp+10]
00408307 |>xor esi, esi
00408309 |>jmp 004083AC
0040830E |>mov edx, [esp+1C]
00408312 |>push edi ; sn_2
00408313 |>push edx
00408314 |>inc esi
00408315 |>call <cinstr>
0040831A |>push 8
0040831C |>push edi ; sn_2
0040831D |>call 00403F71
00408322 |>mov edi, [esp+20]
00408326 |>push 004033D4 ; ASCII "2B5CF397E91B4376A51DA3"
0040832B |>push edi ; p
0040832C |>call <cinstr>
00408331 |>push 004033D0 ; 3
00408336 |>push ebx
00408337 |>call <cinstr>
0040833C |>mov eax, [esp+38]
00408340 |>push 004033B8 ; ASCII "C1CE280BD21C8D573609D"
00408345 |>push eax ; y
00408346 |>call <cinstr>
0040834B |>mov ecx, [esp+3C]
0040834F |>mov edx, [esp+5C]
00408353 |>push ecx
00408354 |>push edx ; zero
00408355 |>push 18
00408357 |>call <bytes_to_big>
0040835C |>push ebp ; sn_1
0040835D |>push ebx ; 3
0040835E |>call <compare>
00408363 |>add esp, 3C
00408366 |>test eax, eax
00408368 |>jnz short 0040836C
0040836A |>xor esi, esi
0040836C |>mov eax, [esp+24]
00408370 |>mov ecx, [esp+14]
00408374 |>push eax
00408375 |>push edi ; p
00408376 |>push ecx ; It's always zero.
00408377 |>push ebx ; 3
00408378 |>call <powmod> ; c=1
0040837D |>mov edx, [esp+30]
00408381 |>mov eax, [esp+2C]
00408385 |>mov ecx, [esp+28]
00408389 |>push edx ; d
0040838A |>push edi ; p
0040838B |>push eax ; sn_2
0040838C |>push ebp ; sn_1
0040838D |>push ebp ; sn_1
0040838E |>push ecx ; y
0040838F |>call <powmod2> ; d = (y^sn_1) * (sn_1^sn_2) (mod p)
00408394 |>mov edx, [esp+4C]
00408398 |>mov eax, [esp+48]
0040839C |>push edx ; c=1
0040839D |>push eax ; d
0040839E |>call <compare>
004083A3 |>add esp, 30
004083A6 |>test eax, eax
004083A8 |>je short 004083AC
整理一下上面的思路,则须有下式成立:
1 = (y^sn_1) * (sn_1^sn_2) (mod p) (*)
是不是有点像ElGamal数字签名算法的左端?呵呵,我费了九牛二虎之力也没有凑出来;怎么办?把等式转换成:
sn_1^sn_2 = (y^sn_1)^(-1) (mod p)
然后给定一个sn_1,来计算离散对数求得sn_2,因为p并不大,所以应该不难找出几组来,但我用指数法也没有找出来一组;到底该怎么办?
换个思路,既然等式(*)左边等于1,那么能不能用费尔玛小定理尝试一下?若直接令sn_1 = y,那么,等式变成:
1 = y^(y + sn_2) (mod p)
即,只需有y + sn_2 = Φ(p) = p - 1 =〉sn_2 = p - 1 - y。
这是一组固定的sn_1和sn_2,可轻松计算得到:C1CE280BD21C8D573609D-1F4011172BF97AA131BD05-sn_3
输入,通过上面的compare验证。
再多想一下,若令sn_1 = y^k (k = 2,3...),只要满足等式y^k + k*sn_2 = Φ(p)即可,可是单y^2就已经比Φ(p)大很多了。根据模运算的性质,我们只要
y^k + k*sn_2 = m*Φ(p)
也可以。此时,求出sn_2来应不成问题。但计算量估计会很大。
好了,这一步就讨论这么多,看下面的sn_3:
00405C19 >pop edi
00405C1A >xor eax, eax
00405C1C >pop esi
00405C1D >retn 10
00405C20 >mov [40EE48], esi
00405C26 >pop edi
00405C27 >mov [40EE44], edx
00405C2D >xor eax, eax
00405C2F >pop esi
00405C30 >retn 10
00405C33 >mov ecx, [4030A0] ; ppg_crac.0040EB70
00405C39 >mov edx, [40309C] ; <ppg_crac.String>
00405C3F >push 0040EB10
00405C44 >push ecx
00405C45 >mov ecx, [403098] ; ppg_crac.0040EBA0
00405C4B >push edx
00405C4C >add ecx, eax
00405C4E >push ecx ; sn_3
00405C4F >call 00408410
00405C54 >add esp, 10
00405C57 >test eax, eax
00405C59 >push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00405C5B >push <Caption> ; |Title = "The PowerPuff Girls"
00405C60 >je short 00405C75 ; |
00405C62 >push <aWhatYouLikeFor> ; |Text = "What you like for christmas?"
00405C67 >push edi ; |hOwner
00405C68 >call [<&user32.MessageBoxA>] ; \MessageBoxA
00405C6E >pop edi ; Default case of switch 00405B41
00405C6F >xor eax, eax
00405C71 >pop esi
00405C72 >retn 10
00405C75 >push <aCongratulation> ; |Text = "Congratulations, Good work!"
00405C7A >push edi ; |hOwner
00405C7B >call [<&user32.MessageBoxA>] ; \MessageBoxA
跟进405C4F瞧瞧去:
00408410 />sub esp, 14
00408413 |>push ebx
00408414 |>push ebp
00408415 |>push esi
00408416 |>push edi
00408417 |>push 0
00408419 |>push 0C8
0040841E |>call <mirsys>
00408423 |>push 0
00408425 |>mov dword ptr [eax+238], 10
0040842F |>call <mirvar>
00408434 |>push 0
00408436 |>mov ebx, eax
00408438 |>call <mirvar>
0040843D |>push 0
0040843F |>mov [esp+30], eax
00408443 |>call <mirvar>
00408448 |>push 0
0040844A |>mov [esp+28], eax
0040844E |>call <mirvar>
00408453 |>push 0
00408455 |>mov [esp+30], eax
00408459 |>call <mirvar>
0040845E |>push 0
00408460 |>mov ebp, eax
00408462 |>call <mirvar>
00408467 |>push 0
00408469 |>mov [esp+44], eax
0040846D |>call <mirvar>
00408472 |>mov [esp+3C], eax
00408476 |>mov eax, [esp+4C]
0040847A |>push eax
0040847B |>push ebp
0040847C |>call <cinstr>
00408481 |>push 0040EE60
00408486 |>call <SHA1_Init>
0040848B |>mov edx, [esp+60]
0040848F |>or ecx, FFFFFFFF
00408492 |>mov edi, edx
00408494 |>xor eax, eax
00408496 |>repne scas byte ptr es:[edi]
00408498 |>not ecx
0040849A |>dec ecx
0040849B |>push ecx
0040849C |>push edx
0040849D |>push 0040EE60
004084A2 |>call <SHA1_Update>
004084A7 |>mov esi, [esp+70]
004084AB |>push 0040EE60
004084B0 |>push esi
004084B1 |>call <SHA1_Final>
004084B6 |>add esp, 44
004084B9 |>push ebx
004084BA |>push esi ; SHA1(0)
004084BB |>push 14 ; 20
004084BD |>call <bytes_to_big>
004084C2 |>push 8
004084C4 |>push esi
004084C5 |>call 00403F71
004084CA |>add esp, 14
004084CD |>mov edi, 2
004084D2 |>/mov ecx, [esp+10]
004084D6 |>|push ecx
004084D7 |>|push ebx ; SHA1(0)
004084D8 |>|call <nxprime>
004084DD |>|add esp, 8
004084E0 |>|dec edi
004084E1 |>\jnz short 004084D2
004084E3 |>push 0040EE60
004084E8 |>call <SHA1_Init>
004084ED |>mov edx, [esp+30]
004084F1 |>or ecx, FFFFFFFF
004084F4 |>mov edi, edx
004084F6 |>xor eax, eax
004084F8 |>repne scas byte ptr es:[edi]
004084FA |>not ecx
004084FC |>dec ecx
004084FD |>push ecx
004084FE |>push edx ; 0
004084FF |>push 0040EE60
00408504 |>call <SHA1_Update>
00408509 |>push 0040EE60
0040850E |>push esi
0040850F |>call <SHA1_Final> ; SHA1(0)
00408514 |>mov edi, [esp+34]
00408518 |>push edi
00408519 |>push esi
0040851A |>push 14
0040851C |>call <bytes_to_big>
00408521 |>push 8
00408523 |>push esi
00408524 |>call 00403F71
00408529 |>mov esi, 3
0040852E |>add esp, 2C
00408531 |>mov [esp+28], esi
00408535 |>/mov edx, [esp+14]
00408539 |>|push edx ; n
0040853A |>|push edi ; SHA1(0)
0040853B |>|call <nxprime>
00408540 |>|add esp, 8
00408543 |>|dec esi
00408544 |>\jnz short 00408535
00408546 |>mov esi, [esp+20]
0040854A |>mov eax, [esp+10]
0040854E |>push esi
0040854F |>push eax ; n
00408550 |>push 1 ; 1
00408552 |>push ebp ; sn_3
00408553 |>call <power> ; sn_3
00408558 |>mov ecx, [esp+28]
0040855C |>mov edx, [esp+24]
00408560 |>push ecx
00408561 |>push edx ; n
00408562 |>push 1 ; 1
00408564 |>push ebp ; sn_3
00408565 |>call <power> ; sn_3
0040856A |>push ebx ; SHA(0)
0040856B |>push esi ; sn_3
0040856C |>call <compare>
00408571 |>add esp, 28
00408574 |>test eax, eax
00408576 |>jnz short 0040858E
00408578 |>mov eax, [esp+18]
0040857C |>push edi
0040857D |>push eax
0040857E |>call <compare>
00408583 |>add esp, 8
00408586 |>test eax, eax
00408588 |>jnz short 0040858E
40856C处可以看到sn_3和SHA1(NULL)比较,而SHA1(NULL)为一常数,所以sn_3 = SHA1(NULL)。因此,目前唯一可用的注册码就是:
C1CE280BD21C8D573609D-1F4011172BF97AA131BD05-DA39A3EE5E6B4B0D3255BFEF95601890AFD80709
大家是不是觉得这个CrackMe怪怪地?反正我就是这样的感觉。我重新跟踪了一下未脱壳的源程序,发现与脱掉的验证算法没有任何不同之处。同时,用上面的注册码验证通过。
也许,程序作者就是想和大家开个圣诞节的玩笑把。反正No Tiger,No RC2。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年01月19日 5:59:00
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课