软件简介:Director的一个插件,支持直接导入用PhotoShop的分层PSD图形文件,并按原样在舞台上自动排列。未注册版会在导入的图形中加上很多蓝色的斜线,从而导致无法正常使用。我在Director中用了一下,感觉确实很不错,稍微遗憾的是,该软件在读取含有汉字的图层文件时,对汉字有点“水土不服”,显示有问题,不过,可以在Director下编辑该层,重新输入一遍汉字就OK了。
下载地址:http://www.medialab.com/downloads/PhotoCaster3Win.zip
引用网页:http://www.medialab.com/products/downloadlist.htm
目标文件:Photocaster.x32 380928 bytes
分析工具:SoftICE 4.05,IDA Pro 4.15
Director运行版本:8.5,序列号:WDW850-02044-87235-26475
前言:这个xtra是网上的一个朋友huihuicn问的,当时问我是否有这个xtra,于是我就用google搜索了一下,还真找到了下载URL,顺便还找到了一篇关于Photocaster
v2的破解文章,这篇文章对我进行分析还是有不少帮助的,让我知道了一些信息,少走了一些弯路,感谢该文的作者。另外,这个xtra有点奇怪,没有什么壳,但不能用W32Dasm反汇编,估计该软件可能作了防W32Dasm处理。不过用IDA可以反汇编,这正是我所希望的(否则在SoftICE中分析岂不痛苦?)。
破解过程:首先Photocaster.x32复制到Director的xtra文件夹(我一般是新建个Photocaster文件夹,然后将相关文件复制到该文件夹下,这样便于管理),启动Director
8.5,选择Insert-->Media Lab Media-->PhotoCaster,调入PhotoCaster,单击About按钮,填入Unlock
Code:654321,Ctrl+D进入SoftICE,设断:bpx getdlgitemtexta,来到下面:
:10017281
call ds:GetDlgItemTextA ;取得注册码字符串
:10017287 test eax, eax
:10017289
jz loc_1001733B
:1001728F
lea eax, [esp+2Ch+String]
:10017293
mov ecx, esi
:10017295
push eax
:10017296 call
sub_1001C640 ;计算并比对的call
:1001729B
test eax, eax
;eax做旗标
:1001729D jz
loc_1001733B ;等于0则错误
:1001C640 arg_0
= 注册码
:1001C640 sub
esp, 5Ch
:1001C643 push ebx
:1001C644 mov ebx, [esp+60h+arg_0]
:1001C65F mov edi, ebx
:1001C661 or ecx, 0FFFFFFFFh
:1001C664 xor eax, eax
:1001C666
repne scasb
:1001C668 not
ecx
:1001C66A dec ecx
:1001C66B cmp ecx, 6 ;注册码长度是否为6
:1001C66E jz short loc_1001C679
;是则转
:1001C670 pop edi
:1001C679 push ebx
:1001C67A
call sub_100024F0 ;将大写字符转为小写
:1001C67F
mov al, [ebx+5] ;取第6个注册码字符
:1001C682
add esp, 4
:1001C685
cmp al, 30h
:1001C687 jl
short loc_1001C691
:1001C689 cmp
al, 39h
:1001C68B jg
short loc_1001C691
:1001C68D add
al, 0D0h
:1001C68F jmp short loc_1001C693
:1001C691 add al, 0C9h
1c685-1c691为取该字符的“0-9A-Z”的排列值
:1001C693 mov esi, [esi+10h]
;常数,我的是23675,这个值很关键,后面说其产生过程
:1001C696 movsx
edi, al ;第一个注册码的取值放到edi
:1001C699
push esi
:1001C69A
mov [esp+6Ch+var_3C], edi
:1001C69E
call _atol ;转为长整数
:1001C6A3
add esp, 4
:1001C6A6
add eax, edi ;加上第一个注册码的值
:1001C6A8
push eax
:1001C6A9
push offset a05lu ; "%05lu"
:1001C6AE
push esi
:1001C6AF
call _sprintf ;转为字符串
:1001C6B4
push 5
:1001C6B6
mov [esp+78h+var_33], 0
:1001C6BB
mov [esp+78h+var_30], 7
:1001C6C3
mov [esp+78h+var_2C], 0Bh
:1001C6CB
mov [esp+78h+var_28], 0Dh
:1001C6D3
mov [esp+78h+var_24], 11h
:1001C6DB
mov [esp+78h+var_20], 13h
:1001C6E3
mov [esp+78h+var_1C], 17h
:1001C6EB
mov [esp+78h+var_18], 1Dh
:1001C6F3
mov [esp+78h+var_14], 1Fh
:1001C6FB
mov [esp+78h+var_10], 25h
:1001C703
mov [esp+78h+var_C], 29h
:1001C70B
mov [esp+78h+var_8], 2Bh
:1001C713
mov [esp+78h+var_4], 2Fh
:1001C71B
call _malloc
:1001C720 mov
esi, eax
:1001C722 push 5
:1001C724 push ebx
:1001C725
push esi
:1001C726
mov [esp+84h+var_58], esi
:1001C72A
call _strncpy
:1001C72F push
5
:1001C731 lea eax, [esp+88h+var_38]
:1001C735 push ebx
:1001C736
push eax
:1001C737
call _strncpy
:1001C73C mov
ecx, esi
:1001C73E lea eax,
[esp+90h+var_38]
:1001C742 add esp,
28h
:1001C745 xor edx, edx
:1001C747
sub ecx, eax
:1001C749
mov [esp+68h+var_44], ecx
:1001C74D
lea eax, [esp+edx+68h+var_38]
:1001C751
mov bl, [ecx+eax] ;取注册码字符
:1001C754
add bl, 0D0h ;字符转为数字
:1001C757 mov [ecx+eax], bl
:1001C75A mov bl, [eax]
;取注册码字符
:1001C75C add bl,
0D0h ;字符转为数字
:1001C75F
inc edx
:1001C760 cmp
edx, 5
:1001C763 mov [eax], bl
:1001C765 jl short loc_1001C74D
:1001C767 mov ebx, 1
:1001C76C
push ebp
:1001C76D
mov [esp+6Ch+var_5C], ebx
:1001C771
xor ebp, ebp ;置初值
:1001C773
jmp short loc_1001C779
:1001C775
mov esi, [esp+6Ch+var_58]
:1001C779
mov cl, [esi+ebp] ;取注册码字符
:1001C77C mov byte ptr [esp+6Ch+var_54],
cl
:1001C780 mov ecx, 5
:1001C785
mov edi, [esp+6Ch+var_54]
:1001C789
and edi, 0FFh
:1001C78F
mov eax, edi
:1001C791 cdq
:1001C792 idiv ecx
;整除5
:1001C794 cmp
ebp, 4 ;当前注册码是否是第5个
:1001C797
mov byte ptr [esp+6Ch+var_50], dl
;取余数值
:1001C79B jge short loc_1001C7A3
;是则转
:1001C79D mov cl, [esi+ebp+1]
;下一个注册码
:1001C7A1 jmp short loc_1001C7A5
:1001C7A3 mov cl, [esi]
;取第1个注册码
:1001C7A5 mov
al, bl
:1001C7A7 mov esi, 0Ah
:1001C7AC imul cl
;al*cl
:1001C7AE mov
dl, al ;dl=al*cl
:1001C7B0
mov eax, [esp+6Ch+var_50]
:1001C7B4
and eax, 0FFh
:1001C7B9
mov byte ptr [esp+6Ch+var_4C], dl
:1001C7BD
lea ecx, [esp+eax+6Ch+var_38]
:1001C7C1
mov al, [esp+eax+6Ch+var_38] ;根据1001C797语句的dl值取进行变换的字符
:1001C7C5 add al, dl
;加上dl
:1001C7C7 and
eax, 0FFh ;取低位
:1001C7CC
cdq
:1001C7CD idiv esi
;整除10
:1001C7CF
xor esi, esi
:1001C7D1 xor
eax, eax
:1001C7D3 mov [ecx],
dl ;余数放到[ecx]
:1001C7D5
mov ecx, 1
:1001C7DA xor
edx, edx
:1001C7DC mov dl,
[esp+eax+6Ch+var_38] ;从变换的字符中取一个
:1001C7E0
imul edx, ecx
;相乘
:1001C7E3 lea ecx, [ecx+ecx*4]
:1001C7E6 add esi, edx
:1001C7E8
shl ecx, 1
:1001C7EA
cmp eax, ebp
:1001C7EC jnz
short loc_1001C7F2
:1001C7EE mov
[esp+6Ch+var_48], ecx
:1001C7F2 inc
eax
:1001C7F3 cmp eax, 5
:1001C7F6 jl short loc_1001C7DA
:1001C7F8 mov eax, ebp
:1001C7FA mov ebx, 0Bh
:1001C7FF
cdq
:1001C800 idiv
ebx
:1001C802 and edx, 0FFh
:1001C808 mov eax, [esp+edx*4+6Ch+var_30]
;取1001C6BB-1001C713的赋值
:1001C80C mov
edx, [esp+6Ch+var_4C]
:1001C810 and
edx, 0FFh
:1001C816 imul eax, edi
:1001C819 imul edx, [esp+6Ch+var_48]
:1001C81E imul edx, [esp+6Ch+var_5C]
:1001C823 add edx, esi
:1001C825
mov edi, 4
:1001C82A
lea esi, [edx+eax]
:1001C82D
mov eax, 66666667h
;注意66666667h/100000000h=0.4
:1001C832 mov
ebx, 0Ah
:1001C837 imul ecx
:1001C839 sar edx, 2
;0.4/4=0.1,说明ecx每次循环的计算结果均*0.1
:1001C83C mov eax, edx
:1001C83E
shr eax, 1Fh
:1001C841
add edx, eax
:1001C843 mov
eax, esi
:1001C845 mov ecx,
edx ;即ecx=ecx/10
(语句1001C82D-1001C841的结果)
:1001C847 cdq
:1001C848
idiv ecx
;eax=esi/ecx
:1001C84A
and eax, 0FFh
;取商的低位
:1001C84F cdq
:1001C850
idiv ebx
;整除10
:1001C852
mov eax, esi
:1001C854 mov
[esp+edi+6Ch+var_38], dl ;余数放回
:1001C858
cdq
:1001C859 idiv ecx
:1001C85B dec edi
;计数器-1
:1001C85C
mov esi, edx
;esi=esi mod ecx
:1001C85E
jns short loc_1001C82D
:1001C860
mov ebx, [esp+6Ch+var_5C]
:1001C864
neg ebx
;ebx=-ebx
:1001C866 inc
ebp
;计数器加1
:1001C867 mov [esp+6Ch+var_5C],
ebx
:1001C86B cmp ebp, 5
;计算了5组了吗
:1001C86E
jl loc_1001C775
;没有则继续
:1001C874 mov
edx, [esp+6Ch+var_44]
:1001C878 xor
ebx, ebx
:1001C87A xor ecx,
ecx
:1001C87C lea eax, [esp+ecx+6Ch+var_38]
;注册码经过5次循环变换计算的结果
:1001C880 add byte
ptr [edx+eax], 30h
:1001C884 add
byte ptr [eax], 30h ;将变换后的字符变为数字
:1001C887
inc ecx
:1001C888 cmp
ecx, 5
:1001C88B jl
short loc_1001C87C
:1001C88D mov
ecx, [esp+6Ch+var_58]
:1001C891 push
ecx
:1001C892 call sub_1002651C
:1001C897 mov ebp, [esp+70h+var_40]
:1001C89B add esp, 4
:1001C89E
xor edi, edi
:1001C8A0
xor eax, eax
:1001C8A2 mov
esi, [ebp+10h]
:1001C8A5 xor
edx, edx
:1001C8A7 xor ecx, ecx
:1001C8A9 mov dl, [esi+eax]
;取"23675"字符串+第6个注册码字符的变换值
:1001C8AC
mov cl, [esp+eax+6Ch+var_38] ;前5个注册码变换生成的字符串
:1001C8B0 xor edx, ecx
;如果相等,则异或为0
:1001C8B2
add edi, edx
;异或结果累加
:1001C8B4
inc eax
:1001C8B5 cmp
eax, 5
:1001C8B8 jl short
loc_1001C8A5
:1001C8BA push esi
:1001C8BB call _atol
:1001C8C0
mov edx, [esp+70h+var_3C]
:1001C8C4
add esp, 4
:1001C8C7
sub eax, edx
:1001C8C9 push
eax
:1001C8CA push offset
a05lu ; "%05lu"
:1001C8CF push
esi
:1001C8D0 call _sprintf
:1001C8D5 add esp, 0Ch
:1001C8D8
cmp edi, ebx
;累加结果是否为0
:1001C8DA
jz short loc_1001C907 ;如果为0则注册码正确
:1001C8DC mov eax, [ebp+5Ch]
:1001C8DF mov [ebp+6Ch], ebx
:1001C8E2
mov ecx, [eax+0Ch] ;取PhotoCaster Lingo
Prefs_D8.PRF文件的注册次数,文件偏移量的0Ch处
:1001C8E5 inc
ecx
;注册次数加1
:1001C8E6 mov [eax+0Ch],
ecx
:1001C8E9 mov edx, [ebp+5Ch]
:1001C8EC cmp dword ptr [edx+0Ch],
32h ;注册次数是否大于50,小小的一暗桩
:1001C8F0 jg
short loc_1001C90E ;大于则转,假装显示注册成功
:1001C8F2 mov ecx, ebp
:1001C8F4
xor esi, esi
;失败旗标
:1001C8F6 call
sub_1001B650 ;注册次数等信息写回文件(PhotoCaster
Lingo Prefs_D8.PRF)
:1001C8FB pop
ebp
:1001C8FC mov eax, esi
;注册失败
:1001C8FE pop edi
:1001C8FF
pop esi
:1001C900
pop ebx
:1001C901 add
esp, 5Ch
:1001C904 retn 4
:1001C907
mov dword ptr [ebp+6Ch], 1
:1001C90E
mov eax, [ebp+5Ch]
:1001C911
mov edi, [esp+6Ch+arg_0] ;注册码
:1001C915
or ecx, 0FFFFFFFFh
:1001C918
mov [eax+14h], bl
:1001C91B
mov edx, [ebp+5Ch]
:1001C91E
xor eax, eax
:1001C920 add
edx, 14h
:1001C923 repne scasb
:1001C925
not ecx
:1001C927
sub edi, ecx
:1001C929 mov
eax, ecx
:1001C92B mov esi,
edi
:1001C92D mov edi, edx
:1001C92F
shr ecx, 2
:1001C932
repe movsd
:1001C934 mov ecx,
eax
:1001C936 and ecx, 3
:1001C939
repe movsb
:1001C93B mov
ecx, ebp
:1001C93D mov esi,
1 ;旗标
:1001C942
call sub_1001B650 ;注册信息写回文件
:1001C947
pop ebp
:1001C948 mov
eax, esi ;注册成功
:1001C94A
pop edi
:1001C94B pop
esi
:1001C94C pop ebx
:1001C94D add esp, 5Ch
:1001C950
retn 4
:1001C950 sub_1001C640
endp
根据上面的计算程序,我用VB编了一个函数,传递参数为Unlock Code,返回值为计算结果,如果返回值等于常数+第6个字符的变换值就说明注册码正确。程序如下:
Function GetSerial(regcode As String)
Dim Serial As String,
i As Integer, j As Integer, k As Integer
Dim ebp As Integer,
al As Integer, bl As Integer, cl As Integer, dl As Integer
Dim eax As Integer, ebx As Long, ecx As Long, edx As Long, esi As Long, edi As
Long
Serial = regcode
bl = 1: ebp = 0
For i = 1 To 5 '对5个注册码字符变换
edi = CInt(Mid(regcode, i, 1)): cl = edi Mod 5
j = i + 1
If i = 5 Then j = 1
eax = cl + 1: cl = CInt(Mid(regcode, j, 1)): dl = bl * cl
If CInt(Mid(Serial, eax,
1)) + dl < 0 Then '检测变换的字符是否有“负值”,如果有则返回
GetSerial = "负值!" '表示该Unlock Code错误
Exit Function
End If
Mid(Serial, eax, 1) = CStr((CInt(Mid(Serial,
eax, 1)) + dl) Mod 10)
dl = CInt("&H" + Right(Hex(dl),
2)) '取低位,即1001C7C7语句
'以上对应于程序的1001C775-1001C7D5语句
ecx = 1: esi = 0
For j =
1 To 5
edx = CLng(Mid(Serial, j,
1))
edx = edx * ecx: esi = esi
+ edx: ecx = ecx * 10
If j = ebp
+ 1 Then ebx = ecx
Next j
'以上对应于程序的1001C7DA-1001C7F6语句
al = 2 * (ebp
Mod 12) + 1
al = CInt("&H" + Mid("070B0D1113171D1F25292B2F",
al, 2)) '其实字符串取前5个就行了
edx = dl * ebx *
bl: esi = esi + al * edi + edx
'以上对应于程序的1001C7F8-1001C82A语句
For j = 5 To 1 Step -1
ecx = ecx / 10: ebx = esi: ebx = ebx \ ecx
ebx = CLng("&H" + Right(Hex(ebx),
2)) Mod 10
Mid(Serial, j, 1) =
CStr(ebx)
esi = esi Mod ecx
Next j
'以上对应于程序的1001C82D-1001C85D语句
bl = -bl: ebp = ebp + 1
Next i
GetSerial = Serial
End Function
根据上面的函数,我编了一个算码程序,共找到了15个注册码,介绍其中好记的一个:98567G