public interface LicenseData // 由 LicenseDataImpl 实现 也就是要修改的地方
{
public abstract boolean willNeedUpgrade();
public abstract boolean isAccepted(); // 是否接受
public abstract void setAccepted(boolean flag);
public abstract boolean needsUpgrade(Date date);
public abstract String getKey(); // 获得序列号
public abstract boolean isEvaluationExpired(Date date); // 是否过期
public abstract boolean isValid(); // 重点分析 爆破点
public abstract boolean isFromUser();
public abstract boolean willExpire();
public abstract long getTimeStamp();
public abstract Date getExpirationDate(); // 获得过期时间 如果为 null 则永不过期
public abstract String getUserName(); // 获得注册用户名
public abstract boolean isNonCommercial(); // 注册类型
public abstract boolean shouldDetectDuplicates();
public abstract Date getUpgradeDeadline();
public abstract boolean isPersonal(); // 注册类型
public abstract boolean isYearAcademic(); // 注册类型
public abstract boolean isOpenSource(); // 注册类型
public abstract int getMajorVersion(); // 版本号
public abstract int getProductId(); // 产品id
}
类 LicenseDataImpl
public class LicenseDataImpl extends AbstractLicenseData
{
public static final int CURRENT_MAJOR_VERSION = 5;
public static final Date DEAD_LINE_DATE = makeDate(2005, 8, 1);
public static final Date FREE_UPGRADE_DATE = makeDate(2005, 4, 1);
private static final long f = 0xa4cb80L;
public static final String IDEA_VERSION = "IntelliJ IDEA 5";
private LicenseInfo g;
protected static Date makeDate(int i, int j, int k)
{
Calendar calendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("Europe/Prague"));
calendar.clear();
calendar.set(i, j, k);
return calendar.getTime();
}
public LicenseDataImpl(String s, String s1)
{
super(s, s1);
g = null;
}
public LicenseDataImpl(String s, String s1, long l)
{
super(s, s1, l);
g = null;
}
public String toString()
{
return getUserName() + ":" + getKey();
}
public boolean willNeedUpgrade()
{
if(getMajorVersion() >= getCurrentMajorVersion())
return false;
if(g.generationDate == null)
return true;
else
return a(g.generationDate, FREE_UPGRADE_DATE);
}
protected int getCurrentMajorVersion()
{
return 5;
}
private boolean a(Date date, Date date1)
{
long l = date.getTime();
long l1 = date1.getTime();
return l < l1 - 0xa4cb80L;
}
public boolean needsUpgrade(Date date)
{
if(date == null)
return false;
if(date.before(getUpgradeDeadline()))
return false;
else
return willNeedUpgrade();
}
public boolean isEvaluationExpired(Date date)
{
if(date == null)
return false;
if(!willExpire())
return false;
else
return date.after(g.expirationDate);
}
public boolean isValid()
{
a();
return true; // 注意 ******************* 修改之前为 return g != null;
}
private void a()
{
if(b())
return;
g = new LicenseInfo(); // 修改之前为 g = LicenseDecoder.decodeLicenseKey(s,s1); 用于验证 用户名序列号
g.userName = "vhly[FR]"; // 由于 LicenseInfo 实际为数据类(可以直接修改变量)那么就用这种方法 可以修改为 g.userName = getUserName();
g.customerId = 830213; // My BirthDay is Good Luck!
g.licenseType = 0; // isCommercial() => true
g.majorVersion = 2;
g.minorVersion = 5;
g.generationDate = new Date(2006,10,4); // 生成时间
g.expirationDate = null; // 完成爆破 修改 LicenseDataImpl 类之后添加到 idea.jar文件中即可
// 但是第一次的注册还是必须的
}
private boolean b()
{
return g != null;
}
public boolean willExpire()
{
return getExpirationDate() != null;
}
public Date getExpirationDate()
{
a();
return g.expirationDate;
}
public boolean isNonCommercial()
{
a();
return g.licenseType == 1;
}
public boolean isCommercial()
{
a();
return g.licenseType == 0;
}
public boolean isSite()
{
a();
return g.licenseType == 2;
}
public boolean isOpenSource()
{
a();
return g.licenseType == 3;
}
public boolean isYearAcademic()
{
a();
return g.licenseType == 5;
}
public boolean shouldDetectDuplicates()
{
return !isSite() && !willExpire();
}
public Date getUpgradeDeadline()
{
return DEAD_LINE_DATE;
}
public boolean isPersonal()
{
a();
return g.licenseType == 4;
}
public Date getGenerationDate()
{
a();
return g.generationDate;
}
public int getMajorVersion()
{
a();
return g.majorVersion;
}
public int getProductId()
{
return g.productId;
}
public static LicenseDataImpl create(String s, String s1)
{
return new LicenseDataImpl(s, s1);
}
public static LicenseDataImpl createFromUser(String s, String s1)
{
LicenseDataImpl licensedataimpl = new LicenseDataImpl(s, s1);
licensedataimpl.setFromUser(true);
licensedataimpl.setAccepted(false);
return licensedataimpl;
}
public static LicenseDataImpl create(String s, String s1, long l)
{
return new LicenseDataImpl(s, s1, l);
}
}
4) 分析注册认证
LicenseDecoder 类的验证方法
需要使用的常量
private static final BigInteger a = new BigInteger("86f71688cdd2612ca117d1f54bdae029", 16);
private static final BigInteger b = new BigInteger("10001", 16);
private static final BigInteger c = new BigInteger("846d7cf2385dddd654629dd2ba94ca87", 16);
private static final BigInteger d = new BigInteger("10001", 16);
private static final BigInteger e = new BigInteger("1030230a52c274c376605b2c1", 16);
private static final BigInteger f = new BigInteger("10001", 16);
if(key has 5 '-')
getCustomerId(the first XXXXX)
key = substring(4 -)
end if
long sum = 0
long temp = 0x39aa400L
for x each - splite key // BigInteger LicenseUtil.decodeGroups(String key)
// 每一个 XXXXX 从最后一格 XXXXX开始向前循环
int k = decodeGroup(XXXXX)
sum *= temp
sum += k
end for
sum**b mod a => sum.modPow(b,a) -> result
result -> toByteArray -> buf
buf .length must 12
short crcsum (name, id, buf) buf的最后2位不参与运算 用于保存计算出的 crc校验和
0 1 2 3 4 5 6 7 8 9 10 11
T I MI MA D D D D E E X X S S
生成的字节数组格式
T 4bit 授权类型 0 - 5
I 4bit 产品ID 5
MI 4bit min Version 5
MA 4bit maj Version 2
D D D D 4Bytes 创建时间
E E 2Bytes 过期时间 0 永不过期
X X 2Bytes unknown 未知
S S 2Bytes CRC32 校验和
function decodeGroup(XXXXX) : return int
int k =0
for each X in XXXXX // 逆序运算
X = X to number // if '0' -> 0; '9' -> 9; 'A' -> 'A' -65 +10
k *= 36
k += X
end for
取 一个数的 三十六进制数值
end function
6) 猜测的注册机方法
public String genKey(String name, int cid)
{
byte buf[] = new byte[12];
buf[0] = 5;
buf[1] = 0x52;
long l = System.currentTimeMills();
l >>= 16;
buf[2] = l & 0xff;
buf[3] = l >> 8 & 0xff;
buf[4] = l >> 16 & 0xff;
buf[5] = l >> 24 & 0xff;
buf[6] = 0;
buf[7] = 0;
buf[8] = 1;
buf[9] = 1;
short word = LicenseUtil.calculateCheckSum(name, id, buf);
buf[10] = word & 0xff;
buf[11] = word >> 8 & 0xff;