首页
社区
课程
招聘
[原创]一个视频工具的注册过程分析
发表于: 2005-9-19 15:36 9553

[原创]一个视频工具的注册过程分析

2005-9-19 15:36
9553

【软件名称】   Super Mp3 Converter 4.2.1

【下载页面】   http://crc.onlinedown.net/soft/7235.htm

【加密方式】   注册码

【软件限制】   功能限制+nag提示

【软件简介】
               Super Mp3 Converter能够在MP3, Wave, WMA,Ogg和Vqf等等这些音频文件格式中自由转换,
               是一个强力的音频转换工具。
【破解声明】   破解只是感兴趣,没有任何目的。失误之处难免,敬望诸位大侠赐教!
-----------------------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////////////////
-----------------------------------------------------------------------------------------------
【跟踪过程】
试验码(第1次)
username:ligyuan
regcode :123456789

试验码(第2次)
username:ligyuan
regcode :123456789abcdef24681

下断点bp GetdlgItem,Alt+F9返回到这里

0042F3DE  push 1388                               ; /Timeout = 5000. ms
0042F3E3  call dword ptr ds:[<&KERNEL32.Sleep>]   ; \Sleep      //调用延时函数得到注册码
0042F3E9  mov edx,dword ptr ds:[ebx+60]
0042F3EC  or ecx,FFFFFFFF
0042F3EF  mov edi,edx
0042F3F1  xor eax,eax
0042F3F3  repne scas byte ptr es:[edi]            ;  扫描注册码     
0042F3F5  not ecx
0042F3F7  dec ecx
0042F3F8  cmp ecx,14                              ;  比较注册码长度是否等于0x14
0042F3FB  jnz smc.0042F5DA                        ;  不等直接跳失败
0042F401  xor ecx,ecx
0042F403  mov al,byte ptr ds:[edx]
0042F405  cmp al,61                               ;  比较是否小于a
0042F407  jl short smc.0042F40F                   ;  小就跳
0042F409  cmp al,66                               ;  是否大于f
0042F40B  jg short smc.0042F40F                   ;  大就跳
0042F40D  sub al,7                                ;  减7
0042F40F  shl al,4                                ;  左移4位
0042F412  mov byte ptr ss:[esp+ecx+3C],al         ;  保存在栈中
0042F416  mov al,byte ptr ds:[edx+1]              ;  取下一个字符
0042F419  cmp al,61                               ;  是否小于a
0042F41B  jl short smc.0042F425                   ;  小就往下跳
0042F41D  cmp al,66                               ;  是否大于f
0042F41F  jg short smc.0042F425                   ;  大就跳
0042F421  sub al,57                               ;  减0x57
0042F423  jmp short smc.0042F427
0042F425  sub al,30                               ;  减0x30
0042F427  add byte ptr ss:[esp+ecx+3C],al         ;  与上一步的值加并存储
0042F42B  inc ecx                                 ;  ecx++
0042F42C  add edx,2                               ;  edx+=2
0042F42F  cmp ecx,0A                              ;  比较是否大于0x10
0042F432  jl short smc.0042F403                   ;  做上面的10次循环
0042F434  push ebp
0042F435  push smc.004EC684                       ;  ASCII "SMConvertr"
0042F43A  lea eax,dword ptr ss:[esp+2C]
0042F43E  push 0A
0042F440  lea ecx,dword ptr ss:[esp+48]
0042F444  push eax
0042F445  push ecx
0042F446  call smc.00442DA0                       ;  关键call (跟进)
0042F44B  mov al,byte ptr ss:[esp+38]             ;  给al 赋值
0042F44F  add esp,14
0042F452  cmp al,72                               ;  比较第1字节是否为'r'
0042F454  jnz smc.0042F5B6                        ;  不等就跳走
0042F45A  cmp byte ptr ss:[esp+25],67             ;  比较第2字节是否等于'f'
0042F45F  jnz smc.0042F5B6
0042F465  cmp byte ptr ss:[esp+2C],63             ;  比较第9字节是否等于'c'
0042F46A  jnz smc.0042F5B6
0042F470  cmp byte ptr ss:[esp+2D],78             ;  比较第10字节是否等于'x'
0042F475  jnz smc.0042F5B6
0042F47B  mov al,byte ptr ss:[esp+27]
0042F47F  mov dl,byte ptr ss:[esp+26]
0042F483  mov cl,byte ptr ss:[esp+28]
0042F487  mov byte ptr ss:[esp+31],al
0042F48B  mov byte ptr ss:[esp+30],dl
0042F48F  mov dl,byte ptr ss:[esp+29]
0042F493  lea eax,dword ptr ss:[esp+30]
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
F7跟进后F8几步后来到这里
00442EF4  cmp edi,ebx
00442EF6  jle short smc.00442F0A
00442EF8  /xor edx,edx                            ;  求得一个ecx=0x36,作为下面的初值
00442EFA  |mov dl,byte ptr ss:[esp+eax+DC]        ;  每次取str1的一个字节
00442F01  |add edx,eax
00442F03  |xor ecx,edx
00442F05  |inc eax
00442F06  |cmp eax,edi
00442F08  \jl short smc.00442EF8
00442F0A  xor eax,eax
00442F0C  cmp edi,ebx
00442F0E  jle short smc.00442F20
00442F10  /mov dl,byte ptr ss:[esp+eax+6C]        ;  "SMConvertr"每个字符和cl++异或后存储
00442F14  |xor dl,cl
00442F16  |inc ecx
00442F17  |mov byte ptr ss:[esp+eax+6C],dl        ;  记为str2
00442F1B  |inc eax
00442F1C  |cmp eax,edi
00442F1E  \jl short smc.00442F10
00442F20  xor esi,esi
00442F22  cmp edi,ebx
00442F24  jle short smc.00442F40
00442F26  /xor eax,eax
00442F28  |mov ebp,35
00442F2D  |mov al,byte ptr ss:[esp+esi+6C]        ;  上一步转换的每一个字符除以0x35的余数存储
00442F31  |cdq
00442F32  |idiv ebp
00442F34  |inc esi
00442F35  |cmp esi,edi
00442F37  |mov byte ptr ss:[esp+esi+A3],dl        ;  记为str3
00442F3E  \jl short smc.00442F26
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
上面的部分都是对字符串的转换,由于str1="SMConvertr"是软件给出的定值,经它变换后的str2,
str3也是一定了的。
下面是对str1,str2,str3,和变换后的假码vcode的处理,
00442F40  mov eax,ecx
00442F42  mov ecx,35
00442F47  cdq
00442F48  idiv ecx
00442F4A  mov eax,dword ptr ss:[esp+11C]
00442F51  xor esi,esi
00442F53  xor cl,cl
00442F55  mov byte ptr ss:[esp+13],bl
00442F59  mov byte ptr ss:[esp+18],cl
00442F5D  mov byte ptr ss:[esp+14],bl
00442F61  mov dword ptr ss:[esp+54],ebx
00442F65  mov dword ptr ss:[esp+58],eax
00442F69  mov dword ptr ss:[esp+5C],edx
00442F6D  mov edx,dword ptr ss:[esp+118]
00442F74  sub edx,eax
00442F76  mov dword ptr ss:[esp+60],edx
00442F7A  /mov edx,dword ptr ss:[esp+60]          ;  给edx赋值edx=0x18
00442F7E  |mov eax,dword ptr ss:[esp+58]
00442F82  |mov edi,dword ptr ss:[esp+120]         ;  需要运行的次数
00442F89  |movsx eax,byte ptr ds:[edx+eax]        ;  这里每一次取经注册码转换后的一个字节
00442F8D  |mov edx,dword ptr ss:[esp+54]          ;  把运行次数赋给edx
00442F91  |cmp edx,edi                            ;  比较是否达到了0xa次
00442F93  |jnb smc.004430BF
00442F99  |mov edx,dword ptr ss:[esp+128]
00442FA0  |test edx,edx                           ;  是否为零
00442FA2  |je short smc.00442FE3                  ;  不就跳
00442FA4  |mov bl,byte ptr ss:[esp+esi+6C]
00442FA8  |mov dl,byte ptr ss:[esp+esi+DC]
00442FAF  |mov edi,ebx
00442FB1  |mov ebp,edx
00442FB3  |and edi,0FF
00442FB9  |and ebp,0FF
00442FBF  |xor edi,ebp
00442FC1  |mov ebp,dword ptr ss:[esp+14]
00442FC5  |and ebp,0FF
00442FCB  |mov byte ptr ss:[esp+14],cl
00442FCF  |xor edi,ebp
00442FD1  |mov ebp,dword ptr ss:[esp+18]
00442FD5  |and ebp,0FF
00442FDB  |xor edi,ebp
00442FDD  |xor eax,edi
00442FDF  |mov cl,al
00442FE1  |jmp short smc.00443026
00442FE3  |mov bl,byte ptr ss:[esp+esi+6C]        ;  每次取str2的一个字节
00442FE7  |mov dl,byte ptr ss:[esp+esi+DC]        ;  每次取str1的一个字节
00442FEE  |mov edi,ebx                            ;  ebx的值给edi
00442FF0  |mov ebp,edx                            ;  edx的值给ebp
00442FF2  |and edi,0FF                            ;  取低位
00442FF8  |and ebp,0FF                            ;  取低位
00442FFE  |xor edi,ebp                            ;  异或后送edi
00443000  |mov ebp,dword ptr ss:[esp+14]          ;  取上轮保存的一个值
00443004  |and ebp,0FF                            ;  取低位
0044300A  |mov dword ptr ss:[esp+68],eax          ;  把eax的值保存
0044300E  |xor edi,ebp                            ;  异或后送edi
00443010  |mov ebp,dword ptr ss:[esp+18]          ;  取上一轮保存的一个值
00443014  |and ebp,0FF                            ;  取低位
0044301A  |mov byte ptr ss:[esp+14],cl            ;  cl保存在ss:[esp+14]中
0044301E  |mov cl,byte ptr ss:[esp+68]            ;  给cl赋值
00443022  |xor edi,ebp                            ;  异或后送edi
00443024  |xor eax,edi                            ;  异或后送eax
00443026  |mov edi,dword ptr ss:[esp+58]          ;  得到偏移地址
0044302A  |mov ebp,dword ptr ss:[esp+64]
0044302E  |mov byte ptr ss:[esp+18],cl            ;  cl的值保存在ss:[esp=18]中
00443032  |mov byte ptr ds:[edi],al               ;  al的值保存在ds:[edi]中 <<<<<<<<<关键部分
00443034  |mov eax,dword ptr ss:[esp+54]
00443038  |inc eax
00443039  |inc edi
0044303A  |mov dword ptr ss:[esp+54],eax          ;  已运行次数保存
0044303E  |xor eax,eax                            ;  清0
00443040  |mov al,byte ptr ss:[esp+esi+A4]        ;  每次取str3的一个字节
00443047  |mov dword ptr ss:[esp+58],edi          ;  保存偏移地址、
0044304B  |mov edi,dword ptr ss:[esp+5C]          ;  给edi赋值
0044304F  |mov al,byte ptr ss:[esp+eax+1C]        ;  给al赋值
00443053  |add al,dl                              ;  al+=dl
00443055  |mov dl,byte ptr ss:[esp+edi+1C]        ;  给dl赋值
00443059  |add dl,bl
0044305B  |mov byte ptr ss:[esp+esi+DC],al        ;  保存al
00443062  |mov byte ptr ss:[esp+esi+6C],dl        ;  保存dl
00443066  |inc esi
00443067  |cmp esi,ebp                            ;  比较是否循环了0xa次
00443069  |jnz smc.00442F7A
从代码可以看出单次处理过程是这样:cl,temp1,temp2的初值是0,c[10]是处理后的注册码
c[i]=str1[i]^str2[i]
c[i]^=temp1;
temp1=cl;
cl=vcode[i]
c[i]^=temp2;
temp2=cl
c[i]^=cl
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
【算法总结】:

注册码与用户名无关但不能为空,注册码的长度为20位,由注册码经过一系列的转换得到c[10]
c[1]=str1[1]^str2[1]^vcode[1]^0^0;
c[2]=str1[2]^str2[2]^vcode[2]^vcode[1]^0
c[3]=str1[3]^str2[3]^vcode[3]^vcode[2]^vcode[1]
c[4]=str1[4]^str2[4]^vcode[4]^vcode[3]^vcode[2]
......
......
c[9]=str1[9]^str2[9]^vcode[9]^vcode[8]^vcode[7]
c[10]=str1[10]^str2[10]^vcode[10]^vcode[9]^vcode[8]

然后比较c[0]==0x72,c[1]==0x67,c[8]==0x63,c[9]==0x78,全等则可以正确注册。
由于str1[i++]^str2[i++]=0x36+i++
可以知道vcode[1]=0x44,vcode[2]=0x14
所以前4位注册码可以简单的得出,比如4414,或者T4q4,3D0D等等皆可
任取后4位,假设为5=0;则有0x78=0x3f^0x0b^0x5d^vcode[8],vcode[8]=0x11
同样可以得到vcode[7]=0x11,这是可以构造这4位为1111或者0A11或0A0A
其他的任填。可以得出一住组册码441400vdasqw0A115=0;
因此只需确定最后4位注册码,整个注册码就可以求出来了。

void main(){
        unsigned char vcode[2];
        char code[17];
        for(int i=0;i<16;i++){
        time_t tt;
        srand((unsigned) time(&tt));
        code[i]=rand()%0x4e+0x30;
        }
        for(int i=0;i<2;i++){
        if(code[2*i+12]>='a'&&code[2*i+12]<='f')
                vcode[i]=code[i+12]-7;
        vcode[i]<<=4;
        if(code[2*i+13]>='a'&&code[2*i+13]<='f')
                vcode[i]+=code[2*i+13]-0x57;
        else
                vcode[i]+=code[2*i+13]-0x30;
        }
        vcode[1]=0x3f^0x78^vcode[1]^vcode[0];
        vcode[0]=0x3e^0x63^vcode[1]^vcode[0];
        code[8]=vcode[0]/16+0x30;
        code[9]=vcode[0]%16+0x30;
        code[10]=vcode[1]/16+0x30;
        code[11]=vcode[1]%16+0x30;
        code[16]='\0';
        printf("4414%s",code);
}
有很多方面没有一一列出。
注册信息放在HKLM\SOFTWARE\SACONVERTER\SACONVERTER下


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (14)
雪    币: 110
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
如此详细的注译,不顶的话,实在过意不去
2005-9-19 17:33
0
雪    币: 229
活跃值: (70)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
加精!
2005-9-19 19:02
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4

详细
2005-9-20 21:10
0
雪    币: 203
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
很祥细,学习了。
2005-9-21 12:03
0
雪    币: 201
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
2005-9-21 13:29
0
雪    币: 251
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不错,学习
2005-9-21 15:26
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
学习中!多谢提供.
2005-9-21 16:50
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
真的学到不少东东,太谢谢了!
2005-9-23 00:57
0
雪    币: 288
活跃值: (112)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
10
0042F3E3  call dword ptr ds:[<&KERNEL32.Sleep>]   ; \Sleep      //调用延时函数得到注册码

这个不太明白,怎么通过Sleep得到注册码的?
2005-10-22 22:58
0
雪    币: 61
活跃值: (160)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
11
Good!
2005-10-23 09:00
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习中!多谢提供.
2005-10-24 08:55
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
谢谢楼主,学习!
2005-10-24 15:09
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
很好,非常感谢楼主用这么详细的注译让我们初学者学习。
2005-10-24 15:43
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
还好,还可以看的懂
2005-10-24 21:40
0
游客
登录 | 注册 方可回帖
返回
//