天下网吧 >> 网吧天地 >> 网吧技术 >> 网吧安全 >> 正文

系统安全之关于Alarm Master破解的分析

2008-2-18赛迪网佚名

  分析过程

  试验码:

  Regname:ligyuan

  Regcode:1234 5678 abcd efgh

  运行软件,有nag和剩余时间提示,点注册弹出注册对话框,输入试验码,下断点

  bp getDlgItem,bp GetDlgItemTextA,bp GetWindowTextA

  点确定,没有被断下。弹出错误对话框,点try again,程序被截下,Ctrl+F9返回 F9几次后,弹出了注册对话框,再次输入试验码,点确定程序运行返回到这里:

  100020C1 51 push ecx
100020C2 68 2D1F0010 push BSSuppor.10001F2D
100020C7 FF71 0C push dword ptr ds:[ecx+C]
100020CA FF71 10 push dword ptr ds:[ecx+10]
100020CD FF71 04 push dword ptr ds:[ecx+4]
100020D0 FF15 54D10010 call dword ptr ds:[<&USER32.DialogBoxParamA>] ;
100020D6 8BF0 mov esi,eax
100020D8 83FE FF cmp esi,-1
100020DB 75 05 jnz short BSSuppor.100020E2
100020DD E8 1EEFFFFF call BSSuppor.10001000
100020E2 8BC6 mov eax,esi ;F8单步运行
100020E4 5E pop esi
100020E5 C3 retn ;运行到这后返回
/////////////////////////////////////////////////////////////////////////
10002DC6 8B06 mov eax,dword ptr ds:[esi] ;来到这里
10002DC8 FFB0 CC010000 push dword ptr ds:[eax+1CC]
10002DCE 8D4D E8 lea ecx,dword ptr ss:[ebp-18]
10002DD1 E8 46FAFFFF call BSSuppor.1000281C ;这里是把每一组注册码
转为16进制
10002DD6 8B06 mov eax,dword ptr ds:[esi]
10002DD8 8B4D AC mov ecx,dword ptr ss:[ebp-54] ;第一组的16进制送ecx
10002DDB 8988 F0010000 mov dword ptr ds:[eax+1F0],ecx ;转存到ds:[eax+1F0]
10002DE1 8B06 mov eax,dword ptr ds:[esi]
10002DE3 8B4D B0 mov ecx,dword ptr ss:[ebp-50] ;第二组的16进制送ecx
10002DE6 8988 F4010000 mov dword ptr ds:[eax+1F4],ecx ;转存到ds:[eax+1F4]
10002DEC 8B06 mov eax,dword ptr ds:[esi]
10002DEE 8B4D B4 mov ecx,dword ptr ss:[ebp-4C] ;第三组的16进制送ecx
10002DF1 8988 F8010000 mov dword ptr ds:[eax+1F8],ecx ;转存到ds:[eax+1F8]
10002DF7 8B06 mov eax,dword ptr ds:[esi]
10002DF9 8B4D B8 mov ecx,dword ptr ss:[ebp-48] ;第四组的16进制送ecx
10002DFC 8988 FC010000 mov dword ptr ds:[eax+1FC],ecx ;转存到ds:[eax+1FC]
10002E02 8B0E mov ecx,dword ptr ds:[esi]
10002E04 8D45 90 lea eax,dword ptr ss:[ebp-70]
10002E07 50 push eax
10002E08 E8 8EFEFFFF call BSSuppor.10002C9B
10002E0D 8B1E mov ebx,dword ptr ds:[esi]
10002E0F 8BCB mov ecx,ebx
10002E11 E8 AEFBFFFF call BSSuppor.100029C4
10002E16 85C0 test eax,eax
10002E18 /74 08 je short BSSuppor.10002E22
10002E1A |6A 02 push 2
10002E1C |5F pop edi
10002E1D |E9 02010000 jmp BSSuppor.10002F24
10002E22 \8D45 BC lea eax,dword ptr ss:[ebp-44]
10002E25 50 push eax
10002E26 8BCB mov ecx,ebx
10002E28 E8 24FFFFFF call BSSuppor.10002D51
10002E2D 8945 F0 mov dword ptr ss:[ebp-10],eax
10002E30 8B0E mov ecx,dword ptr ds:[esi]
10002E32 8B81 F8010000 mov eax,dword ptr ds:[ecx+1F8]
10002E38 8B91 FC010000 mov edx,dword ptr ds:[ecx+1FC]
10002E3E 52 push edx
10002E3F 8945 EC mov dword ptr ss:[ebp-14],eax
10002E42 FF75 EC push dword ptr ss:[ebp-14]
10002E45 8B81 F4010000 mov eax,dword ptr ds:[ecx+1F4]
10002E4B 8B89 F0010000 mov ecx,dword ptr ds:[ecx+1F0]
10002E51 50 push eax
10002E52 51 push ecx
10002E53 FF75 F0 push dword ptr ss:[ebp-10]
10002E56 33DB xor ebx,ebx
10002E58 43 inc ebx
10002E59 8D4D E8 lea ecx,dword ptr ss:[ebp-18]
10002E5C 885D FC mov byte ptr ss:[ebp-4],bl
10002E5F E8 E9FAFFFF call BSSuppor.1000294D ;关键call,F7跟进
10002E64 57 push edi
10002E65 53 push ebx
10002E66 8D4D BC lea ecx,dword ptr ss:[ebp-44]
10002E69 8945 F0 mov dword ptr ss:[ebp-10],eax
10002E6C C645 FC 00 mov byte ptr ss:[ebp-4],0
10002E70 E8 9DE4FFFF call BSSuppor.10001312
10002E75 397D F0 cmp dword ptr ss:[ebp-10],edi
10002E78 0F85 A6000000 jnz BSSuppor.10002F24
下面是跟进后,里面的关键部分,中间省略了一些过程
//////////////////////////////////////////////////////////////对输入的用户名进行处理
10002874 3B7B 14 cmp edi,dword ptr ds:[ebx+14] ;edi是否大于或等于
用户名的长度
10002877 7D 2F jge short BSSuppor.100028A8 ;大就跳
10002879 C745 08 01000>mov dword ptr ss:[ebp+8],1
10002880 57 push edi
10002881 8BCB mov ecx,ebx
10002883 E8 BFFFFFFF call BSSuppor.10002847 ;读取用户名的一个字符
10002888 8038 20 cmp byte ptr ds:[eax],20 ;字符的ASCII值是否为0X20
1000288B 75 0A jnz short BSSuppor.10002897 ;不是就跳
1000288D 47 inc edi
1000288E FF45 08 inc dword ptr ss:[ebp+8]
10002891 837D 08 64 cmp dword ptr ss:[ebp+8],64 ;是否大于0X64
10002895 ^ 7C E9 jl short BSSuppor.10002880 ;不是往上跳取下一个字符
10002897 57 push edi
10002898 8BCB mov ecx,ebx
1000289A E8 A8FFFFFF call BSSuppor.10002847
1000289F 8A00 mov al,byte ptr ds:[eax] ;用户名字符的ASCII值送al
100028A1 884435 E8 mov byte ptr ss:[ebp+esi-18],al ;al转送到堆栈中
100028A5 47 inc edi
100028A6 EB 05 jmp short BSSuppor.100028AD
100028A8 C64435 E8 40 mov byte ptr ss:[ebp+esi-18],40 ;用户名长度小于0X10时,用40填充
100028AD 46 inc esi
100028AE 83FE 10 cmp esi,10 ;比较是否进行了0X10 次操作
100028B1 ^ 7C C1 jl short BSSuppor.10002874 ;不是往上跳继续

  ///////////////////////////////////////////////////////下面是由上面处理后的用户名
得出注册码的过程
100028BC 8D7C1D E8 lea edi,dword ptr ss:[ebp+ebx-18] ;用户名的基址送edi
100028C0 C745 08 04000>mov dword ptr ss:[ebp+8],4 ;ss:[ebp+8]=4,
用来得出4位注册码
100028C7 8B4D FC mov ecx,dword ptr ss:[ebp-4] ;为ecx赋值一个内存地址
100028CA E8 58FFFFFF call BSSuppor.10002827 ;算法call
100028CF 0FBE0F movsx ecx,byte ptr ds:[edi] ;取用户名的一个字符值送ecx
100028D2 33D2 xor edx,edx
100028D4 8D4408 F6 lea eax,dword ptr ds:[eax+ecx-A] ;eax=eax+ecx-0xa
100028D8 6A 0A push 0A
100028DA 59 pop ecx ;ecx=0xa
100028DB F7F1 div ecx ;eax=eax/ecx,edx=eax%ecx
100028DD 83C7 04 add edi,4 ;edi+=4,相当于隔3个字符取
下一字符
100028E0 80C2 30 add dl,30 ;dl+=30
100028E3 889435 E8FEFF>mov byte ptr ss:[ebp+esi-118],dl ;得到值的对应字符送到存储
空间保存
100028EA 46 inc esi ;esi++
100028EB FF4D 08 dec dword ptr ss:[ebp+8] ;从4减到0
100028EE ^ 75 D7 jnz short BSSuppor.100028C7 ;不为0就往上跳继续下一个字符
100028F0 C68435 E8FEFF>mov byte ptr ss:[ebp+esi-118],20 ;每4个字符用空格隔开
100028F8 46 inc esi
100028F9 43 inc ebx ;ebx++(ebx初始为0)
100028FA 83FB 04 cmp ebx,4 ;比较ebx是否小于4
100028FD ^ 7C BD jl short BSSuppor.100028BC ;小就往上跳,获得另一4位
注册码
100028FF C68435 E7FEFF>mov byte ptr ss:[ebp+esi-119],0
10002907 33F6 xor esi,esi
10002909 8D85 FAFEFFFF lea eax,dword ptr ss:[ebp-106]
1000290F 8A18 mov bl,byte ptr ds:[eax] ;下面这段代码是把上面4组
注册码反向
10002911 8D8C35 E8FEFF>lea ecx,dword ptr ss:[ebp+esi-118]
10002918 0FBE11 movsx edx,byte ptr ds:[ecx]
1000291B 8819 mov byte ptr ds:[ecx],bl
1000291D 46 inc esi
1000291E 8810 mov byte ptr ds:[eax],dl
10002920 48 dec eax
10002921 83FE 09 cmp esi,9
10002924 ^ 7C E9 jl short BSSuppor.1000290F ;这个变换后得到的就是
正确的注册码

  ///////////////////////////////////////////////////////////////跟进算法call
10002827 8B01 mov eax,dword ptr ds:[ecx]
10002829 69C0 FD430300 imul eax,eax,343FD ;eax*=0X343FD
1000282F 05 C39E2600 add eax,269EC3 ;eax+=0x269ec3
10002834 8901 mov dword ptr ds:[ecx],eax ;eax的值保存在ds:[ecx]地址中
10002836 C1F8 10 sar eax,10 ;eax>>=10
10002839 25 FF7F0000 and eax,7FFF ;eax^=0x7fff
1000283E 99 cdq ;edx符号扩展
1000283F 6A 0A push 0A
10002841 59 pop ecx ;ecx=0xa
10002842 F7F9 idiv ecx ;eax=eax/ecx,edx=eax%0xa
10002844 8BC2 mov eax,edx ;eax=edx
10002846 C3 retn
////////////////////////////////////////////////////////下面这里是输入的家假码与
真码比较的部分
1000297D 8B45 0C mov eax,dword ptr ss:[ebp+C] ;假码第1部分送eax
10002980 3B45 FC cmp eax,dword ptr ss:[ebp-4] ;与真码第1部分比较
10002983 8B5D 18 mov ebx,dword ptr ss:[ebp+18] ;假码第2部分送ebx
10002986 8B7D 14 mov edi,dword ptr ss:[ebp+14] ;假码第3部分送edi
10002989 8B55 10 mov edx,dword ptr ss:[ebp+10] ;假码第4部分送edx
1000298C 75 0F jnz short BSSuppor.1000299D ;不等就跳
1000298E 3B55 F8 cmp edx,dword ptr ss:[ebp-8] ;与真码第2部分比较
10002991 75 0A jnz short BSSuppor.1000299D
10002993 3B7D F4 cmp edi,dword ptr ss:[ebp-C] ;与真码第3部分比较
10002996 75 05 jnz short BSSuppor.1000299D
10002998 3B5D F0 cmp ebx,dword ptr ss:[ebp-10] ;与真码第4部分比较
1000299B 74 1A je short BSSuppor.100029B7 ;都相等就跳到结束(成功)
1000299D B9 D2040000 mov ecx,4D2 ;上面任一部分不同都会来到这里4d2=1234
100029A2 3BC1 cmp eax,ecx ;第一部分是不是为1234
100029A4 75 16 jnz short BSSuppor.100029BC
100029A6 B8 2E160000 mov eax,162E ;162e=5678
100029AB 3BD0 cmp edx,eax ;第4部分是否为5678
100029AD 75 0D jnz short BSSuppor.100029BC
100029AF 3BF9 cmp edi,ecx ;第3部分是不是为1234
100029B1 75 09 jnz short BSSuppor.100029BC
100029B3 3BD8 cmp ebx,eax ;第2部分是否为5678
100029B5 75 05 jnz short BSSuppor.100029BC;满足上面的4个比较也能成功注册
100029B7 33C0 xor eax,eax ;因此有一个万能码1234-5678-1234-5678
100029B9 40 inc eax
100029BA EB 02 jmp short BSSuppor.100029BE
100029BC 33C0 xor eax,eax

  一个简单的注册机:

  void main(){
char regname[50],regcode[20];
long temp1=0,temp2=0;
printf("请输入Regname:");
gets(regname);
int stlen=strlen(regname);
if(stlen<16)
for(;stlen<16;stlen++)
regname[stlen]=0x40;
for(int i=0, t=0;i<4;i++, t=0){
if(i)regcode[19-5*i]=0x2d;
for(int j=0;j<16;j+=4,t++){
temp1*=0x343FD;
temp1+=0x269ec3;
temp2=temp1;
__asm{
mov eax,temp2
sar eax,010h
and eax,07FFFh
cdq
mov ecx,0ah
idiv ecx
mov temp2,edx
}
temp2=temp2+regname[j+i]-0xa;
temp2=temp2%0xa+0x30;
regcode[18-5*i-t]=temp2;
}
}
regcode[19]='\0';
printf("你的Regcode:%s\n",regcode);
}

  请输入Regname:ligyuan

  你的Regcode:5153-4723-9940-1266

  也可以用万能码:1234-5678-1234-5678

  软件的注册保护没有过多的考虑,找到关键点后能够轻松的实现算法注册机,还留了万能码,差一点我就中了头奖。这样,我这个菜鸟也才有了练手的机会,由于代码中没有考虑到输入空格时的处理,因此有很多不足之处,还望不要笑话鄙人。

欢迎访问最专业的网吧论坛,无盘论坛,网吧经营,网咖管理,网吧专业论坛https://bbs.txwb.com

关注天下网吧微信,了解网吧网咖经营管理,安装维护:


本文来源:赛迪网 作者:佚名

声明
本文来源地址:0
声明:本站所发表的文章、评论及图片仅代表作者本人观点,与本站立场无关。若文章侵犯了您的相关权益,请及时与我们联系,我们会及时处理,感谢您对本站的支持!联系Email:support@txwb.com.,本站所有有注明来源为天下网吧或天下网吧论坛的原创作品,各位转载时请注明来源链接!
天下网吧·网吧天下
  • 本周热门
  • 本月热门
  • 阅读排行