查找 所有.class 文件夹,发现有一个 文件名为:RegisterAction.class的
在
Zend\Zend Studio - 7.0.0\plugins\com.zend.php.ui_7.0.0.v20090614-1641\com\zend\php\ui\actions
从目录看,应该是eclipse的图形化界面的shell接口操作
上一级目录中,有 PHPUIMessages.properties
其中发现有
RegisterAction.3=You will need to restart the workbench for the changes to take effect.\nRestart now?
SerialNumberDialog.5=The entered license key is invalid
等字样
使用jd-gui查看RegisterAction.class的代码
发现有
import com.zend.php.core.core.basic.c;
import com.zend.php.core.core.basic.d;
导入了两个class文件,这两个文件在一个jar中,直接解压
public void run(IAction paramIAction)
中
c localc = c.a(localr.a(), localr.b());
这个c就是import进来的basic.c
往下看
if (localc == null)
{
MessageDialog.openError(this.a.getShell(), PHPUIMessages.a("RegisterAction.4"), PHPUIMessages.a("RegisterAction.0"));
return;
}
try
{
d.b(localc);
if (!(MessageDialog.openQuestion(this.a.getShell(), PHPUIMessages.a("RegisterAction.6"), PHPUIMessages.a("RegisterAction.3"))))
return;
PlatformUI.getWorkbench().restart();
}
查查刚才的PHPUIMessages.properties
确认了一个事实:
可以猜测 localr.a() 和 localr.b() 取出的分别是 username 和 password
那么,首先用 c.a(a, b)进行计算,如果返回不为空,则进行 d.b(c) 的过程
根据返回值确定结果
PHPUIMessages.a()这个函数的参数,对应的那个 properties 文件的内容看,这个推断应该没错
好吧,首先看看 com.zend.php.core.core.basic.c
Zend\Zend Studio - 7.0.0\plugins\com.zend.php.core_7.0.0.v20090607-1658\com\zend\php\core\core\basic
用jd-gui打开 c.class
根据重载参数,找到
public static c a(String paramString1, String paramString2)
{
c localc = null;
try
{
if (localc != null)
break label34;
int k = Integer.parseInt(paramString2.substring(0, 1), 16);
localc = f.a(k).a(paramString1, paramString2);
}
catch (Exception localException)
{
}
label34: return localc;
}
其中,f 是 com.zend.php.core.core.basic.parser.f
打开 Zend\Zend Studio - 7.0.0\plugins\com.zend.php.core_7.0.0.v20090607-1658\com\zend\php\core\core\basic\parser
再看参数
public static b a(int paramInt)
{
if (3 == paramInt)
return new e();
throw new IllegalStateException("Unknown license version");
}
也就是说,paramInt必须为3
那么回到前边的代码
localc = f.a(k).a(paramString1, paramString2);
k必须为3,这样就会返回一个 e();
于是,Integer.parseInt(paramString2.substring(0, 1), 16) == 3 ………………………………………………………………………………………… p2 第一个字符为3
进入 com.zend.php.core.core.basic.parser.e
看参数和返回值(localc = f.a(k).a(paramString1, paramString2);):
public c a(String paramString1, String paramString2)
这个代码:
int i = Integer.parseInt(paramString2.substring(0, 1), 16);
if (i != 3)
return null;
再次验证了 p2[0] == 3的事实
String str1 = paramString2.substring(1, 3);
取出p2 的 [1] [2] 两个字符
String str2 = a(paramString2.substring(3, 16), str1 + paramString2.substring(16));
返回值是 String,看函数
private static String a(String paramString1, String paramString2)
其中是一个循环
算法的php实现是:
<?php
function a($p1, $p2) {
$s = '';
$i = 0;
do {
$j = 0;
do {
$s .= dechex(
hexdec($p1[$i+$j]) ^ hexdec($p2[$j])
);
} while ($j < strlen($p2) && $i+$j < strlen($p1));
$i += strlen($p2);
} while( $i < strlen($p1) );
return $s;
}
?>
根据这个16进制串的返回值,继续往后走,回到刚才的 a()
int j = Integer.parseInt(str2.substring(0, 1), 16);
int k = Integer.parseInt(str2.substring(1, 2), 16);
j 为 上一个返回 str2 的 [0], k 为 [1],两个都是10进制整数。
int l = Integer.parseInt(str2.substring(2, 4), 16);
int i1 = Integer.parseInt(str2.substring(4, 5), 16);
int i2 = Integer.parseInt(str2.substring(5, 7), 16);
又是三个整数变量
然后根据前边定义的
Date localDate = null;
判断:
if ((l != 0) || (i1 != 0) || (i2 != 0))
{
Calendar localCalendar = GregorianCalendar.getInstance();
localCalendar.set(5, l);
localCalendar.set(2, i1 - 1);
localCalendar.set(1, 2000 + i2);
localDate = localCalendar.getTime();
}
//……………………………………………………………………………………………………………………代码求解释
int i3 = Integer.parseInt(str2.substring(7, 9), 16);
long l1 = Long.parseLong(str2.substring(9, 13), 16);
long l2 = a(paramString1, i, str1, j, k, localDate, i3, l1).longValue();
long l3 = Long.parseLong(paramString2.substring(16), 16);
又是对 str2的运算
其中,又将刚才算出来的localDate代入到另外一个a里边
private static Long a(String paramString1, int paramInt1, String paramString2, int paramInt2, int paramInt3, Date paramDate, int paramInt4, long paramLong)
这个函数里边主要做了一些字符串的合并,和时间数据的字符串化(ddMMyy),猜测可能是与expiration有关
补了00000在串后
而后加了一个crc32的计算校验
这个函数的返回值就是 那个 crc32的long值
而其中的那个00000的补全就不知道有何意义了………………莫非函数引用传值?
再次回到最初的a()
if (l3 != l2)
break label403;
也就是说,l3 == l2
下边又是一个循环
do
{
if ((()Math.pow(2.0D, i4) & l1) != 0L)
{
int i5 = 0;
if (bool);
do
{
localArrayList.add(d[i4][i5].getId());
++i5;
}
while (i5 < d[i4].length);
}
++i4;
}
while (i4 < d.length);
这里的 localArrayList 在循环结束后
return new c(i, paramString1, j, k, localDate, i3, (String[])localArrayList.toArray(new String[localArrayList.size()]));
送进构造另外一个对象
这个c是 com.zend.php.core.core.basic.c
========================================================================================
跳出加密验证部分
回到对话框界面的数据获取
还是 RegisterAction.class
r localr = new r(this.a.getShell());
if (localr.open() == 1)
return;
c localc = c.a(localr.a(), localr.b());
看看 r这个类的东西
package com.zend.php.ui.core.dialogs;
看看两个参数的获取:
public String a()
{
return this.j.getText().trim();
}
public String b()
{
return this.k.getText().trim();
}
i和j的定义在:
this.j = new StringDialogField();
this.j.setLabelText(PHPUIMessages.a("SerialNumberDialog.1"));
this.j.setDialogFieldListener(new i(this));
this.j.doFillIntoGrid(localComposite, 2);
LayoutUtil.setHorizontalGrabbing(this.j.getTextControl(null));
this.j.setFocus();
this.k = new StringDialogField();
this.k.setLabelText(PHPUIMessages.a("SerialNumberDialog.2"));
this.k.setDialogFieldListener(new j(this));
this.k.doFillIntoGrid(localComposite, 2);
LayoutUtil.setHorizontalGrabbing(this.k.getTextControl(null));
对应的串:
SerialNumberDialog.1=User Name / Order #:
SerialNumberDialog.2=License Key:
断定数据肯定是在这儿了
但是刚才看了看6版的注册机,license首字节不是限制在1,2,-1之间(虽然6.1代码里只有这三个判断数据)
所以,我觉得这里肯定会有一些数据的预处理过程
继续找
Zend\Zend Studio - 7.0.0\plugins\com.zend.php.ui_7.0.0.v20090614-1641\com\zend\php\ui\core\dialogs
r.class
i.class
现在先尝试按照ui的流程将验证过程实现
然后再做keygen
但是有些初始值怎么定还是个问题