MP3 Stream Creator 2.0.2009.501算法分析与KeyGen

  无壳保护,直接用OD加载后,直接运行。试注册,有提示:“Invalid registration code!”
  查找字符串:
  


  文本字符串参考位于 MP3Strea:CODE,项目 9555
   地址=00535F7A
   反汇编=mov edx,MP3Strea.005360DC
   文本字符串=UNICODE "Invalid registration code!"
  


  
  双击来到这里:
  


  00535F56    |> \8BC3             mov eax,ebx
  00535F58    |.  E8 B7010000      call MP3Strea.00536114
  00535F5D    |.  85C0             test eax,eax
  00535F5F    |.  74 19            je short MP3Strea.00535F7A
  00535F61    |.  BA 5C605300      mov edx,MP3Strea.0053605C              ;  UNICODE "Thank you for registration! All limitations are removed now."
  00535F66    |.  8B83 80030000    mov eax,dword ptr ds:[ebx+380]
  00535F6C    |.  E8 238FFAFF      call MP3Strea.004DEE94
  00535F71    |.  8BC3             mov eax,ebx
  00535F73    |.  E8 84030000      call MP3Strea.005362FC
  00535F78    |.  EB 1E            jmp short MP3Strea.00535F98
  00535F7A    |>  BA DC605300      mov edx,MP3Strea.005360DC              ;  UNICODE "Invalid registration code!"
  

  
  初步判断,发现:call MP3Strea.00536114是关键CALL,返回值EAX,如果EAX==0,则显示注册失败,反之则注册成功。
  不过,我们先不管这些,直接在段首下断,然后重新试注册。
  


  00535E9C    /.  55               push ebp
  00535E9D    |.  8BEC             mov ebp,esp
  00535E9F    |.  33C9             xor ecx,ecx
  00535EA1    |.  51               push ecx
  00535EA2    |.  51               push ecx
  00535EA3    |.  51               push ecx
  00535EA4    |.  51               push ecx
  00535EA5    |.  53               push ebx
  00535EA6    |.  8BD8             mov ebx,eax
  00535EA8    |.  33C0             xor eax,eax
  00535EAA    |.  55               push ebp
  00535EAB    |.  68 C65F5300      push MP3Strea.00535FC6
  00535EB0    |.  64:FF30          push dword ptr fs:[eax]
  00535EB3    |.  64:8920          mov dword ptr fs:[eax],esp
  00535EB6    |.  8D55 F8          lea edx,dword ptr ss:[ebp-8]
  00535EB9    |.  8B83 50030000    mov eax,dword ptr ds:[ebx+350]
  00535EBF    |.  E8 B8A8F2FF      call MP3Strea.0046077C                 ;  取用户名
  00535EC4    |.  8B45 F8          mov eax,dword ptr ss:[ebp-8]
  00535EC7    |.  8D55 FC          lea edx,dword ptr ss:[ebp-4]
  00535ECA    |.  E8 7936EDFF      call MP3Strea.00409548
  00535ECF    |.  8B55 FC          mov edx,dword ptr ss:[ebp-4]
  00535ED2    |.  8D83 70040000    lea eax,dword ptr ds:[ebx+470]
  00535ED8    |.  E8 E7EDECFF      call MP3Strea.00404CC4
  00535EDD    |.  8D55 F0          lea edx,dword ptr ss:[ebp-10]
  00535EE0    |.  8B83 58030000    mov eax,dword ptr ds:[ebx+358]
  00535EE6    |.  E8 91A8F2FF      call MP3Strea.0046077C                 ;  取注册码
  00535EEB    |.  8B45 F0          mov eax,dword ptr ss:[ebp-10]
  00535EEE    |.  8D55 F4          lea edx,dword ptr ss:[ebp-C]
  00535EF1    |.  E8 5236EDFF      call MP3Strea.00409548
  00535EF6    |.  8B55 F4          mov edx,dword ptr ss:[ebp-C]
  00535EF9    |.  8D83 74040000    lea eax,dword ptr ds:[ebx+474]
  00535EFF    |.  E8 C0EDECFF      call MP3Strea.00404CC4
  00535F04    |.  83BB 70040000 00 cmp dword ptr ds:[ebx+470],0           ;  判断用户名是否为空
  00535F0B    |.  75 20            jnz short MP3Strea.00535F2D
  00535F0D    |.  BA D85F5300      mov edx,MP3Strea.00535FD8              ;  UNICODE "Please input your name!"
  00535F12    |.  8B83 80030000    mov eax,dword ptr ds:[ebx+380]
  00535F18    |.  E8 778FFAFF      call MP3Strea.004DEE94
  00535F1D    |.  8B83 50030000    mov eax,dword ptr ds:[ebx+350]
  00535F23    |.  8B10             mov edx,dword ptr ds:[eax]
  00535F25    |.  FF92 C4000000    call dword ptr ds:[edx+C4]
  00535F2B    |.  EB 6B            jmp short MP3Strea.00535F98
  00535F2D    |>  83BB 74040000 00 cmp dword ptr ds:[ebx+474],0           ;  判断注册码是否为空
  00535F34    |.  75 20            jnz short MP3Strea.00535F56
  00535F36    |.  BA 0C605300      mov edx,MP3Strea.0053600C              ;  UNICODE "Please input your registration code!"
  00535F3B    |.  8B83 80030000    mov eax,dword ptr ds:[ebx+380]
  00535F41    |.  E8 4E8FFAFF      call MP3Strea.004DEE94
  00535F46    |.  8B83 58030000    mov eax,dword ptr ds:[ebx+358]
  00535F4C    |.  8B10             mov edx,dword ptr ds:[eax]
  00535F4E    |.  FF92 C4000000    call dword ptr ds:[edx+C4]
  00535F54    |.  EB 42            jmp short MP3Strea.00535F98
  00535F56    |>  8BC3             mov eax,ebx
  

  
  单步跟过,发现上面只是取用户名与注册码,然后比较用户名与注册码是否为空。看来刚才的判断:
  call MP3Strea.00536114是关键CALL是正确的了,我们F7跟进:
  


  00536114    /$  55               push ebp
  00536115    |.  8BEC             mov ebp,esp
  00536117    |.  B9 05000000      mov ecx,5
  0053611C    |>  6A 00            /push 0
  0053611E    |.  6A 00            |push 0
  00536120    |.  49               |dec ecx
  00536121    |.^ 75 F9            \jnz short MP3Strea.0053611C
  00536123    |.  51               push ecx
  00536124    |.  53               push ebx
  00536125    |.  56               push esi
  00536126    |.  57               push edi
  00536127    |.  8BD8             mov ebx,eax
  00536129    |.  33C0             xor eax,eax
  0053612B    |.  55               push ebp
  0053612C    |.  68 DE625300      push MP3Strea.005362DE
  00536131    |.  64:FF30          push dword ptr fs:[eax]
  00536134    |.  64:8920          mov dword ptr fs:[eax],esp
  00536137    |.  33FF             xor edi,edi
  00536139    |.  8D45 FC          lea eax,dword ptr ss:[ebp-4]
  0053613C    |.  8B93 70040000    mov edx,dword ptr ds:[ebx+470]
  00536142    |.  E8 C1EBECFF      call MP3Strea.00404D08
  00536147    |.  8D45 F8          lea eax,dword ptr ss:[ebp-8]
  0053614A    |.  8B93 74040000    mov edx,dword ptr ds:[ebx+474]
  00536150    |.  E8 B3EBECFF      call MP3Strea.00404D08
  00536155    |.  8B45 F8          mov eax,dword ptr ss:[ebp-8]
  00536158    |.  E8 E3EDECFF      call MP3Strea.00404F40                 ;  取注册码长度
  0053615D    |.  83F8 16          cmp eax,16                             ;  与0x16比较
  00536160    |.  0F85 5D010000    jnz MP3Strea.005362C3                  ;  不等则跳转清0退出,提示注册失败
  00536166    |.  8D4D EC          lea ecx,dword ptr ss:[ebp-14]
  00536169    |.  BA 03000000      mov edx,3
  0053616E    |.  8B83 74040000    mov eax,dword ptr ds:[ebx+474]
  00536174    |.  E8 0332F0FF      call MP3Strea.0043937C                 ;  取注册码前3个字符
  00536179    |.  8B45 EC          mov eax,dword ptr ss:[ebp-14]
  0053617C    |.  BA F8625300      mov edx,MP3Strea.005362F8              ;  ASCII "EXP"
  00536181    |.  E8 06EFECFF      call MP3Strea.0040508C                 ;  与固定字符串“EXP”比较
  00536186    |.  0F85 37010000    jnz MP3Strea.005362C3                  ;  不等则跳转清0退出,提示注册失败
  0053618C    |.  8D4D F8          lea ecx,dword ptr ss:[ebp-8]
  0053618F    |.  BA 13000000      mov edx,13
  00536194    |.  8B83 74040000    mov eax,dword ptr ds:[ebx+474]
  0053619A    |.  E8 4D32F0FF      call MP3Strea.004393EC                 ;  取余下的0x13位注册码
  0053619F    |.  837D FC 00       cmp dword ptr ss:[ebp-4],0             ;  再次测试用户名是否为空
  005361A3    |.  0F84 1A010000    je MP3Strea.005362C3                   ;  为空则跳转清0退出,提示注册失败
  005361A9    |.  837D F8 00       cmp dword ptr ss:[ebp-8],0             ;  再次测试注册码是否为空
  005361AD    |.  0F84 10010000    je MP3Strea.005362C3                   ;  为空则跳转清0退出,提示注册失败
  005361B3    |.  33F6             xor esi,esi
  005361B5    |>  8B45 F8          /mov eax,dword ptr ss:[ebp-8]          ;  让EAX指向注册码
  005361B8    |.  8A1C30           |mov bl,byte ptr ds:[eax+esi]          ;  以ESI为索引
  005361BB    |.  80FB 2D          |cmp bl,2D                             ;  按位取ASCII值,与0x2D,即"-"比较
  005361BE    |.  74 15            |je short MP3Strea.005361D5            ;  不等则继续,相等则跳过,继续下一过
  005361C0    |.  8D45 E8          |lea eax,dword ptr ss:[ebp-18]
  005361C3    |.  8BD3             |mov edx,ebx
  005361C5    |.  E8 8EECECFF      |call MP3Strea.00404E58
  005361CA    |.  8B55 E8          |mov edx,dword ptr ss:[ebp-18]
  005361CD    |.  8D45 F4          |lea eax,dword ptr ss:[ebp-C]
  005361D0    |.  E8 73EDECFF      |call MP3Strea.00404F48
  005361D5    |>  46               |inc esi
  005361D6    |.  83FE 13          |cmp esi,13
  005361D9    |.^ 75 DA            \jnz short MP3Strea.005361B5
       //这个循环的作用是过滤剩下的19位注册码中含有的字符"-"后,生成一个新的字符串:str1
  
  005361DB    |.  8D45 F8          lea eax,dword ptr ss:[ebp-8]
  005361DE    |.  8B55 F4          mov edx,dword ptr ss:[ebp-C]
  005361E1    |.  E8 22EBECFF      call MP3Strea.00404D08
  005361E6    |.  8D45 F4          lea eax,dword ptr ss:[ebp-C]
  005361E9    |.  E8 82EAECFF      call MP3Strea.00404C70
  005361EE    |.  8B45 F8          mov eax,dword ptr ss:[ebp-8]
  005361F1    |.  E8 4AEDECFF      call MP3Strea.00404F40                 ;  取str1的长度
  005361F6    |.  83F8 10          cmp eax,10                             ;  与0x10比较
  005361F9    |.  0F85 C4000000    jnz MP3Strea.005362C3                  ;  不等则跳转清0退出,提示注册失败
       //这样一来就表明,后面的19位注册码里,必须含有3个"-"
  
  005361FF    |.  33F6             xor esi,esi                      ;  清0ESI,以ESI为索引
  00536201    |>  8BC6             /mov eax,esi
  00536203    |.  25 01000080      |and eax,80000001                ;  将索引与0x80000001进行AND运算
  00536208    |.  79 05            |jns short MP3Strea.0053620F
  0053620A    |.  48               |dec eax
  0053620B    |.  83C8 FE          |or eax,FFFFFFFE
  0053620E    |.  40               |inc eax
  0053620F    |>  85C0             |test eax,eax
  00536211    |.  75 1B            |jnz short MP3Strea.0053622E
  00536213    |.  8D45 E4          |lea eax,dword ptr ss:[ebp-1C]
  00536216    |.  8B55 F8          |mov edx,dword ptr ss:[ebp-8]
  00536219    |.  8A1432           |mov dl,byte ptr ds:[edx+esi]
  0053621C    |.  E8 37ECECFF      |call MP3Strea.00404E58
  00536221    |.  8B55 E4          |mov edx,dword ptr ss:[ebp-1C]
  00536224    |.  8D45 F0          |lea eax,dword ptr ss:[ebp-10]
  00536227    |.  E8 1CEDECFF      |call MP3Strea.00404F48
  0053622C    |.  EB 19            |jmp short MP3Strea.00536247
  0053622E    |>  8D45 E0          |lea eax,dword ptr ss:[ebp-20]
  00536231    |.  8B55 F8          |mov edx,dword ptr ss:[ebp-8]
  00536234    |.  8A1432           |mov dl,byte ptr ds:[edx+esi]
  00536237    |.  E8 1CECECFF      |call MP3Strea.00404E58
  0053623C    |.  8B55 E0          |mov edx,dword ptr ss:[ebp-20]
  0053623F    |.  8D45 F4          |lea eax,dword ptr ss:[ebp-C]
  00536242    |.  E8 01EDECFF      |call MP3Strea.00404F48
  00536247    |>  46               |inc esi
  00536248    |.  83FE 10          |cmp esi,10
  0053624B    |.^ 75 B4            \jnz short MP3Strea.00536201
        //这个循环是上面得到的Str1按奇偶位,分成2个字符串:
        //奇数位为:oddStr
        //偶数位为:evenStr
  
  0053624D    |.  8D45 FC          lea eax,dword ptr ss:[ebp-4]
  00536250    |.  E8 1BEAECFF      call MP3Strea.00404C70
  00536255    |.  33F6             xor esi,esi
  00536257    |>  8D45 DC          /lea eax,dword ptr ss:[ebp-24]
  0053625A    |.  BA 08000000      |mov edx,8
  0053625F    |.  2BD6             |sub edx,esi
  00536261    |.  8B4D F4          |mov ecx,dword ptr ss:[ebp-C]
  00536264    |.  8A5411 FF        |mov dl,byte ptr ds:[ecx+edx-1]
  00536268    |.  E8 EBEBECFF      |call MP3Strea.00404E58
  0053626D    |.  8B55 DC          |mov edx,dword ptr ss:[ebp-24]
  00536270    |.  8D45 FC          |lea eax,dword ptr ss:[ebp-4]
  00536273    |.  E8 D0ECECFF      |call MP3Strea.00404F48
  00536278    |.  46               |inc esi
  00536279    |.  83FE 08          |cmp esi,8
  0053627C    |.^ 75 D9            \jnz short MP3Strea.00536257     ;  对偶数位字符串:evenStr进行逆序
  0053627E    |.  8D55 D8          lea edx,dword ptr ss:[ebp-28]    ;  得revEvenStr
  00536281    |.  8B45 F0          mov eax,dword ptr ss:[ebp-10]
  00536284    |.  E8 E757FFFF      call MP3Strea.0052BA70           ;  对奇数位oddStr取MD5值
  00536289    |.  8B55 D8          mov edx,dword ptr ss:[ebp-28]
  0053628C    |.  8D45 F0          lea eax,dword ptr ss:[ebp-10]
  0053628F    |.  E8 74EAECFF      call MP3Strea.00404D08
  00536294    |.  8D4D D4          lea ecx,dword ptr ss:[ebp-2C]
  00536297    |.  BA 08000000      mov edx,8
  0053629C    |.  8B45 F0          mov eax,dword ptr ss:[ebp-10]
  0053629F    |.  E8 CC31F0FF      call MP3Strea.00439470           ;  截取MD5值的后8位,得Md5OddStr
  005362A4    |.  8B55 D4          mov edx,dword ptr ss:[ebp-2C]
  005362A7    |.  8D45 F0          lea eax,dword ptr ss:[ebp-10]
  005362AA    |.  E8 59EAECFF      call MP3Strea.00404D08
  005362AF    |.  8B45 FC          mov eax,dword ptr ss:[ebp-4]     ;  revEvenStr
  005362B2    |.  8B55 F0          mov edx,dword ptr ss:[ebp-10]
  005362B5    |.  E8 D2EDECFF      call MP3Strea.0040508C           ;  将revEvenStr与Md5OddStr比较
  005362BA    |.  75 05            jnz short MP3Strea.005362C1      ;  相等则不跳
  005362BC    |.  83CF FF          or edi,FFFFFFFF                  ;  置EDI值为0xFFFFFFFF
  005362BF    |.  EB 02            jmp short MP3Strea.005362C3
  005362C1    |>  33FF             xor edi,edi                      ;  否则清0EDI
  005362C3    |>  33C0             xor eax,eax
  005362C5    |.  5A               pop edx
  005362C6    |.  59               pop ecx
  005362C7    |.  59               pop ecx
  005362C8    |.  64:8910          mov dword ptr fs:[eax],edx
  005362CB    |.  68 E5625300      push MP3Strea.005362E5
  005362D0    |>  8D45 D4          lea eax,dword ptr ss:[ebp-2C]
  005362D3    |.  BA 0B000000      mov edx,0B
  005362D8    |.  E8 B7E9ECFF      call MP3Strea.00404C94
  005362DD    \.  C3               retn
  005362DE     .^ E9 F1E2ECFF      jmp MP3Strea.004045D4
  005362E3     .^ EB EB            jmp short MP3Strea.005362D0
  005362E5     .  8BC7             mov eax,edi
  005362E7     .  5F               pop edi
  005362E8     .  5E               pop esi
  005362E9     .  5B               pop ebx
  005362EA     .  8BE5             mov esp,ebp
  005362EC     .  5D               pop ebp
  005362ED     .  C3               retn
  

  
  由上分析,可得看到:
  1、用户名对没有参与运算,只需要用户名不为空即可.
  2、注册码的长度为22位,且前3位固定为“EXP”
  3、后19位注册码中有3个“-”字符,位置不固定
  
  好了,开始编写KeyGen代码了,呵呵,如下:
  


  #include
  #include
  #include
  #include"md5.h"
  
  const char strC[]="0123456789ABCDEF";
  
  int main(){
    srand((unsigned)time(NULL));
    
    //第一步:随机生成奇数位注册码
    unsigned char OddStr[9]={0};
    for(int i=0;i<8;i++){  
      int tmp=(int)(((double) rand() / (double) RAND_MAX) * 0xF + 0);
      OddStr[i]=strC[tmp];
    }
    printf("OddStr=%s\n",OddStr);  //测试输出
    
    //第二步:获取奇数位注册码的MD5值  
    unsigned char szHash[256]={0};
    char szBuffer[256]={0};
    MD5_CTX context;
    
    MD5Init(&context);
    MD5Update(&context, OddStr, 8);
    MD5Final(szHash, &context);
    for(int i=0; i < 16; i++)   // 将szHash[]中的16进制转换成字符形式显示
      wsprintf(&szBuffer[i*2], "%02X", *(byte*)(szHash+i));
    printf("Md5OddStr=%s\n",szBuffer);  //测试输出
    
    //第三步:获取偶数位的注册码的逆序值
    char revEvenStr[9]={0};
    strncpy(revEvenStr,&szBuffer[24],8);
    printf("revEvenStr=%s\n",revEvenStr);  //测试输出
    
    //第四步:获取偶数位的注册码
    char EvenStr[9]={0};
    for(int i=0;i<8;i++)
      EvenStr[i]=revEvenStr[8-i-1];
    printf("EvenStr=%s\n",EvenStr);  //测试输出
    
    //第5步:合成最终注册码的后19位
    char strCode[20]={0};
    strCode[2]='-';
    strCode[7]='-';
    strCode[12]='-';
    
    int j=0,k=0;
    for(int i=0;i<18;){
      if(strCode[i]=='-')
        i++;
      strCode[i]=OddStr[j];
      i++;
      if(strCode[i]=='-')
        i++;
      strCode[i]=EvenStr[k];
      i++;
      j++;
      k++;    
    }
    //第六步:直接拼接上前3位的固定字符串以输出
    printf("你的注册码是:EXP%s\n",strCode);
    return 0;
  }
  

  
  测试运行结果:
  


  E:\PlusCode\MD5\MD5(cpp)>KeyGen
  OddStr=5392B953
  Md5OddStr=8CC53540F9E78BB99301CFB0EFC0041A
  revEvenStr=EFC0041A
  EvenStr=A1400CFE
  你的注册码是:EXP5A-3194-20B0-9C5F3E
  

“MP3 Stream Creator 2.0.2009.501算法分析与KeyGen”的一个回复

发表评论