-
-
[原创]VB6打印控件SuperPrint的注册分析
-
发表于: 2009-7-13 23:00 6328
-
【文章标题】: VB6打印控件SuperPrint的注册分析
【文章作者】: 波导终结者
【软件名称】: SuperPrint
【加壳方式】: 无
【保护方式】: 机器码+注册码
【编写语言】: VB6
【使用工具】: OD,W32Dasm
【操作平台】: Win32
--------------------------------------------------------------------------------
这个控件是一个VB6的打印预览控件,差不多六七年前的东西了,经过搜索未发现更新的版本,作者也已经停止更新,所留的主页更是惨变成yellow网站-_-。而且当初我在做毕业设计的时候试用,发现有严重BUG,打一页会吐20多页出来,后面的却没了。今天在CSDN看到一个贴子,使我想起一年多前的这篇破文,这个时候发出来想必应该不要紧了吧。
【详细过程】
最近在找VB用的打印预览控件,下了十几二十个,要不有BUG或者不能发布,要不就是要钱。这种控件一般都是加限制在内部,采用注册后发放的方式,遇到一个SuperPrint打印控件,自带一个注册程序,看看。
包里若干文件,一些是VB6的演示工程,编译好的演示主程序,主要文件就是控件本体SuperPrint.ocx和注册程序SuperPrint_info.exe。既然有独立的注册程序,那就先看看它的工作原理。
PEID之,庆幸的是无壳,不幸的是VB6编写,万幸的是最近我都在用VB6写工程……。程序根据机器码注册,随便输入注册码1234567890,弹框提示错误。拦截msgbox往上找,找到比较的地方,但看不到明文,也找不到通常的根据机器码算Code的Call。
用W32Dasm打开,查看输入函数,发现MSVBVM60.rtcR8ValFromBstr,想必是把机器码整串转成数值进行运算。下断点,输假码,点注册,拦下。
00402BEA > \8B4D A8 mov ecx, dword ptr [ebp-58]
00402BED . 51 push ecx ; //ECX指向UNICODE存储的机器码
00402BEE . FF15 28114000 call dword ptr [<&MSVBVM60.#581>] ; MSVBVM60.rtcR8ValFromBstr
00402BF4 . DD9D 00FFFFFF fstp qword ptr [ebp-100] ; //转成浮点数
00402BFA . DD85 00FFFFFF fld qword ptr [ebp-100]
00402C00 . DC0D 38114000 fmul qword ptr [401138] ; //把机器码乘以[401138]=321
00402C06 . 8D55 8C lea edx, dword ptr [ebp-74]
00402C09 . 6A 0A push 0A ; //10位
00402C0B . 52 push edx
00402C0C . C745 8C 05000>mov dword ptr [ebp-74], 5
00402C13 . DC05 30114000 fadd qword ptr [401130] ; //乘完加上[401130]=1234567890
00402C19 . DD5D 94 fstp qword ptr [ebp-6C]
00402C1C . DFE0 fstsw ax
00402C1E . A8 0D test al, 0D
00402C20 . 0F85 1A0B0000 jnz 00403740
00402C26 . 8D85 7CFFFFFF lea eax, dword ptr [ebp-84] ; //这里lea出来的是刚才PUSH的0A
00402C2C . 50 push eax ; //取计算结果前十位
00402C2D . FF15 08114000 call dword ptr [<&MSVBVM60.#617>] ; MSVBVM60.rtcLeftCharVar
00402C33 . 8B0E mov ecx, dword ptr [esi]
00402C35 . 56 push esi
00402C36 . FF91 00030000 call dword ptr [ecx+300]
00402C3C . 8D55 9C lea edx, dword ptr [ebp-64]
00402C3F . 50 push eax
00402C40 . 52 push edx
00402C41 . FF15 54104000 call dword ptr [<&MSVBVM60.__vbaObjSe>; MSVBVM60.__vbaObjSet
00402C47 . 8BF8 mov edi, eax
00402C49 . 8D4D A4 lea ecx, dword ptr [ebp-5C]
00402C4C . 51 push ecx
00402C4D . 57 push edi
00402C4E . 8B07 mov eax, dword ptr [edi]
00402C50 . FF90 A0000000 call dword ptr [eax+A0]
00402C56 . 3BC3 cmp eax, ebx
00402C58 . DBE2 fclex
00402C5A . 7D 12 jge short 00402C6E
00402C5C . 68 A0000000 push 0A0
00402C61 . 68 10264000 push 00402610
00402C66 . 57 push edi
00402C67 . 50 push eax
00402C68 . FF15 44104000 call dword ptr [<&MSVBVM60.__vbaHresu>; MSVBVM60.__vbaHresultCheckObj
00402C6E > 8B45 A4 mov eax, dword ptr [ebp-5C]
00402C71 . 8D95 6CFFFFFF lea edx, dword ptr [ebp-94]
00402C77 . 8985 74FFFFFF mov dword ptr [ebp-8C], eax
00402C7D . 8D85 5CFFFFFF lea eax, dword ptr [ebp-A4]
00402C83 . 52 push edx
00402C84 . 50 push eax
00402C85 . 895D A4 mov dword ptr [ebp-5C], ebx
00402C88 . C785 6CFFFFFF>mov dword ptr [ebp-94], 8
00402C92 . FF15 64104000 call dword ptr [<&MSVBVM60.#520>] ; MSVBVM60.rtcTrimVar
00402C98 . 8D8D 7CFFFFFF lea ecx, dword ptr [ebp-84]
00402C9E . 8D95 5CFFFFFF lea edx, dword ptr [ebp-A4]
00402CA4 . 51 push ecx
00402CA5 . 52 push edx ; //比较注册码
00402CA6 . FF15 88104000 call dword ptr [<&MSVBVM60.__vbaVarTs>; MSVBVM60.__vbaVarTstEq
00402CAC . 8D4D A8 lea ecx, dword ptr [ebp-58]
00402CAF . 8BF8 mov edi, eax
00402CB1 . FF15 20114000 call dword ptr [<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStr
00402CB7 . 8D45 9C lea eax, dword ptr [ebp-64]
00402CBA . 8D4D A0 lea ecx, dword ptr [ebp-60]
00402CBD . 50 push eax
00402CBE . 51 push ecx
00402CBF . 6A 02 push 2
00402CC1 . FF15 30104000 call dword ptr [<&MSVBVM60.__vbaFreeO>; MSVBVM60.__vbaFreeObjList
00402CC7 . 8D95 5CFFFFFF lea edx, dword ptr [ebp-A4]
00402CCD . 8D85 7CFFFFFF lea eax, dword ptr [ebp-84]
00402CD3 . 52 push edx
00402CD4 . 8D8D 6CFFFFFF lea ecx, dword ptr [ebp-94]
00402CDA . 50 push eax
00402CDB . 8D55 8C lea edx, dword ptr [ebp-74]
00402CDE . 51 push ecx
00402CDF . 52 push edx
00402CE0 . 6A 04 push 4
00402CE2 . FF15 20104000 call dword ptr [<&MSVBVM60.__vbaFreeV>; MSVBVM60.__vbaFreeVarList
00402CE8 . 83C4 20 add esp, 20
00402CEB . 66:3BFB cmp di, bx
00402CEE . 0F84 5A080000 je 0040354E ; //注册码不正确就跳走
原来是将机器码转成了浮点数进行运算,将机器码的数值乘以321,再加上1234567890,取前十位,即为注册码。我一开始输的假码也是1234567890,差点以为它拿假码起来运算了。
但是注册完了之后,控件如何知道已注册呢?看函数输入的时候没有看到注册表操作,目录下也没有什么文件生成。
输入正确注册码,输入后继续往下走。
00402D78 > \8B55 A8 mov edx, dword ptr [ebp-58]
00402D7B . 8D7E 34 lea edi, dword ptr [esi+34]
00402D7E . 52 push edx
00402D7F . 68 9C264000 push 0040269C ; UNICODE "\SuperPrint.ocx"
00402D84 . FF15 3C104000 call dword ptr [<&MSVBVM60.__vbaStrCa>; MSVBVM60.__vbaStrCat
00402D8A . 8BD0 mov edx, eax
00402D8C . 8D4D A4 lea ecx, dword ptr [ebp-5C]
00402D8F . FF15 10114000 call dword ptr [<&MSVBVM60.__vbaStrMo>; MSVBVM60.__vbaStrMove
00402D95 . 8BD0 mov edx, eax
00402D97 . 8BCF mov ecx, edi
00402D99 . FF15 E8104000 call dword ptr [<&MSVBVM60.__vbaStrCo>; MSVBVM60.__vbaStrCopy
00402D9F . 8D45 A4 lea eax, dword ptr [ebp-5C] ; //这一段就是app.path & "\SuperPrint.ocx"
00402DA2 . 8D4D A8 lea ecx, dword ptr [ebp-58]
00402DA5 . 50 push eax
00402DA6 . 51 push ecx
00402DA7 . 6A 02 push 2
00402DA9 . FF15 EC104000 call dword ptr [<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStrList
00402DAF . 8B1D 24114000 mov ebx, dword ptr [<&MSVBVM60.__vba>; MSVBVM60.__vbaFreeObj
00402DB5 . 83C4 0C add esp, 0C
00402DB8 . 8D4D A0 lea ecx, dword ptr [ebp-60]
00402DBB . FFD3 call ebx ; <&MSVBVM60.__vbaFreeObj>
00402DBD . 8B17 mov edx, dword ptr [edi]
00402DBF . 52 push edx
00402DC0 . 6A 01 push 1
00402DC2 . 6A FF push -1
00402DC4 . 6A 20 push 20
00402DC6 . FF15 D4104000 call dword ptr [<&MSVBVM60.__vbaFileO>; MSVBVM60.__vbaFileOpen
00402DCC . 8B06 mov eax, dword ptr [esi] ; //打开文件,准备写入
00402DCE . 56 push esi
00402DCF . FF90 00030000 call dword ptr [eax+300]
00402DD5 . 8D4D A0 lea ecx, dword ptr [ebp-60]
00402DD8 . 50 push eax
00402DD9 . 51 push ecx
00402DDA . FF15 54104000 call dword ptr [<&MSVBVM60.__vbaObjSe>; MSVBVM60.__vbaObjSet
00402DE0 . 8BF8 mov edi, eax
00402DE2 . 8D45 A8 lea eax, dword ptr [ebp-58]
00402DE5 . 50 push eax
00402DE6 . 57 push edi
00402DE7 . 8B17 mov edx, dword ptr [edi]
00402DE9 . FF92 A0000000 call dword ptr [edx+A0]
00402DEF . 85C0 test eax, eax
00402DF1 . DBE2 fclex
00402DF3 . 7D 12 jge short 00402E07
00402DF5 . 68 A0000000 push 0A0
00402DFA . 68 10264000 push 00402610
00402DFF . 57 push edi
00402E00 . 50 push eax
00402E01 . FF15 44104000 call dword ptr [<&MSVBVM60.__vbaHresu>; MSVBVM60.__vbaHresultCheckObj
00402E07 > 8B4D A8 mov ecx, dword ptr [ebp-58]
00402E0A . 51 push ecx
00402E0B . FF15 1C104000 call dword ptr [<&MSVBVM60.__vbaLenBs>; MSVBVM60.__vbaLenBstr
00402E11 . 8BC8 mov ecx, eax
00402E13 . FF15 8C104000 call dword ptr [<&MSVBVM60.__vbaI2I4>>; MSVBVM60.__vbaI2I4
00402E19 . 8D4D A8 lea ecx, dword ptr [ebp-58]
00402E1C . 8985 E4FEFFFF mov dword ptr [ebp-11C], eax
00402E22 . 66:C746 46 01>mov word ptr [esi+46], 1
00402E28 . FF15 20114000 call dword ptr [<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStr
00402E2E . 8D4D A0 lea ecx, dword ptr [ebp-60]
00402E31 . FFD3 call ebx
00402E33 > 66:8B95 E4FEF>mov dx, word ptr [ebp-11C]
00402E3A . 8B06 mov eax, dword ptr [esi]
00402E3C . 66:3956 46 cmp word ptr [esi+46], dx ; //判断是否转换完成
00402E40 . 56 push esi
00402E41 . 0F8F F5000000 jg 00402F3C ; //跳走
00402E47 . FF90 00030000 call dword ptr [eax+300]
00402E4D . 8D4D A0 lea ecx, dword ptr [ebp-60]
00402E50 . 50 push eax
00402E51 . 51 push ecx
00402E52 . FF15 54104000 call dword ptr [<&MSVBVM60.__vbaObjSe>; MSVBVM60.__vbaObjSet
00402E58 . 8BF8 mov edi, eax
00402E5A . 8D45 A8 lea eax, dword ptr [ebp-58]
00402E5D . 50 push eax
00402E5E . 57 push edi
00402E5F . 8B17 mov edx, dword ptr [edi]
00402E61 . FF92 A0000000 call dword ptr [edx+A0]
00402E67 . 85C0 test eax, eax
00402E69 . DBE2 fclex
00402E6B . 7D 12 jge short 00402E7F
00402E6D . 68 A0000000 push 0A0
00402E72 . 68 10264000 push 00402610
00402E77 . 57 push edi
00402E78 . 50 push eax
00402E79 . FF15 44104000 call dword ptr [<&MSVBVM60.__vbaHresu>; MSVBVM60.__vbaHresultCheckObj
00402E7F > 8B45 A8 mov eax, dword ptr [ebp-58] ; //EAX指向UNICODE的注册码
00402E82 . 8D8D 7CFFFFFF lea ecx, dword ptr [ebp-84]
00402E88 . 0FBF56 46 movsx edx, word ptr [esi+46]
00402E8C . 8945 94 mov dword ptr [ebp-6C], eax
00402E8F . 51 push ecx
00402E90 . 8D45 8C lea eax, dword ptr [ebp-74]
00402E93 . 52 push edx ; //第几位
00402E94 . 8D8D 6CFFFFFF lea ecx, dword ptr [ebp-94]
00402E9A . 50 push eax
00402E9B . 51 push ecx
00402E9C . C745 84 01000>mov dword ptr [ebp-7C], 1
00402EA3 . C785 7CFFFFFF>mov dword ptr [ebp-84], 2
00402EAD . C745 A8 00000>mov dword ptr [ebp-58], 0
00402EB4 . C745 8C 08000>mov dword ptr [ebp-74], 8
00402EBB . FF15 6C104000 call dword ptr [<&MSVBVM60.#632>] ; MSVBVM60.rtcMidCharVar
00402EC1 . 0FBF7E 46 movsx edi, word ptr [esi+46] ; //取其中一位字符
00402EC5 . 83FF 15 cmp edi, 15
00402EC8 . 72 06 jb short 00402ED0
00402ECA . FF15 7C104000 call dword ptr [<&MSVBVM60.__vbaGener>; MSVBVM60.__vbaGenerateBoundsError
00402ED0 > 8D95 6CFFFFFF lea edx, dword ptr [ebp-94]
00402ED6 . 8D45 A4 lea eax, dword ptr [ebp-5C]
00402ED9 . 52 push edx
00402EDA . 50 push eax
00402EDB . FF15 C4104000 call dword ptr [<&MSVBVM60.__vbaStrVa>; MSVBVM60.__vbaStrVarVal
00402EE1 . 50 push eax ; //转换成数字
00402EE2 . FF15 34104000 call dword ptr [<&MSVBVM60.#516>] ; MSVBVM60.rtcAnsiValueBstr
00402EE8 . 8BC8 mov ecx, eax ; //转成ANSI的字符
00402EEA . FF15 9C104000 call dword ptr [<&MSVBVM60.__vbaUI1I2>; MSVBVM60.__vbaUI1I2
00402EF0 . 8B4D D0 mov ecx, dword ptr [ebp-30]
00402EF3 . 880439 mov byte ptr [ecx+edi], al ; //转换后的字符存入
00402EF6 . 8D4D A4 lea ecx, dword ptr [ebp-5C]
00402EF9 . FF15 20114000 call dword ptr [<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStr
00402EFF . 8D4D A0 lea ecx, dword ptr [ebp-60]
00402F02 . FFD3 call ebx
00402F04 . 8D95 6CFFFFFF lea edx, dword ptr [ebp-94]
00402F0A . 8D85 7CFFFFFF lea eax, dword ptr [ebp-84]
00402F10 . 52 push edx
00402F11 . 8D4D 8C lea ecx, dword ptr [ebp-74]
00402F14 . 50 push eax
00402F15 . 51 push ecx
00402F16 . 6A 03 push 3
00402F18 . FF15 20104000 call dword ptr [<&MSVBVM60.__vbaFreeV>; MSVBVM60.__vbaFreeVarList
00402F1E . 66:8B56 46 mov dx, word ptr [esi+46]
00402F22 . B8 01000000 mov eax, 1
00402F27 . 83C4 10 add esp, 10
00402F2A . 66:03D0 add dx, ax
00402F2D . 0F80 12080000 jo 00403745
00402F33 . 66:8956 46 mov word ptr [esi+46], dx
00402F37 .^ E9 F7FEFFFF jmp 00402E33
原来是写进控件里了,继续往下跟
00403012 > /66:8B46 46 mov ax, word ptr [esi+46]
00403016 . |B9 14000000 mov ecx, 14 ; //ANSI格式注册码 & 空格,达到20位了吗
0040301B . |66:3BC1 cmp ax, cx
0040301E . |7F 3A jg short 0040305A ; //跳走进入写入文件过程
00403020 . |0FBFF8 movsx edi, ax
00403023 . |83FF 15 cmp edi, 15
00403026 . |72 06 jb short 0040302E
00403028 . |FF15 7C104000 call dword ptr [<&MSVBVM60.__vbaGener>; MSVBVM60.__vbaGenerateBoundsError
0040302E > |68 C0264000 push 004026C0
00403033 . |FF15 34104000 call dword ptr [<&MSVBVM60.#516>] ; MSVBVM60.rtcAnsiValueBstr
00403039 . |8BC8 mov ecx, eax ; //eax=0x20,即空格
0040303B . |FF15 9C104000 call dword ptr [<&MSVBVM60.__vbaUI1I2>; MSVBVM60.__vbaUI1I2
00403041 . |8B55 D0 mov edx, dword ptr [ebp-30] ; //合并字符
00403044 . |88043A mov byte ptr [edx+edi], al
00403047 . |66:8B46 46 mov ax, word ptr [esi+46]
0040304B . |66:03C3 add ax, bx
0040304E . |0F80 F1060000 jo 00403745
00403054 . |66:8946 46 mov word ptr [esi+46], ax
00403058 .^\EB B8 jmp short 00403012
原来是将运算后的注册码,用空格补齐20位
0040305A > 66:C746 46 01>mov word ptr [esi+46], 1
00403060 > B8 14000000 mov eax, 14 ; //len(注册码10位+10个空格)=0x14
00403065 . 66:3946 46 cmp word ptr [esi+46], ax
00403069 . 0F8F AD000000 jg 0040311C ; //写完了就接下去写机器码+空格
0040306F . 8B3D 00104000 mov edi, dword ptr [<&MSVBVM60.__vba>; MSVBVM60.__vbaVarSub
00403075 . 8D4D AC lea ecx, dword ptr [ebp-54]
00403078 . 8D95 3CFFFFFF lea edx, dword ptr [ebp-C4]
0040307E . 51 push ecx
0040307F . 8D45 8C lea eax, dword ptr [ebp-74]
00403082 . 52 push edx
00403083 . 50 push eax
00403084 . C785 44FFFFFF>mov dword ptr [ebp-BC], 1
0040308E . C785 3CFFFFFF>mov dword ptr [ebp-C4], 2
00403098 . FFD7 call edi ; <&MSVBVM60.__vbaVarSub>
0040309A . 8B1D 10104000 mov ebx, dword ptr [<&MSVBVM60.__vba>; MSVBVM60.__vbaVarMove
004030A0 . 8BD0 mov edx, eax
004030A2 . 8D4D AC lea ecx, dword ptr [ebp-54]
004030A5 . FFD3 call ebx ; <&MSVBVM60.__vbaVarMove>
004030A7 . 6A 01 push 1
004030A9 . FF15 DC104000 call dword ptr [<&MSVBVM60.#570>] ; MSVBVM60.rtcFileLength
004030AF . 8D8D 3CFFFFFF lea ecx, dword ptr [ebp-C4]
004030B5 . 8985 44FFFFFF mov dword ptr [ebp-BC], eax
004030BB . 8D55 AC lea edx, dword ptr [ebp-54]
004030BE . 51 push ecx
004030BF . 8D45 8C lea eax, dword ptr [ebp-74]
004030C2 . 52 push edx
004030C3 . 50 push eax
004030C4 . C785 3CFFFFFF>mov dword ptr [ebp-C4], 3
004030CE . FFD7 call edi
004030D0 . 8BD0 mov edx, eax
004030D2 . 8D4D DC lea ecx, dword ptr [ebp-24]
004030D5 . FFD3 call ebx
004030D7 . 0FBF7E 46 movsx edi, word ptr [esi+46]
004030DB . 83FF 15 cmp edi, 15
004030DE . 72 06 jb short 004030E6
004030E0 . FF15 7C104000 call dword ptr [<&MSVBVM60.__vbaGener>; MSVBVM60.__vbaGenerateBoundsError
004030E6 > 8D4D DC lea ecx, dword ptr [ebp-24]
004030E9 . 6A 01 push 1
004030EB . 51 push ecx
004030EC . FF15 FC104000 call dword ptr [<&MSVBVM60.__vbaI4Var>; MSVBVM60.__vbaI4Var
004030F2 . 8B55 D0 mov edx, dword ptr [ebp-30] ; //指向注册码&空格前一位
004030F5 . 50 push eax ; //EAX=文件偏移位置
004030F6 . 03D7 add edx, edi ; //edi从1到20
004030F8 . 52 push edx ; //edx指向注册码的第N位
004030F9 . 6A 01 push 1 ; //每次Put一位
004030FB . FF15 2C104000 call dword ptr [<&MSVBVM60.__vbaPut4>>; MSVBVM60.__vbaPut4
00403101 . 66:8B4E 46 mov cx, word ptr [esi+46]
00403105 . B8 01000000 mov eax, 1
0040310A . 66:03C8 add cx, ax
0040310D . 0F80 32060000 jo 00403745
00403113 . 66:894E 46 mov word ptr [esi+46], cx
00403117 .^ E9 44FFFFFF jmp 00403060
后面还有一段是写机器码&空格的,略。
总结一下
注册码为机器码*321+1234567890再取前十位。程序计算完注册码之后,若注册正确,则将机器码和注册码写进SuperPrint.ocx尾部,机器码从EEFC4开始,后面接空格补齐20位,再接注册码,再接空格补齐20位。ocx加载的时候从自身读取保存的机器码和注册码进行比较。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2009年07月13日 22:51:49
赞赏
- 这个……主页有个错别字 3169
- [原创]VB6打印控件SuperPrint的注册分析 6329
- [求助]VB模拟拖放文件操作到一个别的程序,遇到一点问题 4127
- [原创]解决进退魔兽争霸3中文名乱码问题 30044