破解 Aspose 系列 jar包方法

2024-08-17 · 技术分享

详细介绍如何通过修改字节码的方式破解Aspose系列jar包的授权验证,包含完整的代码示例。

标签:Java、Aspose、字节码、Javassist

破解Aspose系列jar包方法

授人以鱼 不如授人以渔

源码分析

1. 下载Aspose.Words for Java21.11官方jar包

2. 开始分析

调用授权方法

``java InputStream is = new FileInputStream("..license.xml"); License license = new License(); license.setLicense(is); ``

license.xml文件内容

```xml Aspose.Total for Java Aspose.Words for Java Enterprise 20991231 20991231 8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7 sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=

```

分析License类的setLicense方法找到关键代码

```java public void setLicense(String licenseName) throws Exception { if (licenseName == null) { throw new NullPointerException(zzVu.zzIR().zzZ42(new byte[]{105, 108, 101, 99, 115, 110, 78, 101, 109, 97, 101})); } else { (new zzXDb()).zzY0J(licenseName, zzWJD.zzWIQ()); } }

public void setLicense(InputStream stream) throws Exception { if (stream == null) { throw new NullPointerException(zzVu.zzIR().zzZ42(new byte[]{116, 115, 101, 114, 109, 97})); } else { (new zzXDb()).zzY0J(stream); } } ```

setLicense的两个重载方法最终都调用了(new zzXDb()).zzY0J(stream);中的zzY0J方法,进入zzY0J方法观察代码发现重点在于void zzY0J方法下面的 (InputStream var1) throws Exception这个重载方法里面,但是里面代码很多不太好找到关键代码,所以转头去寻找关于验证对外调用的静态方法,最终找到了在zzY0J方法下面的

```java static byte[] zzX8p() { boolean var0 = zzWiV == null || zzWiV.zzWSL == zzYeQ.zzX0q || (new Date()).after(zzWiV.zzZ3l) || zzYKk.zzWy3() == 4096; if (zzW5s == 0L) { zzW5s ^= zzVWj; }

boolean var1 = false; if (zzZB8.zzxn() != null) { var1 = zzZB8.zzZ7p() == zzu3.zzX0q; byte[] var2 = var0 && var1 ? zzYeQ.zzX0q : zzYeQ.zzXgr; return var2; } else { return null; } }

static byte[] zzWQR() { boolean var0 = zzWiV == null || zzWiV.zzWSL == zzYeQ.zzX0q || (new Date()).after(zzWiV.zzZ3l) || zzYKk.zzWy3() == 4096; boolean var1 = zzZB8.zzZ7p() == zzu3.zzX0q; byte[] var2 = var0 && var1 ? zzYeQ.zzX0q : zzYeQ.zzXgr; return var2; } ```

这两个方法主要在于对外返回了一个byte数组,返回值是zzYeQ中的静态常量,所以重点就在于上面的判断语句boolean var0 = zzWiV == null || zzWiV.zzWSL == zzYeQ.zzX0q || (new Date()).after(zzWiV.zzZ3l) || zzYKk.zzWy3() == 4096;让它返回什么数据。 这里需要分析zzWiV.zzWSL zzWiV.zzZ3l zzYKk.zzWy3()这三个数据,在当前zzXDbclass文件中搜索找到在void zzY0J(InputStream var1) throws Exception方法中关键的关键位置赋值了

this.zzWSL = zzYeQ.zzXgr;
zzWiV = this;

观察它上下位置代码发现看起来都是做验证错误的处理,所以可以尝试去掉上下的验证。 再来看zzWiV.zzZ3l变量属性为Date应该是时间什么的可以直接给个最大值。 然后是zzYKk.zzWy3()进入看到

static int zzWy3() {
    return zzYU8 == 128 && !zzyS ? 256 : 4096;
}

那么返回值就是256和4096二选一,尝试后选择返回256。

3. 分析结果

this.zzZ3l = new java.util.Date(Long.MAX_VALUE);//Date赋值最大值
this.zzWSL = zzYeQ.zzXgr;//直接返回验证成功的执行
zzWiV = this;//直接返回验证成功的执行
return 256;

4. 破解jar包

1. 添加Javassist修改class字节码文件的依赖

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.28.0-GA</version>
</dependency>

2. 添加修改方法

package top.fanliu;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class Pojie {

    public static void main(String[] args) {
        modifyPptJar();
    }

    /**
     * 修改slides.jar包里面的校验
     */
    public static void modifyPptJar() {
        try {
            //这一步是完整的jar包路径,选择自己解压的jar目录
            ClassPool.getDefault().insertClassPath("C:\\Users\\53094\\Downloads\\aspose-slides-22.11-jdk16.jar");
            CtClass zzZJJClass = ClassPool.getDefault().getCtClass("com.aspose.slides.internal.of.public");
            CtMethod[] methodA = zzZJJClass.getDeclaredMethods();
            for (CtMethod ctMethod : methodA) {
                CtClass[] ps = ctMethod.getParameterTypes();
                if (ps.length == 3 && ctMethod.getName().equals("do")) {
                    System.out.println("ps[0].getName==" + ps[0].getName());
                    ctMethod.setBody("{}");
                }
            }
            //这一步就是将破译完的代码放在桌面上
            zzZJJClass.writeFile("C:\\Users\\53094\\Desktop\\");
        } catch (Exception e) {
            System.out.println("错误==" + e);
        }
    }

}

运行修改方法后会在桌面生成 com 修改后的文件夹

3. 修改jar包里面的数据

  1. 打开jar包将桌面com文件夹覆盖到jar包com文件夹

image-20240817184041346

4. 重新导入修改后的jar包进行测试

  1. maven 移除旧的 jar包,导入修改后的 jar包
  2. 调用测试方法进行测试转换后的文件是否去除水印和数量限制成功
String sourceFile = "D:\\b.doc";//输入的文件
String targetFile = "D:\\转换后.pdf";//输出的文件
/**
 * Word转PDF操作
 *
 * @param sourceFile 源文件
 * @param targetFile 目标文件
 */
public static void doc2pdf(String sourceFile, String targetFile) {
    try {
        long old = System.currentTimeMillis();
        FileOutputStream os = new FileOutputStream(targetFile);
        com.aspose.words.Document doc = new com.aspose.words.Document(sourceFile);
        doc.save(os, com.aspose.words.SaveFormat.PDF);
        os.close();
        long now = System.currentTimeMillis();
        System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒");  //转化用时
    } catch (Exception e) {
        e.printStackTrace();
    }
}

5. 尾言

博主将破解 Aspose 系列的代码放在 github 上面,你也可以克隆到本地进行破解

源码地址:pojieAspose