能力值:
( LV9,RANK:810 )
|
-
-
8 楼
序列号格式:XXXXX-XXXXXX-XXXXX-XXXXX
我们假设输入的四组序列号分别用s1[6],s2[6],s3[7],s4[6]来表示。
其中s1[0]代表第一组序列号的第一个字符。其余类推。
loc46B2EE: mov dword ptr [ebx], offset loc_46A9A0 ;这些地址其实就是验证注册码
mov dword ptr [ebx+4], offset loc_46A910 ;的CALL,软件作者根据计算机
mov dword ptr [ebx+8], offset sub_46A890 ;用户名选择一部分来验证。如
mov dword ptr [ebx+0Ch], offset loc_46A980 ;果只跟踪用到的CALL来做注册
mov dword ptr [ebx+10h], offset loc_46A810 ;机是不能通用的。这大概也是
mov dword ptr [ebx+14h], offset sub_46AC80 ;软件作者对破解的防范。
mov dword ptr [ebx+18h], offset sub_46AD40 ;
mov dword ptr [ebx+1Ch], offset sub_46AE00 ;下面我们一一分析这些CALL。
mov dword ptr [ebx+20h], offset loc_46AEB0 ;
mov dword ptr [ebx+24h], offset sub_46AF40 ;
mov dword ptr [ebx+28h], offset loc_46AB80 ;
mov dword ptr [ebx+2Ch], offset loc_46AB20 ;
mov dword ptr [ebx+30h], offset loc_46AAC0 ;
mov dword ptr [ebx+34h], offset loc_46ABE0 ;
mov dword ptr [ebx+38h], offset loc_46AA60 ;
mov dword ptr [ebx+3Ch], offset loc_46AC40 ;
;///////////////////////////////////////////////////////////////
第一个CALL: s1[4] = 4Dh ('M')
;-------------------------------------------------
loc_46A9A0: ; DATA XREF: sub_46B200+EEo
mov eax, [esp+4] ;第一组序列号
push ebx
push esi
push edi
mov bl, [eax+4] ;指向第五个字符
loc_46AA45: ; CODE XREF: .text:0046AA2Aj
mov edx, dword_490278 ;这个全局变量里是 1 ,追一下可以看到
xor ecx, ecx
movsx eax, bl
add edx, 4Ch
pop edi
cmp eax, edx ;不等于 4Dh 失败
pop esi
setz cl
mov eax, ecx
pop ebx
retn
;///////////////////////////////////////////////////////////////
第二个CALL: s1[2]>=43h && s1[2]<=4Ch
;---------------------------------------------------------------
loc_46A910: ; DATA XREF: sub_46B200+F4o
loc_46A961: ; CODE XREF: .text:0046A94Aj
mov edx, [esp+4] ;第一组序列号
mov al, [edx+2] ;指向第三个字符
cmp al, 43h ;小于43h失败
jl short loc_46A976
cmp al, 4Ch ;大于4Ch失败
jg short loc_46A976
unknown_libname_47:
mov eax, 1
retn
; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
loc_46A976: ; CODE XREF: .text:0046A93Bj
; .text:0046A93Fj .text:0046A955j
; .text:0046A959j .text:0046A96Aj
; .text:0046A96Ej
xor eax, eax
retn
;///////////////////////////////////////////////////////////////
第三个CALL: s1[1]>=42h && s1[1]<=44
;---------------------------------------------------------------
sub_46A890 proc near ; DATA XREF: sub_46B200+FBo
loc_46A8CB: ; CODE XREF: sub_46A890+21j
push ecx
lea ecx, [esp+0Ch+var_8]
mov eax, esp
mov dword ptr [eax], 5
call sub_46B4B0
test eax, eax
jz short loc_46A8F2
mov ecx, [esp+8+arg_0] ;第一组序列号
xor eax, eax
cmp byte ptr [ecx+1], 41h ;第二个字符等于41h则失败
setnl al
add esp, 8
retn
; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
loc_46A8F2: ; CODE XREF: sub_46A890+4Fj
mov edx, [esp+8+arg_0]
mov al, [edx+1]
cmp al, 41h ;小于41h则失败
jl short loc_46A90A
cmp al, 45h ;大于等于45h则失败
jge short loc_46A90A
mov eax, 1
add esp, 8
retn
; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
loc_46A90A: ; CODE XREF: sub_46A890+2Cj
; sub_46A890+30j sub_46A890+6Bj
; sub_46A890+6Fj
xor eax, eax
add esp, 8
retn
sub_46A890 endp
;///////////////////////////////////////////////////////////////
第四个CALL:s1[3]>=42 && s1[3]<=79
;---------------------------------------------------------------
loc_46A980: ; DATA XREF: sub_46B200+102o
mov eax, [esp+4] ;第一组序列号
mov al, [eax+3] ;第四个字符
cmp al, 41h ;小于41h失败
jl short loc_46A995
cmp al, 7Ah ;大于等于7ah失败
jge short loc_46A995
unknown_libname_48:
mov eax, 1
retn
; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
loc_46A995: ; CODE XREF: .text:0046A989j
; .text:0046A98Dj
xor eax, eax
retn
;///////////////////////////////////////////////////////////////
第五个CALL:s1[0] = 44h ('D')
;---------------------------------------------------------------
loc_46A810: ; DATA XREF: sub_46B200+109o
loc_46A866: ; CODE XREF: .text:0046A843j
; DATA XREF: .text:0046A880o
mov eax, [esp+4] ;第一组序列号
mov al, [eax] ;第一个字符
cmp al, 44h ;小于44h失败
jl short loc_46A874
cmp al, 45h ;大于等于45h失败
loc_46A872: ; CODE XREF: .text:0046A856j
; .text:0046A864j
jl short unknown_libname_43 ; default
loc_46A874: ; CODE XREF: .text:0046A852j
; .text:0046A860j .text:0046A86Ej
xor eax, eax
retn
; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
unknown_libname_43: ; CODE XREF: .text:0046A841j
; .text:0046A843j .text:0046A872j
; DATA XREF: .text:0046A880o
mov eax, 1 ; default
retn
;///////////////////////////////////////////////////////////////
第六个CALL: s4[0] = (s1[4]%7 + s1[2]%5 + s1[1]*2 + s1[0]) % 1Ah + 41h
;---------------------------------------------------------------
sub_46AC80 proc near ; DATA XREF: sub_46B200+110o
sub esp, 8
lea eax, [esp+8+var_4]
push eax
call ?GetTickCount@CTime@@SG?AV1@XZ ; CTime::GetTickCount(void)
mov ecx, [eax]
push 0
mov [esp+0Ch+var_8], ecx
lea ecx, [esp+0Ch+var_8]
call ?GetLocalTm@CTime@@QBEPAUtm@@PAU2@@Z ; CTime::GetLocalTm(tm *)
mov eax, [eax+4]
cmp eax, 2Dh
jle short loc_46ACF9
mov ecx, [esp+8+arg_0]
push esi
mov esi, 7
push edi
movsx eax, byte ptr [ecx+4] ;第一组序列号第五个字符
cdq
idiv esi
movsx eax, byte ptr [ecx+2] ;第一组序列号第三个字符
mov edi, 5
mov esi, edx
cdq
idiv edi
pop edi
add esi, edx
movsx edx, byte ptr [ecx+1] ;第一组序列号第二个字符
movsx ecx, byte ptr [ecx] ;第一组序列号第一个字符
lea eax, [esi+edx*2]
pop esi
add eax, ecx ;eax = s1[4]%7 + s1[2]%5 + s1[1]*2 + s1[0]
mov ecx, 1Ah
cdq
idiv ecx
mov eax, [esp+8+arg_C]
movsx ecx, byte ptr [eax] ;s4[0]
xor eax, eax
add dl, 41h ;eax % 1ah +41
and edx, 0FFh
cmp ecx, edx
setz al
add esp, 8
retn
sub_46AC80 endp
;///////////////////////////////////////////////////////////////
第七个CALL: s4[1] = (s2[3]%3 + s2[4]*5 + s2[0]*2 + s2[1] + s2[2]) % 1Ah + 41h
;---------------------------------------------------------------
sub_46AD40 proc near ; DATA XREF: sub_46B200+117o
sub esp, 8
lea eax, [esp+8+var_4]
push eax
call ?GetTickCount@CTime@@SG?AV1@XZ ; CTime::GetTickCount(void)
mov ecx, [eax]
push 0
mov [esp+0Ch+var_8], ecx
lea ecx, [esp+0Ch+var_8]
call ?GetLocalTm@CTime@@QBEPAUtm@@PAU2@@Z ; CTime::GetLocalTm(tm *)
mov eax, [eax+18h]
inc eax
cmp eax, 5
jle short loc_46ADB8
mov ecx, [esp+8+arg_4] ;第二组序列号
push esi
mov esi, 3
movsx eax, byte ptr [ecx+3] ;s2[3]
cdq
idiv esi
movsx eax, byte ptr [ecx+4] ;s2[4]
pop esi
lea eax, [eax+eax*4]
add edx, eax
movsx eax, byte ptr [ecx] ;s2[0]
lea eax, [edx+eax*2]
movsx edx, byte ptr [ecx+2] ;s2[2]
movsx ecx, byte ptr [ecx+1] ;s2[1]
add eax, edx
add eax, ecx
mov ecx, 1Ah
cdq
idiv ecx
mov eax, [esp+8+arg_C] ;第四组序列号
movsx ecx, byte ptr [eax+1] ;s4[1]
xor eax, eax
add dl, 41h
and edx, 0FFh
cmp ecx, edx
setz al
add esp, 8
retn
sub_46AD40 endp
;///////////////////////////////////////////////////////////////
第八个CALL: s4[2] = (s3[3]*23 + s3[5] + s3[0])% 1Ah + 41h
;---------------------------------------------------------------
sub_46AE00 proc near ; DATA XREF: sub_46B200+11Eo
sub esp, 8
lea eax, [esp+8+var_4]
push eax
call ?GetTickCount@CTime@@SG?AV1@XZ ; CTime::GetTickCount(void)
mov ecx, [eax]
push 0
mov [esp+0Ch+var_8], ecx
lea ecx, [esp+0Ch+var_8]
call ?GetLocalTm@CTime@@QBEPAUtm@@PAU2@@Z ; CTime::GetLocalTm(tm *)
mov eax, [eax]
and eax, 80000007h
jns short loc_46AE2C
dec eax
or eax, 0FFFFFFF8h
inc eax
loc_46AE2C: ; CODE XREF: sub_46AE00+25j
cmp eax, 5
jle short loc_46AE70
mov edx, [esp+8+arg_8] ;第三组序列号
movsx ecx, byte ptr [edx+3] ;s[3]
lea eax, [ecx+ecx*2]
shl eax, 3
sub eax, ecx
movsx ecx, byte ptr [edx+5] ;s[5]
movsx edx, byte ptr [edx] ;s[0]
add eax, ecx
mov ecx, 1Ah
add eax, edx
cdq
idiv ecx
mov eax, [esp+8+arg_C] ;第四组序列号
movsx ecx, byte ptr [eax+2] ;s4[2]
xor eax, eax
add dl, 41h
and edx, 0FFh
cmp ecx, edx
setz al
add esp, 8
retn
sub_46AE00 endp
;///////////////////////////////////////////////////////////////
第九个CALL: s4[3] = (s3[1]*7 + s3[2] + s2[2] + s1[3]) % 1Ah + 41h
;---------------------------------------------------------------
loc_46AEB0: ; DATA XREF: sub_46B200+125o
call sub_46A690
cmp eax, 5
jle short loc_46AF06
mov edx, [esp+0Ch] ;第三组序列号
movsx ecx, byte ptr [edx+1] ;s3[1]
movsx edx, byte ptr [edx+2] ;s3[2]
lea eax, ds:0[ecx*8]
sub eax, ecx
mov ecx, [esp+4] ;第一组序列号
movsx ecx, byte ptr [ecx+3] ;s1[3]
add eax, ecx
mov ecx, [esp+8] ;第二组序列号
movsx ecx, byte ptr [ecx+2] ;s2[2]
add eax, ecx
mov ecx, 1Ah
add eax, edx
cdq
idiv ecx
mov eax, [esp+10h] ;第四组序列号
movsx ecx, byte ptr [eax+3] ;s4[3]
xor eax, eax
add dl, 41h
and edx, 0FFh
cmp ecx, edx
setz al
retn
;///////////////////////////////////////////////////////////////
第十个CALL: 返回 1 ,即成功标志
;---------------------------------------------------------------
;///////////////////////////////////////////////////////////////
第十一个CALL: s3[3]>=49h && s3[3]<=52h
;---------------------------------------------------------------
loc_46AB80: ; DATA XREF: sub_46B200+133o
call sub_46A690
cmp eax, 8
jle short loc_46AB9F
mov eax, [esp+0Ch] ;第三组序列号
mov al, [eax+3] ;s3[3]
cmp al, 49h
jl short unknown_libname_63
cmp al, 52h
jg short unknown_libname_63
unknown_libname_60:
mov eax, 1
retn
;///////////////////////////////////////////////////////////////
第十二个CALL: s3[2]>=42h && s3[2]<=4Bh
;---------------------------------------------------------------
loc_46AB20: ; DATA XREF: sub_46B200+13Ao
call sub_46A690
cmp eax, 8
jle short loc_46AB3F
mov eax, [esp+0Ch] ;第三组序列号
mov al, [eax+2] ;s3[2]
cmp al, 42h
jl short unknown_libname_59
cmp al, 4Bh
jg short unknown_libname_59
unknown_libname_56:
mov eax, 1
retn
;///////////////////////////////////////////////////////////////
第十三个CALL: s3[1]>=48h && s3[1]<=51h
;---------------------------------------------------------------
loc_46AAC0: ; DATA XREF: sub_46B200+141o
call sub_46A690
cmp eax, 8
jle short loc_46AADF
mov eax, [esp+0Ch]
mov al, [eax+1]
cmp al, 48h
jl short unknown_libname_55
cmp al, 51h
jg short unknown_libname_55
unknown_libname_52:
mov eax, 1
retn
;///////////////////////////////////////////////////////////////
第十四个CALL: s3[4]>=4bh && s3[4]<=54
;---------------------------------------------------------------
loc_46ABE0: ; DATA XREF: sub_46B200+148o
call sub_46A690
cmp eax, 5
jle short loc_46ABFF
mov eax, [esp+0Ch] ;第三组序列号
mov al, [eax+4] ;s3[4]
cmp al, 4Bh
jl short unknown_libname_67
cmp al, 54h
jg short unknown_libname_67
unknown_libname_64:
mov eax, 1
retn
;///////////////////////////////////////////////////////////////
第十五个CALL: s3[0] = 47h ('G')
;---------------------------------------------------------------
loc_46AA60: ; DATA XREF: sub_46B200+14Fo
call sub_46A690
cmp eax, 8
jle short loc_46AA77
mov ecx, [esp+0Ch] ;第三组序列号
xor eax, eax
cmp byte ptr [ecx], 47h ;s[0] == 47h
setz al
retn
;///////////////////////////////////////////////////////////////
第十六个CALL: s3[5]>=4Ah && s3[5]<=53h
;---------------------------------------------------------------
loc_46AC40: ; DATA XREF: sub_46B200+156o
call sub_46A690
cmp eax, 8
jle short loc_46AC5F
mov eax, [esp+0Ch] ;第三组序列号
mov al, [eax+5] ;s3[5]
cmp al, 4Ah
jl short loc_46AC74
cmp al, 53h
jg short loc_46AC74
unknown_libname_68:
mov eax, 1
retn
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
总结一下:
把所有的条件合并起来,就是生成注册码的方法了。为了省空间和容易阅读,我省去
了一部分代码,而取判断的最小集。软件作者在验证注册码时采用随机验证的方法。因此
不正确的注册码可能当时并不提示。而在过一段时间才提示的。
这个软件的注册方法很值得借鉴,只是验证部分的CALL过于集中,容易给人发现。如
果把验证的CALL分散开,必然会大大增加破解的难度。
软件在注册后的启动画面上仍然是'Trial version',这可能是软件的Bug.软件靠一个
全局标志判断是否出现‘Trial version’或‘Registered to’。但却没有初始化这个
全局标志。
下面的这些算法放在一起就可以做注册机了:
s1[0] = 44h ('D')
s1[1]>=42h && s1[1]<=44
s1[2]>=43h && s1[2]<=4Ch
s1[3]>=42 && s1[3]<=79
s1[4] = 4Dh ('M')
s4[0] = (s1[4]%7 + s1[2]%5 + s1[1]*2 + s1[0]) % 1Ah + 41h
s4[1] = (s2[3]%3 + s2[4]*5 + s2[0]*2 + s2[1] + s2[2]) % 1Ah + 41h
s4[2] = (s3[3]*23 + s3[5] + s3[0])% 1Ah + 41h
s4[3] = (s3[1]*7 + s3[2] + s2[2] + s1[3]) % 1Ah + 41h
s3[0] = 47h ('G')
s3[1]>=48h && s3[1]<=51h
s3[2]>=42h && s3[2]<=4Bh
s3[3]>=49h && s3[3]<=52h
s3[4]>=4bh && s3[4]<=54
s3[5]>=4Ah && s3[5]<=53h
|