老文章档案 · 2003 年

java程序-JPTXXXXXXX1.91

破解教程 · 算法分析 · 2003-10-22 · 作者:dayone 人气: · 出处:赢政天下整理收藏)

目标软件:JPTXXXXXXX1.91

下载地址http://www.fujichinese.com/ygu/showsoft.asp?soft_id=4

软件大小:3.48MB

软件授权:共享软件

加密方式:注册码(注册成功后生成jpt.log文件)

适用平台:WindowsXP/2000/98/95/Me/NT(4.0)+Java(TM) 2 Runtime Environment Version 1.4.0以上

破解工具:Jbuilder7、Java源代码反编译专家。

作者:dayone

E-mail:dayone@wxxd.com

关于本文:本文主要目的在于教学,研究java程序的注册方式,请勿将此教程用于商业目的。

第一次写crack的文章,不对的地方请各位多多指教!

最近在学日语,在google.com上搜索到一学习日语软件"JPTXXXXXXX1.91",于是下载安装,原来是java编的,看来作者java功底不错,闲来无事看看java程序是如何注册的,也好学学~

主程序jpt.exe主要是引导JptDicWindow.jar中的JptStart这个类.很好,把它们全"反"了,可是竟然绝大部分都没反应!看来加密过了,后来发现破绽,主类JptStart.class没被加密,于是一个字"反",看一下这个文件的源代码,其中,“//”处是我自己加入的注释。

//Source File Name: JptStart.java

import java.io.*;

import java.lang.reflect.Method;

import java.security.GeneralSecurityException;

import java.security.SecureRandom;

import java.util.Enumeration;

import java.util.Hashtable;

import java.util.zip.*;

import javax.crypto.*; //javax.crypto是1.4.0以上新增的包,用于加密

import javax.crypto.spec.DESKeySpec;

public class JptStart extends ClassLoader

{

private Hashtable htSizes;

private Hashtable htJarContents;

private String jarFileName;

private SecretKey key;

private Cipher cipher;

public JptStart(SecretKey secretkey, String s)

throws GeneralSecurityException, IOException

{

htSizes = new Hashtable();

htJarContents = new Hashtable();

key = secretkey;

jarFileName = s;

String s1 = "DES";

SecureRandom securerandom = new SecureRandom();

cipher = Cipher.getInstance(s1);//加密算法

cipher.init(2, secretkey, securerandom);

initvalue(s + ".jar");

}

public static void main(String args[])

throws Exception

{

String s = args[1];

String s1 = args[2];

String args1[] = new String[args.length - 3];

System.arraycopy(args, 3, args1, 0, args.length - 3);

byte abyte0[] = Util.readFile(s);

DESKeySpec deskeyspec = new DESKeySpec(abyte0);

SecretKeyFactory secretkeyfactory = SecretKeyFactory.getInstance("DES");

SecretKey secretkey = secretkeyfactory.generateSecret(deskeyspec);

JptStart jptstart = new JptStart(secretkey, s1);

Class class1 = jptstart.loadClass(s1);

String args2[] = new String[1];

Class aclass[] = {

(new String[1]).getClass()

};

Method method = class1.getMethod("main", aclass);

Object aobj[] = {

args1

};

method.invoke(null, aobj);

}

private void initvalue(String s)

{

try

{

ZipFile zipfile = new ZipFile(s);

ZipEntry zipentry;

for(Enumeration enumeration = zipfile.entries(); enumeration.hasMoreElements();

htSizes.put(zipentry.getName(), new Integer((int)zipentry.getSize())))

zipentry = (ZipEntry)enumeration.nextElement();

zipfile.close();

FileInputStream fileinputstream = new FileInputStream(s);

BufferedInputStream bufferedinputstream = new BufferedInputStream(fileinputstream);

ZipInputStream zipinputstream = new ZipInputStream(bufferedinputstream);

for(ZipEntry zipentry1 = null; (zipentry1 = zipinputstream.getNextEntry()) != null;)

if(!zipentry1.isDirectory())

{

int i = (int)zipentry1.getSize();

if(i == -1)

i = ((Integer)htSizes.get(zipentry1.getName())).intvalue();

byte abyte0[] = new byte[i];

int j = 0;

boolean flag = false;

int k;

for(; i - j > 0; j += k)

{

k = zipinputstream.read(abyte0, j, i - j);

if(k == -1)

break;

}

htJarContents.put(zipentry1.getName(), abyte0);

}

}

catch(NullPointerException nullpointerexception)

{

nullpointerexception.printStackTrace();

}

catch(FileNotFoundException filenotfoundexception)

{

filenotfoundexception.printStackTrace();

}

catch(IOException ioexception)

{

ioexception.printStackTrace();

}

}

public byte[] getJarResource(String s)

{

return (byte[])htJarContents.get(s);

}

public Class loadClass(String s, boolean flag)

throws ClassNotFoundException

{

try

{

Class class1 = null;

class1 = findLoadedClass(s);

if(class1 != null)

return class1;

byte abyte0[] = getJarResource(s + ".class");

if(abyte0 != null)

{

byte abyte1[] = cipher.doFinal(abyte0);

class1 = defineClass(s, abyte1, 0, abyte1.length);

}

if(class1 == null)

class1 = findSystemClass(s);

if(flag && class1 != null)

resolveClass(class1);

return class1;

}

catch(GeneralSecurityException generalsecurityexception)

{

throw new ClassNotFoundException(generalsecurityexception.toString());

}

}

}

怪不得要用1.4.0以上,原来是要用其中的加密类。类JptStart的功能主要就是把加密的类解密再load。我们只要改成把加密的类解密再保存成文件不就得了~接下来就把上面的loadClass方法改成

public Class loadClass(String s, boolean flag)

throws ClassNotFoundException

{

try

{

Class class1 = null;

class1 = findLoadedClass(s);

if(class1 != null)

return class1;

byte abyte0[] = getJarResource(s + ".class");

if(abyte0 != null)

{

byte abyte1[] = cipher.doFinal(abyte0);

class1 = defineClass(s, abyte1, 0, abyte1.length);

//add by dayone

try {

Util.writeFile(s + ".class",abyte1);//保存已解密文件

}

catch(IOException e) {

return findSystemClass(s);

}

//

}

if(class1 == null)

class1 = findSystemClass(s);

if(flag && class1 != null)

resolveClass(class1);

return class1;

}

catch(GeneralSecurityException generalsecurityexception)

{

throw new ClassNotFoundException(generalsecurityexception.toString());

}

}

再编译运行就全部OK,下面就简单了,反编译已解密的JptDicWindow.class看其中的getRegisterFlag方法。

private boolean getRegisterFlag()

{

boolean flag = false;

try

{

FileInputStream fileinputstream = new FileInputStream("Jpt.log");

ObjectInputStream objectinputstream = new ObjectInputStream(fileinputstream);

RegisterData registerdata = (RegisterData)objectinputstream.readObject();

String s = System.getProperty("user.name");

String s1 = System.getProperty("os.name");

String s2 = s + "jptjpt" + s1 + "xyz" + registerdata.loginName + "abc" + String.valueOf(diskSerialNumber);

char ac[] = s2.toCharArray();

int i = 1;

for(int j = 0; j < ac.length; j++)

i = Math.abs(ac[j] * i + 3959) % 0xf4240;

i = 0xa04747 + Math.abs(i * (s2.length() + ac.length));//计算登录番号(机器码)

////计算暗证番号(注册码),算法一目了然吧~

int k = 0x7346322 + Math.abs((i / 133) * 171 ^ 0x25cd97d);

//用delphi算注册码为copy(120873762 + Abs(((i div 133) * 171) xor 39639421),0,8)

//以下比较注册码

if(registerdata.registerCode.equals(String.valueOf(k).substring(0, 8)))

{

nativeIndex = registerdata.nativeIndex;

flag = true;

}

if(registerdata.loginName.equals("friend") &&

registerdata.registerCode.equals("1234567")) //靠,万能注册码,省得我写什么注册机了~

{

nativeIndex = registerdata.nativeIndex;

flag = true;

}

fileinputstream.close();

}

catch(Exception exception) { }

return flag; //改成return true;就不用注册了~

}

如果主类JptStart.class也被加密就难破解了,但不知道如何实现。看来共享软件最好不要用java编,除非你真的有很好的加密方法。BTW,这个软件做的不错,对学java的朋友有很大的帮助。

(出处:赢政天下整理收藏)

相关文章:

·语音界面2.0算法分析及注册机源码!

·侠客系统修改器1.21破解手记--算法分析

·中文拨号上网计时计费器 V4.12注册算法分析

·ClockWise 3.22e注册码算法分析

·CoolClock V1.02注册算法分析

·Directory Scanner v1.5 注册算法分析

·Disk Chief 1.2 简单注册算法分析

·EffeTech HTTP Sniffer 3.2注册算法分析

·eLib2.01算法分析

·EZ MP3 Recorder 1.15 注册算法分析

相关软件:

→ 特别推荐

→ 热点TOP10

我为人人《《==》》人人为我

关于我们 |

帮助(?)

| 广告服务 |

版权声明 |

商业合作 |

发展历程 |

加盟我们 |

联系我们

Copyright © 1999-2003

winzheng.com All Rights Reserved.

繁体版:由华琦数码技术提供

Powered

by:MeSky.Net

2003-2004 年,宽带刚刚普及,下载站的文章区是许多人学电脑的第一课堂。
🕰 → 🤖 从那时到现在

当年一篇教程能让一台电脑焕然一新;今天的效率工具换成了 AI。 想知道当下最可靠的 AI 模型怎么选?看 赢政指数——我们用了 28 年的选软件严谨,现在用来评测大模型。

档案性质声明:本页为赢政天下(1998-2011)老文章的历史档案复原, 内容反映当年发表时的原貌——包括当年的技术表述、软件版本与观点,部分方法在今天已不适用或不合规,仅作互联网历史记录与研究用途, 不提供任何形式的下载。原始数据经由公共网络存档(Internet Archive)复原。发现问题请联系我们
← 返回老文章档案 · 软件史档案馆 · 赢政天下站史