Magic DVD Ripper 5.2.1 build 2的算法分析

【文章标题】: Magic DVD Ripper 5.2.1 build 2的算法分析
【软件名称】: Magic DVD Ripper
【加壳方式】: 无
【编写语言】: Borland C++ 1999
【使用工具】: OD
【软件介绍】:    Magic DVD Ripper 是一款DVD 电影抓取工具。
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
——————————————————————————–
【详细过程】
  第一次写算分析,请各位大大不要见笑!常在看雪逛,也分享一点自己的学习!
  
  不说了,请看正文:
  OD载入后,运用F12堆栈调用法找到注册码判断的段:

 
  0041EF18  .  55            push    ebp
  0041EF19  .  8BEC          mov    ebp, esp
  0041EF1B  .  83C4 AC      add    esp, -54
            >>>>>>由于侧重算法,这里就不细说如何找到段首了!
  
  F8单步:
  0041EF56  .  E8 99950B00  call    004D84F4                        ;  取出用户名
  0041EF5B  .  8D45 F4      lea    eax, dword ptr [ebp-C]
  0041EF5E  .  8B00          mov    eax, dword ptr [eax]
            >>>>>>EAX指向的即为用户名了
  
  0041EFA2  > /33C0          xor    eax, eax
  0041EFA4  . |8A03          mov    al, byte ptr [ebx]
            >>>>>>按位取用户名的每位的ASCII值
  0041EFA6  . |03F0          add    esi, eax
  0041EFA8  . |47            inc    edi
  0041EFA9  . |43            inc    ebx
  0041EFAA  > |8B55 B4      mov    edx, dword ptr [ebp-4C]
  0041EFAD  . |52            push    edx
  0041EFAE  . |E8 79BC0E00  call    0050AC2C
  0041EFB3  . |59            pop    ecx
  0041EFB4  . |3BF8          cmp    edi, eax
  0041EFB6  .^\72 EA        jb      short 0041EFA2            ;  将用户名的每位ASCII码值累加
            >>>>>>计算完毕,ESI里的值即为累加的结果了
  
  0041EFC8  > \56            push    esi
  0041EFC9  .  68 A4D85300  push    0053D8A4                  ;  ASCII "%04X"
  0041EFCE  .  8D4D AC      lea    ecx, dword ptr [ebp-54]
  0041EFD1  .  51            push    ecx
  0041EFD2  .  E8 11F70E00  call    0050E6E8                  ;  格式化为4位长的字符串
  
  
  0041F05D  > /0FBE03        movsx  eax, byte ptr [ebx]
  0041F060  . |83F8 6F      cmp    eax, 6F
  0041F063  . |74 05        je      short 0041F06A
  0041F065  . |83F8 4F      cmp    eax, 4F
  0041F068  . |75 03        jnz    short 0041F06D
  0041F06A  > |C603 30      mov    byte ptr [ebx], 30
  0041F06D  > |47            inc    edi
  0041F06E  . |43            inc    ebx
  0041F06F  > |56            push    esi
  0041F070  . |E8 B7BB0E00  call    0050AC2C
  0041F075  . |59            pop    ecx
  0041F076  . |3BF8          cmp    edi, eax                  ;  检查注册码,当出现ASCII值为6F或
  0041F078  .^\72 E3        jb      short 0041F05D            ;  4F时,替换为0X30
  
  0041F0A3  .  BA 02000000  mov    edx, 2
  0041F0A8  .  E8 B3AB0F00  call    00519C60
            >>>>>>此时,ESI指向了我们输入的假注册码了
            >>>>>>      EBP-54指向了用户生成的4位长字符串
            >>>>>>假设,注册码为:strCode[32]
            >>>>>>      字符串为:strTmp[5]
  
  0041F0AD  .  8A4E 05      mov    cl, byte ptr [esi+5]      ;  strCode[5]
  0041F0B0  .  3A4D AC      cmp    cl, byte ptr [ebp-54]    ;  strTmp[0]
  0041F0B3  .  75 26        jnz    short 0041F0DB            ;  不等则出错
            >>>>>>所以,strCode[5]应该等于strTmp[0]
  
  0041F0B5  .  8A46 04      mov    al, byte ptr [esi+4]      ;  strCode[4]
  0041F0B8  .  3A45 AD      cmp    al, byte ptr [ebp-53]    ;  strTmp[1]
  0041F0BB  .  75 1E        jnz    short 0041F0DB
            >>>>>>所以,strCode[4]应该等于strTmp[1]
  
  0041F0BD  .  8A56 12      mov    dl, byte ptr [esi+12]    ;  strCode[18],注12为16进制格式
  0041F0C0  .  3A55 AE      cmp    dl, byte ptr [ebp-52]    ;  strTmp[2]
  0041F0C3  .  75 16        jnz    short 0041F0DB
            >>>>>>所以,strCode[18]应该等于strTmp[2]
  
  0041F0C5  .  8A0E          mov    cl, byte ptr [esi]        ;  strCode[0]
  0041F0C7  .  3A4D AF      cmp    cl, byte ptr [ebp-51]    ;  strTmp[3]
  0041F0CA  .  75 0F        jnz    short 0041F0DB
            >>>>>>所以,strCode[0]应该等于strTmp[3]
  

  如果上面都通过,则显示正确!
  故,只要随意的生成一个长超过19位的字符串,将其中的6,5,19,0替换成按用户名生成的4个字符,即可:
  
  代码如下:

 
  char strName[20];//用户名
  char strCode[32];//注册码
  char strS[]="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  
  void CreateRegCode(HWND hDlg){
          //利用随机数,生成随机的20位长注册码
  for(int i=0;i<20;i++){
    int index=(((double) rand() / (double) RAND_MAX) * 62 + 0);
    strCode[i]=strS[index];
  }
  
          //计算用户各位ASCII值的和,并格式化为字符串
  char strTmp[5];
  int len=strlen(strName);
  int sum=0;
  for(int i=0;i    sum+=strName[i];
  sum&=0x8000FFFF;
  sprintf(strTmp,"%04X",sum);
  
          //替换注册码中的值
  strCode[5]=strTmp[0];
  strCode[4]=strTmp[1];
  strCode[18]=strTmp[2];
  strCode[0]=strTmp[3];
  
          //完成,显示到编辑框
  SetDlgItemText(hDlg,IDC_PWD,strCode);
  return;
  }
  

——————————————————————————–
【经验总结】
  没有什么感觉,只要花点时间,细过一边就一目了然了!也算捡了一个软柿子吧!
  
——————————————————————————–
【版权声明】: 转载请注明作者并保持文章的完整, 谢谢!
                                                      2008年02月01日 22:07:53

发表评论