• 标 题:Ultra Tagger 2.20 Final
  • 作 者:炎之川
  • 时 间:2003/05/13 04:24pm
  • 链 接:http://bbs.pediy.com

Ultra Tagger 2.20 Final 注册算法分析+注册机源代码(tc2)

破解目标:Ultra Tagger 2.20 Final
官方主页:http://www.ultratagger.com/
软件简介:UltraTagger 不仅可以大量修改 MP3 的 ID3v1 及ID3v2文件卷标,同时还具有转换文件的功能,可以将 MP3 转成 WAV,或者由 WAV 转成 MP3文件。
下载地址:http://on165-http.skycn.net/down/setup_ultratagger.exe

使用工具:PEiD 0.8、Ollydbg、W32Dasm、UltraEdit

作者:炎之川[BCG]
时间:2003.5.12
主页:http://skipli.yeah.net/

========================================================================
声明: 本文纯属技术交流,无其他任何目的,转载请注明作者并保持文章的完整。
========================================================================

其实我觉得 MP3 标签批量更改工具里面,还是 Tag&Rename 最好用,Ultra Tagger 用起来感觉不是很习惯……

经过 PEiD 检查,主程序没加壳,Delphi 写的。用 OD 装入程序,运行并输入假码:
Name: 炎之川[BCG]
Serial: 9876-5432-1098

(; 后是 Ollydbg 所分析的内容,// 后是我加的注释)

0053A4AD  |. 8B10           MOV EDX,DWORD PTR DS:[EAX]
0053A4AF  |. FF92 EC000000  CALL DWORD PTR DS:[EDX+EC]
0053A4B5  |. 48             DEC EAX
0053A4B6  |. 0F85 88000000  JNZ UltraTag.0053A544
0053A4BC  |. 8D55 FC        LEA EDX,DWORD PTR SS:[EBP-4]    //断点
0053A4BF  |. A1 FC445400    MOV EAX,DWORD PTR DS:[5444FC]
0053A4C4  |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0053A4C6  |. 8B80 10030000  MOV EAX,DWORD PTR DS:[EAX+310]
0053A4CC  |. E8 3B87F2FF    CALL UltraTag.00462C0C   //获得假码长度
0053A4D1  |. 8B55 FC        MOV EDX,DWORD PTR SS:[EBP-4]
0053A4D4  |. 8BC3           MOV EAX,EBX
0053A4D6  |. E8 558AFFFF    CALL UltraTag.00532F30   //关键call!
0053A4DB  |. 84C0           TEST AL,AL   //比较al是否为0
0053A4DD  |. 74 50          JE SHORT UltraTag.0053A52F   //为0则注册失败
0053A4DF  |. 8D55 F8        LEA EDX,DWORD PTR SS:[EBP-8]   //取假码
0053A4E2  |. A1 FC445400    MOV EAX,DWORD PTR DS:[5444FC]
0053A4E7  |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0053A4E9  |. 8B80 10030000  MOV EAX,DWORD PTR DS:[EAX+310]
0053A4EF  |. E8 1887F2FF    CALL UltraTag.00462C0C
0053A4F4  |. 8B45 F8        MOV EAX,DWORD PTR SS:[EBP-8]
0053A4F7  |. 50             PUSH EAX
0053A4F8  |. 8D55 F4        LEA EDX,DWORD PTR SS:[EBP-C]
0053A4FB  |. A1 FC445400    MOV EAX,DWORD PTR DS:[5444FC]
0053A500  |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0053A502  |. 8B80 0C030000  MOV EAX,DWORD PTR DS:[EAX+30C]
0053A508  |. E8 FF86F2FF    CALL UltraTag.00462C0C
0053A50D  |. 8B55 F4        MOV EDX,DWORD PTR SS:[EBP-C]
0053A510  |. 8BC3           MOV EAX,EBX
0053A512  |. 59             POP ECX
0053A513  |. E8 9088FFFF    CALL UltraTag.00532DA8
0053A518  |. 6A 00          PUSH 0                                   ; /Arg1 = 00000000
0053A51A  |. 66:8B0D 6CA553>MOV CX,WORD PTR DS:[53A56C]              ; |
0053A521  |. B2 02          MOV DL,2                                 ; |
0053A523  |. B8 78A55300    MOV EAX,UltraTag.0053A578                ; |ASCII "Thanks for registering UltraTagger!"
0053A528  |. E8 93DFEFFF    CALL UltraTag.004384C0                   ; \UltraTag.004384C0
0053A52D  |. EB 15          JMP SHORT UltraTag.0053A544
0053A52F  |> 6A 00          PUSH 0                                   ; /Arg1 = 00000000
0053A531  |. 66:8B0D 6CA553>MOV CX,WORD PTR DS:[53A56C]              ; |
0053A538  |. B2 01          MOV DL,1                                 ; |
0053A53A  |. B8 A4A55300    MOV EAX,UltraTag.0053A5A4                ; |ASCII "Invalid registration code!"
0053A53F  |. E8 7CDFEFFF    CALL UltraTag.004384C0                   ; \UltraTag.004384C0
0053A544  |> 33C0           XOR EAX,EAX
0053A546  |. 5A             POP EDX
0053A547  |. 59             POP ECX
0053A548  |. 59             POP ECX
0053A549  |. 64:8910        MOV DWORD PTR FS:[EAX],EDX
0053A54C  |. 68 66A55300    PUSH UltraTag.0053A566
0053A551  |> 8D45 F4        LEA EAX,DWORD PTR SS:[EBP-C]
0053A554  |. BA 03000000    MOV EDX,3
0053A559  |. E8 86A8ECFF    CALL UltraTag.00404DE4
0053A55E  \. C3             RETN
0053A55F   .^E9 A0A1ECFF    JMP UltraTag.00404704
0053A564   .^EB EB          JMP SHORT UltraTag.0053A551
0053A566   . 5B             POP EBX
0053A567   . 8BE5           MOV ESP,EBP
0053A569   . 5D             POP EBP
0053A56A   . C3             RETN


------------------------------------------------------------------------
进入 00532F30 的关键call:

00532F30  /$ 55             PUSH EBP
00532F31  |. 8BEC           MOV EBP,ESP
00532F33  |. 51             PUSH ECX
00532F34  |. 53             PUSH EBX
00532F35  |. 8955 FC        MOV DWORD PTR SS:[EBP-4],EDX   //从edx中取出假码
00532F38  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]   /放到eax中
00532F3B  |. E8 4C23EDFF    CALL UltraTag.0040528C   //检查eax是否为0,即是否已输入
00532F40  |. 33C0           XOR EAX,EAX  //清零
00532F42  |. 55             PUSH EBP
00532F43  |. 68 37305300    PUSH UltraTag.00533037
00532F48  |. 64:FF30        PUSH DWORD PTR FS:[EAX]
00532F4B  |. 64:8920        MOV DWORD PTR FS:[EAX],ESP
00532F4E  |. 33DB           XOR EBX,EBX
00532F50  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]   //取假码
00532F53  |. E8 4421EDFF    CALL UltraTag.0040509C   //求假码长度倒eax
00532F58  |. 83F8 0E        CMP EAX,0E   //比较假码长度是否为14位(0x0E = 14)
00532F5B  |. 0F8C C0000000  JL UltraTag.00533021   //不为14位则死
00532F61  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]   //取假码
00532F64  |. BA 4C305300    MOV EDX,UltraTag.0053304C                ;  ASCII "7413-6386-5454"
//这个是黑名单:)
00532F69  |. E8 7A22EDFF    CALL UltraTag.004051E8   //比较输入的注册码与黑名单的注册码是否相同
00532F6E  |. 0F84 AD000000  JE UltraTag.00533021   //相同就注册失败

00532F74  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]   //取假码到eax,下同
00532F77  |. 8A00           MOV AL,BYTE PTR DS:[EAX]   //取第1个字符
00532F79  |. 3C 36          CMP AL,36   //比较第1个字符的ASCII值是否大于36
00532F7B  |. 0F86 A0000000  JBE UltraTag.00533021   //大于才能继续
00532F81  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532F84  |. 8A40 01        MOV AL,BYTE PTR DS:[EAX+1]   //取第1+1个字符
00532F87  |. 3C 35          CMP AL,35   //比较第1+1个字符的ASCII值是否大于35
00532F89  |. 0F83 92000000  JNB UltraTag.00533021   //小于才能继续
00532F8F  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532F92  |. 8A40 02        MOV AL,BYTE PTR DS:[EAX+2]   //取第1+2个字符
00532F95  |. 3C 31          CMP AL,31   //比较第1+2个字符的ASCII值是否大于31
00532F97  |. 0F85 84000000  JNZ UltraTag.00533021   //等于才能继续
00532F9D  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532FA0  |. 8A40 03        MOV AL,BYTE PTR DS:[EAX+3]   //取第1+3个字符
00532FA3  |. 3C 32          CMP AL,32   //比较第1+3个字符的ASCII值是否大于32
00532FA5  |. 76 7A          JBE SHORT UltraTag.00533021   //大于才能继续
00532FA7  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532FAA  |. 8A40 04        MOV AL,BYTE PTR DS:[EAX+4]   //取第1+4个字符
00532FAD  |. 3C 2D          CMP AL,2D   //比较字符的ASCII值是否等于2D(即“-”)
//注册码第5位必须为“-”
00532FAF  |. 75 70          JNZ SHORT UltraTag.00533021   //等于才能继续
00532FB1  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532FB4  |. 8A40 05        MOV AL,BYTE PTR DS:[EAX+5]   //取第1+5个字符
00532FB7  |. 3C 35          CMP AL,35   //比较第一个字符的ASCII值是否大于35
00532FB9  |. 76 66          JBE SHORT UltraTag.00533021   //大于才能继续
00532FBB  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532FBE  |. 8A40 06        MOV AL,BYTE PTR DS:[EAX+6]   //取第1+6个字符
00532FC1  |. 3C 34          CMP AL,34   //比较第一个字符的ASCII值是否大于34
00532FC3  |. 73 5C          JNB SHORT UltraTag.00533021   //小于才能继续
00532FC5  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532FC8  |. 8A40 07        MOV AL,BYTE PTR DS:[EAX+7]   //取第1+7个字符
00532FCB  |. 3C 38          CMP AL,38   //比较第1+7个字符的ASCII值是否大于38
00532FCD  |. 75 52          JNZ SHORT UltraTag.00533021   //等于才能继续
00532FCF  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532FD2  |. 8A40 08        MOV AL,BYTE PTR DS:[EAX+8]   //取第1+8个字符
00532FD5  |. 3C 37          CMP AL,37   //比较第一个字符的ASCII值是否大于37
00532FD7  |. 73 48          JNB SHORT UltraTag.00533021   //小于才能继续
00532FD9  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532FDC  |. 8A40 09        MOV AL,BYTE PTR DS:[EAX+9]   //取第1+9个字符
00532FDF  |. 3C 2D          CMP AL,2D   //比较字符的ASCII值是否等于2D(即“-”)
//注册码第10位必须为“-”
00532FE1  |. 75 3E          JNZ SHORT UltraTag.00533021
00532FE3  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532FE6  |. 0FB640 0A      MOVZX EAX,BYTE PTR DS:[EAX+A]   //取第1+0xA个字符
00532FEA  |. 83C0 D0        ADD EAX,-30
00532FED  |. 83E8 0A        SUB EAX,0A   //必须为0~9
00532FF0  |. 73 2F          JNB SHORT UltraTag.00533021   //否则注册失败
00532FF2  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00532FF5  |. 0FB640 0B      MOVZX EAX,BYTE PTR DS:[EAX+B]   //取第1+0xB个字符
00532FF9  |. 83C0 D0        ADD EAX,-30
00532FFC  |. 83E8 0A        SUB EAX,0A   //必须为0~9
00532FFF  |. 73 20          JNB SHORT UltraTag.00533021   //否则注册失败
00533001  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00533004  |. 0FB640 0C      MOVZX EAX,BYTE PTR DS:[EAX+C]   //取第1+0xC个字符
00533008  |. 83C0 D0        ADD EAX,-30
0053300B  |. 83E8 0A        SUB EAX,0A   //必须为0~9
0053300E  |. 73 11          JNB SHORT UltraTag.00533021   //否则注册失败
00533010  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00533013  |. 0FB640 0D      MOVZX EAX,BYTE PTR DS:[EAX+D]   //取第1+0xD个字符
00533017  |. 83C0 D0        ADD EAX,-30
0053301A  |. 83E8 0A        SUB EAX,0A   //必须为0~9
0053301D  |. 73 02          JNB SHORT UltraTag.00533021   //否则注册失败
0053301F  |. B3 01          MOV BL,1   //以上比较都跳过的话,将bl置1
00533021  |> 33C0           XOR EAX,EAX
00533023  |. 5A             POP EDX
00533024  |. 59             POP ECX
00533025  |. 59             POP ECX
00533026  |. 64:8910        MOV DWORD PTR FS:[EAX],EDX
00533029  |. 68 3E305300    PUSH UltraTag.0053303E
0053302E  |> 8D45 FC        LEA EAX,DWORD PTR SS:[EBP-4]
00533031  |. E8 8A1DEDFF    CALL UltraTag.00404DC0
00533036  \. C3             RETN
00533037   .^E9 C816EDFF    JMP UltraTag.00404704
0053303C   .^EB F0          JMP SHORT UltraTag.0053302E
0053303E   . 8BC3           MOV EAX,EBX   //ebx值赋给eax
00533040   . 5B             POP EBX
00533041   . 59             POP ECX
00533042   . 5D             POP EBP
00533043   . C3             RETN


算法总结:
1、注册码长度必须为 14 位,注册码与注册名无关
2、注册码格式为:xxxx-xxxx-xxxx(第5、10位为“-”)
3、注册码第1位的ASCII值必须大于36
  注册码第2位的ASCII值必须小于35
  注册码第3位的ASCII值必须等于31,即这一位必须为“1”
  注册码第4位的ASCII值必须大于32
  注册码第6位的ASCII值必须大于35
  注册码第7位的ASCII值必须小于34
  注册码第8位的ASCII值必须等于38,即这一位必须为“8”
  注册码第9位的ASCII值必须小于37
  注册码第11~14位的ASCII值必须介于30~39,即只能为0~9中的任一数字

按照以上算法规则,我们手工创造一个注册码:7413-6386-0123,注册成功!至此 Ultra Tagger 2.20 Final 注册算法分析完成。


注册信息保存:
[HKEY_USERS\S-1-5-21-1177238915-839522115-1060284298-500\Software\UltraTagger]
"Register Name"="炎之川[BCG]"
"Register Code"="7413-6386-0123"
(注意 S-1-5-21-1177238915-839522115-1060284298-500 这个主键在不同机器上不同)


最后顺便提一下爆破的方法:
0053303E   . 8BC3           MOV EAX,EBX   //注意这里给eax赋值!为1则注册成功,所以我们要改这个地方
改为:
0053303E     B0 01          MOV AL,1   //强制给al赋值为1,则在从这段子程序返回后,软件认为已注册成功
//因为代码长度有限,所以给16位寄存器al赋值即可,若要给eax赋值则需3个字节,不够用,又不能占用后面处理堆栈的代码。

这样不管你有没有输入注册码,软件都不会再检查,一运行软件就已经是已注册版本,只是“关于”里面显示的注册用户名为空白而已,需要的话可以自己去注册表里面改。


------------------------------------------------------------------------
注册机源代码,tc2 编译通过

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

main()
{ int sn1,sn2,sn4,sn6,sn7,sn9,sn;
char s;
   printf("\n    -= Ultra Tagger 2.20 Final keygen =-\n           code by lovefire[BCG]\n\n\n");
   key:
   randomize();
   sn1=random(3)+7;
   sn2=random(4);
   sn4=random(3)+3;
   sn6=random(3)+6;
   sn7=random(3);
   sn9=random(6);
   sn=random(8999)+1000;  /* 保证生成的随机数至少是4位数 */
   printf("\nregkey: %d%d1%d-%d%d8%d-%d\n",sn1,sn2,sn4,sn6,sn7,sn9,sn);
   printf("create another regkey? [Y/N]");
   while((s=getchar())!=('n')&&(s=getchar())!=('N'))
   goto key;
   printf("\n\nhave fun^^\nwelcome to http://skipli.yeah.net/");
   getch();
}
------------------------------------------------------------------------


炎之川
属于中国破解组织BCG (BeGiNnEr'S CrAcKiNg Group)

  _/_/_/   _/_/_/  _/_/_/
  _/  _/ _/    _/
 _/_/_/  _/    _/ _/_/
_/  _/ _/    _/  _/
_/_/_/   _/_/_/  _/_/_/