Turbo Note+ V4.4注册机制分析
作者: 囚童[FCG][BCG]
课题: Turbo Note+ V4.4注册机制分析
出品: South Pacific InformationServices Ltd
背景: PACKED WITH Thrink v3
平台: win95/98, winNT/2000
下载: http://turbopress.com/tnplus44.exe
尺寸: 769KB
工具: TRW 2000
冲击波2000
W32Dasm V8.93
关键字: 软件破解 注册码
TurboNote+是一个方便的“即时帖”软件,可以工作在Win95/98, WinNT 和 Win2000
环境下。它可以即时在自己或通过IP地址向其他人的屏幕上贴上一个可定义尺寸和颜色
的"留言条",也可以按预定的时间启动备忘提示功能。
通过"留言条",可以方便地启动可执行程序、互联网址、E-mail地址,也可以把它们作
为附件发送给指定的IP地址。它可以隐藏,也可以再现,甚至关机后信息也不会丢失。
使用十分方便。
TurboNote V4.4未注册版有30天的时间限制。过期后会随时出现延时的注册窗口,程序
仍能使用。
TurboNote+是一个被压缩了的可执行软件,用一般的方法无法修改。它的脱壳较简单,
用冲击波2000找到程序入口,在TRW2000下定位入口,再用MAKEPE命令很容易就脱壳成
功。
TurboNote+在注册时不出现明码,大多数情况下,输入了错误的注册码得不到提示,
因此用动态跟踪寻找注册入口较困难。相反,用静态分析却相当简单。
以下是对其注册机制的分析:
用W32Dasm打开TurboNote+主文件TBNOTE.EXE,以REGISTER为关键字搜索,定位在:
* Possible StringData Ref from Code Obj ->"There was a problem when saving "
->"the registry
key Try again "
->"please."
|
:00412BF4 push 00470968
:00412BF9 push eax
向上看,可以找到:
* Reference To: KERNEL32.lstrlenA, Ord:0000h
|
:00412B4D Call dword ptr [00467128]
:00412B53 cmp eax, 00000014 <==串长≥Ox14
:00412B56 jl 00412DD8
:00412B5C push 00000064
:00412B5E lea ecx, dword ptr [ebp-44]
:00412B61 call 0042AA60
:00412B66 xor ebx, ebx
:00412B68 push 00000019
:00412B6A lea ecx, dword ptr [ebp-50]
:00412B6D mov dword ptr [ebp-04], ebx
:00412B70 call 0042AA60
嗯,有点象,注册码长度可能大于20个字符。怪不得输错了注册码得不到提示,因为大
多数人一开始是不会输入那么长的一串码的。
启动TRW2000,点击OK使其最小化。
双击TurboNote+图标,TurboNote+在屏幕右下脚生成一个TurboNote+图标。
右击这个图标,会弹出一个右键菜单,选GENERAL SETTINGS,GENERAL SETTINGS窗口弹
出,点REGISTER TURBONOTE+选项卡,该卡被调到窗口最前面,在REGISTRATION CODE:
框中随便输入20个字母数字,我们后面称它串。注意,TurboNote+的注册码拒绝键盘上
的某些字符,例如[BCG]的方括号。
按CTRL+N,激活TRW。
下指令:BPX 412B53,按F5,TurboNote+再次被TRW截获。
按F10,一路走一路看,来到:
* Possible StringData Ref from Code Obj ->"SOFTWARE\SPIS Ltd\TurboNote\"
->"Registration"
|
:00412B86 push 004709B4
:00412B8B push 80000002
:00412B90 lea ecx, dword ptr [ebp-6C]
:00412B93 mov [ebp-04], 02
:00412B97 call 0044CA50
:00412B9C push 0000012C
:00412BA1 lea ecx, dword ptr [ebp-20]
:00412BA4 mov [ebp-04], 03
:00412BA8 call 0042AA60
:00412BAD push edi
:00412BAE lea ecx, dword ptr [ebp-20]
:00412BB1 mov [ebp-04], 04
:00412BB5 call 0042AF00
:00412BBA mov eax, dword ptr [ebp-4C]
:00412BBD mov ecx, dword ptr [ebp-40]
:00412BC0 mov edx, dword ptr [ebp-1C]
:00412BC3 mov eax, dword ptr [eax]
:00412BC5 mov ecx, dword ptr [ecx]
:00412BC7 mov edx, dword ptr [edx]
:00412BC9 push eax
:00412BCA push ecx
:00412BCB push edx
:00412BCC call 0044B470 <==注册模块入口,按F8进入
:00412BD1 add esp, 0000000C
:00412BD4 test eax, eax
:00412BD6 je 0 0412D2A
:00412BDC mov ecx, esi
:00412BDE call 00412DF0
:00412BE3 test eax, eax
:00412BE5 jne 00412C05
:00412BE7 mov eax, dword ptr [esi+000001B0]
:00412BED push 00000010
412BCC是注册模块入口,按F8进入,来到:
* Referenced by a CALL at Addresses:
|:00412BCC, :0044AC60, :0044AEE5
|
:0044B470 sub esp, 00000304
:0044B476 lea eax, dword ptr [esp+00000080]
:0044B47D push ebx
:0044B47E push ebp
:0044B47F push esi
:0044B480 push edi
* Possible StringData Ref from Code Obj ->"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"
->"fghijklmnopqrst"
->"uvwxyz0123456789+/="
|
:0044B481 push 00473000
:0044B486 push eax
* Reference To: KERNEL32.lstrcpyA, Ord:0000h
|
:0044B487 Call dword ptr [0046712C]
:0044B48D mov ecx, 00000040 <==从这里开始建密匙对照表
:0044B492 or e ax, FFFFFFFF
:0044B495 lea edi, dword ptr [esp+000000D2]
:0044B49C repz
:0044B49D stosd
:0044B49E mov eax, 00000041
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044B513(C)
|
:0044B4FF mov byte ptr [esp+eax+000001DC], 00
:0044B507 mov byte ptr [esp+eax+00000241], 00
:0044B50F inc eax
:0044B510 cmp eax, 00000064
:0044B513 jl 0044B4FF
:0044B515 mov esi, dword ptr [esp+00000318]
:0044B51C mov dword ptr [esp+000002A8], 3F7FDEFF
:0044B527 push esi
:0044B528 mov byte ptr [esp+000001DC], FF <==第二遍运算时使用的密匙表
:0044B530 mov byte ptr [esp+000001DD], DE
:0044B538 mov byte ptr [esp+000001DE], 7F
:0044B540 mov byte ptr [esp+000001DF], cl
:0044B547 Call dword ptr [00467128]
:0044B54D mov edx, eax
:0044B54F cmp edx, 00000014
:0044B552 jl 0044B6D5
:0044B558 mov dword ptr [esp+18], edi
:0044B55C mov ecx, 00000019
:0044B561 xor eax, eax
:0044B563 lea edi, dword ptr [esp+28]
:0044B567 lea ebp, dword ptr [edx+esi-04]
:0044B56B lea ebx, dword ptr [edx+esi-03]
:0044B56F repz
:0044B570 stosd
:0044B571 mov al, byte ptr [ebp+00]
:0044B574 lea edi, dword ptr [edx+esi-02]
:0044B578 mov byte ptr [esp+10], al
:0044B57C mov cl, byte ptr [ebx]
:0044B57E mov byte ptr [esp+11], cl
:0044B582 mov al, byte ptr [edi]
:0044B584 lea edx, dword ptr [edx+esi-01]
:0044B588 mov byte ptr [esp+12], al
:0044B58C mov dword ptr [esp+24], edx
:0044B590 push 0016EB35
:0044B595 mov cl, byte ptr [edx]
:0044B597 lea edx, dword ptr [esp+1C]
:0044B59B mov byte ptr [esp+17], cl
:0044B59F push edx
:0044B5A0 lea eax, dword ptr [esp+18]
:0044B5A4 push 00000004 <==先处理末4位
:0044B5A6 lea ecx, dword ptr [esp+34]
:0044B5AA push eax
:0044B5AB push ecx
:0044B5AC lea ecx, dword ptr [esp+000000A4]
:0044B5B3 mov dword ptr [esp+34], edi
:0044B5B7 mov [esp+28], 00
:0044B5BC call 00406F20 <==末4位处理模块,按F8进入
:0044B5C1 test eax, eax
:0044B5C3 jne 0044B5D8
:0044B5C5 mov edx, dword ptr [esp+18]
:0044B5C9 pop edi
:0044B5CA pop esi
:0044B5CB pop ebp
:0044B5CC mov byte ptr [esp+edx+1C], al
:0044B5D0 pop ebx
:0044B5D1 add esp, 00000304
:0044B5D7 ret
通过后面对注册机制的分析,可以从上面建立的密匙对照表总结出,TurboNote+的注
册码只接受0-9、A-Z、a-z、“+”和“/”,其它为无效字符。
在44B5BC按F8进入,来到406F20,这是对串尾末4位的处理。我们可以看两种串尾的结
构,一种串尾为任意码,另一种串尾为"==",两种算法的效果基本是一样的,这里我
们来看第一种。
* Referenced by a CALL at Addresses:
|:004074D6, :0044B5BC
|
:00406F20 sub esp, 000000D0
:00406F26 xor eax, eax
:00406F28 push ebx
:00406F29 mov ebx, dword ptr [esp+000000DC]
:00406F30 push ebp
:00406F31 push esi
:00406F32 mov esi, dword ptr [esp+000000E8]
:00406F39 mov ebp, ecx
:00406F3B push edi
:00406F3C mov ecx, 00000019
:00406F41 lea edi, dword ptr [esp+78]
:00406F45 repz
:00406F46 stosd
:00406F47 cmp byte ptr [ebx+esi-01], 3D <==注意这里,串尾一个"="号
:00406F4C je 0 0406FC9
:00406F4E mov ecx, 00000019 <==串尾为任意码的处理
:00406F53 xor eax, eax
:00406F55 lea edi, dword ptr [esp+10]
:00406F59 push esi
:00406F5A repz
:00406F5B stosd
:00406F5C lea eax, dword ptr [esi+2*esi] <==串长x3
:00406F5F mov edi, dword ptr [esp+000000F4]
:00406F66 shl eax, 1 <==结果x2
:00406F68 cdq
:00406F69 and edx, 00000007
:00406F6C push ebx
:00406F6D add eax, edx
:00406F6F mov ecx, ebp
:00406F71 sar eax, 03 <==结果/8
:00406F74 mov dword ptr [edi], eax <==码长关键字,记下这个地址
:00406F76 lea eax, dword ptr [esp+18]
:00406F7A push eax
:00406F7B call 00407220 <==对串尾进行处理
:00406F80 test eax, eax
:00406F82 jne 00406F91 <==成功则跳
:00406F84 pop edi
:00406F85 pop esi
:00406F86 pop ebp
:00406F87 pop ebx
:00406F88 add esp, 000000D0
:00406F8E ret 0014
* Referenced by a CALL at Address:
|:00406F7B
|
:00407220 push ebx
:00407221 push ebp
:00407222 mov ebp, dword ptr [esp+14]
:00407226 push esi
:00407227 push edi
:00407228 xor edi, edi
:0040722A xor edx, edx
:0040722C test ebp, ebp
:0040722E jle 004072D2
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004072CC(C)
|
:00407234 mov ebx, dword ptr [esp+18]
:00407238 lea esi, dword ptr [edx+01]
:0040723B movsx eax, byte ptr [ebx+esi-01] <==四位数一组,取第1位数
:00407240 mov al, byte ptr [eax+ecx+42] <==查表取值
:00407244 test al, al
:00407246 jl 004072DE
:0040724C and eax, 0000003F <==3f内有效
:0040724F shl eax, 06 <==结果=值*Ox40
:00407252 cmp esi, ebp
:00407254 jge 0040726C
:00407256 movsx ebx, byte ptr [edx+ebx+01] <==取下一位数
:0040725B mov bl, byte ptr [ebx+ecx+42] <==查表取值
:0040725F test bl, bl
:00407261 jl 004072DE
:00407263 and ebx, 0000003F <==3f内有效
:00407266 or eax, ebx <==加这个值到结果
:00407268 mov ebx, dword ptr [esp+18]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407254(C)
|
:0040726C lea ebp, dword ptr [esi+01]
:0040726F shl eax, 06 <==结果=值*Ox40
:00407272 cmp ebp, dword ptr [esp+1C]
:00407276 jge 0040728E
:00407278 movsx ebx, byte ptr [edx+ebx+02] <==取下一位数
:0040727D mov bl, byte ptr [ebx+ecx+42] <==查表取值
:00407281 test bl, bl
:00407283 jl 004072DE
:00407285 and ebx, 0000003F <==3f内有效
:00407288 or eax, ebx <==加这个值到结果
:0040728A mov ebx, dword ptr [esp+18]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407276(C)
|
:0040728E mov ebp, dword ptr [esp+1C]
:00407292 add esi, 00000002
:00407295 shl eax, 06 <==结果=值*Ox40
:00407298 cmp esi, ebp
:0040729A jge 004072AE
:0040729C movsx esi, byte ptr [edx+ebx+03] <==取最后一位数
:004072A1 mov bl, byte ptr [esi+ecx+42] <==查表取值
:004072A5 test bl, bl
:004072A7 jl 004072DE
:004072A9 and ebx, 0000003F <==3f内有效
:004072AC or eax, ebx <==加这个值到结果
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040729A(C)
|
:004072AE mov esi, dword ptr [esp+14]
:004072B2 add edx, 00000004
:004072B5 mov byte ptr [edi+esi+02], al <==结果为三位,存为新串
:004072B9 add edi, 00000003
:004072BC shr eax, 08 <==结果/Ox100
:004072BF mov byte ptr [edi+esi-02], al <==取余
:004072C3 shr eax, 08 <==结果/Ox100
:004072C6 mov byte ptr [edi+esi-03], al <==取商
:004072CA cmp edx, ebp
:004072CC jl 00407234
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040722E(C)
|
:004072D2 pop edi
:004072D3 pop esi
:004072D4 pop ebp
:004072D5 mov eax, 00000001
:004072DA pop ebx
:004072DB ret 000C
406F7B的call若运算成功,退出后会跳到406F91:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00406F82(C)
|
:00406F91 mov eax, dword ptr [edi]
:00406F93 xor ecx, ecx
:00406F95 test eax, eax
:00406F97 jle 004070F9
:00406F9D mov eax, dword ptr [esp+000000E4]
:00406FA4 lea esi, dword ptr [esp+10]
:00406FA8 sub esi, eax
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00406FB5(C)
|
:00406FAA mov dl, byte ptr [esi+eax] <==取第一遍的运算结果,存为新串
:00406FAD inc ecx
:00406FAE mov byte ptr [eax], dl <==校验关键字,记下这个地址
:00406FB0 mov edx, dword ptr [edi]
:00406FB2 inc eax
:00406FB3 cmp ecx, edx
:00406FB5 jl 00406FAA
:00406FB7 pop edi
:00406FB8 pop esi
:00406FB9 pop ebp
:00406FBA mov eax, 00000001
:00406FBF pop ebx
:00406FC0 add esp, 000000D0
:00406FC6 ret 0014
校验关键字是由串的末四位运算而来的,它实际上是注册用户名累加和的尾数。
对串的前半部分,要做两遍运算处理,其第一遍运算同样调用的是上面的模块,这里
不再赘述。
第二遍运算,是在407553的调用中进行的,我们来看一下:
* Referenced by a CALL at Address:
|:00407553
|
:00407580 mov eax, dword ptr [ecx+00000144] <==从串首取第一遍的运算结果
:00407586 mov dl, byte ptr [ecx+eax+00000148]
:0040758D mov al, byte ptr [esp+04] <==取4个字的密匙表
:00407591 xor dl, al <==4位一组,做XOR运算
:00407593 mov eax, dword ptr [esp+08]
:00407597 mov byte ptr [eax], dl
:00407599 mov edx, dword ptr [ecx+00000144]
:0040759F inc edx
:004075A0 and edx, 80000003
:004075A6 jns 004075AD
:004075A8 dec edx
:004075A9 or edx, FFFFFFFC
:004075AC inc edx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004075A6(C)
|
:004075AD mov dword ptr [ecx+00000144], edx
:004075B3 mov eax, 00000001
:004075B8 ret 0008
下面进行注册码效验:
* Referenced by a CALL at Address:
|:0040751C
|
:004075C0 sub esp, 0000001C
:004075C3 mov eax, 00000009
:004075C8 push ebp
:004075C9 push esi
:004075CA mov esi, ecx
:004075CC xor ebp, ebp
:004075CE mov ecx, dword ptr [esp+2C] <==取前面记下的码长关键字
:004075D2 push edi
:004075D3 mov edi, dword ptr [esp+2C] <==取第二遍运算结果的串首地址
:004075D7 add ecx, FFFFFFFC <==减4
:004075DA cmp ecx, eax <==大于等于9?
:004075DC jl 004075F0
:004075DE lea ebp, dword ptr [ecx-08]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004075EE(C)
|
:004075E1 mov dl, byte ptr [eax+edi] <==从第9个数取值
:004075E4 mov byte ptr [esi+eax+00000143], dl <==存入存储单元
:004075EB inc eax
:004075EC cmp eax, ecx <==取N个,N=码长关键字-4-9
:004075EE jle 004075E1
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004075DC(C)
|
:004075F0 mov byte ptr [esi+ebp+0000014C], 00
:004075F8 mov di, word ptr [edi+03]
:004075FC and edi, 0000FFFF
:00407602 lea eax, dword ptr [esp+0C]
:00407606 push edi
* Possible StringData Ref from Code Obj ->"N=%d"
|
:00407607 push 0046F31C
:0040760C push eax
* Reference To: USER32.wsprintfA, Ord:0000h
|
:0040760D Call dword ptr [004672B4]
:00407613 add esi, 000001B1
:00407619 push 0000000A
:0040761B push esi
:0040761C push edi
:0040761D call 004628BC
:00407622 add esp, 00000018
:00407625 mov dword ptr [004771BC], 00262D75
:0040762F mov eax, 00000001
:00407634 pop edi
:00407635 pop esi
:00407636 pop ebp
:00407637 add esp, 0000001C
:0040763A ret 0008
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044B633(C)
|
:0044B655 mov ecx, dword ptr [esp+1C]
:0044B659 mov byte ptr [esp+ecx+000002AC], 00
:0044B661 lea ecx, dword ptr [esp+00000090]
:0044B668 call 00407640 <==在EAX中返回4075E4处存储的值
:0044B66D mov edx, dword ptr [esp+28] <==取406FAE处存储的校验关键字
:0044B671 and edx, 000000FF
:0044B677 cmp eax, edx
- 标 题:Turbo Note+ V4.4注册机制分析 (19千字)
- 作 者:囚童
- 时 间:2001-11-7 9:28:09
- 链 接:http://bbs.pediy.com