文章作者: qduwg
题目:注册“豪杰超级音乐工作室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下断点bpxgetwindowtexta,F5退出,点击确定,被拦截。按一次F12来到下面代码处了。
:0040248083EC40subesp,00000040
:004024838B0D38CC4000movecx,dwordptr[0040CC38]
:0040248956pushesi
*ReferenceTo:USER32.GetWindowTextA,Ord:015Eh
|
:0040248A8B3598914000movesi,dwordptr[00409198]
:004024908D442404leaeax,dwordptr[esp+04]
:004024946A08push00000008
:0040249650pusheax
:0040249751pushecx
:00402498FFD6callesi//下面这四个函数分别取一段注册码。
:0040249AA134CC4000moveax,dwordptr[0040CC34]
:0040249F8D542409leaedx,dwordptr[esp+09]
:004024A36A08push00000008
:004024A552pushedx
:004024A650pusheax
:004024A7FFD6callesi
:004024A98B1540CC4000movedx,dwordptr[0040CC40]
:004024AF8D4C240Eleaecx,dwordptr[esp+0E]
:004024B36A08push00000008
:004024B551pushecx
:004024B652pushedx
:004024B7FFD6callesi
:004024B98B0D3CCC4000movecx,dwordptr[0040CC3C]
:004024BF8D442413leaeax,dwordptr[esp+13]
:004024C36A08push00000008
:004024C550pusheax
:004024C651pushecx
:004024C7FFD6callesi
:004024C98B1530CC4000movedx,dwordptr[0040CC30]
:004024CF6800010000push00000100
:004024D4B02Dmoval,2D//"-"号的ASSIC码送AL。
:004024D66880CD4000push0040CD80
:004024DB52pushedx
:004024DC8844241Emovbyteptr[esp+1E],al//把减号置入注册码内做分隔符。
:004024E088442419movbyteptr[esp+19],al
:004024E488442414movbyteptr[esp+14],al
:004024E8C644242300mov[esp+23],00
:004024EDFFD6callesi//取用户名。
:004024EFA158C74000moveax,dwordptr[0040C758]
:004024F45Epopesi
:004024F585C0testeax,eax
:004024F7740Eje00402507
:004024F98D4C2400leaecx,dwordptr[esp]
:004024FD51pushecx
:004024FE6880CD4000push0040CD80
:00402503FFD0calleax//这个函数计算注册码。EAX为函数地址100010A0。分析见后面。(*)
:00402505EB0Fjmp00402516
*省去多行
:0040251633C9xorecx,ecx
:004025188D542400leaedx,dwordptr[esp]
:0040251C85C0testeax,eax//根据返回的EAX值,下面置CL。
:0040251E0F95C1setnecl
:0040252152pushedx
:004025226880CD4000push0040CD80
:00402527890D40F84000movdwordptr[0040F840],ecx
:0040252DE82E000000call00402560
:004025328B4C244Cmovecx,dwordptr[esp+4C]
:004025368B1564CD4000movedx,dwordptr[0040CD64]
:0040253C83C408addesp,00000008
:0040253F8D442400leaeax,dwordptr[esp]
:0040254350pusheax
:0040254468E0234000push004023E0
:0040254951pushecx
*PossibleReferencetoDialog:DialogID_0069
:0040254A6A69push00000069
:0040254C52pushedx
*ReferenceTo:USER32.DialogBoxParamA,Ord:0093h
:0040254DFF15C4914000Calldwordptr[004091C4]//显示成功信息。
:00402553A140F84000moveax,dwordptr[0040F840]
:0040255883C440addesp,00000040
:0040255BC3ret
==============================================================
下面分析:00402503处的函数:(*)
:100010A083EC20subesp,00000020
:100010A333C0xoreax,eax
:100010A5B908000000movecx,00000008
:100010AA53pushebx
:100010AB56pushesi
:100010AC57pushedi
:100010AD8D7C240Cleaedi,dwordptr[esp+0C]
:100010B1F3repz
:100010B2ABstosd
:100010B38B442430moveax,dwordptr[esp+30]//用户名地址送EAX。
:100010B733FFxoredi,edi
:100010B950pusheax
:100010BAE8D1010000call10001290//这个函数处理用户名。分析在后面。(**)
:100010BF89442410movdwordptr[esp+10],eax//用户名变换结果送[esp+10]
:100010C383C404addesp,00000004
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:100010E9(C)
|
:100010C68D743C0Cleaesi,dwordptr[esp+edi+0C]//变换后的用户名地址送ESI。
:100010CA0FBE06movsxeax,byteptr[esi]//依次取变换后的用户名字符送EAX。
:100010CD83F841cmpeax,00000041
:100010D07C08jl100010DA
:100010D283F85Acmpeax,0000005A
:100010D57F03jg100010DA
:100010D783C020addeax,00000020//如果不在A-Z之间,则加20。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddresses:
|:100010D0(C),:100010D5(C)
|
:100010DA50pusheax
:100010DB47incedi
:100010DCE86F040000call10001550//把字符变换为1-9或者a-z之间。(***)
:100010E183C404addesp,00000004
:100010E48806movbyteptr[esi],al
:100010E683FF04cmpedi,00000004
:100010E97CDBjl100010C6
:100010EB33C9xorecx,ecx
:100010ED8B742434movesi,dwordptr[esp+34]//假码地址送ESI。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001113(C)
|
:100010F10FBE040Emovsxeax,byteptr[esi+ecx]//假码依次送EAX。
:100010F583F841cmpeax,00000041//判断假码字符是否在A-Z之间。
:100010F87C08jl10001102
:100010FA83F85Acmpeax,0000005A
:100010FD7F03jg10001102
:100010FF83C020addeax,00000020//如果是,则加20。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddresses:
|:100010F8(C),:100010FD(C)
|
:100011020FBE540C0Cmovsxedx,byteptr[esp+ecx+0C]//真码送EDX。
:100011073BD0cmpedx,eax//真假比较。
:100011090F8527010000jne10001236
:1000110F41incecx
:1000111083F904cmpecx,00000004
:100011137CDCjl100010F1//如果未完则循环。
:100011158B44240Cmoveax,dwordptr[esp+0C]//第一组真码送EAX。
:1000111933DBxorebx,ebx
:1000111B8D0C80leaecx,dwordptr[eax+4*eax]//ECX=5*EAX。
:1000111E8D1489leaedx,dwordptr[ecx+4*ecx]//EDX=5*ECX。
:1000112189542410movdwordptr[esp+10],edx//保存EDX在第一组后面。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001148(C)
|
:100011258D7C1C10leaedi,dwordptr[esp+ebx+10]//第二段真码地址送EDI。
:100011298A07moval,byteptr[edi]//取每个真码字符。
:1000112B50pusheax
:1000112C53pushebx
:1000112D43incebx
:1000112EE83D010000call10001270//变换字符。(****)
:1000113383C408addesp,00000008
:1000113633C9xorecx,ecx
:100011388AC8movcl,al
:1000113A51pushecx
:1000113BE810040000call10001550//把字符变换为1-9或者a-z之间。
:1000114083C404addesp,00000004
:100011438807movbyteptr[edi],al
:1000114583FB04cmpebx,00000004
:100011487CDBjl10001125
:1000114A33C9xorecx,ecx
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:1000116F(C)
|
:1000114C0FBE440E05movsxeax,byteptr[esi+ecx+05]//下面比较第二段码。
:1000115183F841cmpeax,00000041
:100011547C08jl1000115E
:1000115683F85Acmpeax,0000005A
:100011597F03jg1000115E
:1000115B83C020addeax,00000020
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddresses:
|:10001154(C),:10001159(C)
|
:1000115E0FBE540C10movsxedx,byteptr[esp+ecx+10]
:100011633BD0cmpedx,eax
:100011650F85D6000000jne10001241
:1000116B41incecx
:1000116C83F904cmpecx,00000004
:1000116F7CDBjl1000114C
:100011718B442410moveax,dwordptr[esp+10]//EAX保存第二组码。
:100011758B4C2410movecx,dwordptr[esp+10]//ECX保存第二组码。
:100011793344240Cxoreax,dwordptr[esp+0C]//EAX与第一组异或。
:1000117D33DBxorebx,ebx
:1000117F83C009addeax,00000009//EAX加9。
:100011820FAF44240Cimuleax,dwordptr[esp+0C]//EAX乘以第一组码。
:100011878D1488leaedx,dwordptr[eax+4*ecx]//EDX=4*ECX+EAX。
:1000118A89542414movdwordptr[esp+14],edx//保存结果。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:100011A4(C)
|
:1000118E8D7C1C14leaedi,dwordptr[esp+ebx+14]//取真码地址。
:1000119243incebx
:100011930FBE07movsxeax,byteptr[edi]//取每位真码送EAX。
:1000119650pusheax
:10001197E8B4030000call10001550//把字符变换为1-9或者a-z之间。
:1000119C83C404addesp,00000004
:1000119F8807movbyteptr[edi],al
:100011A183FB04cmpebx,00000004
:100011A47CE8jl1000118E
:100011A633C9xorecx,ecx
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:100011CB(C)
|
:100011A80FBE440E0Amovsxeax,byteptr[esi+ecx+0A]//下面比较第三段注册码。
:100011AD83F841cmpeax,00000041
:100011B07C08jl100011BA
:100011B283F85Acmpeax,0000005A
:100011B57F03jg100011BA
:100011B783C020addeax,00000020
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddresses:
|:100011B0(C),:100011B5(C)
|
:100011BA0FBE540C14movsxedx,byteptr[esp+ecx+14]
:100011BF3BD0cmpedx,eax
:100011C10F8585000000jne1000124C
:100011C741incecx
:100011C883F904cmpecx,00000004
:100011CB7CDBjl100011A8
:100011CD8B4C2410movecx,dwordptr[esp+10]//ECX保存第二段注册码。
:100011D18B442414moveax,dwordptr[esp+14]//EAX保存第三段注册码。
:100011D50FAF4C2414imulecx,dwordptr[esp+14]//ECX乘以第三段注册码。
:100011DA83C106addecx,00000006//ECX加6。
:100011DD33FFxoredi,edi
:100011DF0FAF4C240Cimulecx,dwordptr[esp+0C]//ECX乘以第一段注册码。
:100011E42BC8subecx,eax//ECX=ECX-EAX。
:100011E68D14C1leaedx,dwordptr[ecx+8*eax]//EDX=ECX+8*EAX。
:100011E989542418movdwordptr[esp+18],edx//保存结果。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001203(C)
|
:100011ED8D5C3C18leaebx,dwordptr[esp+edi+18]//取真码地址送EBX。
:100011F147incedi
:100011F20FBE03movsxeax,byteptr[ebx]//取每位字符送EAX。
:100011F550pusheax
:100011F6E855030000call10001550//把字符变换为1-9或者a-z之间。
:100011FB83C404addesp,00000004
:100011FE8803movbyteptr[ebx],al
:1000120083FF04cmpedi,00000004
:100012037CE8jl100011ED
:1000120533C9xorecx,ecx
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001226(C)
|
:100012070FBE440E0Fmovsxeax,byteptr[esi+ecx+0F]//下面比较第四段注册码。
:1000120C83F841cmpeax,00000041
:1000120F7C08jl10001219
:1000121183F85Acmpeax,0000005A
:100012147F03jg10001219
:1000121683C020addeax,00000020
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddresses:
|:1000120F(C),:10001214(C)
|
:100012190FBE540C18movsxedx,byteptr[esp+ecx+18]
:1000121E3BD0cmpedx,eax
:100012207535jne10001257
:1000122241incecx
:1000122383F904cmpecx,00000004
:100012267CDFjl10001207
:10001228B801000000moveax,00000001//注册码正确则置EAX为1。
:1000122D5Fpopedi
:1000122E5Epopesi
:1000122F5Bpopebx
:1000123083C420addesp,00000020
:10001233C20800ret0008
==============================================================
下面是100010BA处call10001290(**)函数的代码:
:1000129081EC00020000subesp,00000200
:1000129633C0xoreax,eax
:10001298B980000000movecx,00000080
:1000129D53pushebx
:1000129E56pushesi
:1000129F33DBxorebx,ebx
:100012A157pushedi
:100012A255pushebp
:100012A38D7C2410leaedi,dwordptr[esp+10]
:100012A7F3repz
:100012A8ABstosd
:100012A98BB42414020000movesi,dwordptr[esp+00000214]//用户名地址送ESI。
:100012B056pushesi
*ReferenceTo:KERNEL32.lstrlenA,Ord:0308h
|
:100012B1FF1504600010Calldwordptr[10006004]//取用户名长度。
:100012B73D00020000cmpeax,00000200
:100012BC8BE8movebp,eax
:100012BE7612jbe100012D2
:100012C0BD00020000movebp,00000200
:100012C58D7C2410leaedi,dwordptr[esp+10]
:100012C9B980000000movecx,00000080
:100012CEF3repz
:100012CFA5movsd
:100012D0EB0Cjmp100012DE
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:100012BE(C)
|
:100012D28D442410leaeax,dwordptr[esp+10]
:100012D656pushesi
:100012D750pusheax
*ReferenceTo:KERNEL32.lstrcpyA,Ord:0302h
|
:100012D8FF1584600010Calldwordptr[10006084]//复制用户名到另外一地址。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:100012D0(U)
|
:100012DE8BC5moveax,ebp//用户名长度送EAX。
:100012E099cdq
:100012E183E203andedx,00000003
:100012E403C2addeax,edx
:100012E6C1F802sareax,02//EAX右移2次。
:100012E9F7C503000000testebp,00000003
:100012EF8BF0movesi,eax
:100012F17401je100012F4
:100012F346incesi
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:100012F1(C)
|
:100012F433FFxoredi,edi
:100012F685EDtestebp,ebp
:100012F87E17jle10001311
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:1000130F(C)
|
:100012FA8B443C10moveax,dwordptr[esp+edi+10]//用户名字符依次送EAX。
:100012FE50pusheax
:100012FF57pushedi
:1000130047incedi
:10001301E86AFFFFFFcall10001270//用户名字符依次进行移位变换。
:1000130688443C17movbyteptr[esp+edi+17],al//送另一地址保存。
:1000130A83C408addesp,00000008
:1000130D3BFDcmpedi,ebp
:1000130F7CE9jl100012FA//未完继续。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:100012F8(C)
|
:1000131133FFxoredi,edi
:1000131385F6testesi,esi
:100013157E1Ajle10001331
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:1000132F(C)
|
:10001317035CBC10addebx,dwordptr[esp+4*edi+10]//变换后的用户名依次累加到EBX内。
:1000131B8BC7moveax,edi//右移次数送EAX。
:1000131D83E01Fandeax,0000001F
:1000132047incedi
:1000132150pusheax
:1000132253pushebx
:10001323E808020000call10001530//把EBX内的值右移EAX次。
:1000132883C408addesp,00000008
:1000132B8BD8movebx,eax//新结果送EBX保存。
:1000132D3BFEcmpedi,esi
:1000132F7CE6jl10001317//未完继续。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001315(C)
|
:100013318BC3moveax,ebx
:100013335Dpopebp
:100013345Fpopedi
:100013355Epopesi
:100013365Bpopebx
:1000133781C400020000addesp,00000200
:1000133DC3ret
==============================================================
下面分析:100010DC处的函数call10001550。(***)
:100015508B442404moveax,dwordptr[esp+04]//依次取变换后的用户名(或者注册码)
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001591(U)
|
:1000155483E07Fandeax,0000007F//只取低字节。
:100015573C41cmpal,41//判断是否在A-Z之间。
:100015597208jb10001563
:1000155B83F85Acmpeax,0000005A
:1000155E7F03jg10001563
:1000156083C820oreax,00000020//如果是,则加20变为小写字符。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddresses:
|:10001559(C),:1000155E(C)
|
:1000156383F86Fcmpeax,0000006F
:100015667505jne1000156D
:1000156835FF000000xoreax,000000FF
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001566(C)
|
:1000156D83F830cmpeax,00000030//与30比较。
:100015707505jne10001577
:1000157235FF000000xoreax,000000FF
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001570(C)
|
:1000157783F861cmpeax,00000061//判断是否在a-z之间。如果是则OK。
:1000157A7C05jl10001581
:1000157C83F87Acmpeax,0000007A
:1000157F7E12jle10001593
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:1000157A(C)
|
:1000158183F831cmpeax,00000031//判断是否在1-9之间,如果是也OK。
:100015847C05jl1000158B
:1000158683F839cmpeax,00000039
:100015897E08jle10001593
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001584(C)
|
:1000158B83F03Fxoreax,0000003F
:1000158E83C831oreax,00000031
:10001591EBC1jmp10001554
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddresses:
|:1000157F(C),:10001589(C)
|
:10001593C3ret
==============================================================
下面分析:1000112E处的函数call10001270。(****)
:1000127053pushebx
:100012718A442408moval,byteptr[esp+08]//取循环次数到AL。
:100012758A5C240Cmovbl,byteptr[esp+0C]//取参数到BL。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:10001284(C)
|
:10001279F6C3C3testbl,C3//测试BL。
:1000127C7A01jpe1000127F//如果为偶数个1,则跳。
:1000127EF9stc//否则置进位标志为1。
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:1000127C(C)
|
:1000127FC0DB01rcrbl,01//BL右移1次。
:10001282FEC8decal//循环次数递减。
:1000128475F3jne10001279//未完继续。
:10001286885C240Cmovbyteptr[esp+0C],bl//最后的结果保存。
:1000128A8A44240Cmoval,byteptr[esp+0C]//由AL返回主调函数。
:1000128E5Bpopebx
:1000128FC3ret
==============================================================
后记:
豪杰系列《超级解霸3000英雄版》、《豪杰超级DVDIII》、《豪杰大眼睛2.1》、《豪杰视频通2.0》、《豪杰超级音乐工作室1.1》中,我还有《豪杰超级DVDIII》没有分析。都一样的方法。希望对菜鸟能够起点作用。感谢您的阅读!
结论:
用户名:wanggang
注册码:7zq3-1w5q-splq-5l5s