源码分析
1. 下载Aspose.Slides for Java21.10官方jar包
2. 开始分析
- 调用授权方法
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>
复制代码
- 分析License类的setLicense方法找到关键代码
public final void setLicense(InputStream stream) throws AsposeLicenseException {
try {
ByteArrayInputStream var2 = null;
if (stream != null) {
ByteArrayOutputStream var3 = new ByteArrayOutputStream();
byte[] var4 = new byte[1024];
int var5;
while((var5 = stream.read(var4)) > 0) {
var3.write(var4, 0, var5);
}
var3.flush();
var2 = new ByteArrayInputStream(var3.toByteArray());
}
public var7 = new public();
var7.do(var2);
} catch (IOException var6) {
throw new InvalidOperationException("License stream is not available for reading");
}
}
public final void setLicense(String namePath) throws AsposeLicenseException {
FileInputStream var2 = null;
try {
if (null != namePath && !"".equals(namePath)) {
var2 = new FileInputStream(namePath);
}
this.setLicense((InputStream)var2);
} catch (FileNotFoundException var9) {
try {
String var4 = DOMResourcesUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath();
if (null != var4) {
String var5 = URLDecoder.decode(var4, "UTF-8");
File var6 = new File(var5);
var2 = new FileInputStream(var6.getParentFile().getPath() + File.separator + namePath);
}
this.setLicense((InputStream)var2);
} catch (FileNotFoundException var7) {
throw new InvalidOperationException("License stream is not available for reading");
} catch (UnsupportedEncodingException var8) {
throw new InvalidOperationException("License stream is not available for reading");
}
}
}
复制代码
看下来发现setLicense的两个重载方法最终都调用了43行var7.do(var2); 也就是public类里的 do方法,由于public和do是修饰符,所以先找到上方导入的public类路径
import com.aspose.slides.internal.of.public;,然后进入到依赖引用的of目录去搜索找到
进入
public类看到do方法
public final void do(InputStream var1) {
if (var1 != null) {
this.if(var1);
this.for(this.for);
for(this.do);
do(this.int);
if(this.new);
try = this;
native.do(try);
} else {
try = null;
native.do(try);
}
}
复制代码
看到这个内容,有些头大很多都是修饰符还有个native,不过还好public文件不大,整个类扫视一遍发现了关键的信息
private static void do(Node var0, Node var1, String[] var2) {
try {
String var3 = var0 != null ? do(var0) : "";
byte[] var4 = var3.getBytes("UTF-16LE");
String var5 = var1 != null ? var1.getFirstChild().getNodeValue() : "";
byte[] var6 = com.aspose.slides.internal.of.try.do(var5);
PublicKey var7 = null;
try {
KeyFactory var8 = KeyFactory.getInstance("RSA");
RSAPublicKeySpec var9 = long.do(if(var2), var6);
var7 = var8.generatePublic(var9);
} catch (Exception var10) {
(new const() {
}).do((new switch() {
}).if, var10);
}
Signature var12;
if (var6.length == 128) {
var12 = Signature.getInstance("SHA1withRSA");
var12.initVerify(var7);
var12.update(var4);
do(var12, var6);
} else {
var12 = Signature.getInstance("SHA256withRSA");
var12.initVerify(var7);
var12.update(var4);
do(var12, var6);
}
} catch (Exception var11) {
(new const() {
}).do((new switch() {
}).int, var11);
}
}
复制代码
方法里面带有RSA这种加密的关键词,所以推测这里就是验证用的方法,解决也是老方法不知道干什么的也不清楚最终执行的,直接把内容清空。
3. 分析结果
- 修改
private static void do(Node var0, Node var1, String[] var2)方法为
private static void do(Node var0, Node var1, String[] var2) {
}
复制代码
执行操作
1. 添加Javassist修改class字节码文件
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.28.0-GA</version>
</dependency>
复制代码
2. 添加修改方法
/**
* 修改slides.jar包里面的校验
*/
public static void modifyPptJar() {
try {
//这一步是完整的jar包路径,选择自己解压的jar目录
ClassPool.getDefault().insertClassPath("D:\aspose-slides-21.10-java\lib\aspose-slides-21.10-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\roc\Desktop\");
} catch (Exception e) {
System.out.println("错误==" + e);
}
}
复制代码
运行修改方法后会在桌面生成 com 修改后的文件夹
3. 修改jar包里面的数据
为了不修改原jar包建议复制一份重命名。
- 打开jar包将桌面com文件夹覆盖到jar包com文件夹
2. 删除jar包里面的
.RSA和.SF文件
4. 重新导入修改后的jar包进行测试
- maven移除旧的jar包,导入修改后的jar包
- 调用测试方法进行测试转换后的文件是否去除水印和数量限制成功
String sourceFile = "D:\b.pptx";//输入的文件
String targetFile = "D:\转换后.pdf";//输出的文件
/**
* PPT转PDF操作
*
* @param sourceFile 源文件
* @param targetFile 目标文件
*/
public static void PptToPdf(String sourceFile, String targetFile) {
try {
long old = System.currentTimeMillis();
FileOutputStream os = new FileOutputStream(targetFile);
Presentation ppt = new Presentation(sourceFile);//加载源文件数据
ppt.save(os, com.aspose.slides.SaveFormat.Pdf);//设置转换文件类型并转换
os.close();
long now = System.currentTimeMillis();
System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); //转化用时
} catch (Exception e) {
e.printStackTrace();
}
}
复制代码
声明
本方法只做个人研究学习使用,切勿用于商用。
其他参考
作者:Aroc
链接:juejin.cn/post/703441…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。