软件名称:UltraEdit-32 10.00.c
编程语言:VC++ 6.0
运行环境:Win9x/NT/2000/XP
保护措施:注册码,有45天使用期限
破 解 人:wolverine [CCG]
使用工具:Trw2000 1.23 IDA Pro 4.3
作者声明:初学破解,纯属技术交流,无其它目的。
由于它的注册方式与其他软件不一样,所以我用了大约3天的时间才找到关键点,我都看见星星了.
在这里我只讲讲它的加密算法,并给出必要的代码.由于我的语文水平有限,可能有些语病.请多包涵.如果有科学性错误,请大家指出.我会加以改正,以免误人子弟.:-)
016F:004185F0 AND BYTE [EBP-14],00
016F:004185F4
AND BYTE [EBP-54],00
016F:004185F8 AND
BYTE [EBP+FFFFFF6C],00
016F:004185FF CMP
[EBP+14],EBX
016F:00418602 JZ NEAR 0041890C
016F:00418608 PUSH ESI
016F:00418609 PUSH
EDI
016F:0041860A CALL 004FF590
016F:0041860F
POP ECX
016F:00418610 PUSH BYTE +3C
016F:00418612 POP ESI
016F:00418613
CMP EAX,ESI
016F:00418615 JA
00418620
016F:00418617 PUSH EDI
016F:00418618
CALL 004FF590
016F:0041861D POP ECX
016F:0041861E MOV ESI,EAX
016F:00418620
MOV [EBP-0C],ESI
016F:00418623 XOR
ECX,ECX
016F:00418625 MOV AL,CL
016F:00418627 MOV DL,03
016F:00418629 IMUL
DL
016F:0041862B SUB AL,DL
016F:0041862D
MOV [EBP+ECX+FFFFFF70],AL
016F:00418634 INC
ECX
016F:00418635 CMP ECX,BYTE +3D
016F:00418638 JC 00418625
上面的一段程序完成下面操作:
有一个存储空间(或者叫数组)M[3Dh],
ecx=0
1) M[ecx]=ecx*3-3
2) ecx=ecx+1
重复执行1、2 3Dh次,
============================================================
016F:0041863A PUSH ESI
016F:0041863B LEA
EAX,[EBP+FFFFFF70]
016F:00418641 PUSH EDI
016F:00418642 PUSH EAX
016F:00418643 CALL
004FF990 将name复制到M中,也就是[ebp+ffffff70]
016F:00418648 AND
BYTE [EBP+ESI+FFFFFF70],00
016F:00418650 ADD
ESP,BYTE +0C
016F:00418653 XOR ECX,ECX
016F:00418655 DEC ESI
016F:00418656 PUSH
BYTE +01
016F:00418658 MOV [EBP-10],ECX
016F:0041865B POP EDX
016F:0041865C
CMP ESI,EDX
016F:0041865E JNG
0041869A
016F:00418660 MOV DWORD [EBP+10],02
016F:00418667 MOVSX EDI,BYTE [EBP+EDX+FFFFFF6F]
016F:0041866F
MOVSX EBX,BYTE [EBP+EDX+FFFFFF71]
016F:00418677 LEA
EAX,[EBP+EDX+FFFFFF71]
016F:0041867E IMUL
EDI,EBX
016F:00418681 MOVSX EAX,BYTE [EAX-01]
016F:00418685
SUB EDI,EAX
016F:00418687 SUB
EDI,[EBP+10]
016F:0041868A ADD DWORD [EBP+10],BYTE
+02
016F:0041868E INC EDX
016F:0041868F
CMP EDX,ESI
016F:00418691 LEA
ECX,[ECX+EDI+03]
016F:00418695 JL 00418667
016F:00418697 MOV [EBP-10],ECX
对name的处理,过程如下
设name的地址为X,name的长度为Z,n∈[1,3ch],C=2h,S=0 :
1)T=[X(n)*X(n+2)-X(n+1)-C]
2)C=C+2
3)n=n+1
4)S=S+T+3
重复执行1、2、3、4,Z-1次,最后结果放在[ebp-10]中,后面会用到
=================================================================================
从这开始计算注册码,其过程比较繁琐,我理解它的算法,但我不道怎样去描述,
如果你能详细描述出算法,并且易懂,请告诉我
016F:0041869A
XOR ECX,ECX
016F:0041869C XOR
EDI,EDI
016F:0041869E MOV DWORD [EBP-08],01
016F:004186A5 LEA EAX,[EBP+FFFFFF70]
016F:004186AB
SUB [EBP-08],EAX
016F:004186AE MOV
[EBP-04],EDI
016F:004186B1 MOV [005933F4],ECX
016F:004186B7 MOV EAX,[EBP-08]
016F:004186BA
LEA ESI,[EBP+ECX+FFFFFF70]
016F:004186C1 ADD
EAX,ESI
016F:004186C3 CMP EAX,BYTE
+3C eax是否大于3ch
016F:004186C6 JNL NEAR
0041874C
016F:004186CC MOV EAX,ECX
ecx=0
016F:004186CE PUSH BYTE +04
016F:004186D0 CDQ
016F:004186D1 POP
EDI
016F:004186D2 IDIV EDI
; edx=ecx mod 4h
016F:004186D4 MOV EAX,ECX
016F:004186D6 PUSH BYTE +20
016F:004186D8 POP
EBX
016F:004186D9 PUSH BYTE +3B
016F:004186DB
MOV EDI,EDX ;edi=edx=ecx mod 4h
016F:004186DD CDQ
016F:004186DE IDIV EBX ;
016F:004186E0 MOV EAX,EDX ; eax=ecx mod 20h
016F:004186E2
CDQ
016F:004186E3 SUB EAX,EDX
016F:004186E5 MOV EDX,[EDI*4+00586C38] ;(ecx mod
20h)*4+586C38
016F:004186EC SAR EAX,1
;eax=eax*2
016F:004186EE
POP EDI ;edi=3bh
016F:004186EF MOVZX
EAX,BYTE [EDX+EAX]
016F:004186F3 MOV DL,CL
016F:004186F5 PUSH BYTE +12
016F:004186F7 ADD
DL,[EBP-10]
016F:004186FA MOVZX EDX,DL
016F:004186FD XOR EAX,EDX
016F:004186FF CDQ
016F:00418700 IDIV EDI
016F:00418702
POP EDI //edi=12h
016F:00418703 PUSH
BYTE +04
016F:00418705 POP EBX //edx=4h
016F:00418706
PUSH BYTE +20
016F:00418708 MOV DL,[EBP+EDX+FFFFFF70]
016F:0041870F MOVZX EAX,DL
016F:00418712 ADD
EAX,ECX
016F:00418714 MOV [EBP+13],DL
016F:00418717 CDQ
016F:00418718 IDIV
EDI
016F:0041871A MOV EDI,EDX
016F:0041871C
MOV EAX,EDI
016F:0041871E CDQ
016F:0041871F IDIV EBX
016F:00418721 MOV
EAX,EDI
016F:00418723 POP EDI //edi=20h
016F:00418724 MOV EBX,EDX
016F:00418726
CDQ
016F:00418727 IDIV EDI
016F:00418729
MOV EDI,[EBP-04]
016F:0041872C MOV
EAX,EDX
016F:0041872E CDQ
016F:0041872F
SUB EAX,EDX
016F:00418731 MOV
EDX,[EBX*4+00586C38]
016F:00418738 SAR EAX,1
016F:0041873A MOV AL,[EDX+EAX]
016F:0041873D
MOV DL,[ESI+01]
016F:00418740 XOR
AL,[EBP+13]
016F:00418743 SHL DL,1
016F:00418745 ADD AL,[EBP+13]
016F:00418748
XOR AL,DL
016F:0041874A MOV
[ESI],AL
016F:0041874C CMP EDI,BYTE +3C
016F:0041874F
JNL 004187C2
016F:00418751 MOV
EAX,ECX
016F:00418753 PUSH BYTE +05
016F:00418755
CDQ
016F:00418756 POP EBX //ebx=5h
016F:00418757 IDIV EBX
016F:00418759 MOV
EBX,EDX
016F:0041875B TEST EBX,EBX
016F:0041875D MOV [EBP+10],EBX
016F:00418760
JZ 0041876C
016F:00418762 CMP
EBX,BYTE +02
016F:00418765 JZ 0041876C
016F:00418767
CMP EBX,BYTE +04
016F:0041876A JNZ
00418786
016F:0041876C MOVZX EAX,BYTE [ESI]
016F:0041876F PUSH BYTE +1A
016F:00418771 CDQ
016F:00418772 POP EBX //ebx=1ah
016F:00418773
IDIV EBX
016F:00418775 MOV EBX,[EBP+10]
016F:00418778 ADD DL,41
016F:0041877B
MOV [EBP+EDI+FFFFFF30],DL
016F:00418782 INC
EDI
016F:00418783 MOV [EBP-04],EDI
016F:00418786 CMP EDI,BYTE +3C
016F:00418789
JNL 004187C2
016F:0041878B CMP
EBX,BYTE +01
016F:0041878E JZ 00418795
016F:00418790
CMP EBX,BYTE +03
016F:00418793 JNZ
004187AC
016F:00418795 MOVZX EAX,BYTE [ESI]
016F:00418798 PUSH BYTE +0A
016F:0041879A CDQ
016F:0041879B POP ESI
016F:0041879C
IDIV ESI
016F:0041879E ADD DL,30
016F:004187A1 MOV [EBP+EDI+FFFFFF30],DL
016F:004187A8
INC EDI
016F:004187A9 MOV [EBP-04],EDI
016F:004187AC CMP EDI,BYTE +3C
016F:004187AF
JNL 004187C2
016F:004187B1 CMP
EBX,BYTE +04
016F:004187B4 JNZ 004187C2
016F:004187B6
MOV BYTE [EBP+EDI+FFFFFF30],2D
016F:004187BE INC
EDI
016F:004187BF MOV [EBP-04],EDI
016F:004187C2 TEST ECX,ECX
016F:004187C4 JNG
004187E5
016F:004187C6 CMP ECX,[EBP-0C]
016F:004187C9 JNL 004187E5
016F:004187CB
CMP EDI,[EBP-0C]
016F:004187CE JNL
004187E5
016F:004187D0 MOV EAX,[EBP+08]
016F:004187D3 MOVSX EDX,BYTE [ECX+EAX-01]
016F:004187D8
MOVSX EAX,BYTE [EDI+EAX]
016F:004187DC IMUL
EDX,EAX
016F:004187DF ADD [005933F4],EDX
;这个值好像没用到呀?
016F:004187E5 INC ECX
016F:004187E6
CMP ECX,BYTE +3C
016F:004187E9 JL
NEAR 004186B7
算法分析:
一.做准备工作:
有一个存储空间(或者叫数组)M[3Dh],
ecx=0
1) M[ecx]=ecx*3-3
2) ecx=ecx+1
重复执行1、2 3Dh次,再将name复制到M中,也就是上面的[ebp+ffffff70]
二.对name的处理,过程如下:
设name为X,name的长度为Z,n∈[1,3ch],C=2h,S=0
1)T=[X(n)*X(n+2)-X(n+1)-C]
2)C=C+2
3)n=n+1
4)S=S+T+3
重复执行1、2、3、4,Z-1次,最后结果放在S中也就是[ebp-10]中,只用到S的低8为
三.计算注册码
初始化:
[ebp-4]=0
ecx=0
[5933f4]=0
1. 计算ecx mod 4h,将算出的值*4+00586C38,从目录(见附录)中取出相应的地址p,再计算(ecx
mod 20h)/2算出q,然后以p+q为地址从码表取出相应的值,假设为Q
计算(ecx+S xor Q) mod 3bh,以算出的值为索引值,从M中取出相应的值,假设该值为t,计算[(t+ecx)
mod 12h] mod 4h 将算出的值*4+00586C38,从目录(见附录)中取出相应的地址p ,{[(t+ecx) mod 12h] mod 20h}/2算出q,然后以p+q为地址从码表取出相应的值AL,计算[(AL
xor t)+t] xor M[esi+1]*2,将结果保存再M[esi]中.
2. 计算 ecx mod 5h,将算出的值保存到[ebp+10]中,如果等于0或等于2或等于4,则计算(M[esi]
mod 1Ah)+41h.如果等于1或3,则计算(M[esi] mod 1Ah)+30h,结果放在[EBP+EDI+FFFFFF30]中,这就是注册码,当然这不是最后的注册码.
3.ecx=ecx+1
重复1,2,3直到ecx>3ch为止
在计算注册码的过程中,每隔5位插入一个"-".
.text:004187F1 loc_4187F1:
; CODE XREF: sub_4185B8+295j
.text:004187F1 mov
cl, [ebp+edx+var_90]
.text:004187F8
lea eax, [ebp+edx+var_90]
.text:004187FF
cmp cl, 80h
.text:00418802 jb
short loc_418809
.text:00418804
add cl, 80h
.text:00418807
mov [eax], cl
.text:00418809
.text:00418809 loc_418809:
; CODE XREF: sub_4185B8+24Aj
.text:00418809 mov
cl, [eax]
.text:0041880B
cmp cl, 7Fh
.text:0041880E
jl short loc_418815
.text:00418810 sub
cl, 7Fh
.text:00418813
mov [eax], cl
.text:00418815
.text:00418815 loc_418815:
; CODE XREF: sub_4185B8+256j
.text:00418815
mov cl, [eax]
.text:00418817
cmp cl, 21h
.text:0041881A jg
short loc_418821
.text:0041881C
add cl, 21h
.text:0041881F
mov [eax], cl
.text:00418821
.text:00418821 loc_418821:
; CODE XREF: sub_4185B8+262j
.text:00418821 cmp
byte ptr [eax], 22h
.text:00418824
jnz short loc_418829
.text:00418826
mov byte ptr [eax],
23h
.text:00418829
.text:00418829 loc_418829:
; CODE XREF:
sub_4185B8+26Cj
.text:00418829
cmp byte ptr [eax], 27h
.text:0041882C
jnz short loc_418831
.text:0041882E mov
byte ptr [eax], 28h
.text:00418831
.text:00418831 loc_418831:
; CODE XREF: sub_4185B8+274j
.text:00418831
cmp byte ptr [eax], 2Eh
.text:00418834
jnz short loc_418839
.text:00418836 mov
byte ptr [eax], 2Fh
.text:00418839
.text:00418839 loc_418839:
; CODE XREF: sub_4185B8+27Cj
.text:00418839
cmp byte ptr [eax], 60h
.text:0041883C
jnz short loc_418841
.text:0041883E mov
byte ptr [eax], 61h
.text:00418841
.text:00418841 loc_418841:
; CODE XREF: sub_4185B8+284j
.text:00418841
cmp byte ptr [eax], 7Ch
.text:00418844
jnz short loc_418849
.text:00418846 mov
byte ptr [eax], 6Ch
.text:00418849
.text:00418849 loc_418849:
; CODE XREF: sub_4185B8+28Cj
.text:00418849
inc edx
.text:0041884A
cmp edx, 3Ch
.text:0041884D
jl short
loc_4187F1
.text:0041884F
mov esi, [ebp+arg_C]
.text:00418852
push 6
.text:00418854
and [ebp+var_81],
0
.text:0041885B and
[ebp+var_B9], 0
.text:00418862
pop ecx
.text:00418863
lea eax, [ebp+var_50]
.text:00418866
push eax
; char *
.text:00418867
lea edi, [ebp+var_50]
.text:0041886A
push [ebp+arg_4]
; char *
.text:0041886D
mov [ebp+var_CF], 30h
.text:00418874
repe movsd
.text:00418876
and [ebp+var_39], 0
.text:0041887A mov
[ebp+var_4F], 30h
.text:0041887E
mov [ebp+var_46], 30h
.text:00418882
mov [ebp+var_44],
30h
.text:00418886
mov [ebp+var_42], 30h
.text:0041888A
mov [ebp+var_3A], 30h
.text:0041888E
mov [ebp+var_C6],
30h
.text:00418895
mov [ebp+var_C4], 30h
.text:0041889C
mov [ebp+var_C2], 30h
.text:004188A3
mov [ebp+var_BA],
30h
.text:004188AA
call _strcmp
.text:004188AF
pop ecx
.text:004188B0
pop ecx
.text:004188B1
pop esi
.text:004188B2
test eax, eax
.text:004188B4 jnz
short loc_4188D6
.text:004188B6
lea eax, [ebp+var_50]
.text:004188B9
push eax
; char *
.text:004188BA
push [ebp+arg_4] ; char
*
.text:004188BD call
_strcmp
.text:004188C2
pop ecx
.text:004188C3
test eax, eax
.text:004188C5
pop ecx
.text:004188C6
jnz short loc_418919
.text:004188C8 push
[ebp+arg_4] ; char *
.text:004188CB
call _strlen
.text:004188D0
cmp eax, 0Ch
.text:004188D3 pop
ecx
.text:004188D4
jz short loc_418919
.text:004188D6
.text:004188D6
loc_4188D6:
; CODE XREF: sub_4185B8+2FCj
.text:004188D6
lea eax, [ebp+var_90]
.text:004188DC push
eax ; char *
.text:004188DD
lea eax, [ebp+var_50]
.text:004188E0 push
eax ; char *
.text:004188E1
call _strcmp
.text:004188E6 pop
ecx
.text:004188E7
test eax, eax
.text:004188E9
pop ecx
.text:004188EA
jz short loc_418912
.text:004188EC lea
eax, [ebp+var_D0] ;这是最后算出的注册码
.text:004188F2
push eax
; char *
.text:004188F3
lea eax, [ebp+var_50] ;这是我们输入的注册码
.text:004188F6
push eax
; char *
.text:004188F7
call _strcmp
;比较注册码
.text:004188FC
pop ecx
.text:004188FD
test eax, eax
.text:004188FF
pop ecx
.text:00418900
jz short
loc_418912
.text:00418902
mov dword_593518, 1
.text:0041890C
.text:0041890C
loc_41890C:
; CODE XREF: sub_4185B8+29j
.text:0041890C
; sub_4185B8+32j ...
.text:0041890C
xor eax, eax
.text:0041890E
.text:0041890E loc_41890E:
; CODE XREF: sub_4185B8+364j
.text:0041890E pop
edi
.text:0041890F
pop ebx
.text:00418910
leave
.text:00418911
retn
别以为这样找到的注册码就能顺利过关.当你输入注册码后,重新启动后发现注册成功.关闭后再启动,UltraEdit-32又会弹出注册窗口,再看看UltraEdit-32目录,Uedit32.reg文件被删除了.这说明还有其他的地方检查注册码.于是下bpx
deletefilea,再注册一次,找到
016F:004486E1 MOV EAX,[005933F4]
016F:004486E6 PUSH DWORD [005933D8]
016F:004486EC MOV [EBP-1C],EAX
016F:004486EF
CALL 004FF590
016F:004486F4 POP ECX
016F:004486F5 CMP EAX,BYTE +0F
016F:004486F8
POP ECX
016F:004486F9 JC NEAR
004487F6
016F:004486FF CMP [0059DD3C],EDI
016F:00448705 JNZ NEAR 004487F6
016F:0044870B
CMP [0059DD40],EDI
016F:00448711 JZ
NEAR 004487F6
016F:00448717 MOVZX EDI,BYTE [EBP-1C]
016F:00448717 MOVZX
EDI,BYTE [EBP-1C]
016F:0044871B MOV
EAX,EDI
eax=byte prt [005933f4]
016F:0044871D PUSH BYTE +09
016F:0044871F CDQ
016F:00448720 POP
EBX
016F:00448721 MOV ECX,[005933D8]
016F:00448727 IDIV EBX
016F:00448729 MOVSX
EAX,BYTE [ECX+0E] //取注册码的第15位
016F:0044872D
ADD EDX,BYTE +41
EDX=(eax mod 9h)+41h
016F:00448730 CMP EAX,EDX
EDX与注册码的第15位进行比较
016F:00448732 JNZ 0044874D
若不等,Game Over
016F:00448734 MOV
EAX,EDI
016F:00448736 PUSH BYTE +07
016F:00448738 CDQ
016F:00448739 POP
EDI
016F:0044873A MOV CL,[ECX+16]
//取出注册码的第23位
016F:0044873D
IDIV EDI
;
016F:0044873F MOVSX EAX,CL
;
016F:00448742 ADD
EDX,BYTE +41 ;EDX=(eax mod 7h)+41h
016F:00448745
CMP EAX,EDX
EDX与注册码的第23位进行比较
016F:00448747 JZ NEAR 004487F3
若不等,Game Over
016F:0044874D AND
DWORD [0059DD40],BYTE +00
016F:00448754 CALL 00533F9D
016F:00448759 MOV EAX,[EAX+04]
016F:0044875C
LEA ECX,[EBP-10]
016F:0044875F PUSH
DWORD [EAX+8C]
016F:00448765 CALL 00519DBA
016F:0044876A
MOV EAX,[EBP-10]
016F:0044876D LEA
ECX,[EBP-10]
016F:00448770 MOV BYTE [EBP-04],01
016F:00448774 MOV EAX,[EAX-08]
016F:00448777
ADD EAX,BYTE -03
016F:0044877A PUSH
EAX
016F:0044877B LEA EAX,[EBP-24]
016F:0044877E
PUSH EAX
016F:0044877F CALL 00511C19
016F:00448784 PUSH DWORD 00587018
016F:00448789
PUSH EAX
016F:0044878A LEA EAX,[EBP-1C]
016F:0044878D MOV BYTE [EBP-04],02
016F:00448791
PUSH EAX
016F:00448792 CALL 00519FE1
016F:00448797 PUSH EAX
016F:00448798 LEA
ECX,[EBP-10]
016F:0044879B MOV BYTE [EBP-04],03
016F:0044879F CALL 00519E85
016F:004487A4 LEA
ECX,[EBP-1C]
016F:004487A7 MOV BYTE
[EBP-04],02
016F:004487AB CALL 00519D4C
016F:004487B0
LEA ECX,[EBP-24]
016F:004487B3 MOV
BYTE [EBP-04],01
016F:004487B7 CALL 00519D4C
016F:004487BC PUSH DWORD 80
016F:004487C1 PUSH
DWORD [EBP-10]
016F:004487C4 CALL `KERNEL32!SetFileAttributesA`
016F:004487CA PUSH DWORD [EBP-10]
016F:004487CD
CALL `KERNEL32!DeleteFileA`
还记得在计算注册码时有个值没用到吗?
对了,就是[005933F4].它在这里用来检验注册码的有效性.将[005933F4]中的低8位(二进制)分别与09h进行异或运算后加上41h,再与我们输入的注册码的第15位和第23位进行比较,有一位不对,就删掉Uedit32.reg.真够狡猾的.
至此整个算法分析完了。这是我加入CCG后的第一篇文章,让各位高手见笑了.
User Naem:
wolverine[CCG]
Authorization:V7H7L-M2O6S-J1F3H-I8D9B
wolverine[CCG]
2003-5-17
==========================>附录<=============================
1.
586c38{00586C28,00586B30, ;\
0058CA38,0058D288
;=>我称这个为目录
}
;/
===================码表====================
00586C28{
D8,00,FE,00,
8E,00,66,00,
2F,00,DE,00,
43,00,A5,00
}
00586B30{
D3,00,1F,00,
78,00,6F,00,
38,00,8F,00,
65,00,5A,00
}
0058CA38{
00,10,00,F1,
00,A5,00,2F,
00,1F,00,CB,
00,98,00,F3
}
0058D288{
00,EF,00,E0,
00,73,00,78,
00,73,00,34,
00,77,00,33
}
2.注册机:
(至于注册机……)