-
-
[原创]Key_Gen_Me_3算法详细分析
-
发表于: 2005-12-26 16:20 5590
-
【原创】Key_Gen_Me_3算法详细分析
【作者】WindayJiang
【破解声明】纯粹学习,算法简单,适合新手学习
【破解工具】OLLDBG
【破解难度】EASY
【软件保护】SN
【软件下载】附件:kengen.rar
这篇文章我打算写得详细点,希望借此能或多或少扫一扫大家对VB破解的雾区,写得不一定好,只望抛砖引玉罢了!
有兴趣了解VB破解的可以结合我之前的VB破解文章对比学习一下
http://bbs.pediy.com/showthread.php?s=&threadid=19703
好了,开工!
运行CRACKME,我们知道它不会把结果用对话框显示,取而代之的是写一个FEEDBACK.TXT到程序所在目录。所以不能用RTCMSGBOX,要用FILEOPE
N。用OD载入,ALT+E到模块MSVBVM60,CTRL+N查找参考,在__VBAFILEOPEN处下断,F9运行程序后中断取消断点,ALT+F9返回程序领空:
004058D8 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFileO>; MSVBVM60.__vbaFileOpen //中断在这里
004058DE LEA EAX,DWORD PTR SS:[EBP-28]
004058E1 PUSH EAX
004058E2 LEA ECX,DWORD PTR SS:[EBP-24]
004058E5 PUSH ECX
004058E6 PUSH 2
004058E8 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStrList
004058EE ADD ESP,0C
004058F1 LEA ECX,DWORD PTR SS:[EBP-38]
004058F4 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeO>; MSVBVM60.__vbaFreeObj
004058FA MOV DWORD PTR SS:[EBP-4],9
00405901 PUSH Key_Gen_.00403878 ; UNICODE "You are incorrect! Try Again!" //记事本写入此字串!
我们向上找一下,如你非要向下找的话,你会找到VBAEND,那是程序退出的函数来的,所以该向上找:
00405697 MOV DWORD PTR SS:[EBP-E4],Key_Gen_.00403>; UNICODE "You are correct!" //看到了吧?
004056A1 MOV DWORD PTR SS:[EBP-EC],8
004056AB MOV DWORD PTR SS:[EBP-F4],Key_Gen_.00403>; UNICODE "I cant believe it! "
004056B5 MOV DWORD PTR SS:[EBP-FC],8
004056BF MOV DWORD PTR SS:[EBP-104],Key_Gen_.0040>; UNICODE "Wait For crack me 4."
004056C9 MOV DWORD PTR SS:[EBP-10C],8
004056D3 MOV DWORD PTR SS:[EBP-114],Key_Gen_.0040>; UNICODE "You cant solve that!"
.......再向上
004054A9 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarTs>; MSVBVM60.__vbaVarTstEq //是用变量比较
.......再向上
00405262 CALL DWORD PTR DS:[<&MSVBVM60.#611>] ; MSVBVM60.rtcGetTimeBstr //我最终选择在这里下断
..............................................
再重新运行程序后来到这里:
00405262 CALL DWORD PTR DS:[<&MSVBVM60.#611>] ; MSVBVM60.rtcGetTimeBstr//获取当前时间
00405268 MOV EDX,EAX ; //EAX是时间
0040526A LEA ECX,DWORD PTR SS:[EBP-30] ; //缓冲区
0040526D CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMove>] ; MSVBVM60.__vbaStrMove//移动字串
00405273 CALL DWORD PTR DS:[<&MSVBVM60.#609>] ; MSVBVM60.rtcGetDateBstr//获取当前日期
00405279 MOV EDX,EAX ; //EAX是日期
0040527B LEA ECX,DWORD PTR SS:[EBP-34] ; //缓冲区
0040527E CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMove>] ; MSVBVM60.__vbaStrMove//移动字串
.............................................
F8来到这里:
004052FE MOV EAX,DWORD PTR SS:[EBP-24] ; //注册码到EAX
00405301 MOV DWORD PTR SS:[EBP-168],EAX ; //注册码放到[EBP-168]
00405307 MOV DWORD PTR SS:[EBP-24],0 ; //把原来的地址清空
0040530E MOV ECX,DWORD PTR SS:[EBP-168] ; //注册码放到ECX
00405314 MOV DWORD PTR SS:[EBP-C4],ECX ; //注册码又写到[EBP-C4]
0040531A MOV DWORD PTR SS:[EBP-CC],8008 ; // 参数
这里一连串几个MOV,是初始化变量、参数等等为后来的算法做好准备
.............................................
F8来到这里:
0040539E MOV EAX,DWORD PTR SS:[EBP-28] ; //用户名到EAX
004053A1 PUSH EAX ; //入栈
004053A2 CALL DWORD PTR DS:[<&MSVBVM60.#516>] ; MSVBVM60.rtcAnsiValueBstr//转换为ASCII码
004053A8 ADD AX,1 ; //这里看得很清楚,第一个字符+1
004053AC JO Key_Gen_.00405B4A
004053B2 MOVSX ECX,AX ; //放到ECX
004053B5 PUSH ECX ; //入栈
004053B6 LEA EDX,DWORD PTR SS:[EBP-4C] ; //缓冲区地址
004053B9 PUSH EDX ; //入栈
004053BA CALL DWORD PTR DS:[<&MSVBVM60.#608>] ; MSVBVM60.rtcVarBstrFromAnsi//转换ASCII码
004053C0 MOV EAX,DWORD PTR SS:[EBP-30] ; //时间到EAX
004053C3 MOV DWORD PTR SS:[EBP-16C],EAX ; //时间 ->ebp-16c
004053C9 MOV DWORD PTR SS:[EBP-30],0 ; //原来的清空
004053D0 MOV ECX,DWORD PTR SS:[EBP-16C] ; //时间到ECX
004053D6 MOV DWORD PTR SS:[EBP-54],ECX ; //放到EBP-54
004053D9 MOV DWORD PTR SS:[EBP-5C],8 ; //参数
004053E0 PUSH 2 ; //参数2入栈,重要!
004053E2 LEA EDX,DWORD PTR SS:[EBP-5C] ; //时间缓冲区
004053E5 PUSH EDX ; //入栈
004053E6 LEA EAX,DWORD PTR SS:[EBP-6C] ; //缓冲区地址
004053E9 PUSH EAX ; //缓冲区入栈
004053EA CALL DWORD PTR DS:[<&MSVBVM60.#619>] ; MSVBVM60.rtcRightCharVar//向时间右取2位字符
004053F0 MOV ECX,DWORD PTR SS:[EBP-34] ; //日期到ECX
004053F3 MOV DWORD PTR SS:[EBP-170],ECX ; //再存到EBP-170
004053F9 MOV DWORD PTR SS:[EBP-34],0 ; //原来地址清空
00405400 PUSH 2 ; //参数2入栈
00405402 MOV EDX,DWORD PTR SS:[EBP-170] ; //EDX是日期
00405408 LEA ECX,DWORD PTR SS:[EBP-2C] ; //准备移动到的地址
0040540B CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMove>] ; MSVBVM60.__vbaStrMove//字串移动
00405411 PUSH EAX ; //日期入栈
00405412 CALL DWORD PTR DS:[<&MSVBVM60.#618>] ; MSVBVM60.rtcRightCharBstr//向日期右取2位
00405418 MOV DWORD PTR SS:[EBP-84],EAX ; //日期右2位存到EBP-84
0040541E MOV DWORD PTR SS:[EBP-8C],8 ;
00405428 MOV DWORD PTR SS:[EBP-E4],Key_Gen_.004036F8 ; UNICODE "Grand-Theft-Auto-Vice-City"
00405432 MOV DWORD PTR SS:[EBP-EC],8 ;
0040543C MOV DWORD PTR SS:[EBP-F4],Key_Gen_.00403734 ; UNICODE "bbidhan-ThE-Great"
00405446 MOV DWORD PTR SS:[EBP-FC],8 ;
.......................................................; 上面又是初始化
00405450 LEA EDX,DWORD PTR SS:[EBP-CC] ; //注册码的缓冲区
00405456 PUSH EDX
00405457 LEA EAX,DWORD PTR SS:[EBP-4C] ; //计算过的第一个字符
0040545A PUSH EAX
0040545B LEA ECX,DWORD PTR SS:[EBP-6C] ; //时间右2位
0040545E PUSH ECX
0040545F LEA EDX,DWORD PTR SS:[EBP-7C] ; //缓冲区
00405462 PUSH EDX
00405463 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarCat>] ; MSVBVM60.__vbaVarCat//连接字符串
00405469 PUSH EAX ; //新字串缓冲区
0040546A LEA EAX,DWORD PTR SS:[EBP-8C]
00405470 PUSH EAX ; //日期右2位的缓冲区
00405471 LEA ECX,DWORD PTR SS:[EBP-9C]
00405477 PUSH ECX ; //缓冲区
00405478 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarCat>] ; MSVBVM60.__vbaVarCat//连接字符串
0040547E PUSH EAX ; //新字串缓冲区
0040547F LEA EDX,DWORD PTR SS:[EBP-EC]
00405485 PUSH EDX ; //“Grand-Theft-Auto-Vice-City”缓冲区
00405486 LEA EAX,DWORD PTR SS:[EBP-AC]
0040548C PUSH EAX ; //缓冲区
0040548D CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarCat>] ; MSVBVM60.__vbaVarCat//连接字符串
00405493 PUSH EAX ; //新字串缓冲区
00405494 LEA ECX,DWORD PTR SS:[EBP-FC]
0040549A PUSH ECX ; //"bbidhan-ThE-Great"缓冲区
0040549B LEA EDX,DWORD PTR SS:[EBP-BC]
004054A1 PUSH EDX ; //缓冲区
004054A2 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarCat>] ; MSVBVM60.__vbaVarCat//连接字符串
004054A8 PUSH EAX ; //新字串缓冲区
004054A9 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarTstEq>>; MSVBVM60.__vbaVarTstEq//变量比较
004054AF MOV WORD PTR SS:[EBP-150],AX ; //比较后的标志值放到EBP-150
.......................................................
004054B6 LEA EAX,DWORD PTR SS:[EBP-34]
004054B9 PUSH EAX
004054BA LEA ECX,DWORD PTR SS:[EBP-30]
004054BD PUSH ECX
004054BE LEA EDX,DWORD PTR SS:[EBP-2C]
004054C1 PUSH EDX
004054C2 LEA EAX,DWORD PTR SS:[EBP-28]
004054C5 PUSH EAX
004054C6 PUSH 4
004054C8 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeStrLi>; MSVBVM60.__vbaFreeStrList
004054CE ADD ESP,14
004054D1 LEA ECX,DWORD PTR SS:[EBP-3C]
004054D4 PUSH ECX
004054D5 LEA EDX,DWORD PTR SS:[EBP-38]
004054D8 PUSH EDX
004054D9 PUSH 2
004054DB CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeObjLi>; MSVBVM60.__vbaFreeObjList
004054E1 ADD ESP,0C
004054E4 LEA EAX,DWORD PTR SS:[EBP-BC]
004054EA PUSH EAX
004054EB LEA ECX,DWORD PTR SS:[EBP-CC]
004054F1 PUSH ECX
004054F2 LEA EDX,DWORD PTR SS:[EBP-AC]
004054F8 PUSH EDX
004054F9 LEA EAX,DWORD PTR SS:[EBP-9C]
004054FF PUSH EAX
00405500 LEA ECX,DWORD PTR SS:[EBP-8C]
00405506 PUSH ECX
00405507 LEA EDX,DWORD PTR SS:[EBP-7C]
0040550A PUSH EDX
0040550B LEA EAX,DWORD PTR SS:[EBP-6C]
0040550E PUSH EAX
0040550F LEA ECX,DWORD PTR SS:[EBP-4C]
00405512 PUSH ECX
00405513 LEA EDX,DWORD PTR SS:[EBP-5C]
00405516 PUSH EDX
00405517 PUSH 9
00405519 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeVarLi>; MSVBVM60.__vbaFreeVarList
0040551F ADD ESP,28
上面一大段作释放字串、对象、变量动作,这些在破解时快速略过
..................................................................
00405522 MOVSX EAX,WORD PTR SS:[EBP-150] ; //把标志取出来
00405529 TEST EAX,EAX ; //比较
0040552B JE Key_Gen_.004057C2 ; //等于0就GAMEOVE
算法总结一下:
(第一个字串ASC码+1)&时间右2位&日期右2位&Grand-Theft-Auto-Vice-City&bbidhan-ThE-Great
注册机我不会写,因为时间是变动的,程序中运行获取到的时间绝不可能跟我手动输入的时间相吻,估计要用到一些其他函数,我没有去仔细
想。我只要想了解一下VB的函数在汇编下是如何操作的。
VB破解再总结一下:
1. 由于VB的特殊,会用到大量内存寻址,这会令你觉得很头晕,如果你实在记性不好,建议你拿笔记下一些关键的内存地址,如[EBP-7C]什
么的等等
2. 遇到VBAFREEXXXLIST语句之前的LEA、PUSH,不要耗力气了,人家都处理完了,你看他释放内存有什么用呢??
3. 熟悉一下函数调用前什么参数入栈了
4. 还是那句话:耐心。对付VB,急也急不来!!
这是我本年度最后一篇文章了,谢谢观赏!C U NEXT YEAR!
////////////////////////////////////////////////////////////////
If you want to crack well, learn ASM well !
WiNDaYJiANg 2005-12-26
////////////////////////////////////////////////////////////////
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)