• 标 题:Speaking Clock Deluxe V3.05 算法分析 (14千字)
  • 作 者:Nnewell
  • 时 间:2002-7-19 9:41:17
  • 链 接:http://bbs.pediy.com

Speaking Clock Deluxe V3.05 算法分析

软件大小:  1505 KB
软件语言:  英文
软件类别:  国外软件 / 共享版 / 时钟日历
应用平台:  Win9x/NT/2000/XP

软件介绍:
    主要特点/功能有:四种精美图形界面/语音报时/日历/50种任意设置的闹铃/计时器/计算器/同步校正/引语等。其模拟的实际时钟外观极其逼真;能够用 20 多种语言报时(需安装语音支持,从其主页上可以下载到更多的语言包,包括中文普通话);其 50 种闹铃可设置在每天、每周、每月甚至每年的特定时刻重复地响;计时器功能能够象秒表那样向上向下计时。数字钟的显示区域还可以用作内置的计算器,或设置“飞梭”引语。

工具:ollydbg 1.07    W32dasm 8.93

Name:Nnewell/iPB
License code:45454545


:004E7789 E82A9DF7FF              call 004614B8
:004E778E 8BD8                    mov ebx, eax
:004E7790 8BC3                    mov eax, ebx
:004E7792 8B10                    mov edx, dword ptr [eax]
:004E7794 FF92E8000000            call dword ptr [edx+000000E8]
:004E779A 48                      dec eax
:004E779B 0F859C000000            jne 004E783D
:004E77A1 8D55F8                  lea edx, dword ptr [ebp-08]
:004E77A4 8B83F0020000            mov eax, dword ptr [ebx+000002F0]
:004E77AA E8D913F6FF              call 00448B88
:004E77AF 8B55F8                  mov edx, dword ptr [ebp-08]    <<--edx=="Nnewell/iPB"
:004E77B2 8D4DFC                  lea ecx, dword ptr [ebp-04]
:004E77B5 8BC6                    mov eax, esi
:004E77B7 E8B8C8FFFF              call 004E4074            <<--算法
:004E77BC 8B45FC                  mov eax, dword ptr [ebp-04]    <<--eax=="/ICC16746"
:004E77BF 50                      push eax
:004E77C0 8D55F4                  lea edx, dword ptr [ebp-0C]
:004E77C3 8B83F4020000            mov eax, dword ptr [ebx+000002F4]<<--eax=="/ICC16746"
:004E77C9 E8BA13F6FF              call 00448B88
:004E77CE 8B55F4                  mov edx, dword ptr [ebp-0C]    <<--edx=="45454545"
:004E77D1 58                      pop eax            <<--eax=="/ICC16746"
:004E77D2 E85DD5F1FF              call 00404D34            <<--注册码比较
:004E77D7 754F                    jne 004E7828            <<--不等则注册失败
:004E77D9 8D55F0                  lea edx, dword ptr [ebp-10]
:004E77DC 8B83F0020000            mov eax, dword ptr [ebx+000002F0]
:004E77E2 E8A113F6FF              call 00448B88
:004E77E7 8B55F0                  mov edx, dword ptr [ebp-10]
:004E77EA 8D8638270000            lea eax, dword ptr [esi+00002738]

既然是算法分析,那就要进call 004E4074看看注册码是如何计算的:

======================call 004E4074====================
:004E4074 55                      push ebp
:004E4075 8BEC                    mov ebp, esp
:004E4077 51                      push ecx
:004E4078 B904000000              mov ecx, 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E4082(C)
|
:004E407D 6A00                    push 00000000
:004E407F 6A00                    push 00000000
:004E4081 49                      dec ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E400B(C)
|
:004E4082 75F9                    jne 004E407D
:004E4084 51                      push ecx
:004E4085 874DFC                  xchg dword ptr [ebp-04], ecx
:004E4088 53                      push ebx
:004E4089 56                      push esi
:004E408A 894DF8                  mov dword ptr [ebp-08], ecx
:004E408D 8955FC                  mov dword ptr [ebp-04], edx
:004E4090 8B45FC                  mov eax, dword ptr [ebp-04]    <<--eax=="Nnewell/iPB"
:004E4093 E8400DF2FF              call 00404DD8
:004E4098 33C0                    xor eax, eax
:004E409A 55                      push ebp
:004E409B 6898414E00              push 004E4198
:004E40A0 64FF30                  push dword ptr fs:[eax]
:004E40A3 648920                  mov dword ptr fs:[eax], esp
:004E40A6 33C0                    xor eax, eax            <<--eax==0
:004E40A8 8945EC                  mov dword ptr [ebp-14], eax    <<--将eax==0送入内存地址[ebp-14]
:004E40AB 8D4DE4                  lea ecx, dword ptr [ebp-1C]
:004E40AE BA08000000              mov edx, 00000008
:004E40B3 B8642C1C00              mov eax, 001C2C64        <<--eax==0x001C2C64
:004E40B8 E82351F2FF              call 004091E0            <<--转换为字符串
:004E40BD 8B4DE4                  mov ecx, dword ptr [ebp-1C]    <<--ecx=="001C2C64"
:004E40C0 8D45E8                  lea eax, dword ptr [ebp-18]
:004E40C3 8B55FC                  mov edx, dword ptr [ebp-04]    <<--edx=="Nnewell/iPB"
:004E40C6 E8710BF2FF              call 00404C3C            <<--连接字符串
:004E40CB 8B45E8                  mov eax, dword ptr [ebp-18]    <<--eax=="Nnewell/iPB001C2064"
:004E40CE 8D55F4                  lea edx, dword ptr [ebp-0C]
:004E40D1 E83A4CF2FF              call 00408D10            <<--转换为大写
:004E40D6 8B45F4                  mov eax, dword ptr [ebp-0C]    <<--eax=="NNEWELL/IPB001C2C64"
:004E40D9 E8120BF2FF              call 00404BF0            <<--计算长度
:004E40DE 8BF0                    mov esi, eax            <<--esi==0x13 (长度)
:004E40E0 85F6                    test esi, esi            <<--用户名是否为空
:004E40E2 7E59                    jle 004E413D
:004E40E4 BB01000000              mov ebx, 00000001        <<--ebx==1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E413B(C)
|
:004E40E9 8B45F4                  mov eax, dword ptr [ebp-0C]    <<--eax=="NNEWELL/IPB001C2C64"
:004E40EC 8A4418FF                mov al, byte ptr [eax+ebx-01]    <<--取每个字符
:004E40F0 E833FFFFFF              call 004E4028
:004E40F5 84C0                    test al, al            <<--eax是否为0
:004E40F7 7425                    je 004E411E            <<--是跳,不是则将该字符保存起来,做为注册码的一部分。
:004E40F9 8D45DC                  lea eax, dword ptr [ebp-24]
:004E40FC 8B55F4                  mov edx, dword ptr [ebp-0C]    <<--eax=="NNEWELL/IPB001C2C64"
:004E40FF 8A541AFF                mov dl, byte ptr [edx+ebx-01]    <<--取未被整除的字符
:004E4103 E8100AF2FF              call 00404B18
:004E4108 8B45DC                  mov eax, dword ptr [ebp-24]
:004E410B 8D55E0                  lea edx, dword ptr [ebp-20]
:004E410E E8FD4BF2FF              call 00408D10
:004E4113 8B55E0                  mov edx, dword ptr [ebp-20]
:004E4116 8D45F0                  lea eax, dword ptr [ebp-10]
:004E4119 E8DA0AF2FF              call 00404BF8            <<--将该字符保存起来,做为注册码的一部分。

上面是取出字符在call 004E4028里计算al是否为0,不为0 则该字符作为注册码的一部分,所以有必要进去看看:
======================call 004E4028=====================
:004E4028 55                      push ebp
:004E4029 8BEC                    mov ebp, esp
:004E402B 51                      push ecx
:004E402C 53                      push ebx
:004E402D 56                      push esi
:004E402E 8845FF                  mov byte ptr [ebp-01], al    <<--[ebp-01] <= al
:004E4031 C645FD02                mov [ebp-03], 02        <<--[ebp-03]==2
:004E4035 C645FE01                mov [ebp-02], 01        <<--[ebp-02]==1
:004E4039 8A4DFF                  mov cl, byte ptr [ebp-01]    <<--cl <= [ebp-01]
:004E403C 49                      dec ecx
:004E403D 80E902                  sub cl, 02
:004E4040 722A                    jb 004E406C
:004E4042 41                      inc ecx            <<--实际上cl==cl-2

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E3FDC(C)
|
:004E4043 B302                    mov bl, 02            <<--bl==2

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E406A(C)
|
:004E4045 33C0                    xor eax, eax
:004E4047 8A45FF                  mov al, byte ptr [ebp-01]    <<--al <= [ebp-01]
:004E404A 33D2                    xor edx, edx
:004E404C 8AD3                    mov dl, bl            <<--dl==bl==2
:004E404E 8BF2                    mov esi, edx            <<--esi==edx==2
:004E4050 33D2                    xor edx, edx
:004E4052 F7F6                    div esi            <<--eax==eax/esi
:004E4054 85D2                    test edx, edx            <<--测试余数edx是否为零
:004E4056 7503                    jne 004E405B            <<--不为0跳
:004E4058 FE45FD                  inc [ebp-03]            <<--否则[ebp-03]+1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E4056(C)
|
:004E405B 807DFD02                cmp byte ptr [ebp-03], 02    <<--比较
:004E405F 7606                    jbe 004E4067            <<--小于等于跳
:004E4061 C645FE00                mov [ebp-02], 00        <<--[ebp-02]==0
:004E4065 EB05                    jmp 004E406C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E405F(C)
|
:004E4067 43                      inc ebx            <<--除数ebx加1
:004E4068 FEC9                    dec cl
:004E406A 75D9                    jne 004E4045            <<--继续

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004E4009(C), :004E4040(C), :004E4065(U)
|
:004E406C 8A45FE                  mov al, byte ptr [ebp-02]    <<--al <= [ebp-02]
:004E406F 5E                      pop esi
:004E4070 5B                      pop ebx
:004E4071 59                      pop ecx
:004E4072 5D                      pop ebp
:004E4073 C3                      ret
==================end call 004E4028=======================
call 004028的作用是取得字符的16进制数,作为被除数,除数从2开始递增与被除数进行除法运算,直至除数与被除数相等就结束运算。运算中间若该字符被除数整除,则置al为0,否则置al为1。

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E40F7(C)
|
:004E411E 83FB01                  cmp ebx, 00000001        <<--是1吗?
:004E4121 740A                    je 004E412D            <<--是跳,否则不跳
:004E4123 8B45F4                  mov eax, dword ptr [ebp-0C]    <<--eax=="NNEWELL/IPB001C2C64"
:004E4126 0FB64418FE              movzx eax, byte ptr [eax+ebx-02]<<--取字符(从第一个开始)
:004E412B EB06                    jmp 004E4133            <<--跳

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E4121(C)
|
:004E412D 8B45F4                  mov eax, dword ptr [ebp-0C]    <<--eax=="NNEWELL/IPB001C2C64"
:004E4130 0FB600                  movzx eax, byte ptr [eax]    <<--取每个字符

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E412B(U)
|
:004E4133 C1E003                  shl eax, 03            <<--eax左移3 位
:004E4136 0145EC                  add dword ptr [ebp-14], eax    <<--累加
:004E4139 43                      inc ebx
:004E413A 4E                      dec esi
:004E413B 75AC                    jne 004E40E9            <<--累加结果为0x2760

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E40E2(C)
|
:004E413D 8145EC0A1A0000          add dword ptr [ebp-14], 00001A0A<<--[ebp-14]==0x2760+0x1A0A=0X416A (16746)
:004E4144 8D55D8                  lea edx, dword ptr [ebp-28]
:004E4147 8B45EC                  mov eax, dword ptr [ebp-14]    <<--eax==0x416A
:004E414A E82D50F2FF              call 0040917C            <<--转换为10进制
:004E414F 8B4DD8                  mov ecx, dword ptr [ebp-28]    <<--ecx=="16746"
:004E4152 8D45F4                  lea eax, dword ptr [ebp-0C]
:004E4155 8B55F0                  mov edx, dword ptr [ebp-10]    <<--edx=="/ICC"
:004E4158 E8DF0AF2FF              call 00404C3C            <<--连接字符串
:004E415D 8B45F8                  mov eax, dword ptr [ebp-08]
:004E4160 8B55F4                  mov edx, dword ptr [ebp-0C]    <<--edx=="/ICC16746"
:004E4163 E82408F2FF              call 0040498C
:004E4168 33C0                    xor eax, eax
:004E416A 5A                      pop edx
:004E416B 59                      pop ecx
:004E416C 59                      pop ecx
:004E416D 648910                  mov dword ptr fs:[eax], edx
:004E4170 689F414E00              push 004E419F

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E419D(U)
|
:004E4175 8D45D8                  lea eax, dword ptr [ebp-28]
:004E4178 BA05000000              mov edx, 00000005
:004E417D E8DA07F2FF              call 0040495C
:004E4182 8D45F0                  lea eax, dword ptr [ebp-10]
:004E4185 BA02000000              mov edx, 00000002
:004E418A E8CD07F2FF              call 0040495C
:004E418F 8D45FC                  lea eax, dword ptr [ebp-04]
:004E4192 E8A107F2FF              call 00404938
:004E4197 C3                      ret
==================end call 004E4074==================
:004E77F0 E897D1F1FF              call 0040498C
:004E77F5 8D55EC                  lea edx, dword ptr [ebp-14]
:004E77F8 8B83F4020000            mov eax, dword ptr [ebx+000002F4]
:004E77FE E88513F6FF              call 00448B88
:004E7803 8B55EC                  mov edx, dword ptr [ebp-14]
:004E7806 8D863C270000            lea eax, dword ptr [esi+0000273C]
:004E780C E87BD1F1FF              call 0040498C
:004E7811 6A00                    push 00000000
:004E7813 668B0D7C784E00          mov cx, word ptr [004E787C]
:004E781A B202                    mov dl, 02

* Possible StringData Ref from Code Obj ->"Registration was successful, thank "
                                        ->"you for registering!"
                                  |
:004E781C B888784E00              mov eax, 004E7888
:004E7821 E8E2A0F5FF              call 00441908
:004E7826 EB15                    jmp 004E783D

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E77D7(C)
|
:004E7828 6A00                    push 00000000
:004E782A 668B0D7C784E00          mov cx, word ptr [004E787C]
:004E7831 B201                    mov dl, 01

* Possible StringData Ref from Code Obj ->"Registration was unsuccessful, "
                                        ->"please check name and license "
                                        ->"code and try again."
                                  |
:004E7833 B8C8784E00              mov eax, 004E78C8
:004E7838 E8CBA0F5FF              call 00441908

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004E779B(C), :004E7826(U)
|
:004E783D 8BC6                    mov eax, esi
:004E783F E8E0000000              call 004E7924
:004E7844 8BC3                    mov eax, ebx
:004E7846 E83DDFF7FF              call 00465788
:004E784B 33C0                    xor eax, eax
:004E784D 5A                      pop edx
:004E784E 59                      pop ecx
:004E784F 59                      pop ecx
:004E7850 648910                  mov dword ptr fs:[eax], edx
:004E7853 6875784E00              push 004E7875

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004E7873(U)
|
:004E7858 8D45EC                  lea eax, dword ptr [ebp-14]
:004E785B BA04000000              mov edx, 00000004
:004E7860 E8F7D0F1FF              call 0040495C
:004E7865 8D45FC                  lea eax, dword ptr [ebp-04]
:004E7868 E8CBD0F1FF              call 00404938
:004E786D C3                      ret

-------------------------------------------------------------
                    Nnewell[iPB][FCG]
                    2002.07.17