您的位置:首页 > 编程语言 > Java开发

Java混乱器Zelix KlassMaster逆向工程(二)软件运行流程以及爆破去除时间限制

2007-02-02 14:43 666 查看
对于Zelix KlassMaster(简称ZKM)有一个时间限制,有固定的过期时间。为了对ZKM进行破解,
可以通过反编译的方式进行。一般的软件首先要找到入口点,然后分析软件的流程。
1、软件ZKM的入口点。
通过分析,ZKM的入口点为com.zelix.ZKM,反编译com.zelix.ZKM,分析 public static void main(String... args)
主方法,发现调用了 Class.forName(z[6]); 通过字符串信息搜集,发现调用的是 com.zelix.zo
public static void main(String args[])
{
label0:
{
int i = rb.a;
try
{
Class.forName(z[6]); // com.zelix.zo
}
catch(ClassNotFoundException _ex)
{
System.err.println(a + z[12] + a);
System.exit(1);
}
try
{
Class aclass[] = new Class[1];
aclass[0] = c == null ? (c = a(z[24])) : c;
Constructor constructor = (d == null ? (d = a(z[2])) : d).getConstructor(aclass);
Object aobj[] = new Object[1];
aobj[0] = args;
constructor.newInstance(aobj); // 调用 new com.zelix.zo(String... args)
break label0;
}
.....
}

2、分析com.zelix.zo的运行过程
public zo(String as1[])
{
boolean flag3 = tb.b;
super();
if(as1.length == 0) // 无参调用 f();
{
f();
return;
}
.....//处理参数
}

f()方法非常重要,主要处理软件启动

private void f()
{
String s1 = "";
System.out.println(z[8] + q + " " + z[4] + s1 + z[9] + "?" + z[7]);
// 以上现实软件信息
String s2 = a(3);
boolean flag = s2.indexOf(p) != -1;
String s3 = null;
if(r.k())
s3 = UIManager.getCrossPlatformLookAndFeelClassName();
else
s3 = UIManager.getSystemLookAndFeelClassName();
if(s3 != null)
try
{
UIManager.setLookAndFeel(s3);
}
catch(Exception exception) { }
wu wu1 = new wu();
wu wu2 = a();
it it1 = new it(wu1, wu2, false, flag, oc.h);
fv fv1 = new fv(false);

String s4 = a(fv1, it1.q(), wu2, true);
ds ds1 = new ds();
gv gv1 = gv.b();
PrintWriter printwriter = null;
try
{
printwriter = new PrintWriter(new FileWriter(z[3]), true);
}
catch(IOException ioexception)
{
ds1.b(z[11], z[6] + ioexception.getClass().getName());
}
PrintWriter printwriter1 = printwriter;
Properties properties = System.getProperties();
px.a(properties, printwriter1);
printwriter1.println();
long l1 = px.a();
if(l1 > -1L)
{
printwriter1.println(z[5] + l1 + z[10]);
printwriter1.println();
}
String s5 = z[8] + q + " " + z[4];
String s6 = vh.e() + " " + s5 + s1;
printwriter1.println(s6);
ap ap1 = new ap(gv1, it1, ds1, printwriter1);
(new Thread(ap1)).start();
z2 z2_1 = new z2(z[8] + q, it1, wu1, wu2, printwriter1, r);
it1.a(z2_1);
Dimension dimension = z2_1.getSize();
dimension.width--;
z2_1.setSize(dimension);
hv hv1 = new hv(this);
new g1(z2_1, fv1, s4, hv1); // 此处为NAG("I agree")窗口
}

软件运行时显示过期,通过分析ZKM类,发现ZKM类中包含了异常处理代码。
通过重写ZKM类的main方法如下
public static void main(String... args)throws Exception{
zo zo1 = new zo(args);
}
运行后软件抛出com.zelix.a1异常,同时提示过期。

因此在com.zelix.zo类中搜索抛出com.zelix.a1异常的方法。
找到方法:
static String a(String s1, String s2, String s3, Object obj)
{
boolean flag = tb.b;
String s4;
long l2;
String s5;
long l4;
long l5;
cy cy1;
Object aobj[];
int i1;
s4 = obj.getClass().getName();
SimpleDateFormat simpledateformat = new SimpleDateFormat(z[16]);
TimeZone timezone = TimeZone.getDefault();
simpledateformat.setTimeZone(timezone);
long l1 = sc.a(s1);
l2 = sc.a(s2);
long l3 = sc.a(s3);
Date date = new Date(l1);
s5 = simpledateformat.format(date);
l4 = System.currentTimeMillis();
Date date1 = new Date(l4);
if(l3 * 4L * 4L != l2) // 过期
throw new a1(s5 + z[20]);
if(l4 > l1) //过期
throw new a1(s5 + z[22]);
if(l4 < l1 - l2) // 使用时间为12天
throw new a1(s5 + z[17]);
l5 = l4 + l3;
cy1 = new cy(System.getProperty(z[1]), oc.h);
aobj = cy1.a();
i1 = 0;
if(!flag) goto _L2; else goto _L1
_L1:
if(aobj[i1] instanceof File)
{
long l6 = ((File)aobj[i1]).lastModified(); // 通过文件判断是否修改
if(l6 > l5)
throw new a1(s5 + z[19]);
} else
{
File file = new File(((ZipFile)aobj[i1]).getName());
if(file.exists())
{
long l7 = file.lastModified();
if(l7 > l5) // 过期
throw new a1(s5 + z[24]);
if(file.getName().endsWith(z[25]))
try
{
w6 w6_1 = new w6(file);
ZipEntry zipentry = w6_1.getEntry(s4.replace('.', '/') + z[12]);
if(zipentry != null)
{
long l8 = zipentry.getTime();
if(l8 > l5)
throw new a1(s5 + z[21]);
if(l8 != -1L && l4 > l8 + l2)
throw new a1(s5 + z[23]);
w6_1.close();
}
}
catch(IOException ioexception) { }
}
}
i1++;
_L2:
if(i1 >= aobj.length)
{
cy1.a();
return s5; // 返回过期时间
}
if(true) goto _L1; else goto _L3
_L3:
JVM INSTR pop ;
throw new a1(z[18]);
}

方法 a() 由于整个类无法通过反编译后再次编译
因此需要使用字节代码操作类库来进行修改

简单的设定为
ldc #string // ldc "This is cracked by vhly[FR] AT 2006/12/10"
areturn

实际上的代码相对于

static a(String s1, String s2, String s3, Object obj)
{
return "This is cracked by vhly[FR] AT 2006/12/10";
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐