【文章标题】: Flash ScreenSaver Builder v4.7 算法分析
【文章作者】: Suyana
【作者邮箱】: Suyasha@163.com
【作者QQ号】: 517949855(请注明来自看雪论坛)
【软件名称】: Flash ScreenSaver Builder v4.7
【加壳方式】: 无壳
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: OD
【软件介绍】: 把Flash动画转换成屏保程序,除此之外,它也可以将图像、文本、各种音频视频文件组合起来制作成屏保程序。
【作者声明】: 我只是一只小菜鸟,失误之处难免,敬望诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
用OD载入,运行注册,输入注册码
下断点:GetWindowTextA (VC++编译的程序基本都是这条) ,点ok,中断在:
004AB0D3 call [<&USER32.GetWindowTextA>]
运行到返回,来到:
0043B784 mov edi, [esp+C]
0043B788 lea eax, [esi+60]
0043B78B push eax ; /Arg3
0043B78C push 3E8 ; |Arg2 = 000003E8
0043B791 push edi ; |Arg1
0043B792 call 004AB0A4 ; \得到用户名
0043B797 add esi, 64
0043B79A push esi ; /Arg3
0043B79B push 3E9 ; |Arg2 = 000003E9
0043B7A0 push edi ; |Arg1
0043B7A1 call 004AB0A4 ; \得到注册码
0043B7A6 pop edi ; 00166C08
0043B7A7 pop esi
0043B7A8 retn 4
运行到返回,来到:
0049ABE5 mov ecx, esi
0049ABE7 call [eax+84] ;得到用户名和注册码(怎么VC++编译出的代码都这样)
0049ABED mov dword ptr [ebp+8], 1 ;返回到这里
0049ABF4 jmp short 0049AC1D
0049AC1D:
这里没做什么事,直接返回到:
0043B889 call 0049AB98
0043B88E test eax, eax ;返回到这里
0043B890 je 0043BA7C
0043B896 fld dword ptr [4EA6BC]
0043B89C sub esp, 8
0043B89F fstp qword ptr [esp]
0043B8A2 push ecx
0043B8A3 mov ecx, esp
0043B8A5 mov [esp+20], esp
0043B8A9 push 84EF
0043B8AE call 0049CE49
0043B8B3 push 3
0043B8B5 lea ecx, [esp+2C]
0043B8B9 call 00476340
0043B8BE mov eax, [esi+60]
0043B8C1 mov dword ptr [esp+4C], 0
0043B8C9 mov ecx, [eax-8]
0043B8CC test ecx, ecx
0043B8CE je 0043B9E7
0043B8D4 mov eax, [esi+64] ; 注册码
0043B8D7 lea ecx, [esp+1C]
0043B8DB push eax ; 注册码做参数
0043B8DC call 00476940 ; 计算注册码(严格上说是比较)
0043B8E1 test al, al
0043B8E3 je 0043B9E7 ; al=0,则注册失败
进入0043B8DC call 00476940:
00476940 /$ 53 push ebx
00476941 |. 8B5C24 08 mov ebx, [esp+8]
00476945 |. 55 push ebp
00476946 |. 56 push esi
00476947 |. 57 push edi
00476948 |. 8BE9 mov ebp, ecx
0047694A |. 53 push ebx ; /String
0047694B |. FF15 50544C00 call [<&KERNEL32.lstrlenA>] ; \lstrlenA
00476951 |. 83F8 11 cmp eax, 11 ; 注册码要17位
00476954 |. 0F85 DA000000 jnz 00476A34
0047695A |. 8A03 mov al, [ebx] ; 注册码第n位
0047695C |. 33FF xor edi, edi
0047695E |. 84C0 test al, al ; 是否为0
00476960 |. 8BF3 mov esi, ebx
00476962 |. 74 44 je short 004769A8
00476964 |> 8A06 /mov al, [esi] ; 注册码第n位
00476966 |. 3C 2D |cmp al, 2D ; 为'-' tiao
00476968 |. 74 2C |je short 00476996
0047696A |. 0FBEC0 |movsx eax, al
0047696D |. 50 |push eax
0047696E |. E8 47D00000 |call 004839BA
00476973 |. 83C4 04 |add esp, 4
00476976 |. 85C0 |test eax, eax
00476978 |. 8A06 |mov al, [esi]
0047697A |. 74 0A |je short 00476986
0047697C |. 3C 30 |cmp al, 30
0047697E |. 7C 0E |jl short 0047698E ; <=30 跳
00476980 |. 3C 39 |cmp al, 39
00476982 |. 7E 1C |jle short 004769A0 ; <= 39,跳
00476984 |. EB 08 |jmp short 0047698E
00476986 |> 3C 41 |cmp al, 41
00476988 |. 7C 04 |jl short 0047698E
0047698A |. 3C 46 |cmp al, 46
0047698C |. 7E 12 |jle short 004769A0
0047698E |> 3C 2D |cmp al, 2D
00476990 |. 0F85 9E000000 |jnz 00476A34
00476996 |> 47 |inc edi
00476997 |. 83FF 02 |cmp edi, 2
0047699A |. 0F8F 94000000 |jg 00476A34 ; 超过2个'-'就注册失败
004769A0 |> 8A46 01 |mov al, [esi+1]
004769A3 |. 46 |inc esi
004769A4 |. 84C0 |test al, al
004769A6 |.^ 75 BC \jnz short 00476964
004769A8 |> 6A 2D push 2D
...下面还有一些函数,是拿注册码去做运算的,但最后好像都没用到,就不贴出来了...
004769DB mov esi, eax
004769DD push 6 ; /n = 6
004769DF push ebx ; |String2
004769E0 push esi ; |String1
004769E1 call [<&KERNEL32.lstrcpynA>] ; \lstrcpynA,复制注册码第一段
004769E7 mov edx, [esp+14]
004769EB add edx, 3
004769EE push edx ; /StringToAdd
004769EF push esi ; |ConcatString
004769F0 call [<&KERNEL32.lstrcatA>] ; \lstrcatA,加上注册码第三段的后3位
004769F6 lea eax, [esp+14]
004769FA push 10
004769FC inc edi
004769FD push eax
004769FE push edi
004769FF call 004838A3 ; 第二段注册码转成数字
00476A04 push 10
00476A06 mov edi, eax ; eax=转换后的数字
00476A08 imul edi, [ebp+8] ; [ebp+8]=[0012e8b4]=5c,定值
00476A0C push 0
00476A0E push esi ; 第一段注册码+第三段注册码的后3位
00476A0F call 004838A3 ; 转成数字
00476A14 mov ebx, [ebp+10] ; 25da8a35,定值
00476A17 push esi
00476A18 add eax, ebx ; 加上25da8a35
00476A1A imul eax, [ebp+C] ; 35,定值
00476A1E cmp edi, eax
00476A20 sete bl ; 不等则 bl=0
00476A23 call 0049C002
00476A28 add esp, 1C
00476A2B mov al, bl ; al=bl
00476A2D pop edi
--------------------------------------------------------------------------------
注册码算法:
第二段注册码转成数字*5c = ((第一段注册码+第三段注册码的后3位)转成数字+25da8a35)*35
我用第二段注册码算出第一段注册码+第三段注册码的后3位:公式:
第二段注册码转成数字*5c/35-25da8a35,但在除以35h时一定要整除,所以偶直接用35
例如:第二段注册码:35,则注册码为:
(35*5c)/35-25da8a35=DA257627=第一段注册码+第三段注册码的后3位。
第三段注册码的前2位随便填就可以了,得出的注册码。
DA257-00035-77627
注册码保存在:HKEY_LOCAL_MACHINE\SOFTWARE\XemiComputers\FSSBuilder\Registration\4.70
------------------------------------------
附件:注册机(MASM32),这个注册机的模板是我自己写的,有兴趣的可以找我拿源代码(MASM32)
下面是计算注册码的函数:(用35h的倍数来算)
GetSN proc uses ecx hWnd
local szBuffer[30]:byte,szKey1[6]:byte,szKey3[6]:byte
add key2,35h
mov eax,key2
push 5ch
pop ecx
imul ecx
push 35h
pop ecx
idiv ecx
sub eax,25da8a35h
invoke wsprintf,addr szBuffer,addr szFmtS,eax
invoke lstrcpyn,addr szKey1,addr szBuffer,6
lea eax,szBuffer
add eax,5
invoke lstrcpy,addr szKey3,eax
invoke wsprintf,addr szBuffer,addr szFmt,addr szKey1,key2,addr szKey3
invoke SetDlgItemText,hWnd,1001,addr szBuffer ;显示注册码
ret
_GetSN endp
代码写得不好,请指教。有更好算法的欢迎指出。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
------------------------------------------------------------------
文章写于2007-08-18
[注意]APP应用上架合规检测服务,协助应用顺利上架!