官网下载地址:Aspose Repository Browser /repo/com/aspose/aspose-slides/22.5/
一、分析
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>
2、分析License类的setLicense方法找到关键代码
使用jd-gui反编译jar包,搜索 License
分析setLicense
方法,设置许可证,完成许可的验证,有2个一个是文件路径,一个是io流,但是最终都是走的io流那个方法。
public final void setLicense(InputStream stream) throws AsposeLicenseException {try {ByteArrayInputStream byteArrayInputStream = null;if (stream != null) {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] arrayOfByte = new byte[1024];int i;while ((i = stream.read(arrayOfByte)) > 0)byteArrayOutputStream.write(arrayOfByte, 0, i); byteArrayOutputStream.flush();byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());} return return = new return();return.do(byteArrayInputStream);} catch (IOException iOException) {throw new InvalidOperationException("License stream is not available for reading");} }
return return = new return();
return.do(byteArrayInputStream);
在 com.aspose.slides.internal.oh 包下
public final void do(InputStream paramInputStream) {if (paramInputStream != null) {if(paramInputStream);for(this.for);for(this.do);do(this.int);if(this.new);try = this;public.do(try);} else {try = null;public.do(try);} }
定位到RSA验证签名,签名错误抛出异常。把这个方法体清空不抛异常就可以了。
private static void do(Node paramNode1, Node paramNode2, String[] paramArrayOfString) {try {String str1 = (paramNode1 != null) ? do(paramNode1) : "";byte[] arrayOfByte1 = str1.getBytes("UTF-16LE");String str2 = (paramNode2 != null) ? paramNode2.getFirstChild().getNodeValue() : "";byte[] arrayOfByte2 = try.do(str2);PublicKey publicKey = null;try {KeyFactory keyFactory = KeyFactory.getInstance("RSA");RSAPublicKeySpec rSAPublicKeySpec = this.do(if(paramArrayOfString), arrayOfByte2);publicKey = keyFactory.generatePublic(rSAPublicKeySpec);} catch (Exception exception) {(new final() {}).do((new boolean() {}, ).if, exception);} if (arrayOfByte2.length == 128) {Signature signature = Signature.getInstance("SHA1withRSA");signature.initVerify(publicKey);signature.update(arrayOfByte1);do(signature, arrayOfByte2);} else {try {Signature signature = Signature.getInstance("SHA256withRSA");signature.initVerify(publicKey);signature.update(arrayOfByte1);do(signature, arrayOfByte2);} catch (InvalidOperationException invalidOperationException) {try {String str3;if (if(paramArrayOfString)) {str3 = long.if(arrayOfByte2);} else {str3 = long.do(arrayOfByte2);} String str4 = "AQAB";byte[] arrayOfByte3 = try.do(str3);byte[] arrayOfByte4 = try.do(str4);if (!instanceof.do(arrayOfByte1, arrayOfByte2, arrayOfByte3, arrayOfByte4))(new final() {}).do((new boolean() {}, ).int, (Exception)invalidOperationException); } catch (Exception exception) {(new final() {}).do((new boolean() {}, ).int, (Exception)invalidOperationException);} } } } catch (Exception exception) {(new final() {}).do((new boolean() {}, ).int, exception);} }
3、分析结果
清空方法 void do(Node paramNode1, Node paramNode2, String[] paramArrayOfString)
private static void do(Node paramNode1, Node paramNode2, String[] paramArrayOfString) {}
二、修改方式
1、添加Javassist修改class字节码文件
<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.29.0-GA</version></dependency>
2、修改方法
package test;import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;public class Demo6 {public static void main(String[] args) {try {ClassPool pool = ClassPool.getDefault();//取得需要反编译的jar文件,设定路径pool.insertClassPath("F:/aspose-slides-22.5-jdk16.jar");CtClass ctClass = pool.get("com.aspose.slides.internal.oh.return");CtMethod[] methods = ctClass.getDeclaredMethods("do");for (CtMethod method : methods) {CtClass[] ps = method.getParameterTypes();//参数个数为3个if (ps.length == 3 && method.getName().equals("do")) {method.setBody("{}");//重新设置方法体的内容}}ctClass.writeFile("F:/");} catch (Exception e) {e.printStackTrace();}}
}
3、替换class文件
重命名 aspose-slides-22.5-jdk16.jar 为 aspose-slides-22.5-jdk16.jar.zip 解压
MANIFEST.MF只保留以下部分
Manifest-Version: 1.0
Application-Name: Aspose.Slides for Java
Implementation-Title: Aspose.Slides for Java
Copyright: Copyright 2004-2022 Aspose Pty Ltd
Bundle-SymbolicName: com.aspose.slides
Implementation-Version: 22.5
Release-Date: 2022.05.31
Specification-Vendor: Aspose Pty Ltd
Bundle-ManifestVersion: 2
Specification-Title: Aspose.Slides for Java
Bundle-Vendor: Aspose Pty Ltd
Application-Library-Allowable-Codebase: *
Import-Package: javax.xml.parsers;resolution:=optional,javax.imageio;resolution:=optional,org.xml.sax;resolution:=optional
Implementation-Vendor: Aspose Pty Ltd
Ant-Version: Apache Ant 1.9.7
Export-Package: com.aspose.slides;version=22.5,com.aspose.slides.Collections;version=22.5,com.aspose.slides.exceptions;version=22.5
Bundle-Version: 22.5
Bundle-Name: Aspose.Slides for Java
Caller-Allowable-Codebase: *
Permissions: all-permissions
Created-By: 1.8.0_162-b12 (Oracle Corporation)
Specification-Version: 22.5
替换class文件:直接将生成的com文件夹覆盖到解压包的com文件夹
将压缩成的zip重新命名为jar包