题目:注册“豪杰超级音乐工作室 V1.1”
功能简介:
万能音频播放,支持CD、MP3、AC3、VOB、MID、WAV等多种音频格式,支持VCD、DVD的音频播放;支持多种音频文件的相互转换,DVD、VCD、CD、MID、WAV转WAV、MP3;支持磁带与音频的外部录音,轻松把磁带转换到电脑及MP3播放器上;轻松制作自己的电子音乐相册;轻松玩转音乐数字CD抓轨。
工具:SOFTICE,PEID。
引子:今天刚写完豪杰大眼睛破文,接着又遇到这个豪杰音乐工作室,一起写出破文吧。到现在为止,豪杰的几个主打产品,我基本都过了一遍了。感觉豪杰的产品比较朴实无华,注册码的算法也是中规中矩。当然各个软件稍微有些不同而已,但基本思路一样。启动软件,输入你的用户名,注册码。比如wanggang, 1111-2222-3333-4444。打开SOFTICE下断点bpx getwindowtexta,F5退出,点击确定,被拦截。按一次F12来到下面代码处了。
:00402480 83EC40 sub esp, 00000040
:00402483 8B0D38CC4000 mov ecx, dword ptr [0040CC38]
:00402489 56 push esi
* Reference To: USER32.GetWindowTextA, Ord:015Eh
|
:0040248A 8B3598914000 mov esi, dword ptr [00409198]
:00402490 8D442404 lea eax, dword ptr [esp+04]
:00402494 6A08 push 00000008
:00402496 50 push eax
:00402497 51 push ecx
:00402498 FFD6 call esi //下面这四个函数分别取一段注册码。
:0040249A A134CC4000 mov eax, dword ptr [0040CC34]
:0040249F 8D542409 lea edx, dword ptr [esp+09]
:004024A3 6A08 push 00000008
:004024A5 52 push edx
:004024A6 50 push eax
:004024A7 FFD6 call esi
:004024A9 8B1540CC4000 mov edx, dword ptr [0040CC40]
:004024AF 8D4C240E lea ecx, dword ptr [esp+0E]
:004024B3 6A08 push 00000008
:004024B5 51 push ecx
:004024B6 52 push edx
:004024B7 FFD6 call esi
:004024B9 8B0D3CCC4000 mov ecx, dword ptr [0040CC3C]
:004024BF 8D442413 lea eax, dword ptr [esp+13]
:004024C3 6A08 push 00000008
:004024C5 50 push eax
:004024C6 51 push ecx
:004024C7 FFD6 call esi
:004024C9 8B1530CC4000 mov edx, dword ptr [0040CC30]
:004024CF 6800010000 push 00000100
:004024D4 B02D mov al, 2D //"-"号的ASSIC码送AL。
:004024D6 6880CD4000 push 0040CD80
:004024DB 52 push edx
:004024DC 8844241E mov byte ptr [esp+1E], al //把减号置入注册码内做分隔符。
:004024E0 88442419 mov byte ptr [esp+19], al
:004024E4 88442414 mov byte ptr [esp+14], al
:004024E8 C644242300 mov [esp+23], 00
:004024ED FFD6 call esi //取用户名。
:004024EF A158C74000 mov eax, dword ptr [0040C758]
:004024F4 5E pop esi
:004024F5 85C0 test eax, eax
:004024F7 740E je 00402507
:004024F9 8D4C2400 lea ecx, dword ptr [esp]
:004024FD 51 push ecx
:004024FE 6880CD4000 push 0040CD80
:00402503 FFD0 call eax //这个函数计算注册码。EAX为函数地址100010A0。分析见后面。(*)
:00402505 EB0F jmp 00402516
*省去多行
:00402516 33C9 xor ecx, ecx
:00402518 8D542400 lea edx, dword ptr [esp]
:0040251C 85C0 test eax, eax //根据返回的EAX值,下面置CL。
:0040251E 0F95C1 setne cl
:00402521 52 push edx
:00402522 6880CD4000 push 0040CD80
:00402527 890D40F84000 mov dword ptr [0040F840], ecx
:0040252D E82E000000 call 00402560
:00402532 8B4C244C mov ecx, dword ptr [esp+4C]
:00402536 8B1564CD4000 mov edx, dword ptr [0040CD64]
:0040253C 83C408 add esp, 00000008
:0040253F 8D442400 lea eax, dword ptr [esp]
:00402543 50 push eax
:00402544 68E0234000 push 004023E0
:00402549 51 push ecx
* Possible Reference to Dialog: DialogID_0069
:0040254A 6A69 push 00000069
:0040254C 52 push edx
* Reference To: USER32.DialogBoxParamA, Ord:0093h
:0040254D FF15C4914000 Call dword ptr [004091C4] //显示成功信息。
:00402553 A140F84000 mov eax, dword ptr [0040F840]
:00402558 83C440 add esp, 00000040
:0040255B C3 ret
==============================================================
下面分析:00402503处的函数:(*)
:100010A0 83EC20 sub esp, 00000020
:100010A3 33C0 xor eax, eax
:100010A5 B908000000 mov ecx, 00000008
:100010AA 53 push ebx
:100010AB 56 push esi
:100010AC 57 push edi
:100010AD 8D7C240C lea edi, dword ptr [esp+0C]
:100010B1 F3 repz
:100010B2 AB stosd
:100010B3 8B442430 mov eax, dword ptr [esp+30] //用户名地址送EAX。
:100010B7 33FF xor edi, edi
:100010B9 50 push eax
:100010BA E8D1010000 call 10001290 //这个函数处理用户名。分析在后面。(**)
:100010BF 89442410 mov dword ptr [esp+10], eax //用户名变换结果送 [esp+10]
:100010C3 83C404 add esp, 00000004
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100010E9(C)
|
:100010C6 8D743C0C lea esi, dword ptr [esp+edi+0C] //变换后的用户名地址送ESI。
:100010CA 0FBE06 movsx eax, byte ptr [esi] //依次取变换后的用户名字符送EAX。
:100010CD 83F841 cmp eax, 00000041
:100010D0 7C08 jl 100010DA
:100010D2 83F85A cmp eax, 0000005A
:100010D5 7F03 jg 100010DA
:100010D7 83C020 add eax, 00000020 //如果不在A-Z之间,则加20。
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:100010D0(C), :100010D5(C)
|
:100010DA 50 push eax
:100010DB 47 inc edi
:100010DC E86F040000 call 10001550 //把字符变换为1-9或者a-z之间。 (***)
:100010E1 83C404 add esp, 00000004
:100010E4 8806 mov byte ptr [esi], al
:100010E6 83FF04 cmp edi, 00000004
:100010E9 7CDB jl 100010C6
:100010EB 33C9 xor ecx, ecx
:100010ED 8B742434 mov esi, dword ptr [esp+34] //假码地址送ESI。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001113(C)
|
:100010F1 0FBE040E movsx eax, byte ptr [esi+ecx] //假码依次送EAX。
:100010F5 83F841 cmp eax, 00000041 //判断假码字符是否在A-Z之间。
:100010F8 7C08 jl 10001102
:100010FA 83F85A cmp eax, 0000005A
:100010FD 7F03 jg 10001102
:100010FF 83C020 add eax, 00000020 //如果是,则加20。
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:100010F8(C), :100010FD(C)
|
:10001102 0FBE540C0C movsx edx, byte ptr [esp+ecx+0C] //真码送EDX。
:10001107 3BD0 cmp edx, eax //真假比较。
:10001109 0F8527010000 jne 10001236
:1000110F 41 inc ecx
:10001110 83F904 cmp ecx, 00000004
:10001113 7CDC jl 100010F1 //如果未完则循环。
:10001115 8B44240C mov eax, dword ptr [esp+0C] //第一组真码送EAX。
:10001119 33DB xor ebx, ebx
:1000111B 8D0C80 lea ecx, dword ptr [eax+4*eax] //ECX=5*EAX。
:1000111E 8D1489 lea edx, dword ptr [ecx+4*ecx] //EDX=5*ECX。
:10001121 89542410 mov dword ptr [esp+10], edx //保存EDX在第一组后面。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001148(C)
|
:10001125 8D7C1C10 lea edi, dword ptr [esp+ebx+10] //第二段真码地址送EDI。
:10001129 8A07 mov al, byte ptr [edi] //取每个真码字符。
:1000112B 50 push eax
:1000112C 53 push ebx
:1000112D 43 inc ebx
:1000112E E83D010000 call 10001270 //变换字符。 (****)
:10001133 83C408 add esp, 00000008
:10001136 33C9 xor ecx, ecx
:10001138 8AC8 mov cl, al
:1000113A 51 push ecx
:1000113B E810040000 call 10001550 // 把字符变换为1-9或者a-z之间。
:10001140 83C404 add esp, 00000004
:10001143 8807 mov byte ptr [edi], al
:10001145 83FB04 cmp ebx, 00000004
:10001148 7CDB jl 10001125
:1000114A 33C9 xor ecx, ecx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000116F(C)
|
:1000114C 0FBE440E05 movsx eax, byte ptr [esi+ecx+05] //下面比较第二段码。
:10001151 83F841 cmp eax, 00000041
:10001154 7C08 jl 1000115E
:10001156 83F85A cmp eax, 0000005A
:10001159 7F03 jg 1000115E
:1000115B 83C020 add eax, 00000020
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:10001154(C), :10001159(C)
|
:1000115E 0FBE540C10 movsx edx, byte ptr [esp+ecx+10]
:10001163 3BD0 cmp edx, eax
:10001165 0F85D6000000 jne 10001241
:1000116B 41 inc ecx
:1000116C 83F904 cmp ecx, 00000004
:1000116F 7CDB jl 1000114C
:10001171 8B442410 mov eax, dword ptr [esp+10] //EAX保存第二组码。
:10001175 8B4C2410 mov ecx, dword ptr [esp+10] //ECX保存第二组码。
:10001179 3344240C xor eax, dword ptr [esp+0C] //EAX与第一组异或。
:1000117D 33DB xor ebx, ebx
:1000117F 83C009 add eax, 00000009 //EAX加9。
:10001182 0FAF44240C imul eax, dword ptr [esp+0C] //EAX乘以第一组码。
:10001187 8D1488 lea edx, dword ptr [eax+4*ecx] //EDX=4*ECX+EAX。
:1000118A 89542414 mov dword ptr [esp+14], edx //保存结果。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100011A4(C)
|
:1000118E 8D7C1C14 lea edi, dword ptr [esp+ebx+14] //取真码地址。
:10001192 43 inc ebx
:10001193 0FBE07 movsx eax, byte ptr [edi] //取每位真码送EAX。
:10001196 50 push eax
:10001197 E8B4030000 call 10001550 // 把字符变换为1-9或者a-z之间。
:1000119C 83C404 add esp, 00000004
:1000119F 8807 mov byte ptr [edi], al
:100011A1 83FB04 cmp ebx, 00000004
:100011A4 7CE8 jl 1000118E
:100011A6 33C9 xor ecx, ecx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100011CB(C)
|
:100011A8 0FBE440E0A movsx eax, byte ptr [esi+ecx+0A] //下面比较第三段注册码。
:100011AD 83F841 cmp eax, 00000041
:100011B0 7C08 jl 100011BA
:100011B2 83F85A cmp eax, 0000005A
:100011B5 7F03 jg 100011BA
:100011B7 83C020 add eax, 00000020
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:100011B0(C), :100011B5(C)
|
:100011BA 0FBE540C14 movsx edx, byte ptr [esp+ecx+14]
:100011BF 3BD0 cmp edx, eax
:100011C1 0F8585000000 jne 1000124C
:100011C7 41 inc ecx
:100011C8 83F904 cmp ecx, 00000004
:100011CB 7CDB jl 100011A8
:100011CD 8B4C2410 mov ecx, dword ptr [esp+10] //ECX保存第二段注册码。
:100011D1 8B442414 mov eax, dword ptr [esp+14] //EAX保存第三段注册码。
:100011D5 0FAF4C2414 imul ecx, dword ptr [esp+14] //ECX乘以第三段注册码。
:100011DA 83C106 add ecx, 00000006 //ECX加6。
:100011DD 33FF xor edi, edi
:100011DF 0FAF4C240C imul ecx, dword ptr [esp+0C] //ECX乘以第一段注册码。
:100011E4 2BC8 sub ecx, eax //ECX=ECX-EAX。
:100011E6 8D14C1 lea edx, dword ptr [ecx+8*eax] //EDX=ECX+8*EAX。
:100011E9 89542418 mov dword ptr [esp+18], edx //保存结果。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001203(C)
|
:100011ED 8D5C3C18 lea ebx, dword ptr [esp+edi+18] //取真码地址送EBX。
:100011F1 47 inc edi
:100011F2 0FBE03 movsx eax, byte ptr [ebx] //取每位字符送EAX。
:100011F5 50 push eax
:100011F6 E855030000 call 10001550 // 把字符变换为1-9或者a-z之间。
:100011FB 83C404 add esp, 00000004
:100011FE 8803 mov byte ptr [ebx], al
:10001200 83FF04 cmp edi, 00000004
:10001203 7CE8 jl 100011ED
:10001205 33C9 xor ecx, ecx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001226(C)
|
:10001207 0FBE440E0F movsx eax, byte ptr [esi+ecx+0F] //下面比较第四段注册码。
:1000120C 83F841 cmp eax, 00000041
:1000120F 7C08 jl 10001219
:10001211 83F85A cmp eax, 0000005A
:10001214 7F03 jg 10001219
:10001216 83C020 add eax, 00000020
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:1000120F(C), :10001214(C)
|
:10001219 0FBE540C18 movsx edx, byte ptr [esp+ecx+18]
:1000121E 3BD0 cmp edx, eax
:10001220 7535 jne 10001257
:10001222 41 inc ecx
:10001223 83F904 cmp ecx, 00000004
:10001226 7CDF jl 10001207
:10001228 B801000000 mov eax, 00000001 //注册码正确则置EAX为1。
:1000122D 5F pop edi
:1000122E 5E pop esi
:1000122F 5B pop ebx
:10001230 83C420 add esp, 00000020
:10001233 C20800 ret 0008
==============================================================
下面是100010BA处 call 10001290(**)函数的代码:
:10001290 81EC00020000 sub esp, 00000200
:10001296 33C0 xor eax, eax
:10001298 B980000000 mov ecx, 00000080
:1000129D 53 push ebx
:1000129E 56 push esi
:1000129F 33DB xor ebx, ebx
:100012A1 57 push edi
:100012A2 55 push ebp
:100012A3 8D7C2410 lea edi, dword ptr [esp+10]
:100012A7 F3 repz
:100012A8 AB stosd
:100012A9 8BB42414020000 mov esi, dword ptr [esp+00000214] //用户名地址送ESI。
:100012B0 56 push esi
* Reference To: KERNEL32.lstrlenA, Ord:0308h
|
:100012B1 FF1504600010 Call dword ptr [10006004] //取用户名长度。
:100012B7 3D00020000 cmp eax, 00000200
:100012BC 8BE8 mov ebp, eax
:100012BE 7612 jbe 100012D2
:100012C0 BD00020000 mov ebp, 00000200
:100012C5 8D7C2410 lea edi, dword ptr [esp+10]
:100012C9 B980000000 mov ecx, 00000080
:100012CE F3 repz
:100012CF A5 movsd
:100012D0 EB0C jmp 100012DE
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100012BE(C)
|
:100012D2 8D442410 lea eax, dword ptr [esp+10]
:100012D6 56 push esi
:100012D7 50 push eax
* Reference To: KERNEL32.lstrcpyA, Ord:0302h
|
:100012D8 FF1584600010 Call dword ptr [10006084] //复制用户名到另外一地址。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100012D0(U)
|
:100012DE 8BC5 mov eax, ebp //用户名长度送EAX。
:100012E0 99 cdq
:100012E1 83E203 and edx, 00000003
:100012E4 03C2 add eax, edx
:100012E6 C1F802 sar eax, 02 //EAX右移2次。
:100012E9 F7C503000000 test ebp, 00000003
:100012EF 8BF0 mov esi, eax
:100012F1 7401 je 100012F4
:100012F3 46 inc esi
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100012F1(C)
|
:100012F4 33FF xor edi, edi
:100012F6 85ED test ebp, ebp
:100012F8 7E17 jle 10001311
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000130F(C)
|
:100012FA 8B443C10 mov eax, dword ptr [esp+edi+10] //用户名字符依次送EAX。
:100012FE 50 push eax
:100012FF 57 push edi
:10001300 47 inc edi
:10001301 E86AFFFFFF call 10001270 // 用户名字符依次进行移位变换。
:10001306 88443C17 mov byte ptr [esp+edi+17], al //送另一地址保存。
:1000130A 83C408 add esp, 00000008
:1000130D 3BFD cmp edi, ebp
:1000130F 7CE9 jl 100012FA //未完继续。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100012F8(C)
|
:10001311 33FF xor edi, edi
:10001313 85F6 test esi, esi
:10001315 7E1A jle 10001331
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000132F(C)
|
:10001317 035CBC10 add ebx, dword ptr [esp+4*edi+10] //变换后的用户名依次累加到EBX内。
:1000131B 8BC7 mov eax, edi //右移次数送EAX。
:1000131D 83E01F and eax, 0000001F
:10001320 47 inc edi
:10001321 50 push eax
:10001322 53 push ebx
:10001323 E808020000 call 10001530 //把EBX内的值右移EAX次。
:10001328 83C408 add esp, 00000008
:1000132B 8BD8 mov ebx, eax //新结果送EBX保存。
:1000132D 3BFE cmp edi, esi
:1000132F 7CE6 jl 10001317 //未完继续。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001315(C)
|
:10001331 8BC3 mov eax, ebx
:10001333 5D pop ebp
:10001334 5F pop edi
:10001335 5E pop esi
:10001336 5B pop ebx
:10001337 81C400020000 add esp, 00000200
:1000133D C3 ret
==============================================================
下面分析:100010DC 处的函数 call 10001550。(***)
:10001550 8B442404 mov eax, dword ptr [esp+04] //依次取变换后的用户名(或者注册码)
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001591(U)
|
:10001554 83E07F and eax, 0000007F //只取低字节。
:10001557 3C41 cmp al, 41 //判断是否在A-Z之间。
:10001559 7208 jb 10001563
:1000155B 83F85A cmp eax, 0000005A
:1000155E 7F03 jg 10001563
:10001560 83C820 or eax, 00000020 //如果是,则加20变为小写字符。
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:10001559(C), :1000155E(C)
|
:10001563 83F86F cmp eax, 0000006F
:10001566 7505 jne 1000156D
:10001568 35FF000000 xor eax, 000000FF
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001566(C)
|
:1000156D 83F830 cmp eax, 00000030 //与30比较。
:10001570 7505 jne 10001577
:10001572 35FF000000 xor eax, 000000FF
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001570(C)
|
:10001577 83F861 cmp eax, 00000061 //判断是否在a-z之间。如果是则OK。
:1000157A 7C05 jl 10001581
:1000157C 83F87A cmp eax, 0000007A
:1000157F 7E12 jle 10001593
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000157A(C)
|
:10001581 83F831 cmp eax, 00000031 //判断是否在1-9之间,如果是也OK。
:10001584 7C05 jl 1000158B
:10001586 83F839 cmp eax, 00000039
:10001589 7E08 jle 10001593
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001584(C)
|
:1000158B 83F03F xor eax, 0000003F
:1000158E 83C831 or eax, 00000031
:10001591 EBC1 jmp 10001554
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:1000157F(C), :10001589(C)
|
:10001593 C3 ret
==============================================================
下面分析:1000112E处的函数 call 10001270 。 (****)
:10001270 53 push ebx
:10001271 8A442408 mov al, byte ptr [esp+08] //取循环次数到AL。
:10001275 8A5C240C mov bl, byte ptr [esp+0C] //取参数到BL。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001284(C)
|
:10001279 F6C3C3 test bl, C3 //测试BL。
:1000127C 7A01 jpe 1000127F //如果为偶数个1,则跳。
:1000127E F9 stc //否则置进位标志为1。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000127C(C)
|
:1000127F C0DB01 rcr bl, 01 //BL右移1次。
:10001282 FEC8 dec al //循环次数递减。
:10001284 75F3 jne 10001279 //未完继续。
:10001286 885C240C mov byte ptr [esp+0C], bl //最后的结果保存。
:1000128A 8A44240C mov al, byte ptr [esp+0C] //由AL返回主调函数。
:1000128E 5B pop ebx
:1000128F C3 ret
==============================================================
后记:
豪杰系列《超级解霸3000英雄版》、《豪杰超级DVDIII》、《豪杰大眼睛2.1》、《豪杰视频通2.0》、《豪杰超级音乐工作室1.1》中,我还有《豪杰超级DVDIII》没有分析。都一样的方法。希望对菜鸟能够起点作用。感谢您的阅读!
结论:
用户名:wanggang
注册码:7zq3-1w5q-splq-5l5s
完稿日期:2006/1/28
qduwg
qduwg@163.com