Aspose.PDF for Java21.11去除水印和数量限制

8,061 阅读4分钟

前言 工欲善其事,必先利其器

源码分析

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

2. 开始分析

  1. 调用授权方法
InputStream is = new FileInputStream("..license.xml");
License license = new License();
license.setLicense(is);

license.xml文件内容这里是个过期的文件主要是格式

<License>
    <Data>
        <Products>
            <Product>Aspose.Total for Java</Product>
            <Product>Aspose.Words for Java</Product>
        </Products>
        <EditionType>Enterprise</EditionType>
        <SubscriptionExpiry>20991231</SubscriptionExpiry>
        <LicenseExpiry>20991231</LicenseExpiry>
        <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
    </Data>
    <Signature>
        sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=
    </Signature>
</License>
  1. 分析License类的setLicense方法 setLicense代码太长我就不贴了,源码里面有。
    主要分析里面的核心代码,setLicense第两个重载方法主要验证在139和140行
l9f var10 = new l9f();
var10.lI(var9);

进入l9f类的lT方法

void lI(InputStream var1) throws Exception {
    l19n.lI(0);
    if (var1 == null) {
        throw new NullPointerException("stream");
    } else {
        String[] var2 = new String[]{new String(new byte[]{97, 115, 112, 111, 115, 101, 46, 116, 111, 116, 97, 108}), new String(new byte[]{99, 111, 110, 104, 111, 108, 100, 97, 116, 101, 46, 116, 111, 116, 97, 108})};
        Document var3 = com.aspose.pdf.internal.l1f.ld.lc().parse(var1);
        boolean var4 = true;
        if (!this.lI(var3)) {
            var4 = false;
        }

        this.ly();
        Iterator var5 = (com.aspose.pdf.internal.l1f.lu.lI() ? (ArrayList)l0t.get() : l9f.lf.lf).iterator();

        while(var5.hasNext()) {
            String var6 = (String)var5.next();
            if (this.lv.equals(var6)) {
                throw new IllegalStateException(new String(new byte[]{84, 104, 105, 115, 32, 108, 105, 99, 101, 110, 115, 101, 32, 105, 115, 32, 100, 105, 115, 97, 98, 108, 101, 100, 44, 32, 112, 108, 101, 97, 115, 101, 32, 99, 111, 110, 116, 97, 99, 116, 32, 65, 115, 112, 111, 115, 101, 32, 116, 111, 32, 111, 98, 116, 97, 105, 110, 32, 97, 32, 110, 101, 119, 32, 108, 105, 99, 101, 110, 115, 101, 46}));
            }
        }

        if (this.lc() != l9f.lj.lj) {
            String var12 = this.lc() == l9f.lj.lI ? var2[0] : var2[1];
            if (l19n.lj() <= 0) {
                boolean var13 = false;
                String var7 = "";
                String[] var8 = this.lh;
                int var9 = var8.length;
                int var10 = 0;

                while(var10 < var9) {
                    String var11 = var8[var10];
                    var7 = l10l.lu(var11);
                    if (!var12.equals(var7) && !(var12 + " for java").equals(var7) && !(var12 + " product family").equals(var7)) {
                        if (this.lc() == l9f.lj.lI && l10l.lu(com.aspose.pdf.internal.l1f.lI.lt).equals(var7)) {
                            var13 = true;
                            break;
                        }

                        if (this.lc() == l9f.lj.lI && var11.equals(com.aspose.pdf.internal.l1f.lI.lt.concat(new String(new byte[]{32, 102, 111, 114, 32, 74, 97, 118, 97})))) {
                            var13 = true;
                            break;
                        }

                        if (this.lc() == l9f.lj.lI && l10l.ly(var11).equals(l10l.ly(com.aspose.pdf.internal.l1f.lI.lt.concat(new String(new byte[]{32, 80, 114, 111, 100, 117, 99, 116, 32, 70, 97, 109, 105, 108, 121}))))) {
                            var13 = true;
                            break;
                        }

                        if (this.lc() != l9f.lj.lI || !var11.equals(com.aspose.pdf.internal.l1f.lI.lj.concat(new String(new byte[]{32, 102, 111, 114, 32, 74, 97, 118, 97}))) && !var11.equals(com.aspose.pdf.internal.l1f.lI.lj.concat(new String(new byte[]{32, 80, 114, 111, 100, 117, 99, 116, 32, 70, 97, 109, 105, 108, 121})))) {
                            ++var10;
                            continue;
                        }

                        var13 = true;
                        break;
                    }

                    var13 = true;
                    break;
                }

                if (!var13) {
                    throw new IllegalStateException(new String(new byte[]{84, 104, 101, 32, 108, 105, 99, 101, 110, 115, 101, 32, 105, 115, 32, 110, 111, 116, 32, 118, 97, 108, 105, 100, 32, 102, 111, 114, 32, 116, 104, 105, 115, 32, 112, 114, 111, 100, 117, 99, 116, 46, 32, 70, 111, 114, 32, 102, 114, 101, 101, 32, 116, 101, 99, 104, 110, 105, 99, 97, 108, 32, 115, 117, 112, 112, 111, 114, 116, 44, 32, 112, 108, 101, 97, 115, 101, 32, 112, 111, 115, 116, 32, 116, 104, 105, 115, 32, 101, 114, 114, 111, 114, 32, 97, 110, 100, 32, 116, 104, 101, 32, 102, 105, 108, 101, 32, 105, 110, 32, 116, 104, 101, 32, 65, 115, 112, 111, 115, 101, 46, 80, 68, 70, 32, 70, 111, 114, 117, 109, 115, 32, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 97, 115, 112, 111, 115, 101, 46, 99, 111, 109, 47, 99, 111, 109, 109, 117, 110, 105, 116, 121, 47, 102, 111, 114, 117, 109, 115, 47, 97, 115, 112, 111, 115, 101, 46, 112, 100, 102, 45, 112, 114, 111, 100, 117, 99, 116, 45, 102, 97, 109, 105, 108, 121, 47, 50, 48, 47, 115, 104, 111, 119, 102, 111, 114, 117, 109, 46, 97, 115, 112, 120}));
                } else {
                    Date var14 = (new SimpleDateFormat("yyyy.MM.dd", Locale.ENGLISH)).parse(com.aspose.pdf.internal.l1f.lI.lu);
                    if (var14.after(this.lc)) {
                        throw new IllegalStateException(new String(new byte[]{84, 104, 101, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 32, 105, 110, 99, 108, 117, 100, 101, 100, 32, 105, 110, 32, 116, 104, 105, 115, 32, 108, 105, 99, 101, 110, 115, 101, 32, 97, 108, 108, 111, 119, 115, 32, 102, 114, 101, 101, 32, 117, 112, 103, 114, 97, 100, 101, 115, 32, 117, 110, 116, 105, 108, 32}) + (new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH)).format(this.lc) + ", " + new String(new byte[]{98, 117, 116, 32, 116, 104, 105, 115, 32, 118, 101, 114, 115, 105, 111, 110, 32, 111, 102, 32, 116, 104, 101, 32, 112, 114, 111, 100, 117, 99, 116, 32, 119, 97, 115, 32, 114, 101, 108, 101, 97, 115, 101, 100, 32, 111, 110, 32}) + (new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH)).format(var14) + ". " + new String(new byte[]{80, 108, 101, 97, 115, 101, 32, 114, 101, 110, 101, 119, 32, 116, 104, 101, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 32, 111, 114, 32, 117, 115, 101, 32, 97, 32, 112, 114, 101, 118, 105, 111, 117, 115, 32, 118, 101, 114, 115, 105, 111, 110, 32, 111, 102, 32, 116, 104, 101, 32, 112, 114, 111, 100, 117, 99, 116, 46}));
                    } else if ((new Date()).after(this.ly)) {
                        throw new IllegalStateException(new String(new byte[]{84, 104, 101, 32, 108, 105, 99, 101, 110, 115, 101, 32, 104, 97, 115, 32, 101, 120, 112, 105, 114, 101, 100, 46}));
                    } else if (l19n.lj() > 0) {
                        throw new PdfException("Invalid license signature. Please make sure the license file was not modified.");
                    } else {
                        this.l0if = l10if.lf;
                        Helper.help1();
                        lI(this);
                    }
                }
            }
        }
    }
}

仔细观察你会发现这个方法就是验证的,主要是做验证失败抛异常和添加一些标识,这个分析下来就简单了,我们直接找到验证成功的最终执行176~179行,然后尝试修改试一下。

this.l0if = l10if.lf;
Helper.help1();
lI(this);

3. 分析结果

  • 修改void lI(InputStream var1)方法为
void lI(InputStream var1) throws Exception {
    this.l0if = l10if.lf;
    Helper.help1();
    lI(this);
}

执行操作

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

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

2. 添加修改方法

/**
 * 修改pdf jar包里面的校验
 */
public static void modifyPDFJar() {
    try {
        //这一步是完整的jar包路径,选择自己解压的jar目录
        ClassPool.getDefault().insertClassPath("D:\\aspose.pdf-21.11-java\\lib\aspose.pdf-21.11.jar");
        //获取指定的class文件对象
        CtClass zzZJJClass = ClassPool.getDefault().getCtClass("com.aspose.pdf.l9f");
        //从class对象中解析获取所有方法
        CtMethod[] methodA = zzZJJClass.getDeclaredMethods();
        for (CtMethod ctMethod : methodA) {
            //获取方法获取参数类型
            CtClass[] ps = ctMethod.getParameterTypes();
            //筛选同名方法,入参是Document
            if (ps.length == 1 && ctMethod.getName().equals("lI") && ps[0].getName().equals("java.io.InputStream")) {
                System.out.println("ps[0].getName==" + ps[0].getName());
                //替换指定方法的方法体
                ctMethod.setBody("{this.l0if = com.aspose.pdf.l10if.lf;com.aspose.pdf.internal.imaging.internal.p71.Helper.help1();lI(this);}");
            }
        }
        //这一步就是将破译完的代码放在桌面上
        zzZJJClass.writeFile("C:\\Users\\roc\\Desktop\\");

    } catch (Exception e) {
        System.out.println("错误==" + e);
    }
}

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

3. 修改jar包里面的数据

为了不修改原jar包建议复制一份重命名。

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

image.png 2. 删除jar包里面的.RSA.SF文件

image.png

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

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

声明 本方法只做个人研究学习使用,切勿用于商用。 其他参考 Aspose.Words for Java21.11去除水印和数量限制
Aspose.Cells for Java21.11去除水印和数量限制
Aspose.Slides for Java21.10去除水印和数量限制