• 标 题:专业名片、卡片、胸牌制作系统CardMaker 3.3
  • 作 者:yesky1
  • 时 间:2003年10月01日 07:47
  • 链 接:http://bbs.pediy.com

软件名称:   专业名片、卡片、胸牌制作系统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     ecxeax
.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     ebpeax
.text:0042891A                 test    ebpebp
.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    eaxeax
.text:0042893E                 jle     short loc_42897D
.text:00428940                 lea     ecx, [eax+ecx-1]
.text:00428944                 mov     edxeax
.text:00428946 
.text:00428946 loc_428946:                             ; CODE XREF: sub_428440+537j
.text:00428946                 lea     eaxds:0[edi*8]  ; //开始对注册码进行变换,从右至左
.text:0042894D                 sub     eaxedi
.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     edieax        ; 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     esiesi
.text:0042898C                 lea     edx, [esp+1BCh+cbData]
.text:00428990                 mov     eax, [ecx-8]
.text:00428993                 lea     ecx, [esp+1BCh+Type]
.text:00428997                 sub     eaxebp
.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    eaxeax
.text:004289AA                 jle     short loc_4289E4
.text:004289AC                 lea     ecx, [eax+ecx-1]
.text:004289B0                 mov     edxeax
.text:004289B2 
.text:004289B2 loc_4289B2:                             ; CODE XREF: sub_428440+5A2j
.text:004289B2                 mov     eaxesi
.text:004289B4                 shl     eax, 4
.text:004289B7                 add     eaxesi
.text:004289B9                 shl     eax, 1
.text:004289BB                 mov     esieax
.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     esieax
.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     ediedi
.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    ediedi
.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     ecxeax
.text:0042549F                 push    ecx
.text:004254A0                 call    sub_4253B0   ; 查表做变换,算法见下
.text:004254A5                 mov     edx, [esi]
.text:004254A7                 push    esi
.text:004254A8                 xor     edxeax
.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     eaxeax
.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     edxedx
.text:004253B6                 mov     ecxeax
.text:004253B8                 push    ebx
.text:004253B9                 shr     ecx, 18h        ; 高8位
.text:004253BC                 and     ecx, 0Fh        ; 24 --- 28位
.text:004253BF                 xor     ebxebx
.text:004253C1                 mov     dl, byte_56AD8C[ecx] ;  查表
.text:004253C7                 mov     ecxedx
.text:004253C9                 mov     edxeax
.text:004253CB                 shr     edx, 1Ch        ; 29 --- 32位
.text:004253CE                 mov     bl, byte_56AD9C[edx]
.text:004253D4                 mov     edxeax
.text:004253D6                 shl     ebx, 4
.text:004253D9                 shr     edx, 14h
.text:004253DC                 or      ecxebx
.text:004253DE                 and     edx, 0Fh
.text:004253E1                 xor     ebxebx
.text:004253E3                 mov     bl, byte_56AD7C[edx]
.text:004253E9                 mov     edxeax
.text:004253EB                 shl     ecx, 4
.text:004253EE                 shr     edx, 10h
.text:004253F1                 or      ecxebx
.text:004253F3                 and     edx, 0Fh
.text:004253F6                 xor     ebxebx
.text:004253F8                 mov     bl, byte_56AD6C[edx]
.text:004253FE                 mov     edxeax
.text:00425400                 shl     ecx, 4
.text:00425403                 shr     edx, 0Ch
.text:00425406                 or      ecxebx
.text:00425408                 and     edx, 0Fh
.text:0042540B                 xor     ebxebx
.text:0042540D                 mov     bl, byte_56AD5C[edx]
.text:00425413                 mov     edxeax
.text:00425415                 shl     ecx, 4
.text:00425418                 shr     edx, 8
.text:0042541B                 or      ecxebx
.text:0042541D                 and     edx, 0Fh
.text:00425420                 xor     ebxebx
.text:00425422                 mov     bl, byte_56AD4C[edx]
.text:00425428                 mov     edxeax
.text:0042542A                 shl     ecx, 4
.text:0042542D                 shr     edx, 4
.text:00425430                 or      ecxebx
.text:00425432                 and     edx, 0Fh
.text:00425435                 xor     ebxebx
.text:00425437                 and     eax, 0Fh
.text:0042543A                 mov     bl, byte_56AD3C[edx]
.text:00425440                 xor     edxedx
.text:00425442                 mov     dl, byte_56AD2C[eax]
.text:00425448                 shl     ecx, 4
.text:0042544B                 or      ecxebx
.text:0042544D                 pop     ebx
.text:0042544E                 shl     ecx, 4
.text:00425451                 or      ecxedx
.text:00425453                 mov     eaxecx
.text:00425455                 shr     eax, 15h
.text:00425458                 shl     ecx, 0Bh
.text:0042545B                 or      eaxecx
.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    eaxeax
.text:00428DD0                 pop     esi
.text:00428DD1                 jbe     short loc_428E20
.text:00428DD3 
.text:00428DD3 loc_428DD3:                             ; CODE XREF: .text:00428E1Ej
.text:00428DD3                 xor     edxedx
.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     ecxedx
.text:00428E11                 shr     ecx, 1
.text:00428E13                 add     ecxedx
.text:00428E15                 shr     ecx, 5
.text:00428E18                 mov     eaxecx
.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    eaxeax
.text:00428E46                 jbe     short loc_428E8D
.text:00428E48 
.text:00428E48 loc_428E48:                             ; CODE XREF: .text:00428E8Bj
.text:00428E48                 xor     edxedx
.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     eaxedx
.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     EDXEDX
    MOV     ECXEAX
    PUSH    EBX
    SHR     ECX, 18h
    AND     ECX, 0Fh
    XOR     EBXEBX
    MOV     DLBYTE PTR rawData[ECX+80h] ; DS:[ECX+56AD8C]
    MOV     ECXEDX
    MOV     EDXEAX
    SHR     EDX, 1Ch
    MOV     BLBYTE PTR rawData[EDX+90h]
    MOV     EDXEAX
    SHL     EBX, 4
    SHR     EDX, 14h
    OR      ECXEBX
    AND     EDX, 0Fh
    XOR     EBXEBX
    MOV     BLBYTE PTR rawData[EDX+70h]
    MOV     EDXEAX
    SHL     ECX, 4
    SHR     EDX, 10h
    OR      ECXEBX
    AND     EDX, 0Fh
    XOR     EBXEBX
    MOV     BLBYTE PTR rawData[EDX+60h]
    MOV     EDXEAX
    SHL     ECX, 4
    SHR     EDX, 0Ch
    OR      ECXEBX
    AND     EDX, 0Fh
    XOR     EBXEBX
    MOV     BLBYTE PTR rawData[EDX+50h]
    MOV     EDXEAX
    SHL     ECX, 4
    SHR     EDX, 8
    OR      ECXEBX
    AND     EDX, 0Fh
    XOR     EBXEBX
    MOV     BLBYTE PTR rawData[EDX+40h]
    MOV     EDXEAX
    SHL     ECX, 4
    SHR     EDX, 4
    OR      ECXEBX
    AND     EDX, 0Fh
    XOR     EBXEBX
    AND     EAX, 0Fh
    MOV     BLBYTE PTR rawData[EDX+30h]
    XOR     EDXEDX
    MOV     DLBYTE PTR rawData[EAX+20h]
    SHL     ECX, 4
    OR      ECXEBX
    POP     EBX
    SHL     ECX, 4
    OR      ECXEDX
    MOV     EAXECX
    SHR     EAX, 15h
    SHL     ECX, 0Bh
    OR      EAXECX
    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 EAXDWORD 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);

}

够啰嗦的,不知道说清楚了没有。
最后祝看雪的兄弟们国庆快乐,:)