2023年12月2日发(作者:)

如何破解已签名JAR包本文版权归赣州兆鑫软件所有,原创未经许可禁止转载!本文仅作学习交流目的,提倡软件正版,反对盗版!工欲善其事必先利其器Java Decompiler 1.4.0,简称JDInteliJ IDEA 2017,简称IDEAdirtyJOEOracle JDK 1.8做事要先掌握大局1. 将已签名包转化为未签名包;2. 定位关键代码位置;3. 修改class文件字节码;4. 替换class文件重新打包;不行动总也不能成功1.将已签名包转化为未签名包如果你用到的Jar文件使用了签名,它会保证里面的每个class文件不能被修改,所以即使你成功修改了class文件中的字节码,得到的Jar也是无法运行的。这些经过签名的Jar包的META-INF文件夹中一般包含了*.SF和相应的*.RSA文件。这些文件记录Jar包中每个文件的签名信息,以保证代码不被篡改。使用下面的方法可以重新生成一个未签名Jar包。参考自stackoverflow作者Houtman的回答// 使用JDK编译代码javac // 执行JarUnsigner,如果是同一个文件夹java -cp . JarUnsigner 附上源代码,免得回答被删// port edReader;import ;import tputStream;import ption;import tream;import treamReader;import ation;import ry;import e;import putStream;public class JarUnsigner { private static final String MANIFEST = "META-INF/"; public static void main(String[] args){ public static void main(String[] args){ if (!=2){ n("Arguments: <> <>"); (1); } String infile = args[0]; String outfile = args[1]; if ((new File(outfile)).exists()){ n("Output file already exists:" + outfile); (1); } try{ ZipFile zipFile = new ZipFile(infile); final ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outfile)); for (Enumeration e = s(); eElements();) { ZipEntry entryIn = (ZipEntry) ement(); if (! exclude_file( e() ) ) { /* copy the entry as-is */ tEntry( new ZipEntry( e() )); InputStream is = utStream(entryIn); byte[] buf = new byte[1024]; int len; while ((len = ((buf))) > 0) { (buf, 0, len); } ntry(); } else { if ((e())){ /* if MANIFEST, adjust the entry */ tEntry(new ZipEntry(MANIFEST)); // manifest entries until first empty line. i.e. the 'MainAttributes' section // (this method is used so to keep the formatting exactly the same) InputStream mIS = utStream(entryIn); BufferedReader in = new BufferedReader(new InputStreamReader(mIS)); String line = ne(); byte[] mNL = "n".getBytes("UTF-8"); while( line != null && !().isEmpty() ) { ( es("UTF-8")); ( mNL ); line = ne(); } ( mNL ); ntry(); }else{ /* else: Leave out the Signature files */ } } } (); n("Successfully unsigned " + outfile); }catch(IOException ex){ n("Error for file: " + infile); tackTrace(); (1); } } /** * Exclude .SF signature file * Exclude .RSA and DSA (signed version of .SF file)

* Exclude SIG- files (unknown sign types for signed .SF file) * Exclude Manifest file * @param filename * @param filename * @return

*/ public static boolean exclude_file(String filename){ return ("META-INF/") || With("META-INF/SIG-") ||

With("META-INF/") && ( th(".SF") || th(".RSA") || th(".DSA") ); }}2. 定位代码关键位置举一个需要输入序列号才能试用的库文件的例子,但是为了保护Jar包作者权益,对包名进行打码了。通过Jar包的说明书,可以知道如何使用它,就知道是什么地方输入序列号啦,要不然是个正常人也没法用对吧。例如// 文档说这样子可以验证序列号("333");("94306-56191-128286-2967422");rock & roll1. 使用JD反编译Jar包,然后Save All Sources,具体步骤这里省略;2. 从IDEA新建一个工程,把反编译的源代码放到源目录,Jar包可能是经过混淆过的,不过这个关系不大,我们字节码都能改,还怕看不懂混淆?继续往下走3. 右击authentication这个类文件,选择Find Usages,快捷键一般是Ctrl+G,看到有个叫做的文件用到,做了一些判断操作Blabla,看屏幕截图1:屏幕截图14. 点开这个类搜索到的地方,可以看到,它在比较一个返回结果,然后给出不同的错误提示,这个结果是由一个t.a(三个参数)的方法计算得到,并且看得出来当计算结果的a属性值为0时就是Licence OK!,看屏幕截图2:屏幕截图25. 好,我们再来看这个文件的a方法又有什么东东(按住Ctrl键,鼠标点击那个t.a),我们只要保证他得到的结果的a属性等于0就好了,可以看到只有一种情况下a属性才会等于0,其他时候都是等于-1的,到这一步IDEA的使命就完成了,看屏幕截图3:屏幕截图3结果通过上面5步(取决于不同的包,不一定都是5步),我们知道了需要改动t类里面的a方法,让它里面操作属性a时,值为-1的都改为0就能成功。3. 修改class文件字节码接下来就要使用dirtyJOE软件来定位并修改字节码了,作者也试过Class Editor, Java Bytecode Editor都因年久失修,没改成功。通过查阅JVM文档我们知道给整数赋值有几种指令,这里就说两种:iconst_ i可以为

m1,0,1,2,3,4,5,分别设置的值为-1,0,1,2,3,4,5,指令16进制字节码分别是02设置-1,03设置0,04设置1,以此类推bipush i范围可以是0-255,指令16进制字节码是10,比如代码里面有的21就是bipush 21,16字节码表示为10 15let's go1. 使用dirtyJOE打开文件,切换到

Methods 页上,如下图所示:2. 双击我们需要修改的方法(同名时通过比对方法签名来区分),进入编辑界面,图中的两个指令的组合就是将值-1赋值给t$a.a属性,双击图中的iconst_ml,字节码是02,改为03,然后回车即可,可以使用Ctrl+F查找多处进行修改:3. 关闭编辑窗口,保存修改。warning要保证字节码的数量不增多,也不减少,因为类和类之间代码调用跟字节位置关系密切。不然会导致修改的class文件无法使用。原来一行是1个字节的,继续用1个字节,2个的就继续两个,3个的继续保持三个。4. 替换class文件重新打包这是最简单的一步,将修改好的class文件,使用zip压缩工具替换掉即可。如果是你Windows用户不推荐使用WinRaR,可以将jar文件(第一步生成的未签名包)重命名为zip文件,然后选择用Windows资源管理器打开,将修改的class文件复制粘贴进去。