【原创】一个伊朗程序员的VB CRACKME算法详细分析
【作者】WindayJiang
【破解声明】纯粹学习,算法简单但烦琐,需要有一定基础
【破解工具】OLLDBG, PEID
【破解难度】MEDIUM
【软件保护】SN
【软件下载】http://bbs.pediy.com/upload/2005/37/files/iranskg2.zip
断点不会太难,随便下几个你很快来到这里:
0041378B >MOV ECX,DWORD PTR SS:[EBP-18] ; //机器码到ECX
0041378E >LEA EAX,DWORD PTR SS:[EBP-18] ; //机器码地址到EAX
00413791 >PUSH ECX ; //机器码入栈
00413792 >MOV DWORD PTR SS:[EBP-AC],EAX
00413798 >MOV DWORD PTR SS:[EBP-B4],4008 ; //4008,不知道有什么用
004137A2 >CALL EDI ; //获取机器码长度
004137A4 >SUB EAX,1 ; //长度减1
004137A7 >LEA EDX,DWORD PTR SS:[EBP-B4]
004137AD >JO CrackMe2.00413D0D
004137B3 >PUSH EAX ; //新长度
004137B4 >LEA EAX,DWORD PTR SS:[EBP-54] ; //缓冲区,等会要用
004137B7 >PUSH EDX
004137B8 >PUSH EAX
004137B9 >CALL DWORD PTR DS:[<&MSVBVM60.#619>] ; //在字符串右边取长度的字符串
004137BF >MOV EBX,DWORD PTR DS:[<&MSVBVM60.__vbaI4ErrVar>] ; MSVBVM60.__vbaI4ErrVar
004137C5 >LEA ECX,DWORD PTR SS:[EBP-54] ; //缓冲区地址到ECX
004137C8 >PUSH ECX ; //入栈
004137C9 >CALL EBX ; <&MSVBVM60.__vbaI4ErrVar>
004137CB >PUSH EAX ; //EAX=新字串的HEX
004137CC >CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrI4>] ; //把他从长整转为字串
004137D2 >MOV EDX,EAX ; //放到EDX
004137D4 >LEA ECX,DWORD PTR SS:[EBP-18] ; //还记得吗?机器码的地址
004137D7 >CALL ESI ; //新的字串移到原来机器码的地址了*等会我们叫这新机器码
004137D9 >LEA EDX,DWORD PTR SS:[EBP-54]
004137DC >LEA EAX,DWORD PTR SS:[EBP-54]
004137DF >PUSH EDX
004137E0 >PUSH EAX
004137E1 >PUSH 2
004137E3 >CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeVarList>] ; //将缓冲区释放了
004137E9 >MOV EDX,DWORD PTR SS:[EBP-18] ; //新机器码
004137EC >ADD ESP,0C
004137EF >LEA ECX,DWORD PTR SS:[EBP-18]
004137F2 >MOV DWORD PTR SS:[EBP-B4],4008
004137FC >PUSH EDX ; //新机器码入栈
004137FD >MOV DWORD PTR SS:[EBP-AC],ECX
00413803 >CALL EDI ; //获取新机器码的长度
00413805 >SUB EAX,1 ; //又减1,搞什么东东。。。。。。
00413808 >LEA ECX,DWORD PTR SS:[EBP-54] ; //缓冲区
0041380B >JO CrackMe2.00413D0D
00413811 >PUSH EAX ; //新长度
00413812 >LEA EAX,DWORD PTR SS:[EBP-B4]
00413818 >PUSH EAX ; //4008,这里清晰了,应该是调用的参数来的
00413819 >PUSH ECX ; //缓冲区入栈
0041381A >CALL DWORD PTR DS:[<&MSVBVM60.#619>] ; //向右拿新长度的字串
00413820 >LEA EDX,DWORD PTR SS:[EBP-54] ; // 缓冲区地址
00413823 >LEA EAX,DWORD PTR SS:[EBP-24] ; //另一缓冲区地址
00413826 >PUSH EDX ; //入栈调用
00413827 >PUSH EAX ; //入栈调用
00413828 >CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrVarVal>] ; //字串转换为数值
0041382E >PUSH EAX ; //EAX=新字串
0041382F >CALL DWORD PTR DS:[<&MSVBVM60.#713>] ; //字串反转
00413835 >MOV EDX,EAX
00413837 >LEA ECX,DWORD PTR SS:[EBP-28] ; //缓冲区,好晕好晕.......
0041383A >CALL ESI ; //字串移动
0041383C >MOV EDI,DWORD PTR DS:[<&MSVBVM60.__vbaI4Str>] ; MSVBVM60.__vbaI4Str
00413842 >PUSH EAX ; //新字串入栈
00413843 >CALL EDI ; //转换为长整; <&MSVBVM60.__vbaI4Str>
00413845 >MOV ECX,DWORD PTR SS:[EBP-18] ; //新的机器码放到ECX
00413848 >MOV EDX,EAX ; //长整数放到EDX
0041384A >PUSH ECX ; //新机器码入栈
0041384B >MOV DWORD PTR SS:[EBP-11C],EDX ; //保存长整数,肯定等会又要用
00413851 >CALL EDI ; //把机器码换长整
00413853 >MOV EDX,DWORD PTR SS:[EBP-11C] ; //还没说完就用上了,计算出来的长整数
00413859 >ADD EAX,1CD7 ; //把新机器码的长整数加上1CD7
0041385E >JO CrackMe2.00413D0D
00413864 >ADD EDX,EAX ; //把计算过的新机器码的长整数加上计算出来的
00413866 >JO CrackMe2.00413D0D
0041386C >PUSH EDX
0041386D >CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrI4>] ; //又把结果转换为字串
00413873 >MOV EDX,EAX
00413875 >LEA ECX,DWORD PTR SS:[EBP-20] ; //缓冲区
00413878 >CALL ESI ; //保存好这个字串
0041387A >LEA EAX,DWORD PTR SS:[EBP-28]
0041387D >LEA ECX,DWORD PTR SS:[EBP-24]
00413880 >PUSH EAX
00413881 >PUSH ECX
00413882 >PUSH 2
00413884 >CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeStrList>] ; //释放内存,开始吐血了。。。
0041388A >ADD ESP,0C
0041388D >LEA ECX,DWORD PTR SS:[EBP-54]
00413890 >CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeVar>] ; //继续释放
00413896 >LEA EAX,DWORD PTR SS:[EBP-B4] ; //4008参数地址
0041389C >PUSH 2 ; //常量2,等会有用
0041389E >LEA ECX,DWORD PTR SS:[EBP-54] ; //缓冲区
004138A1 >LEA EDX,DWORD PTR SS:[EBP-18] ; //新机器码地址,希望你还记得
004138A4 >MOV EDI,4008
004138A9 >PUSH EAX
004138AA >PUSH ECX ; //缓冲区入栈
004138AB >MOV DWORD PTR SS:[EBP-AC],EDX
004138B1 >MOV DWORD PTR SS:[EBP-B4],EDI
004138B7 >CALL DWORD PTR DS:[<&MSVBVM60.#617>] ; //新机器码向左取2位
004138BD >LEA EAX,DWORD PTR SS:[EBP-C4] ; //参数8008的地址
004138C3 >PUSH 1 ; //常量1入栈
004138C5 >LEA ECX,DWORD PTR SS:[EBP-64] ; //缓冲区
004138C8 >LEA EDX,DWORD PTR SS:[EBP-18] ; //EDX是新机器码地址
004138CB >PUSH EAX
004138CC >PUSH ECX
004138CD >MOV DWORD PTR SS:[EBP-BC],EDX
004138D3 >MOV DWORD PTR SS:[EBP-C4],EDI
004138D9 >CALL DWORD PTR DS:[<&MSVBVM60.#619>] ; //新机器码向右取1位
004138DF >LEA EDX,DWORD PTR SS:[EBP-64]
004138E2 >PUSH EDX ; //缓冲区数据入栈
004138E3 >CALL EBX ; //转换为长整
004138E5 >MOV EDI,EAX ; //放到EDI
004138E7 >LEA EAX,DWORD PTR SS:[EBP-54] ; //你还记得吧,向左取2位的缓冲区
004138EA >PUSH EAX ; //入栈
004138EB >CALL EBX ; //转换为长整
004138ED >IMUL EDI,EAX ; //2次的结果相乘到EDI
004138F0 >MOV ECX,DWORD PTR SS:[EBP-20] ; //上一次的计算结果出来了
004138F3 >PUSH ECX
004138F4 >JO CrackMe2.00413D0D
004138FA >CALL DWORD PTR DS:[<&MSVBVM60.__vbaI4Str>] ; //转换为长整
00413900 >ADD EDI,EAX ; //加上刚才的结果再放回到EDI
00413902 >JO CrackMe2.00413D0D
00413908 >PUSH EDI ; //新结果
00413909 >CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrI4>] ; //转换为字串
0041390F >MOV EDX,EAX
00413911 >LEA ECX,DWORD PTR SS:[EBP-20] ; //又把结果放回到这里
00413914 >CALL ESI ; //又把结果放回到这里
00413916 >LEA EDX,DWORD PTR SS:[EBP-64]
00413919 >LEA EAX,DWORD PTR SS:[EBP-64]
0041391C >PUSH EDX
0041391D >LEA ECX,DWORD PTR SS:[EBP-54]
00413920 >PUSH EAX
00413921 >LEA EDX,DWORD PTR SS:[EBP-54]
00413924 >PUSH ECX
00413925 >PUSH EDX
00413926 >PUSH 4
00413928 >CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeVarList>] ; //这里懒得看了,释放字串
0041392E >MOV EDI,DWORD PTR DS:[<&MSVBVM60.#632>] ; MSVBVM60.rtcMidCharVar
00413934 >ADD ESP,14
00413937 >LEA EAX,DWORD PTR SS:[EBP-18] ; //新机器码
0041393A >LEA ECX,DWORD PTR SS:[EBP-54]
0041393D >MOV DWORD PTR SS:[EBP-AC],EAX
00413943 >PUSH ECX
00413944 >LEA EDX,DWORD PTR SS:[EBP-B4] ; //4008
0041394A >PUSH 2 ; //常数2
0041394C >LEA EAX,DWORD PTR SS:[EBP-64] ; //又一个缓冲区
0041394F >PUSH EDX
00413950 >PUSH EAX
00413951 >MOV DWORD PTR SS:[EBP-4C],1
00413958 >MOV DWORD PTR SS:[EBP-54],2
0041395F >MOV DWORD PTR SS:[EBP-B4],4008
00413969 >CALL EDI ; //用MID取字串; <&MSVBVM60.#632>
0041396B >LEA ECX,DWORD PTR SS:[EBP-18]
0041396E >LEA EDX,DWORD PTR SS:[EBP-74]
00413971 >MOV DWORD PTR SS:[EBP-CC],ECX
00413977 >PUSH EDX
00413978 >LEA EAX,DWORD PTR SS:[EBP-D4]
0041397E >PUSH 3 ; //常数3
00413980 >LEA ECX,DWORD PTR SS:[EBP-84]
00413986 >PUSH EAX ; //参数
00413987 >PUSH ECX ; 缓冲区
00413988 >MOV DWORD PTR SS:[EBP-6C],1
0041398F >MOV DWORD PTR SS:[EBP-74],2
00413996 >MOV DWORD PTR SS:[EBP-D4],4008
004139A0 >CALL EDI ; //取字串
004139A2 >LEA EDX,DWORD PTR SS:[EBP-18] ; //头晕了,这些大多数一样,省略:P
004139A5 >MOV DWORD PTR SS:[EBP-8C],1
004139AF >MOV DWORD PTR SS:[EBP-94],2
004139B9 >MOV DWORD PTR SS:[EBP-EC],EDX
004139BF >MOV DWORD PTR SS:[EBP-F4],4008
004139C9 >LEA EAX,DWORD PTR SS:[EBP-94]
004139CF >LEA ECX,DWORD PTR SS:[EBP-F4]
004139D5 >PUSH EAX
004139D6 >PUSH 4 ; //常数4
004139D8 >LEA EDX,DWORD PTR SS:[EBP-A4]
004139DE >PUSH ECX ; //参数
004139DF >PUSH EDX ; //缓冲区
004139E0 >CALL EDI ; //取字串
004139E2 >LEA EAX,DWORD PTR SS:[EBP-84]
004139E8 >PUSH EAX
004139E9 >CALL EBX ; //缓冲区的结果转换为长整
004139EB >LEA ECX,DWORD PTR SS:[EBP-64]
004139EE >MOV EDI,EAX
004139F0 >PUSH ECX
004139F1 >CALL EBX ; //常数2的那个结果缓冲区,转长整,不记得往长翻
004139F3 >IMUL EDI,EAX ; //2次结果相乘
004139F6 >LEA EDX,DWORD PTR SS:[EBP-A4]
004139FC >PUSH EDX
004139FD >JO CrackMe2.00413D0D
00413A03 >CALL EBX ; //常数4的那个缓冲区转长整
00413A05 >IMUL EDI,EAX ; //再乘头2次MID后的结果
00413A08 >MOV EAX,DWORD PTR SS:[EBP-20] ; //最上一次保存的结果到EAX
00413A0B >PUSH EAX
00413A0C >JO CrackMe2.00413D0D
00413A12 >CALL DWORD PTR DS:[<&MSVBVM60.__vbaI4Str>] ; //转长整
00413A18 >ADD EDI,EAX ; //加上所有MID后处理的结果
00413A1A >JO CrackMe2.00413D0D
00413A20 >PUSH EDI ; //EDI入栈
00413A21 >CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrI4>] ; //转长整为字串
00413A27 >MOV EDX,EAX
00413A29 >LEA ECX,DWORD PTR SS:[EBP-20]
00413A2C >CALL ESI ; //保存结果
00413A2E >LEA ECX,DWORD PTR SS:[EBP-A4]
00413A34 >LEA EDX,DWORD PTR SS:[EBP-A4]
00413A3A >PUSH ECX
00413A3B >LEA EAX,DWORD PTR SS:[EBP-94]
00413A41 >PUSH EDX
00413A42 >LEA ECX,DWORD PTR SS:[EBP-84]
00413A48 >PUSH EAX
00413A49 >LEA EDX,DWORD PTR SS:[EBP-84]
00413A4F >PUSH ECX
00413A50 >LEA EAX,DWORD PTR SS:[EBP-74]
00413A53 >PUSH EDX
00413A54 >LEA ECX,DWORD PTR SS:[EBP-64]
00413A57 >PUSH EAX
00413A58 >LEA EDX,DWORD PTR SS:[EBP-64]
00413A5B >PUSH ECX
00413A5C >LEA EAX,DWORD PTR SS:[EBP-54]
00413A5F >PUSH EDX
00413A60 >PUSH EAX
00413A61 >PUSH 9
00413A63 >CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeVarList>] ; //上面一大串释放内存
00413A69 >MOV EBX,DWORD PTR DS:[<&MSVBVM60.__vbaStrCopy>] ; MSVBVM60.__vbaStrCopy
00413A6F >ADD ESP,28
00413A72 >MOV EDX,CrackMe2.00409748 ; UNICODE "Ok Man Key Is Generated!"
00413A77 >LEA ECX,DWORD PTR SS:[EBP-1C]
00413A7A >CALL EBX ; <&MSVBVM60.__vbaStrCopy>
00413A7C >MOV EDX,CrackMe2.00409780 ; UNICODE "Here I am Checking the Key you have Entered in "Registeration Key" Textbox..."
00413A81 >LEA ECX,DWORD PTR SS:[EBP-1C]
破解过程总结一下:
1. 跟VB的程序最好熟悉一些普通的函数如:VBASTRCOPY等,可以的话最好熟悉它们
在调用函数前会将一些什么东西入栈、顺序如何。
2. 不要跟进VB运行库跟踪,切记!相信我,不然的话一定会吐血不止!!
3. 还有最重要的一点就是:耐心!!
算法总结如下:(VB)
Dim MCode As String
Dim Tempstr1 As String
Dim Counter As Long
Dim Counter1 As Long
Dim Counter2 As Long
MCode = Me.Text1.Text 'systemcode
NewMcode = Right(MCode, Len(MCode) - 1) 'newsystemcode
Tempstr1 = Right(NewMcode, Len(NewMcode) - 1) 'new string
Tempstr1 = StrReverse(Tempstr1) 'reverse thestring
LongResult = Val(Tempstr1) 'After reverse the string, the string's value
Counter = Val(NewMcode) + &H1CD7 '**********CALC 1
Counter1 = Val(Left(NewMcode, 2)) * Val(Right(NewMcode, 1)) '********calc 2
Counter2 = Val(Mid(NewMcode, 3, 1)) * Val(Mid(NewMcode, 4, 1)) *
Val(Mid(NewMcode, 2, 1)) '******** calc 3
LongResult = LongResult + Counter + Counter1 + Counter2
'here, add together
Me.Text2.Text = Trim(Str(LongResult))
'regcode is here
注册机放上来:
附件:kengen.rar
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!