【软件大小】: 2216 KB
【软件语言】: 英文
【软件类别】: 国外软件 / 共享版 / 音频处理
【应用平台】: Win9x/NT/2000/XP
【加入时间】: 2005-02-15 15:27:50
【下载次数】: 9691
【推荐等级】: ★★★★
【软件下载】: 天空软件站
【作者声明】:初学破解,仅作学习交流之用,失误之处敬请大侠赐教!
【破解工具】:Ollydbg1.10、PEid
用PEid检测无壳,为VC编写,用OD中载入,输入用户名:sharpair及假码:SMRPR000B07807128712"下断getwindowtexta,你一定会来到如下代码(多用几次Ctrl+F9):
程序调试后会有异常,用Shift+F9可跳过!但是调试时F9、F8键无效,但可用菜单项调试,看
输入表中有SetUnhandledExceptionFilter函数,懒得跟了,得过且过吧!^_^
【算法的第一部分】
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
..........
004207E0 push -1
004207E2 push smrpro.004D2BC0 ; SE handler installation
004207E7 mov eax,dword ptr fs:[0]
004207ED push eax
004207EE mov dword ptr fs:[0],esp
004207F5 sub esp,40
004207F8 push ebx
004207F9 push ebp
004207FA push esi
004207FB push edi
004207FC mov esi,ecx
004207FE push 1
00420800 mov dword ptr ss:[esp+14],esi
00420804 call smrpro.004A5162
00420809 push 7F02 ; /RsrcName = IDC_WAIT
0042080E push 0 ; |hInst = NULL
00420810 call dword ptr ds:[<&USER32.Lo>; \LoadCursorA
00420816 push eax ; /hCursor
00420817 call dword ptr ds:[<&USER32.Se>; \SetCursor
0042081D push 1388 ; /Timeout = 5000. ms
00420822 call dword ptr ds:[<&KERNEL32.>; \我们点注册后出现的停顿由此函数产生
00420828 mov ebp,dword ptr ds:[esi+5C] ; ebp="65148455",假码
0042082B mov esi,smrpro.004F8B54 ; esi="4L14A67H9P72Z569WY90",真码已产生了?
00420830 mov eax,ebp ; 后面一般的老套路,按位比较
00420832 mov dl,byte ptr ds:[eax]
00420834 mov bl,byte ptr ds:[esi]
00420836 mov cl,dl
00420838 cmp dl,bl
0042083A jnz short smrpro.0042085A
0042083C test cl,cl
0042083E je short smrpro.00420856
00420840 mov dl,byte ptr ds:[eax+1]
00420843 mov bl,byte ptr ds:[esi+1]
00420846 mov cl,dl
00420848 cmp dl,bl
0042084A jnz short smrpro.0042085A
0042084C add eax,2
0042084F add esi,2
00420852 test cl,cl
00420854 jnz short smrpro.00420832
00420856 xor ebx,ebx
00420858 jmp short smrpro.0042085F
0042085A sbb ebx,ebx ;注意这两句,会使ebx=-1
0042085C sbb ebx,-1 ;注意这后面出现了一段和上面类同的比较,莫非有两个注册码?
0042085F mov esi,smrpro.004F8B38 ;ASCII "#j14NeRo111143000059"
00420864 mov eax,ebp
00420866 mov dl,byte ptr ds:[eax]
00420868 mov cl,dl
0042086A cmp dl,byte ptr ds:[esi]
0042086C jnz short smrpro.0042088A
0042086E test cl,cl
00420870 je short smrpro.00420886
00420872 mov dl,byte ptr ds:[eax+1]
00420875 mov cl,dl
00420877 cmp dl,byte ptr ds:[esi+1]
0042087A jnz short smrpro.0042088A
0042087C add eax,2
0042087F add esi,2
00420882 test cl,cl
00420884 jnz short smrpro.00420866
00420886 xor edx,edx
00420888 jmp short smrpro.0042088F
0042088A sbb edx,edx ; edx清0
0042088C sbb edx,-1 ; edx=1
0042088F mov edi,ebp
00420891 or ecx,FFFFFFFF
00420894 xor eax,eax
00420896 repne scas byte ptr es:[edi]
00420898 not ecx
0042089A dec ecx ; 上面一小段经典的取字串位数代码
0042089B cmp ecx,14 ; 正确码应该为20位
0042089E jnz smrpro.00420B89
004208A4 test ebx,ebx ; ebx的值还记得吗,上面比较通过后被置为0
004208A6 je smrpro.00420B89 ; 这个跳转很远,凭感觉不大对
004208AC test edx,edx ; 呵呵,又来一个判断
004208AE je smrpro.00420B89 ; 呵呵,原来上面为内置的两个黑名单注册码
004208B4 cmp byte ptr ss:[ebp+5],30 ; 这里才是真正的正假码比较开始,从假码第6位开始
004208B8 jnz short smrpro.004208D0
004208BA cmp byte ptr ss:[ebp+6],30 ; 真码第7位,同第6位,也应该为0
004208BE jnz short smrpro.004208D0
004208C0 cmp byte ptr ss:[ebp+7],30 ; 真码第8位为0
004208C4 jnz short smrpro.004208D0
004208C6 cmp byte ptr ss:[ebp+8],30 ; 真码第9位不能为0(上面的判断也是跳向这里)
004208CA je smrpro.00420B89
004208D0 xor ecx,ecx ; ecx清0
004208D2 mov edx,ebp ; 再取假码
004208D4 mov al,byte ptr ds:[edx] ; 从第1位开始取
-------------------------------------------------------------------------
004208D6 cmp al,61
004208D8 jl short smrpro.004208E0
004208DA cmp al,66
004208DC jg short smrpro.004208E0
004208DE sub al,7
-------------------------------------------------------------------------
这一小段代码很简单,若字符为(a,f)之间的则sub al,7
004208E0 shl al,4 ; 结果再shl al,4,注意为al,高位会自动舍去
004208E3 mov byte ptr ss:[esp+ecx+44],al ; 再存入ss:[esp+ecx+44]中,ecx作指针用
004208E7 mov al,byte ptr ds:[edx+1] ; 取假码第2位
004208EA cmp al,61 ; 以下的判断同上,不过后面的处理方法不同
004208EC jl short smrpro.004208F6
004208EE cmp al,66
004208F0 jg short smrpro.004208F6
004208F2 sub al,57 ; 若字符在(a,f)之间则sub al,57,否则sub al,30
004208F4 jmp short smrpro.004208F8
004208F6 sub al,30
004208F8 mov bl,byte ptr ss:[esp+ecx+44] ; 第1位计算后的值取到bl中
004208FC add edx,2 ; add edx,2,调整指针取下一组字符
004208FF add bl,al ; 1、2位转换后的值累加到bl中
00420901 mov byte ptr ss:[esp+ecx+44],bl ; 累加和再存到ss:[esp+ecx+44]中
00420905 inc ecx ; ecx步进1
00420906 cmp ecx,0A ; 循环10次,取完假码
00420909 jl short smrpro.004208D4
0042090B push 0 ;结束后我的累加值在内存中为4D 40 20 00 B0 78 07 12 87 12
0042090D push smrpro.004F8428 ; 固定串压入堆栈"SMRPRO0000"
00420912 lea eax,dword ptr ss:[esp+34] ; 这个地址可能用来传出结果
00420916 push 0A ; 0A压入堆栈
00420918 lea ecx,dword ptr ss:[esp+50] ; 不用说,指向注册码前10位的计算值
0042091C push eax
0042091D push ecx
0042091E call smrpro.00401DC0 ; 这个Call干什么呢?我们要跟进去看一下
00420923 mov al,byte ptr ss:[esp+40] ;注意这里ss:[esp+40]指向"55 14 37 7B 1C 45 41 72 B2 A6"
00420927 add esp,14 ; 调整一下堆栈,迷惑cracker一下^_^
0042092A cmp al,72 ; 往下看可知要满足条件我们Call之后的ss:[esp+40]中
0042092C jnz smrpro.00420B3F ; 指向的值应为"72 67 37 7B 1C 45 41 72 63 78"
00420932 cmp byte ptr ss:[esp+2D],67 ; 我们强行改变Z标志,使其能通过校验继续往下看
00420937 jnz smrpro.00420B3F
0042093D cmp byte ptr ss:[esp+34],63
00420942 jnz smrpro.00420B3F
00420948 cmp byte ptr ss:[esp+35],78
0042094D jnz smrpro.00420B3F
00420953 mov al,byte ptr ss:[esp+2F] ;al=7B,第4位
00420957 mov dl,byte ptr ss:[esp+2E] ;dl=37,第3位
0042095B mov cl,byte ptr ss:[esp+30] ;cl=1C,第5位
0042095F mov byte ptr ss:[esp+39],al ;下面将al,dl保存起来
00420963 mov byte ptr ss:[esp+38],dl
00420967 mov dl,byte ptr ss:[esp+31] ;dl=45,第6位
0042096B lea eax,dword ptr ss:[esp+38]
0042096F mov byte ptr ss:[esp+3A],cl ;cl值也保存起来
00420973 push eax
00420974 mov byte ptr ss:[esp+3F],dl ;dl值保存起来,此时观察内存区eax所指向的为"37 7B 1C 45"
00420978 mov byte ptr ss:[esp+40],0 ;ss:[esp+40]赋0,用来表示字符结束
0042097D call smrpro.0046B58C
这个Call干什么呢,先不要跟(我们的原则是能偷懒就偷懒),我们看压入栈的为37 7B 1C 45,
而此Call后在eax中的返回值为7,莫非是ASCII字符值转换成字符?但后面的数值到哪儿去呢?
我们可以手工把压入栈的值改为别的值如"37 32 36 69"我们发现调用后ecx中为字符形式"7269",
而eax中为1C64(7269值的Hex进制形式)!多换几组值试一下我们可猜测出此Call将压入栈的值
转换成Dec形式(而如果其中任一位值<30 or >39则条件不满足跳出,如若压入的堆栈处
为37 33 1C 45,则返回49(73的Hex进制形式),而若为7B 37 1C 45,则返回0)这样描述感觉
有些不妥,没办法了,自己看代码吧!有兴趣的也可自己跟一下!
00420982 mov cl,byte ptr ss:[esp+36] ;cl=41,第7位
00420986 mov dl,byte ptr ss:[esp+37] ;dl=72,第8位
0042098A mov esi,eax
0042098C lea eax,dword ptr ss:[esp+3C]
00420990 push eax ;注意这个地址中的内容
00420991 mov byte ptr ss:[esp+40],cl ;cl值传给堆栈
00420995 mov byte ptr ss:[esp+41],dl ;dl值传给堆栈
00420999 mov byte ptr ss:[esp+42],0 ;格式同上相同,此时看eax指向的内容为"41 72 00 45"
0042099E call smrpro.0046B58C
004209A3 mov ecx,eax
004209A5 mov eax,esi ;eax=07
004209A7 cdq
004209A8 mov esi,59 ;esi=59
004209AD add esp,8
004209B0 idiv esi
004209B2 mov esi,0D ;esi赋值0D
004209B7 mov eax,edx ;上面运算的余数存入eax中,eax=7
004209B9 cdq
004209BA idiv esi ;再除以esi,此时esi=0D了
004209BC cmp edx,ecx ; 最后一次判断了
----------------------------------------------------------
这里小结一下,上面对"55 14 37 7B 1C 45 41 72 B2 A6"的中间6位进行校验
要求3~6位经Call 0046B58C后的返回值a与7~8位经Call 0046B58C后的返回值b满足以下关系
即(a%59)%0D=b,则最后的校验通过!可以偷着乐了!^_^
004209BE jnz smrpro.00420B3F ; 照例是不能跳的,后面应该是把住息写到文件和注册表中
004209C4 push smrpro.004F8444 ; ASCII "HotKeyString"
004209C9 lea ecx,dword ptr ss:[esp+24]
004209CD call smrpro.004A1EF1
004209D2 xor ebx,ebx
004209D4 push smrpro.004F8438 ; ASCII "UserName"
004209D9 lea ecx,dword ptr ss:[esp+20]
004209DD mov dword ptr ss:[esp+5C],ebx
004209E1 call smrpro.004A1EF1
004209E6 mov edi,dword ptr ss:[esp+10]
004209EA mov byte ptr ss:[esp+58],1
004209EF mov esi,dword ptr ds:[edi+5C]
004209F2 call smrpro.004BF645
004209F7 mov ecx,dword ptr ss:[esp+20]
004209FB mov eax,dword ptr ds:[eax+4]
004209FE push esi ; /Arg3
004209FF push ecx ; |Arg2
00420A00 push smrpro.004F806C ; |Arg1 = 004F806C ASCII "smr"
00420A05 mov ecx,eax ; |
00420A07 call smrpro.004B227F ; \smrpro.004B227F
00420A0C mov esi,dword ptr ds:[edi+60]
00420A0F call smrpro.004BF645
00420A14 mov edx,dword ptr ss:[esp+1C]
00420A18 mov eax,dword ptr ds:[eax+4]
00420A1B push esi ; /Arg3
00420A1C push edx ; |Arg2
00420A1D push smrpro.004F806C ; |Arg1 = 004F806C ASCII "smr"
00420A22 mov ecx,eax ; |
00420A24 call smrpro.004B227F ; \smrpro.004B227F
00420A29 push smrpro.004F8294
00420A2E push smrpro.004FDB78 ;ASCII "D:\Program Files\Admiresoft\Super Mp3 Recorder Professional\scheme.dat"
00420A33 mov dword ptr ds:[4FDA60],ebx
00420A39 call smrpro.0046B137
00420A3E mov esi,eax
00420A40 add esp,8
00420A43 cmp esi,ebx
00420A45 je short smrpro.00420A5F
00420A47 mov eax,dword ptr ds:[edi+5C]
00420A4A push eax
00420A4B push smrpro.004F8B28 ; ASCII "as341%sghn33
"
00420A50 push esi
00420A51 call smrpro.0046B4C5
00420A56 push esi
00420A57 call smrpro.0046B14A
00420A5C add esp,10
00420A5F mov ecx,dword ptr ds:[4F97C8] ; smrpro.004F97DC
.......
此处后面略去一些写信息到注册表的操作!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
【算法的第二部分】
我们跟进0042091E call smrpro.00401DC0,看看这个Call里都干些什么:
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
0040A090 sub esp,104
0040A096 push ebx
0040A097 mov ebx,dword ptr ss:[esp+118]
0040A09E push ebp
0040A09F push esi
0040A0A0 push edi
0040A0A1 mov edi,ebx
0040A0A3 or ecx,FFFFFFFF
0040A0A6 xor eax,eax
0040A0A8 repne scas byte ptr es:[edi] ;[edi]中为"SMRPRO0000"
0040A0AA not ecx
0040A0AC dec ecx ;取得上面串的位数为0A
-------------------------------------------------------
0040A0AD mov byte ptr ss:[esp+1C],3
0040A0B2 mov edi,ecx
0040A0B4 mov byte ptr ss:[esp+1D],5
0040A0B9 mov byte ptr ss:[esp+1E],7
0040A0BE mov byte ptr ss:[esp+1F],0B
0040A0C3 mov byte ptr ss:[esp+20],0D
0040A0C8 mov byte ptr ss:[esp+21],11
0040A0CD mov byte ptr ss:[esp+22],13
0040A0D2 mov byte ptr ss:[esp+23],17
0040A0D7 mov byte ptr ss:[esp+24],1D
0040A0DC mov byte ptr ss:[esp+25],1F
0040A0E1 mov byte ptr ss:[esp+26],25
0040A0E6 mov byte ptr ss:[esp+27],29
0040A0EB mov byte ptr ss:[esp+28],2B
0040A0F0 mov byte ptr ss:[esp+29],2F
0040A0F5 mov byte ptr ss:[esp+2A],35
0040A0FA mov byte ptr ss:[esp+2B],3B
0040A0FF mov byte ptr ss:[esp+2C],3D
0040A104 mov byte ptr ss:[esp+2D],43
0040A109 mov byte ptr ss:[esp+2E],47
0040A10E mov byte ptr ss:[esp+2F],49
0040A113 mov byte ptr ss:[esp+30],4F
0040A118 mov byte ptr ss:[esp+31],53
0040A11D mov byte ptr ss:[esp+32],59
0040A122 mov byte ptr ss:[esp+33],61
0040A127 mov byte ptr ss:[esp+34],65
0040A12C mov byte ptr ss:[esp+35],67
0040A131 mov byte ptr ss:[esp+36],6B
0040A136 mov byte ptr ss:[esp+37],6D
0040A13B mov byte ptr ss:[esp+38],71
0040A140 mov byte ptr ss:[esp+39],7F
0040A145 mov byte ptr ss:[esp+3A],83
0040A14A mov byte ptr ss:[esp+3B],89
0040A14F mov byte ptr ss:[esp+3C],8B
0040A154 mov byte ptr ss:[esp+3D],0E
0040A159 mov byte ptr ss:[esp+3E],97
0040A15E mov byte ptr ss:[esp+3F],9D
0040A163 mov byte ptr ss:[esp+40],0A3
0040A168 mov byte ptr ss:[esp+41],0A7
0040A16D mov byte ptr ss:[esp+42],0AD
0040A172 mov byte ptr ss:[esp+43],0B3
0040A177 mov byte ptr ss:[esp+44],0B5
0040A17C mov byte ptr ss:[esp+45],0BF
0040A181 mov byte ptr ss:[esp+46],0C1
0040A186 mov byte ptr ss:[esp+47],0C5
0040A18B mov byte ptr ss:[esp+48],0C7
0040A190 mov byte ptr ss:[esp+49],0D3
0040A195 mov byte ptr ss:[esp+4A],0DF
0040A19A mov byte ptr ss:[esp+4B],0E3
0040A19F mov byte ptr ss:[esp+4C],0E5
0040A1A4 mov byte ptr ss:[esp+4D],0E9
0040A1A9 mov byte ptr ss:[esp+4E],0EF
0040A1AE mov byte ptr ss:[esp+4F],0F1
0040A1B3 mov byte ptr ss:[esp+50],0FB
-----------------------------------------------
这一段建立一张大表格,和很明显,后面会有查表运算
0040A1B8 mov dword ptr ss:[esp+64],edi
0040A1BC js short smrpro.0040A1DE
---------------------------------------
0040A1BE lea edx,dword ptr ss:[esp+DC]
0040A1C5 lea esi,dword ptr ss:[esp+6C]
0040A1C9 sub edx,ebx
0040A1CB mov eax,ebx
0040A1CD sub esi,ebx
0040A1CF lea ebx,dword ptr ds:[edi+1] ;ebx=0b
0040A1D2 mov cl,byte ptr ds:[eax] ;ds:[eax]中为"SMRPRO0000"
0040A1D4 mov byte ptr ds:[edx+eax],cl
0040A1D7 mov byte ptr ds:[esi+eax],cl
0040A1DA inc eax
0040A1DB dec ebx
0040A1DC jnz short smrpro.0040A1D2
---------------------------------------
这一小段把字串"SMRPRO0000"复制了两份在地址ss:[esp+DC]和ss:[esp+6C]中
0040A1DE xor ebx,ebx
0040A1E0 xor ecx,ecx
0040A1E2 xor eax,eax
0040A1E4 cmp edi,ebx
0040A1E6 jle short smrpro.0040A1FA
0040A1E8 xor edx,edx
0040A1EA mov dl,byte ptr ss:[esp+eax+DC] ;取上面复制的字串,dl=53("S")
0040A1F1 add edx,eax ;和累加到edx中
0040A1F3 xor ecx,edx ;再与ecx或
0040A1F5 inc eax ;指针
0040A1F6 cmp eax,edi ;比较是否取完字串
0040A1F8 jl short smrpro.0040A1E8
-----------------------------------------
这一小段可简单描述为
for(i=0;i<11;i++)
{
a=name[i]+i;
d=d^a;
j++;}
}结果为0x18h
-----------------------------------------
0040A1FA xor eax,eax
0040A1FC cmp edi,ebx
0040A1FE jle short smrpro.0040A210
0040A200 mov dl,byte ptr ss:[esp+eax+6C] ;取复制的另一份字串,dl=53("S")
0040A204 xor dl,cl ;与上面运算后的结果或
0040A206 inc ecx
0040A207 mov byte ptr ss:[esp+eax+6C],dl ;结果存回原位置
0040A20B inc eax
0040A20C cmp eax,edi ;比较是否取完字串
0040A20E jl short smrpro.0040A200
-----------------------------------------
上面这一小段更简单了,把上面计算得到的值0x18h再与字串"SMRPRO0000"的每位或存回
原处,在内存中其Hex值显示为4B 54 48 4B 4E 52 2E 2F 10 11
★★★★★★★★★★★★★★★★★★★★★★★
0040A210 xor esi,esi
0040A212 cmp edi,ebx
0040A214 jle short smrpro.0040A230
0040A216 xor eax,eax
0040A218 mov ebp,35 ;ebp赋值35,后面将参与运算
0040A21D mov al,byte ptr ss:[esp+esi+6C];上面运算后的结果再按位取:4B 54 48 4B 4E 52 2E 2F 10 11
0040A221 cdq ;扩展成双字
0040A222 idiv ebp
0040A224 inc esi
0040A225 cmp esi,edi
0040A227 mov byte ptr ss:[esp+esi+A3],dl;余数存入堆栈中"16 1F 13 16 19 1D 2E 2F 10 11"
0040A22E jl short smrpro.0040A216
★★★★★★★★★★★★★★★★★★★★★★★
这上面一小段可描述为将上面或运算后得到的值每位再分别除以35将余数存入一地址
0040A230 mov eax,ecx ;eax=ecx=22,即(0A+1)*2,往上看应该不难理解
0040A232 mov ecx,35
0040A237 cdq
0040A238 idiv ecx ;余数为22
0040A23A mov eax,dword ptr ss:[esp+11C] ;ss:[esp+11c],可能作buffer用
0040A241 xor esi,esi
0040A243 xor cl,cl
------------------------------------------
0040A245 mov byte ptr ss:[esp+13],bl
0040A249 mov byte ptr ss:[esp+18],cl
0040A24D mov byte ptr ss:[esp+14],bl
0040A251 mov dword ptr ss:[esp+54],ebx
0040A255 mov dword ptr ss:[esp+58],eax
0040A259 mov dword ptr ss:[esp+5C],edx ;余数存入ss:[esp+5C]
------------------------------------------
这一段给特定临时变量赋值0,后面会以用到
0040A25D mov edx,dword ptr ss:[esp+118]
0040A264 sub edx,eax ;edx=18
0040A266 mov dword ptr ss:[esp+60],edx
下面开始一个大循环
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
0040A26A mov edx,dword ptr ss:[esp+60]
0040A26E mov eax,dword ptr ss:[esp+58]
0040A272 mov edi,dword ptr ss:[esp+120] ;edi=0A
0040A279 movsx eax,byte ptr ds:[edx+eax]
-----------------------------------------------
ds:[edx+eax]指向我们的假码转换后的值4D 40 20 00 B0 78 07 12 87 12
0040A27D mov edx,dword ptr ss:[esp+54] ;还记得上面的一小段赋值吗?现在用到了,后面还会用到
0040A281 cmp edx,edi ;循环判断,edi中为0A
0040A283 jnb smrpro.0040A3AF
0040A289 mov edx,dword ptr ss:[esp+128]
0040A290 test edx,edx
0040A292 je short smrpro.0040A2D3 ;第1次此处会跳
下面的这一段看起来有点乱,我的描述能力有限,只好在每行后加注释,看不明白的话最好自己跟一下
就清楚了
0040A294 mov bl,byte ptr ss:[esp+esi+6C] bl=4B ,"
0040A298 mov dl,byte ptr ss:[esp+esi+DC] dl=53 ,"
0040A29F mov edi,ebx
0040A2A1 mov ebp,edx
0040A2A3 and edi,0FF
0040A2A9 and ebp,0FF
0040A2AF xor edi,ebp
0040A2B1 mov ebp,dword ptr ss:[esp+14]
0040A2B5 and ebp,0FF
0040A2BB mov byte ptr ss:[esp+14],cl
0040A2BF xor edi,ebp
0040A2C1 mov ebp,dword ptr ss:[esp+18]
0040A2C5 and ebp,0FF
0040A2CB xor edi,ebp
0040A2CD xor eax,edi
0040A2CF mov cl,al
0040A2D1 jmp short smrpro.0040A316
0040A2D3 mov bl,byte ptr ss:[esp+esi+6C];接上跳转,bl=4B,"4B 54 48 4B 4E 52 2E 2F 10 11"
0040A2D7 mov dl,byte ptr ss:[esp+esi+DC];dl=53,"53 4D 52 50 52 4F 30 30 30 30"
0040A2DE mov edi,ebx
0040A2E0 mov ebp,edx
0040A2E2 and edi,0FF ;取低位,edi=4B
0040A2E8 and ebp,0FF ;取低位,edi=53
0040A2EE xor edi,ebp ;edi=4B^53=18
0040A2F0 mov ebp,dword ptr ss:[esp+14] ;ss:[esp+14]前面赋过值
0040A2F4 and ebp,0FF ;取低位,ebp=0
0040A2FA mov dword ptr ss:[esp+68],eax ;eax=4D,往前看,假码转换后的
0040A2FE xor edi,ebp ;edi=18^0=18
0040A300 mov ebp,dword ptr ss:[esp+18]
0040A304 and ebp,0FF ;ebp=0
0040A30A mov byte ptr ss:[esp+14],cl ;cl的值先保存在ss:[esp+14]下一轮循环用
0040A30E mov cl,byte ptr ss:[esp+68] ;cl=4D
0040A312 xor edi,ebp ;edi=18^0=18
0040A314 xor eax,edi ;eax=4D^18=55
0040A316 mov edi,dword ptr ss:[esp+58] ;ss:[esp+58]可能作为一个缓冲地址
0040A31A mov ebp,dword ptr ss:[esp+64]
0040A31E mov byte ptr ss:[esp+18],cl ;cl=4D存入ss:[esp+18],下一轮循环用
0040A322 mov byte ptr ds:[edi],al ;果然,al的值存入
0040A324 mov eax,dword ptr ss:[esp+54] ;ss:[esp+54]初始为0,保存控制循环
0040A328 inc eax ;步进,调整指针
0040A329 inc edi ;同上
0040A32A mov dword ptr ss:[esp+54],eax ;果然,再存入
0040A32E xor eax,eax
0040A330 mov al,byte ptr ss:[esp+esi+A4] ;这里存着什么呢,al=16,"16 1F 13 16 19 1D 2E 2F 10 11"
0040A337 mov dword ptr ss:[esp+58],edi ;保存edi
0040A33B mov edi,dword ptr ss:[esp+5C] ;ss:[esp+5C]中存放着余数22
0040A33F mov al,byte ptr ss:[esp+eax+1C] ;还记得刚开始建的一张大表吗,这里就是由eax值查表,al=59
0040A343 add al,dl ;al=59+53=AC
0040A345 mov dl,byte ptr ss:[esp+edi+1C] ;由edi值查表,dl=97
0040A349 add dl,bl ;dl=97+4B=E2
0040A34B mov byte ptr ss:[esp+esi+DC],al ;结果存回原处
0040A352 mov byte ptr ss:[esp+esi+6C],dl ;结果存回原处
0040A356 inc esi
0040A357 cmp esi,ebp
0040A359 jnz smrpro.0040A26A
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
这一段看起来不少,我们尽量简单描述成如下:(40A2D3~40A322段代码为以下运算)
4B 54 48 4B 4E 52 2E 2F 10 11 看上面的解释吧
53 4D 52 50 52 4F 30 30 30 30 对应字串"SMRPRO0000"
00 00 4D 40 20 00 20 78 07 12
00 4D 40 20 00 20 78 07 12 87
4D 40 20 00 20 78 07 12 87 12
---------------------------------按位或运算
55 14 37 7B 1C 45 41 72 B2 A6
而40A330至40A359处代码实现由余数值"16 1F 13 16 19 1D 2E 2F 10 11"
查表与"53 4D 52 50 52 4F 30 30 30 30"的每位加运算,结果为
ss:[esp+esi+DC]中:AC D6 9B A9 B9 CE 0F 13 6D 73
以及用余数值22查表与"4B 54 48 4B 4E 52 2E 2F 10 11 "的每位加
运算(即每位加上97舍去高位),结果
在ss:[esp+esi+6C]中为E2 EB DF E2 E5 E9 C5 C6 A7 A8(为定值)
0040A35F mov al,byte ptr ss:[esp+13]
0040A363 inc al
0040A365 mov byte ptr ss:[esp+13],al
0040A369 jnz short smrpro.0040A3A8
0040A36B xor edx,edx
0040A36D xor eax,eax
0040A36F cmp ebp,edx
0040A371 jle short smrpro.0040A3A8
0040A373 mov bl,byte ptr ss:[esp+eax+A4]
0040A37A inc bl
0040A37C cmp bl,35
0040A37F mov byte ptr ss:[esp+eax+A4],bl
0040A386 jnz short smrpro.0040A38F
0040A388 mov byte ptr ss:[esp+eax+A4],dl
0040A38F mov bl,byte ptr ss:[esp+eax+1C]
0040A393 add byte ptr ss:[esp+eax+6C],bl
0040A397 inc edi
0040A398 cmp edi,35
0040A39B jnz short smrpro.0040A39F
0040A39D xor edi,edi
0040A39F inc eax
0040A3A0 cmp eax,ebp
0040A3A2 jl short smrpro.0040A373
0040A3A4 mov dword ptr ss:[esp+5C],edi
0040A3A8 xor esi,esi
0040A3AA jmp smrpro.0040A26A
0040A3AF mov eax,dword ptr ss:[esp+11C]
0040A3B6 pop edi
0040A3B7 pop esi
0040A3B8 pop ebp
0040A3B9 mov byte ptr ds:[edx+eax],0
0040A3BD xor eax,eax
0040A3BF pop ebx
0040A3C0 add esp,104
0040A3C6 retn
这个函数的返回值为或运算后的结果55 14 37 7B 1C 45 41 72 B2 A6,其余两个查表后得到的值
在注册码的校验中没有用到,在后面的写注册信息时用到!对此我不感兴趣,有兴趣的自己跟一下!
【算法总结】:
说实话,写到这有点头晕眼花了,死老外,弄个这么麻烦的算法!还是稍微梳理一下吧!
注册码与用户名无关,注册码须为20位,其中第6、7、8位须为0,第9位不得为0,假设我们的
注册码为 abcde000fghijklmnopq,经004208D4~00420909处的代码转换为n1n2n3n4n5n6n7n8n9n10
a b c d e 0 0 0 f g h i j k l m n o p q
┕┘ ┕┘ ┕┘ ┕┘ ┕┘ ┕┘ ┕┘ ┕┘ ┕┘ ┕┘
n1 n2 n3 n4 n5 n6 n7 n8 n9 n10
然后后将此值与几组程序内定值按位或运算后得到一个值
4B 54 48 4B 4E 52 2E 2F 10 11 固定值
53 4D 52 50 52 4F 30 30 30 30 固定值
00 00 n1 n2 n3 n4 n5 n6 n7 n8
00 n1 n2 n3 n4 n5 n6 n7 n8 n9
n1 n2 n3 n4 n5 n6 n7 n8 n9 n10
---------------------------------按位或运算
j1 j2 j3 j4 j5 j6 j7 j8 j9 j10
要求j1、j2、j9、j10须为r、g、c、x
而j3~j6位经call smrpro.0046B58C后的返回值a与j7~j8经call smrpro.0046B58C后的
返回值b须满足(a%59)%0Dh=b,满足以上条件的即为正确注册码!
【注册机】:
呵呵,不要指望我了,还是请高手出招了,我只想要一个能用的注册码,让我们看看有没有
偷懒的办法!由于程序涉及到的校验太多,而且会把信息写到注册表和文件中,所以要爆破的
话得工作量可能不小,而且是非明码比较,用程序自身作注册机太麻烦,但我们注意到程序开
始进行了校验黑名单操作,我们不凡用黑名单中的注册码试一下!运行程序,再输入
假码4L14A0009P72Z569WY90(注意把把6~8位改为0),注册试试,失败!别灰心,再
换#j14N000111143000059(同上,6~8位改为0)试试,呵呵.....笑开花了吧!注册成功了!^_^
用户名随意,一个可用注册码#j14N000111143000059!
欢迎e-mail到sharpair@163.com交流!