反编译jar包破解ASPOSE
准备工作
- 下载原始jar包:aspose-html-22.8-jdk11.jar
- 准备反编译工具,这里推荐使用jd-gui或者jadx。
破解思路
Aspose 系列产品主要依赖许可证文件(license.xml)的注册来工作。首先,让我们看看 Aspose 是如何注册许可证的:
1
2
3
4
5
6
7
8
9InputStream is;
try {
is = Files.newInputStream(Paths.get("C:\\xxx\\license.xml"));
License license = new License();
license.setLicense(is);
is.close();
} catch (Exception e) {
throw new RuntimeException(e);
}license.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<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>破解的思路很简单,就是查看
setLicense方法中实际做了哪些操作,然后对源码进行修改。我们使用JD-GUI反编译 jar 包,找到License类,位于com.aspose.html包下。我们可以看到有两个
setLicense方法,而代码中调用的是第二种形式。这里使用了传入的文件流,我们可以重点查看z16调用的m1方法:
1
z16.m1(byteArrayInputStream);
- 我们进入 z16 类,逐步查看里面的实现,找到一个可疑的方法。
在这段代码中,m1 方法的主要功能是验证许可文件的签名,以确保文件的合法性和未被篡改。
- 获取许可类型:
- 通过 switch 语句,根据许可的类型(如 “Professional” 或 “Enterprise”)进行区分,以确定许可文件的类型。
- 处理节点数据:
- 将传入的 XML Node 数据转化为字符串并以 UTF-16LE 编码转换为字节数组 (arrayOfByte1)。
- 从第二个节点 paramNode2 中提取 Base64 编码的签名,并将其解码为字节数组 (arrayOfByte2)。
- 选择签名算法:
- 根据许可文件的安全要求,选择使用 SHA1withRSA 或 SHA256withRSA 作为签名算法。如果系统启用了 FIPS 安全模式,则需要使用 FIPS 认证的提供程序 (m186)。
- 公钥选择:
- arrayOfString1 和 arrayOfString2 数组中存储了多个可能的公钥或公钥片段,通过索引选择合适的公钥。
- 使用 m5 方法从字符串中生成公钥 (PublicKey)。
- 签名验证:
- 使用 initVerify 方法初始化公钥验证。
- 调用 update 方法传入已编码的数据字节数组 (arrayOfByte1),然后使用 verify 方法验证 Base64 解码后的签名 (arrayOfByte2) 是否匹配。
- 返回结果:
- 验证成功后返回许可状态 paramz3,如果验证失败,则抛出异常并返回失败状态 (z3.m205)。
- 获取许可类型:
那么破解的思路非常简单:直接让这个方法返回 paramz3 就行了。
修改字节码文件
接下来,我们使用
Javassist修改字节码文件。首先添加依赖:1
2
3
4
5<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.28.0-GA</version>
</dependency>我们只需要需要修改
z16类中的m1(Node node, Node node2, z3 z3Var)方法,让它直接返回 paramz3。修改的代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24try {
String jarPath = "D:\\html\\aspose-html-22.8-jdk11.jar";
ClassPool classPool = ClassPool.getDefault();
classPool.insertClassPath(jarPath);
// z16类里的m1方法,同时三个参数类型分别是Node, Node, z3,这个z3我找了一下,是z16里的一个枚举类
CtClass ctClass = classPool.getCtClass("com.aspose.html.z16");
CtClass[] paramTypes = new CtClass[3];
paramTypes[0] = classPool.get("org.w3c.dom.Node");
paramTypes[1] = classPool.get("org.w3c.dom.Node");
paramTypes[2] = classPool.get("com.aspose.html.z16$z3");
CtMethod ctMethod = ctClass.getDeclaredMethod("m1", paramTypes);
// 修改方法体,使其直接返回第三个参数
ctMethod.setBody("{\n" +
" return $3;\n" +
" }");
ctClass.writeFile("D:\\html\\");
System.out.println("Modification completed successfully.");
} catch (Exception e) {
e.printStackTrace();
}编译执行之后会生成一个.class文件,我们把这个.class文件替换到原来的jar包中,并且删除jar包中原本的.RSA和.SF文件,使用mvn install安装一下这个jar包就可以调用了。
注意事项
- ASPOSE.SLIDE、ASPOSE.WORDS等其他产品,破解思路基本都是一样的,都是看setLicense方法的实现,然后修改源码。
- 破解版的 jar 包可能存在后台向外部服务器发送数据的风险,因此本文仅限于学习研究,不涉及商业用途。请勿将其用于非法活动。
怎么偷偷用?
方案设计
主要技术点
参数化Java程序
- 通过 main 方法接受参数,并规范参数顺序:
- args[0]:任务类型(如 report、summary)。
- args[1]:统一业务参数(可为 JSON 等)。
- args[2]:输出路径。
- 其余参数:不同任务类型独有的参数。
- 运行时使用 java -jar xxx.jar args0 args1 args2 传递参数。
- Java 程序只能有一个 main 方法,所有任务分发逻辑在 main 内实现。
- 通过 main 方法接受参数,并规范参数顺序:
使用 Docker 进行环境隔离
- 通过 Dockerfile` 创建独立的运行环境,确保所需的 Java 依赖完整可用。
- 运行时使用
--network none选项断网,防止商业库进行外部联网验证。
- 提供远程调用接口
- 通过
Python Flask创建HTTP API,接收外部请求并执行Docker命令。 - Java 代码通过
OkHttpClient发送HTTP请求,实现远程文档生成任务。
- 通过
代码实现
Java代码
1 | public class DocGenerateApplication { |
核心命令
- 重点是
--network none,随后在启动jar包的时候,传递自己需要的参数。1
2
3docker run --network none
-e LANG = C.UTF - 8
doc-generate-test java -jar /data/ppt.jar args0 args1 args2 args3 args4 ...
Python代码
1 | # encoding=utf-8 |
调用代码
1 | public void sendExecutorCMD(String ...args) throws IOException { |
评论




