好友
阅读权限 40
听众
最后登录 1970-1-1
zaas
发表于 2010-2-28 20:41
【破文标题】Luckly的单注册码型 CrackMe算法分析及算法注册机
【破文作者】zaas[PYG][FCT]
【破解 工具】OllyICE,PEiD v0.94
【破解平台】WinXP
【破解声明】我是一只小菜鸟,偶得一点心得,愿与大家分享:)
--------------------------------------------------------------
【破解内容】
--------------------------------------------------------------
**************************************************************
用PEiD查壳,为Microsoft Visual C++ 6.0,MFC
**************************************************************
搜索字符串有提示,直接来到注册算法部分:00401543 . 53 push ebx
00401544 . 33C0 xor eax, eax
00401546 . 55 push ebp
00401547 . 56 push esi
00401548 . 894424 19 mov dword ptr [esp+19], eax
0040154C . BE 01000000 mov esi, 1
00401551 . 57 push edi
00401552 . 8BD9 mov ebx, ecx
00401554 . 894424 21 mov dword ptr [esp+21], eax
00401558 . 56 push esi
00401559 . 895C24 14 mov dword ptr [esp+14], ebx
0040155D . C64424 20 00 mov byte ptr [esp+20], 0
00401562 . 884424 29 mov byte ptr [esp+29], al
00401566 . E8 CF030000 call <jmp.&MFC42.#6334>
0040156B . 8B4B 60 mov ecx, dword ptr [ebx+60]
0040156E . 8B51 F8 mov edx, dword ptr [ecx-8]
00401571 . 83FA 0B cmp edx, 0B
00401574 . 7D 18 jge short 0040158E
00401576 . 6A 00 push 0
00401578 . 6A 00 push 0
0040157A . 68 64304000 push 00403064 ; 请输入11位注册码!
0040157F . 8BCB mov ecx, ebx
00401581 . E8 AE030000 call <jmp.&MFC42.#4224>
由此得知注册码为11位,修正假码后继续。00401586 . 5F pop edi
00401587 . 5E pop esi
00401588 . 5D pop ebp
00401589 . 5B pop ebx
0040158A . 83C4 18 add esp, 18
0040158D . C3 retn
0040158E > 0FBE01 movsx eax, byte ptr [ecx] ; 第一位
00401591 . 8D7A FD lea edi, dword ptr [edx-3] ; 8
00401594 . 894424 14 mov dword ptr [esp+14], eax
00401598 . 897C24 18 mov dword ptr [esp+18], edi
0040159C > 0FBE2C31 movsx ebp, byte ptr [ecx+esi] ; 第二位开始-第9位
004015A0 . 03C6 add eax, esi ; +计数器
004015A2 . 25 FF000000 and eax, 0FF ; 保留后两位
004015A7 . 33C5 xor eax, ebp ; 和下一位Xor
004015A9 . 46 inc esi
004015AA . 3BF7 cmp esi, edi
004015AC .^ 7E EE jle short 0040159C ; 求得一个初始值A
004015AE . 0FBE7411 FE movsx esi, byte ptr [ecx+edx-2] ; 第十位
004015B3 . 83C0 42 add eax, 42 ; 初始值A+42
004015B6 . 8BF8 mov edi, eax
004015B8 . C1FF 04 sar edi, 4 ; 右移一位
004015BB . 83C7 41 add edi, 41 ; +41
004015BE . 3BF7 cmp esi, edi ; 第十位真假码比较
004015C0 74 18 je short 004015DA ; 不跳则死
004015C2 . 6A 00 push 0
004015C4 . 6A 00 push 0
004015C6 . 68 58304000 push 00403058 ; 密码错误!
004015CB . 8BCB mov ecx, ebx
004015CD . E8 62030000 call <jmp.&MFC42.#4224>
004015D2 . 5F pop edi
004015D3 . 5E pop esi
004015D4 . 5D pop ebp
004015D5 . 5B pop ebx
004015D6 . 83C4 18 add esp, 18
004015D9 . C3 retn
004015DA > 0FBE5411 FF movsx edx, byte ptr [ecx+edx-1] ; 第十一位
004015DF . 83E0 0F and eax, 0F ; 初始值A+42 mod 16
004015E2 . 83C0 41 add eax, 41 ; +41
004015E5 . 3BD0 cmp edx, eax ; 第十一位真假码比较
004015E7 74 18 je short 00401601 ; 不跳则死
004015E9 . 6A 00 push 0
004015EB . 6A 00 push 0
004015ED . 68 58304000 push 00403058 ; 密码错误!
004015F2 . 8BCB mov ecx, ebx
004015F4 . E8 3B030000 call <jmp.&MFC42.#4224>
这一段弄清楚了注册码第10位,第11位的由来。
首先把2-9位注册码依次+1跟下一位Xor,加上42得出一个中间值K。
第十位为K右移一位+42,第十一位为K除以16求余+41,修正假码后继续。004015F9 . 5F pop edi
004015FA . 5E pop esi
004015FB . 5D pop ebp
004015FC . 5B pop ebx
004015FD . 83C4 18 add esp, 18
00401600 . C3 retn
00401601 > BD 01000000 mov ebp, 1
00401606 . 33FF xor edi, edi
00401608 . 8BF5 mov esi, ebp
0040160A . 8D51 01 lea edx, dword ptr [ecx+1] ; 从第二位开始
0040160D . 2BF1 sub esi, ecx
0040160F > 8A0A mov cl, byte ptr [edx] ; 取字符B
00401611 . 8D0416 lea eax, dword ptr [esi+edx] ; 上面取得的是第X位
00401614 . 0FBE5A 01 movsx ebx, byte ptr [edx+1] ; 下一位的ascii-->C
00401618 . 83E1 0F and ecx, 0F ; B mod 16
0040161B . C1E1 04 shl ecx, 4 ; 左移一位
0040161E . D1F8 sar eax, 1 ; 位数\2
00401620 . 8D4C19 AF lea ecx, dword ptr [ecx+ebx-51] ; 第二位尾数F(B)+第三位 C-51--》D
00401624 . 8B5C24 14 mov ebx, dword ptr [esp+14] ; 第一位
00401628 . 83C0 06 add eax, 6 ; 位数\2 +6=7,8,9,A,B
0040162B . 8D4403 FF lea eax, dword ptr [ebx+eax-1] ; =第一位的ascii 依次+6,7,8,9,A
0040162F . 25 FF000000 and eax, 0FF ; 取byte
00401634 . 33C8 xor ecx, eax ; 和 D Xor
00401636 . 83F9 20 cmp ecx, 20 ; 数值范围必须在20-80间
00401639 . 0F8C AF000000 jl 004016EE
0040163F . 81F9 80000000 cmp ecx, 80
00401645 . 0F8F A3000000 jg 004016EE
0040164B . 884C3C 1C mov byte ptr [esp+edi+1C], cl ; 写入内存
0040164F . 8B4C24 18 mov ecx, dword ptr [esp+18]
00401653 . 83C5 02 add ebp, 2 ; 取下一组
00401656 . 83C2 02 add edx, 2
00401659 . 47 inc edi ; 计数器+1
0040165A . 41 inc ecx
0040165B . 3BE9 cmp ebp, ecx
0040165D .^ 7E B0 jle short 0040160F ; 未取完循环
0040165F . 83FF 02 cmp edi, 2 ; 至少取到满足以上条件2组
00401662 . 7D 1A jge short 0040167E
00401664 . 8B4C24 10 mov ecx, dword ptr [esp+10]
00401668 . 6A 00 push 0
0040166A . 6A 00 push 0
0040166C . 68 48304000 push 00403048 ; 注册码错误 !
00401671 . E8 BE020000 call <jmp.&MFC42.#4224>
注册码第2-9位,两两一组。偶数位第n位除以16求余左移一位然后和第n+1位奇数位相加,再减去51.得到M
注册码第一位依次加6,7,8,9,A得到数值N,M xor N得到的数字须在20H和80H之间。修正假码后继续。。。。00401676 . 5F pop edi
00401677 . 5E pop esi
00401678 . 5D pop ebp
00401679 . 5B pop ebx
0040167A . 83C4 18 add esp, 18
0040167D . C3 retn
0040167E > 8D7C24 1C lea edi, dword ptr [esp+1C] ; 取出写入内存的字符串
00401682 . 83C9 FF or ecx, FFFFFFFF
00401685 . 33C0 xor eax, eax
00401687 . F2:AE repne scas byte ptr es:[edi] ; 搬运
00401689 . F7D1 not ecx
0040168B . 49 dec ecx
0040168C . 83F9 03 cmp ecx, 3 ; 长度至少3位
0040168F . 7D 18 jge short 004016A9 ; 否则死
00401691 . 8B4C24 10 mov ecx, dword ptr [esp+10]
00401695 . 50 push eax
00401696 . 50 push eax
00401697 . 68 3C304000 push 0040303C ; 注册码错误!
0040169C . E8 93020000 call <jmp.&MFC42.#4224>
以上结果转化为字符串004016A1 . 5F pop edi
004016A2 . 5E pop esi
004016A3 . 5D pop ebp
004016A4 . 5B pop ebx
004016A5 . 83C4 18 add esp, 18
004016A8 . C3 retn
004016A9 > 6A 02 push 2 ; /maxlen = 2
004016AB . 8D540C 1D lea edx, dword ptr [esp+ecx+1D] ; |第6,7,8,9位注册码转换的字符串和字符串“PS”比较
004016AF . 68 38304000 push 00403038 ; |ps
004016B4 . 52 push edx ; |s1
004016B5 . FF15 B4214000 call dword ptr [<&MSVCRT.strncmp>] ; \strncmp
004016BB . 83C4 0C add esp, 0C
004016BE . 85C0 test eax, eax
004016C0 . 6A 00 push 0
004016C2 . 6A 00 push 0
004016C4 . 74 07 je short 004016CD ; 相等则跳向成功
004016C6 . 68 3C304000 push 0040303C ; 注册码错误!
004016CB . EB 05 jmp short 004016D2
004016CD > 68 2C304000 push 0040302C ; 注册成功!
004016D2 > 8B7424 1C mov esi, dword ptr [esp+1C]
004016D6 . 8BCE mov ecx, esi
004016D8 . E8 57020000 call <jmp.&MFC42.#4224> ; 成功对话框
004016DD . 6A 00 push 0 ; (initial cpu selection)
004016DF . 8BCE mov ecx, esi
004016E1 . E8 54020000 call <jmp.&MFC42.#6334>
004016E6 . 5F pop edi
004016E7 . 5E pop esi
004016E8 . 5D pop ebp
004016E9 . 5B pop ebx
004016EA . 83C4 18 add esp, 18
004016ED . C3 retn
004016EE > 8B4C24 10 mov ecx, dword ptr [esp+10]
004016F2 . 6A 00 push 0
004016F4 . 6A 00 push 0
004016F6 . 68 20304000 push 00403020 ; 密码错误!!
004016FB . E8 34020000 call <jmp.&MFC42.#4224>
00401700 . 5F pop edi
00401701 . 5E pop esi
00401702 . 5D pop ebp
00401703 . 5B pop ebx
00401704 . 83C4 18 add esp, 18
00401707 . C3 retn
第6,7,8,9位注册码转换的字符串和字符串“PS”比较,6,7位为50,8,9为53。相等注册成功,否则还是失败。
算法总结】这个Cm是单注册码型,自身进行运算比较,每一步都影响到下一步的运算。
第1位是基础,第10,11位和第2-9位相关联,其他位的注册码都跟第一位相关联。在注释里都写的很清楚了,根据以上分析写出注册机。(VB)
注册机做了多次do loop判断,运行速度还行。不过其实可以写的更简练些。。Private Sub Command1_Click()
Text1.Text = ""
Dim Reg(11) As Integer
Dim Check As Integer
Dim Sum As Integer
Dim temp As Integer
Do
'首先确定第1位
Reg(1) = Randnum()
'确定 2,3,4,5位
For b = 1 To 2
Do
Reg(2 * b) = Randnum()
Reg(2 * b + 1) = Randnum()
Check = ((Reg(2 * b) Mod 16) * 16 + Reg(2 * b + 1) - &H51) Xor (Reg(1) + b + 5)
Loop While Check < &H20 Or Check > &H80
Next
'确定第6,7,8,9位
For a = 1 To 2
Do
Do
Reg(4 + a * 2) = Randnum()
temp = Reg(1) + a + 7
Reg(4 + a * 2 + 1) = (((&H50 + a * 3 - 3) Xor temp) + &H51) - (Reg(4 + a * 2) Mod 16) * 16
Loop Until (Reg(4 + a * 2 + 1) > 47 And Reg(4 + a * 2 + 1) < 58) Or (Reg(4 + a * 2 + 1) > 64 And Reg(4 + a * 2 + 1) < 91)
Check = (Reg(4 + a * 2) Mod 16) * 16 + Reg(4 + a * 2 + 1) - &H51
Check = Check Xor (Reg(1) + a + 7)
Loop While Check < &H20 Or Check > &H80
Next
'计算10,11位
Sum = Reg(1)
For c = 1 To 8
Sum = (Sum + c) Xor Reg(c + 1) And &HFF
Next
Reg(10) = ((Sum + &H42) \ 16) + &H41
Reg(11) = ((Sum + &H42) And &HF) + &H41
Check = ((Reg(10) Mod 16) * 16 + Reg(11) - &H51) Xor (Reg(1) + 10)
Loop While Check < &H20 Or Check > &H80
For d = 1 To 11
Text1.Text = Text1.Text & Chr(Reg(d))
Next
End Sub
Function Randnum() As Integer
Do
Randomize
Randnum = (90 - 48) * Rnd() + 48
Loop While Randnum > 57 And Randnum < 65
End Function
【版权声明】破文是学习的手记,兴趣是成功的源泉;本破文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
Crack.rar
(7.04 KB, 下载次数: 43)