| 
 | 
 
破解日期】 2006年11月12日 
【破解作者】 yzs 
【作者主页】 http://www.freewebs.com/realplayerassist/ 
【使用工具】 OD 
【破解平台】 Win9x/NT/2000/XP 
【软件名称】 realplayer广告拦截超级助手 V1.36 
【下载地址】 自己网上找 
【软件大小】 607KB 
【加壳方式】 无(Microsoft Visual C++ 7.0 Method2) 
【破解声明】 我是一只小菜鸟,第一次写破文,偶得一点心得,愿与大家分享:),写的很差,希望大家勿怪,呵呵 
-------------------------------------------------------------------------------- 
【破解内容】 
代码: 
________________________________________ 
机器码: PKRMMSJV 用户名:yzs  注册码:11111111,点注册跟踪来到: 
 
00408000    /$  83EC 14   sub esp,14 
00408003    |.  53        push ebx 
00408004    |.  33C0      xor eax,eax 
00408006    |.  894424 04 mov dword ptr ss:[esp+4],eax 
0040800A    |.  55        push ebp 
0040800B    |.  56        push esi 
0040800C    |.  894424 10 mov dword ptr ss:[esp+10],eax 
00408010    |.  57        push edi 
00408011    |.  8B7C24 2C mov edi,dword ptr ss:[esp+2C] 
00408015    |.  894424 18 mov dword ptr ss:[esp+18],eax 
00408019    |.  894424 1C mov dword ptr ss:[esp+1C],eax 
0040801D    |.  8BCF      mov ecx,edi 
0040801F    |.  33DB      xor ebx,ebx――――――――――――――――清零,准备循环 
00408021    |.  884424 20 mov byte ptr ss:[esp+20],al 
00408025    |.  33F6      xor esi,esi――――――――――――――――-清零,准备循环 
00408027    |.  FF15 00B4>call dword ptr ds:[<&MFC71.#2902>]    ――得到注册码长度,送入EAX 
0040802D    |.  85C0      test eax,eax 
0040802F    |.  7E 2D     jle short RealOneA.0040805E――――――长度为零跳走,否则继续 
00408031    |>  56        /push esi 
00408032    |.  8BCF      |mov ecx,edi 
00408034    |.  FF15 BCB3>|call dword ptr ds:[<&MFC71.#865>] -----将注册码的ASC码值赋值给al 
0040803A    |.  3C 2D     |cmp al,2D ――――――――――判断是否输入“-”号,不知何意,呵呵 
0040803C    |.  74 0E     |je short RealOneA.0040804C――-只要不输入“-”号,就不会跳 
0040803E    |.  56        |push esi 
0040803F    |.  8BCF      |mov ecx,edi 
00408041    |.  FF15 BCB3>|call dword ptr ds:[<&MFC71.#865>]       ;  MFC71.7C1894E7 
00408047    |.  88441C 10 |mov byte ptr ss:[esp+ebx+10],al――――将注册码的ASC逐位入栈 
0040804B    |.  43        |inc ebx  ――――――――――――――――――计数加1 
0040804C    |>  83FB 10   |cmp ebx,10   ――――――――判断所取注册码是否超16位 
0040804F    |.  7D 0D     |jge short RealOneA.0040805E――――――是,跳走,否则继续 
00408051    |.  8BCF      |mov ecx,edi 
00408053    |.  46        |inc esi   ―――――――――――――――――计数加1 
00408054    |.  FF15 00B4>|call dword ptr ds:[<&MFC71.#2902>]      ;  MFC71.7C146AB0 
0040805A    |.  3BF0      |cmp esi,eax ―――――与注册码长度相比较,看注册码是否都取完 
0040805C    |.^ 7C D3     \jl short RealOneA.00408031 
////////////////////////////////////////////////////////////////////////////////////////// 
从这里我们可以看出注册码的有效位数最长为16位,多余位数系统是不认可的。 
////////////////////////////////////////////////////////////////////////////////////////// 
0040805E    |>  8B6C24 28 mov ebp,dword ptr ss:[esp+28] 
00408062    |.  33FF      xor edi,edi      
00408064    |>  0FBE447C >/movsx eax,byte ptr ss:[esp+edi*2+10] ―――将注册码第一位(以后循环是取注册码的奇数位)的ASC码移至eax,记为a, 
00408069    |.  83E8 41   |sub eax,41  ――――――――减去41,记为b 
0040806C    |.  78 20     |js short RealOneA.0040808E――――――跳就OVER 
0040806E    |.  83F8 1A   |cmp eax,1A  ―――――――比较b与1A大小 
00408071    |.  7D 1B     |jge short RealOneA.0040808E――――――――跳就OVER 
/////////////////////////////////////////////////////////////////////////////////////////// 
到这里,我们可以判断得出,注册码的ASC必须大于41,小于(41+1A),即输入的注册码必须为大写字母,长度为16位,重新输入注册码:ABABABABABABABAB 
////////////////////////////////////////////////////////////////////////////////////////// 
00408073    |.  8A98 6CCE>|mov bl,byte ptr ds:[eax+40CE6C] 
/////////////////////////////////////////////////////////////////////////////////////////// 
该命令是根据上面b值,在 “UEKXWHNFQLGVYIAPJSCRDBMZOT”找出相应字符的ASC码赋值给bl,我们刚刚输入是A,经过上面计算后b=0,所以此时bl=55,即“U” 
////////////////////////////////////////////////////////////////////////////////////////// 
00408079    |.  8A447C 11 |mov al,byte ptr ss:[esp+edi*2+11]―――――――将注册码的第二位(以后循环是取注册码的偶数位)的ASC码赋值给al 
0040807D    |.  33F6      |xor esi,esi 
0040807F    |.  90        |nop 
/////////////////////////////////////////////////////////////////////////////////////// 
00408080    |>  3A86 88CE>|/cmp al,byte ptr ds:[esi+40CE88] 
00408086    |.  74 12     ||je short RealOneA.0040809A 
00408088    |.  46        ||inc esi 
00408089    |.  83FE 24   ||cmp esi,24 
0040808C    |.^ 7C F2     |\jl short RealOneA.00408080 
上面这个小循环是判断注册码的偶数位是否能在“S4X5DQMHIYV6NP80B2LE91J3UKGF7ATWZRCO”这36位字符中找到,如不能找到,注册失败,如能找到,记录ESI的值,刚刚我们输入的是B,所以此时ESI=10,即是字符窜的第16位。 
////////////////////////////////////////////////////////////////////////////////////// 
0040808E    |>  5F        |pop edi 
0040808F    |.  5E        |pop esi 
00408090    |.  5D        |pop ebp 
00408091    |.  33C0      |xor eax,eax 
00408093    |.  5B        |pop ebx 
00408094    |.  83C4 14   |add esp,14 
00408097    |.  C2 0800   |retn 8 
0040809A    |>  83FE 24   |cmp esi,24――――――前面条件都满足后,跳到这里 
0040809D    |.^ 7D EF     |jge short RealOneA.0040808E――――条件满足这里自然就不跳 
0040809F    |.  57        |push edi 
004080A0    |.  8BCD      |mov ecx,ebp 
004080A2    |.  FF15 BCB3>|call dword ptr ds:[<&MFC71.#865>]  ――应该是将机器码移送al 
004080A8    |.  0FBED3    |movsx edx,bl――――――将bl的值给EDX,此时EDX=55 
004080AB    |.  0FBEC8    |movsx ecx,al―――――将第一位机器码的ASC码赋值给ECX,ECX=50(P) 
004080AE    |.  33D6      |xor edx,esi――――――对EDX和刚刚得到ESI进行XOR运算 
004080B0    |.  3BCA      |cmp ecx,edx――――――然后与机器码的ASC值相比较 
004080B2    |.^ 75 DA     |jnz short RealOneA.0040808E――――跳就OVER 
004080B4    |.  47        |inc edi 
004080B5    |.  83FF 08   |cmp edi,8――――――――判断8位机器码是否比较完,这里我们也可看到注册码是必需为16位的。 
004080B8    |.^ 7C AA     \jl short RealOneA.00408064―――没判断完,跳回再循环,过程一样,就不多写了。 
004080BA    |.  5F        pop edi 
004080BB    |.  5E        pop esi 
004080BC    |.  5D        pop ebp 
004080BD    |.  B8 010000>mov eax,1―――――标志位赋值 
004080C2    |.  5B        pop ebx 
004080C3    |.  83C4 14   add esp,14 
004080C6    \.  C2 0800   retn 8 
///////////////////////////////////////////////////////////////////// 
这里就可以收工了,呵呵 
算法小结: 
 
1) 注册码必需是大写字母,且必需是16位。 
1) 取注册码的奇数位的ASC值减41后,在UEKXWHNFQLGVYIAPJSCRDBMZOT查出相应字符的ASC,记为A 
2) 取注册码的偶数位,在“S4X5DQMHIYV6NP80B2LE91J3UKGF7ATWZRCO”这36位字符中找到,记下位置为B 
3) 对A和B进行XOR运算得出C 
4) 将C与机器码的ASC值逐位比较,全部相等注册成功 
//////////////////////////////////////////////////////////////////// 
返回 
004069C2     .  50        push eax 
004069C3     .  B9 380141>mov ecx,RealOneA.00410138               煳@ 
004069C8     .  899C24 B8>mov dword ptr ss:[esp+3B8],ebx 
004069CF     .  E8 CC1700>call RealOneA.004081A0----产生机器码,有兴趣自己去跟 
004069D4     .  68 640141>push RealOneA.00410164              
004069D9     .  8D4C24 10 lea ecx,dword ptr ss:[esp+10]       
004069DD     .  51        push ecx                            
004069DE     .  B9 380141>mov ecx,RealOneA.00410138           
004069E3     .  E8 181600>call RealOneA.00408000   
004069E8     .  85C0      test eax,eax―――――――――――返回这里 
004069EA     .  0F95C0    setne al―――――――――――――爆破点 
004069ED     .  3AC3      cmp al,bl 
004069EF     .  A2 440141>mov byte ptr ds:[410144],al  ――――标志位赋值 
004069F4     .  0F85 6402>jnz RealOneA.00406C5E ―――跳就over 
004069FA     .  B9 380141>mov ecx,RealOneA.00410138              煳@ 
004069FF     .  E8 7C1900>call RealOneA.00408380 
00406A04     .  8D5424 14 lea edx,dword ptr ss:[esp+14] 
 
//////////////////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////////////////// 
 
 
________________________________________ 
 
-------------------------------------------------------------------------------- 
【破解总结】 
本身这个程序的注册验证相对简单,而眀由于程序对注册码的偶数位检测只是简单判断,因此注册码并不是一一对应,而是一对多,这可能是作者没注意到,也是这个算法失败的一个地方。 
给出一个注册码,注册码与用户无关 
机器码: PKRMMSJV 用户名:yzs  注册码:PSCSTSWSWSRSQSLS |   
 
 
 
 |