软件名称: 专业名片、卡片、胸牌制作系统CardMaker
最新版本: 3.3
适用平台: Win9x, WinME, WinNT, Win2000, WinXP
软件作者: 方丽
作者主页: http://www.flisoft.net
主要功能:
专业名片、卡片、胸牌制作系统CardMaker,内置超大图形库(近百种,包括基本线条、基本形状、箭头总汇、流程图、星与旗帜、标注等
)、超大图像库(近百种,包括各类背景、各类线条等,并还在不断扩充),具有强大的图形处理能力、强大的图像处理能力、强大的文字处
理能力,对各类要素都提供了丰富的要素渲染方案,系统提供了完善的数据库功能,完全解决了编辑一张卡片打印不同姓名、不同职位、不
同...的任意多张卡片这一卡片系统业的长期困扰。使用本系统你可以打印名片、各类卡片、各类胸牌、餐票,可以一次性打印出你单位所有人
的出入证、胸牌而不需你再手工添上他们的姓名、职位,可以一次性打印出给你所有朋友或客户的信封标贴,可以打印出超级专业、优美无比
的各类名片。
【软件限制】:10天后功能限制
【难 度】: 爆破简单,算法稍繁
【作者声明】:初学Crack,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教!
【破解工具】:olldydbg、IDA Pro
—————————————————————————————————
【过 程】:
首先 Peid测无壳,VC程序,就是个头有些大,2兆多,IDA跑了好一会,才反汇编完。
首先注意到未注册标题栏有'[Not register 0/10]'字样,于是
IDA中查找,找到Not register的其引用之处:
SoftwareMicrosoftWindowsCurrentVersion下RdPrintCurrentVersion301项明码,使用了几天就是几,:)
在读写了System32jgldog301.dll此文件,不是dll文件,只是个数据文件。估计也是保存使用信息的,没深究。
....
前面省去读取注册表和jgldog301.dll校验使用时间的代码。
....
.text:0042888B lea edx, [esp+1BCh+FileSystemFlags]
.text:0042888F lea ecx, [esp+1BCh+VolumeSerialNumber]
.text:00428896 push 0Ah ; nFileSystemNameSize
.text:00428898 push eax ; lpFileSystemNameBuffer
.text:00428899 lea eax, [esp+1C4h+MaximumComponentLength]
.text:0042889D push edx ; lpFileSystemFlags
.text:0042889E push eax ; lpMaximumComponentLength
.text:0042889F push ecx ; lpVolumeSerialNumber
.text:004288A0 push 0Ch ; nVolumeNameSize
.text:004288A2 push esi ; lpVolumeNameBuffer
.text:004288A3 push offset aC ; lpRootPathName
.text:004288A8 call ds:GetVolumeInformationA ; 读取C盘的序列号
.text:004288AE mov edx, [esp+1BCh+VolumeSerialNumber]
.text:004288B5 lea eax, [esp+1BCh+var_190]
.text:004288B9 push offset unk_56AD0C ; 内存中一张表,变换C盘序列号时使用
.text:004288BE lea ecx, [esp+1C0h+var_194]
.text:004288C2 push eax
.text:004288C3 push ecx
.text:004288C4 mov [esp+1C8h+var_194], edx ; C盘序列号
.text:004288C8 mov [esp+1C8h+var_190], 19320h ; 种子数
.text:004288D0 call sub_425480 ; <========== *********追算法关键,
.text:004288D5 fild [esp+1C8h+var_194] ; 将变换后结果作为整数压入浮点栈
.text:004288D9 add esp, 0Ch
.text:004288DC fstp qword ptr [esp+1BCh+var_188] ; 变换后结果作为浮点数,弹出浮点栈,留待待会比较
.text:004288E0 call ?AfxGetModuleState@@YGPAVAFX_MODULE_STATE@@XZ ; AfxGetModuleState(void)
.text:004288E5 mov eax, [eax+4]
.text:004288E8 push edi
.text:004288E9 push offset aSerilno ; "SerilNo"
.text:004288EE lea edx, [esp+1C4h+Type]
.text:004288F2 push offset aVSV ; "注册信息"
.text:004288F7 push edx
.text:004288F8 mov ecx, eax
.text:004288FA call sub_508B2B ; 读取保存在注册表中的待验证注册码
HKEY_CURRENT_USERSoftwareFLi'SoftCardMaker注册信息 下 Serial项
.text:004288FF push offset asc_56939C ; "-"
.text:00428904 lea ecx, [esp+1C0h+Type]
.text:00428908 mov [esp+1C0h+var_4], 4
.text:00428913 call sub_4E60A8 ; 注册码中"-"位置
.text:00428918 mov ebp, eax
.text:0042891A test ebp, ebp
.text:0042891C jle loc_428A0D ; 若没有"-",则出错
.text:00428922 lea eax, [esp+1BCh+MaximumComponentLength]
.text:00428926 push ebp
.text:00428927 push eax
.text:00428928 lea ecx, [esp+1C4h+Type]
.text:0042892C mov [esp+1C4h+var_1A8], edi
.text:00428930 call sub_4E5FE3 ; 取注册码中"-"前部分
.text:00428935 mov ecx, [esp+1BCh+MaximumComponentLength]
.text:00428939 mov eax, [ecx-8]
.text:0042893C test eax, eax
.text:0042893E jle short loc_42897D
.text:00428940 lea ecx, [eax+ecx-1]
.text:00428944 mov edx, eax
.text:00428946
.text:00428946 loc_428946: ; CODE XREF: sub_428440+537j
.text:00428946 lea eax, ds:0[edi*8] ; //开始对注册码进行变换,从右至左
.text:0042894D sub eax, edi
.text:0042894F lea edi, [eax+eax*4] ; 以上三句实现功能类似edi = 35d * edi
.text:00428952 mov al, [ecx]
.text:00428954 cmp al, 61h ; 如果ASCII码值大于'a'
.text:00428956 jb short loc_42895C
.text:00428958 sub al, 3Dh
.text:0042895A jmp short loc_428966
.text:0042895C ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:0042895C
.text:0042895C loc_42895C: ; CODE XREF: sub_428440+516j
.text:0042895C cmp al, 41h ; 如果ASCII码值大于'A'
.text:0042895E jb short loc_428964
.text:00428960 sub al, 37h
.text:00428962 jmp short loc_428966
.text:00428964 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00428964
.text:00428964 loc_428964: ; CODE XREF: sub_428440+51Ej
.text:00428964 sub al, 30h
.text:00428966
.text:00428966 loc_428966: ; CODE XREF: sub_428440+51Aj
.text:00428966 ; sub_428440+522j
.text:00428966 mov byte ptr [esp+1BCh+FileSystemFlags], al
.text:0042896A mov eax, [esp+1BCh+FileSystemFlags]
.text:0042896E and eax, 0FFh
.text:00428973 add edi, eax ; edi = edi + eax
.text:00428975 dec ecx
.text:00428976 dec edx
.text:00428977 jnz short loc_428946 ; //循环前一字节对注册码进行变换
.text:00428979 mov [esp+1BCh+var_1A8], edi
.text:0042897D
.text:0042897D loc_42897D: ; CODE XREF: sub_428440+4FEj
.text:0042897D lea ecx, [esp+1BCh+MaximumComponentLength]
.text:00428981 call sub_4EE588
.text:00428986 mov ecx, [esp+1BCh+Type]
.text:0042898A xor esi, esi
.text:0042898C lea edx, [esp+1BCh+cbData]
.text:00428990 mov eax, [ecx-8]
.text:00428993 lea ecx, [esp+1BCh+Type]
.text:00428997 sub eax, ebp
.text:00428999 dec eax
.text:0042899A push eax
.text:0042899B push edx
.text:0042899C call sub_4E5F67 ; 取注册码中"-"后部分,不过好像验证注册码没有用到这里的结果?? 算法于前一部
分类似
.text:004289A1 mov ecx, [esp+1BCh+cbData]
.text:004289A5 mov eax, [ecx-8]
.text:004289A8 test eax, eax
.text:004289AA jle short loc_4289E4
.text:004289AC lea ecx, [eax+ecx-1]
.text:004289B0 mov edx, eax
.text:004289B2
.text:004289B2 loc_4289B2: ; CODE XREF: sub_428440+5A2j
.text:004289B2 mov eax, esi
.text:004289B4 shl eax, 4
.text:004289B7 add eax, esi
.text:004289B9 shl eax, 1
.text:004289BB mov esi, eax
.text:004289BD mov al, [ecx]
.text:004289BF cmp al, 61h
.text:004289C1 jb short loc_4289C7
.text:004289C3 sub al, 3Dh
.text:004289C5 jmp short loc_4289D1
.text:004289C7 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:004289C7
.text:004289C7 loc_4289C7: ; CODE XREF: sub_428440+581j
.text:004289C7 cmp al, 41h
.text:004289C9 jb short loc_4289CF
.text:004289CB sub al, 37h
.text:004289CD jmp short loc_4289D1
.text:004289CF ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:004289CF
.text:004289CF loc_4289CF: ; CODE XREF: sub_428440+589j
.text:004289CF sub al, 30h
.text:004289D1
.text:004289D1 loc_4289D1: ; CODE XREF: sub_428440+585j
.text:004289D1 ; sub_428440+58Dj
.text:004289D1 mov byte ptr [esp+1BCh+FileSystemFlags], al
.text:004289D5 mov eax, [esp+1BCh+FileSystemFlags]
.text:004289D9 and eax, 0FFh
.text:004289DE add esi, eax
.text:004289E0 dec ecx
.text:004289E1 dec edx
.text:004289E2 jnz short loc_4289B2
.text:004289E4
.text:004289E4 loc_4289E4: ; CODE XREF: sub_428440+56Aj
.text:004289E4 lea ecx, [esp+1BCh+cbData]
.text:004289E8 call sub_4EE588
.text:004289ED fild [esp+1BCh+var_1A8] ; 将注册码中"-"前部分变换结果压入浮点栈
.text:004289F1 mov [esp+1BCh+var_194], edi
.text:004289F5 mov [esp+1BCh+var_190], esi
.text:004289F9 fcomp qword ptr [esp+1BCh+var_188] <======== ******* 关键比较, 注册码中"-"前部分变换结果 与
用户c盘序列号变换结果进行比较。
.text:004289FD fnstsw ax
.text:004289FF test ah, 40h
.text:00428A02 jz short loc_428A0B ; 注册码错误则跳,爆破可以修改这里
.text:00428A04 mov edi, 1
.text:00428A09 jmp short loc_428A0D
.text:00428A0B ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00428A0B
.text:00428A0B loc_428A0B: ; CODE XREF: sub_428440+5C2j
.text:00428A0B xor edi, edi
.text:00428A0D
.text:00428A0D loc_428A0D: ; CODE XREF: sub_428440+4DCj
.text:00428A0D ; sub_428440+5C9j
.text:00428A0D lea ecx, [esp+1BCh+Type]
.text:00428A11 mov [esp+1BCh+var_4], ebx
.text:00428A18 call sub_4EE588
.text:00428A1D test edi, edi
.text:00428A1F pop edi
.text:00428A20 pop esi
.text:00428A21 pop ebp
.text:00428A22 pop ebx
.text:00428A23 jz short loc_428A3B
.text:00428A25 mov ecx, [esp+1ACh+var_18C]
.text:00428A29 push offset aPowerfulCardMa ; lpString "Powerful Card Maker 3.3"
.text:00428A2E add ecx, 0ACh
.text:00428A34 call ??4CString@@QAEABV0@PBD@Z ; CString::operator=(char const *)
.text:00428A39 jmp short loc_428A59
.text:00428A3B ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00428A3B
.text:00428A3B loc_428A3B: ; CODE XREF: sub_428440+5E3j
.text:00428A3B mov edx, [esp+1ACh+var_1A4]
.text:00428A3F mov eax, [esp+1ACh+var_18C]
.text:00428A43 push 0Ah
.text:00428A45 push edx
.text:00428A46 add eax, 0ACh
.text:00428A4B push offset aPowerfulCard_0 ; "Powerful Card Maker 3.3[Not register%d/"...
.text:00428A50 push eax
.text:00428A51 call sub_4E642E
.text:00428A56 add esp, 10h
.text:00428A59
.text:00428A59 loc_428A59: ; CODE XREF: sub_428440+5F9j
.text:00428A59 mov ecx, [esp+1ACh+arg_0]
.text:00428A60 mov eax, 1
.text:00428A65 mov dword ptr [ecx+20h], 1CF8000h
.text:00428A6C mov ecx, [esp+1ACh+var_C]
.text:00428A73 mov large fs:0, ecx
.text:00428A7A add esp, 1ACh
.text:00428A80
.text:00428A80 unknown_libname_45:
.text:00428A80 retn 4
.text:00428A80 sub_428440 endp
下面看一下对硬盘序列号的变换:
sub_425480
.text:00425480 push ebx
.text:00425481 mov ebx, [esp+arg_0] ; ebx 高32位 种子数19320h
.text:00425485 push ebp
.text:00425486 mov ebp, [esp+4+arg_8] ; ebp -->56AD0C 内存中表查表
.text:0042548A push esi
.text:0042548B mov esi, [esp+8+arg_4] ; esi 低32位 硬盘序列号
.text:0042548F push edi
.text:00425490 mov edi, offset unk_56ADAC ; 还是内存中的表
.text:00425495
.text:00425495 loc_425495: ; CODE XREF: sub_425480+3Ej
.text:00425495 mov eax, [edi]
.text:00425497 mov ecx, [ebp+eax*4+0]
.text:0042549B mov eax, [ebx]
.text:0042549D add ecx, eax
.text:0042549F push ecx
.text:004254A0 call sub_4253B0 ; 查表做变换,算法见下
.text:004254A5 mov edx, [esi]
.text:004254A7 push esi
.text:004254A8 xor edx, eax
.text:004254AA push ebx
.text:004254AB mov [esi], edx
.text:004254AD call sub_425460 ; 高32位和低32位值调换位置
.text:004254B2 add edi, 4
.text:004254B5 add esp, 0Ch
.text:004254B8 cmp edi, offset aClinecapmenuit ; "CLineCapMenuItem"
.text:004254BE jb short loc_425495 ; 终了位置
.text:004254C0 push esi
.text:004254C1 push ebx
.text:004254C2 call sub_425460
.text:004254C7 add esp, 8
.text:004254CA xor eax, eax
.text:004254CC pop edi
.text:004254CD pop esi
.text:004254CE pop ebp
.text:004254CF pop ebx
.text:004254D0
.text:004254D0 unknown_libname_44:
.text:004254D0 retn
.text:004254D0 sub_425480 endp
.text:004254D0
变换:
函数DWORD sub_4253B0(DWORD)
输入一个DWORD值,进行查表变换,表值如下,因为是单输入单输出函数还算简单
0056ACEC 04 02 00 03 00 02 01 09 07 04 00 01 00 06 01 02 .....
0056ACFC 07 07 5F 5F 01 03 05 09 07 03 00 01 08 09 08 5F __..._
0056AD0C 04 02 00 03 02 04 01 09 07 08 00 05 00 03 03 08 ....
0056AD1C 08 07 5F 5F 01 03 05 09 07 03 00 01 08 09 08 5F __..._
0056AD2C 04 0A 09 02 0D 08 00 0E 06 0B 01 0C 07 0F 05 03 ....
.
0056AD3C 0E 0B 04 0C 06 0D 0F 0A 02 03 08 01 00 07 05 09
.....
0056AD4C 05 08 01 0D 0A 03 04 02 0E 0F 0C 07 06 00 09 0B .....
0056AD5C 07 0D 0A 01 00 08 09 0F 0E 04 06 0C 0B 02 05 03 .....
0056AD6C 06 0C 07 01 05 0F 0D 08 04 0A 09 0E 00 03 0B 02 .....
0056AD7C 04 0B 0A 00 07 02 01 0D 03 06 08 05 09 0C 0F 0E
.....
0056AD8C 0D 0B 04 01 03 0F 05 09 00 0A 0E 07 06 08 02 0C .
....
0056AD9C 01 0F 0D 00 05 07 0A 04 09 02 03 0E 06 0B 08 0C ....
.
0056ADAC 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 .............
0056ADBC 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 ............
0056ADCC 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 .............
0056ADDC 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 ............
0056ADEC 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 .............
0056ADFC 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 ............
0056AE0C 07 00 00 00 06 00 00 00 05 00 00 00 04 00 00 00 ............
0056AE1C 03 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 .............
0056AE2C 43 4C 69 6E 65 43 61 70 4D 65 6E 75 49 74 65 6D CLineCapMenuItem
.text:004253B0 sub_4253B0 proc near ; CODE XREF: sub_425480+20p
.text:004253B0
.text:004253B0 arg_0 = dword ptr 4
.text:004253B0
.text:004253B0 mov eax, [esp+arg_0]
.text:004253B4 xor edx, edx
.text:004253B6 mov ecx, eax
.text:004253B8 push ebx
.text:004253B9 shr ecx, 18h ; 高8位
.text:004253BC and ecx, 0Fh ; 24 --- 28位
.text:004253BF xor ebx, ebx
.text:004253C1 mov dl, byte_56AD8C[ecx] ; 查表
.text:004253C7 mov ecx, edx
.text:004253C9 mov edx, eax
.text:004253CB shr edx, 1Ch ; 29 --- 32位
.text:004253CE mov bl, byte_56AD9C[edx]
.text:004253D4 mov edx, eax
.text:004253D6 shl ebx, 4
.text:004253D9 shr edx, 14h
.text:004253DC or ecx, ebx
.text:004253DE and edx, 0Fh
.text:004253E1 xor ebx, ebx
.text:004253E3 mov bl, byte_56AD7C[edx]
.text:004253E9 mov edx, eax
.text:004253EB shl ecx, 4
.text:004253EE shr edx, 10h
.text:004253F1 or ecx, ebx
.text:004253F3 and edx, 0Fh
.text:004253F6 xor ebx, ebx
.text:004253F8 mov bl, byte_56AD6C[edx]
.text:004253FE mov edx, eax
.text:00425400 shl ecx, 4
.text:00425403 shr edx, 0Ch
.text:00425406 or ecx, ebx
.text:00425408 and edx, 0Fh
.text:0042540B xor ebx, ebx
.text:0042540D mov bl, byte_56AD5C[edx]
.text:00425413 mov edx, eax
.text:00425415 shl ecx, 4
.text:00425418 shr edx, 8
.text:0042541B or ecx, ebx
.text:0042541D and edx, 0Fh
.text:00425420 xor ebx, ebx
.text:00425422 mov bl, byte_56AD4C[edx]
.text:00425428 mov edx, eax
.text:0042542A shl ecx, 4
.text:0042542D shr edx, 4
.text:00425430 or ecx, ebx
.text:00425432 and edx, 0Fh
.text:00425435 xor ebx, ebx
.text:00425437 and eax, 0Fh
.text:0042543A mov bl, byte_56AD3C[edx]
.text:00425440 xor edx, edx
.text:00425442 mov dl, byte_56AD2C[eax]
.text:00425448 shl ecx, 4
.text:0042544B or ecx, ebx
.text:0042544D pop ebx
.text:0042544E shl ecx, 4
.text:00425451 or ecx, edx
.text:00425453 mov eax, ecx
.text:00425455 shr eax, 15h
.text:00425458 shl ecx, 0Bh
.text:0042545B or eax, ecx
.text:0042545D retn
.text:0042545D sub_4253B0 endp
发现这里缺乏将硬盘序列号转换为显示在注册对话框中的软件号software Serial中的函数,在PE Explore中查看找注册对话框窗口ID号为1024
即 418h,于是在IDA中查找立即数0x418h即可找到这里:0041AA18
通过查找注册窗口ID 1024 即 418h,即可找到这里:0041AA18
.text:0041AA0F push 418h
.text:0041AA14 mov [esp+20h+var_10], esi
.text:0041AA18 call ??0CDialog@@QAE@IPAVCWnd@@@Z ; CDialog::CDialog(uint,CWnd *)
查看其Cross Reference找到这里
...
.text:00428D9D call ds:GetVolumeInformationA
.text:00428DA3 mov ecx, [esp+1Ch]
.text:00428DA7 lea edx, [esp+14h]
.text:00428DAB push offset unk_56ACEC
.text:00428DB0 lea eax, [esp+14h]
.text:00428DB4 push edx
.text:00428DB5 push eax
.text:00428DB6 mov [esp+1Ch], ecx
.text:00428DBA mov dword ptr [esp+20h], 19320h
.text:00428DC2 call sub_425480
.text:00428DC7 mov eax, [esp+1Ch]
.text:00428DCB add esp, 0Ch
.text:00428DCE test eax, eax
.text:00428DD0 pop esi
.text:00428DD1 jbe short loc_428E20
.text:00428DD3
.text:00428DD3 loc_428DD3: ; CODE XREF: .text:00428E1Ej
.text:00428DD3 xor edx, edx
.text:00428DD5 mov ecx, 23h
.text:00428DDA div ecx
.text:00428DDC cmp edx, 0Ah
.text:00428DDF jl short loc_428DEF
.text:00428DE1 add dl, 37h
.text:00428DE4 mov [esp+14h], dl
.text:00428DE8 mov edx, [esp+14h]
.text:00428DEC push edx
.text:00428DED jmp short loc_428DFB
.text:00428DEF ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00428DEF
.text:00428DEF loc_428DEF: ; CODE XREF: .text:00428DDFj
.text:00428DEF add dl, 30h
.text:00428DF2 mov [esp+4], dl
.text:00428DF6 mov eax, [esp+4]
.text:00428DFA push eax
.text:00428DFB
.text:00428DFB loc_428DFB: ; CODE XREF: .text:00428DEDj
.text:00428DFB lea ecx, [esp+4]
.text:00428DFF call sub_4EE98B
.text:00428E04 mov ecx, [esp+0Ch]
.text:00428E08 mov eax, 0D41D41D5h
.text:00428E0D mul ecx
.text:00428E0F sub ecx, edx
.text:00428E11 shr ecx, 1
.text:00428E13 add ecx, edx
.text:00428E15 shr ecx, 5
.text:00428E18 mov eax, ecx
.text:00428E1A mov [esp+0Ch], eax
.text:00428E1E jnz short loc_428DD3 ; 前半截机器码
.text:00428E20
.text:00428E20 loc_428E20: ; CODE XREF: .text:00428DD1j
.text:00428E20 push offset asc_56939C ; "-"
.text:00428E25 lea ecx, [esp+4]
.text:00428E29 call sub_4EE964 ; 前半截机器码 + "-"
.text:00428E2E mov ecx, off_56B748
.text:00428E34 mov [esp+8], ecx
.text:00428E38 mov eax, [esp+10h]
.text:00428E3C mov byte ptr [esp+2ECh], 1
.text:00428E44 test eax, eax
.text:00428E46 jbe short loc_428E8D
.text:00428E48
.text:00428E48 loc_428E48: ; CODE XREF: .text:00428E8Bj
.text:00428E48 xor edx, edx
.text:00428E4A mov ecx, 22h
.text:00428E4F div ecx
.text:00428E51 cmp edx, 0Ah
.text:00428E54 jl short loc_428E64
.text:00428E56 add dl, 37h
.text:00428E59 mov [esp+4], dl
.text:00428E5D mov edx, [esp+4]
.text:00428E61 push edx
.text:00428E62 jmp short loc_428E70
.text:00428E64 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00428E64
.text:00428E64 loc_428E64: ; CODE XREF: .text:00428E54j
.text:00428E64 add dl, 30h
.text:00428E67 mov [esp+14h], dl
.text:00428E6B mov eax, [esp+14h]
.text:00428E6F push eax
.text:00428E70
.text:00428E70 loc_428E70: ; CODE XREF: .text:00428E62j
.text:00428E70 lea ecx, [esp+0Ch]
.text:00428E74 call sub_4EE98B
.text:00428E79 mov eax, 0F0F0F0F1h
.text:00428E7E mul dword ptr [esp+10h]
.text:00428E82 mov eax, edx
.text:00428E84 shr eax, 5
.text:00428E87 mov [esp+10h], eax
.text:00428E8B jnz short loc_428E48 ; 后半截机器码
.text:00428E8D
.text:00428E8D loc_428E8D: ; CODE XREF: .text:00428E46j
.text:00428E8D lea ecx, [esp+8]
.text:00428E91 push ecx
.text:00428E92 lea ecx, [esp+4] ; 合成最终机器码
.text:00428E96 call ??YCString@@QAEABV0@ABV0@@Z ; CString::operator+=(CString const &)
.text:00428E9B push 0
.text:00428E9D lea ecx, [esp+28h]
.text:00428EA1 call sub_41A9F0 ; 显示注册窗口
这里的变换和前面的变换类似,只是内存表不同,逆向起来有些繁,于是直接根据前面比较注册码过程,注册机直接调用
GetVolumeInformationA 来取硬盘序列号。
这个软件好像没有用注册标志位,每一次都调是用GetVolumeInformationA 获取硬盘序列号来验证,所以可以在IDA中查看
GetVolumeInformationA 的Cross Reference来找到比较之处
.text:004289F9 fcomp qword ptr [esp+1BCh+var_188] <======== ******* 关键比较, 注册码中"-"前部分变换结果 与
用户c盘序列号变换结果进行比较。
.text:004289FD fnstsw ax
.text:004289FF test ah, 40h
.text:00428A02 jz short loc_428A0B ; 注册码错误则跳,爆破可以类似修改这里
软件算法:
注册码形如xxxxxx-xxxxx, 注册码比较计算只用了"-"前部分,所以"-"后随便输
硬盘序列号的变换及基本上是查表
用户注册码的变换是算法类似从右至左
X(n) = 35*X(n-1) + Y
Y为此次值
附注册机:(写注册机.花了我半天时间,看来还是爆破容易阿,:))
vc6.0下编译通过,使用时调用GetRegisterCode()即可,
// 从0056AD0C开始的内存表,由HEX WorkShop生成
unsigned char rawData[308] =
{
0x04, 0x02, 0x00, 0x03, 0x02, 0x04, 0x01, 0x09, 0x07, 0x08, 0x00, 0x05, 0x00, 0x03, 0x03, 0x08,
0x08, 0x07, 0x5F, 0x5F, 0x01, 0x03, 0x05, 0x09, 0x07, 0x03, 0x00, 0x01, 0x08, 0x09, 0x08, 0x5F,
0x04, 0x0A, 0x09, 0x02, 0x0D, 0x08, 0x00, 0x0E, 0x06, 0x0B, 0x01, 0x0C, 0x07, 0x0F, 0x05, 0x03,
0x0E, 0x0B, 0x04, 0x0C, 0x06, 0x0D, 0x0F, 0x0A, 0x02, 0x03, 0x08, 0x01, 0x00, 0x07, 0x05, 0x09,
0x05, 0x08, 0x01, 0x0D, 0x0A, 0x03, 0x04, 0x02, 0x0E, 0x0F, 0x0C, 0x07, 0x06, 0x00, 0x09, 0x0B,
0x07, 0x0D, 0x0A, 0x01, 0x00, 0x08, 0x09, 0x0F, 0x0E, 0x04, 0x06, 0x0C, 0x0B, 0x02, 0x05, 0x03,
0x06, 0x0C, 0x07, 0x01, 0x05, 0x0F, 0x0D, 0x08, 0x04, 0x0A, 0x09, 0x0E, 0x00, 0x03, 0x0B, 0x02,
0x04, 0x0B, 0x0A, 0x00, 0x07, 0x02, 0x01, 0x0D, 0x03, 0x06, 0x08, 0x05, 0x09, 0x0C, 0x0F, 0x0E,
0x0D, 0x0B, 0x04, 0x01, 0x03, 0x0F, 0x05, 0x09, 0x00, 0x0A, 0x0E, 0x07, 0x06, 0x08, 0x02, 0x0C,
0x01, 0x0F, 0x0D, 0x00, 0x05, 0x07, 0x0A, 0x04, 0x09, 0x02, 0x03, 0x0E, 0x06, 0x0B, 0x08, 0x0C,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x43, 0x4C, 0x69, 0x6E, 0x65, 0x43, 0x61, 0x70, 0x4D, 0x65, 0x6E, 0x75, 0x49, 0x74, 0x65, 0x6D,
0x00, 0x00, 0x00, 0x00,
} ;
char bb[50]; //全局变量,保存软件找到的注册码
// 因为软件码(software serial)变换, 只是内存表不太一样同,逆向起来有些繁,
// 于是直接根据前面比较注册码过程,注册机直接调用,不过必须在本机上运行 :)
DWORD APIENTRY GetDiskSerialNo(void)
{
LPCTSTR lpRootPathName="c:\"; //取C盘的序列号
LPTSTR lpVolumeNameBuffer=new char[12];//磁盘卷标
DWORD nVolumeNameSize=12;
DWORD VolumeSerialNumber;//磁盘序列号
DWORD MaximumComponentLength;
LPTSTR lpFileSystemNameBuffer=new char[10];
DWORD nFileSystemNameSize=10;
DWORD FileSystemFlags;
GetVolumeInformation(lpRootPathName,
lpVolumeNameBuffer, nVolumeNameSize,
&VolumeSerialNumber, &MaximumComponentLength,
&FileSystemFlags,
lpFileSystemNameBuffer, nFileSystemNameSize);
return VolumeSerialNumber;
}
DWORD Encrypt1(DWORD dwSource)
{
DWORD dwResult=0;
DWORD dwTemp = 0;
// 查表变换,直接从IDA中拷贝出来,稍微修改一下就可以了,偷点懒
_asm
{
MOV EAX, dwSource
XOR EDX, EDX
MOV ECX, EAX
PUSH EBX
SHR ECX, 18h
AND ECX, 0Fh
XOR EBX, EBX
MOV DL, BYTE PTR rawData[ECX+80h] ; DS:[ECX+56AD8C]
MOV ECX, EDX
MOV EDX, EAX
SHR EDX, 1Ch
MOV BL, BYTE PTR rawData[EDX+90h]
MOV EDX, EAX
SHL EBX, 4
SHR EDX, 14h
OR ECX, EBX
AND EDX, 0Fh
XOR EBX, EBX
MOV BL, BYTE PTR rawData[EDX+70h]
MOV EDX, EAX
SHL ECX, 4
SHR EDX, 10h
OR ECX, EBX
AND EDX, 0Fh
XOR EBX, EBX
MOV BL, BYTE PTR rawData[EDX+60h]
MOV EDX, EAX
SHL ECX, 4
SHR EDX, 0Ch
OR ECX, EBX
AND EDX, 0Fh
XOR EBX, EBX
MOV BL, BYTE PTR rawData[EDX+50h]
MOV EDX, EAX
SHL ECX, 4
SHR EDX, 8
OR ECX, EBX
AND EDX, 0Fh
XOR EBX, EBX
MOV BL, BYTE PTR rawData[EDX+40h]
MOV EDX, EAX
SHL ECX, 4
SHR EDX, 4
OR ECX, EBX
AND EDX, 0Fh
XOR EBX, EBX
AND EAX, 0Fh
MOV BL, BYTE PTR rawData[EDX+30h]
XOR EDX, EDX
MOV DL, BYTE PTR rawData[EAX+20h]
SHL ECX, 4
OR ECX, EBX
POP EBX
SHL ECX, 4
OR ECX, EDX
MOV EAX, ECX
SHR EAX, 15h
SHL ECX, 0Bh
OR EAX, ECX
MOV dwResult, EAX
}
return dwResult;
}
//使用迭代取注册码
//
DWORD Encrypt2(DWORD Xn)
{
DWORD dwYushu = 0;
DWORD Xn1 = 0;
int yushu = 0; // 余数
char c1[2];
Xn1 = Xn/35;
yushu = Xn - Xn1*35;
c1[0]=0;
c1[1]=0;
if(Xn >0)
{
if (yushu==0)
c1[0]='0';
else if(yushu<=9)
c1[0]=yushu+48;
else
c1[0]=yushu+55;
lstrcat(bb,c1);
return Encrypt3(Xn1);
}
else
{
return 0;
}
}
//主函数
void GetRegisterCode()
{
DWORD dwEn1 = GetDiskSerialNo(); //获取硬盘序列号
DWORD dwEn2 = 0x19320; // 种子数
DWORD dwTemp = 0;
DWORD dwTemp2 = 0;
int j = 0;
for(int i = 0;i<0x20;i++)
{
j =rawData[4*i+0x0A0];
int k =4*j;
// 好久没写过程序了,不知道怎么从unsigned char数组中取出DWORD值,只好借助汇编了,呵呵
__asm mov EDX, k
__asm mov EAX, DWORD PTR rawData[EDX]
__asm mov dwTemp, EAX
dwTemp = dwEn1 + dwTemp;
dwTemp2 = dwEn1;
dwTemp = Encrypt1(dwTemp);
dwEn1 = dwEn2^dwTemp;
dwEn2 = dwTemp2;
}
dwTemp = dwEn2;
dwEn2 = dwEn1;
dwEn1 = dwTemp;
// dwEn1保存是硬盘序列号变换后的结果
// 注册码通过往这里凑
::ZeroMemory(bb,sizeof(bb));
Encrypt2(dwEn1); // 获取注册码
char aa[100];
::ZeroMemory(aa,sizeof(aa));
wsprintf(aa,"注册码为:%s - 任意字符串",bb);
MessageBox(0,aa,"Powerful Card Maker 3.2注册机",0);
}
够啰嗦的,不知道说清楚了没有。
最后祝看雪的兄弟们国庆快乐,:)