反编译工具
jd-gui
JD-GUI,一个独立的图形实用程序,用于显示来自 CLASS 文件的 Java 源代码。

如下图,Save All Sources 点击此按钮,保存所有反编译代码
缺点:经常某些代码反编译的有问题,某些新特性也不能很好的处理
CFR
cfr是一个非常强大的java反编译器,支持java5,java8的新特性,如枚举,lambda表达式等。
反编译命令:java -jar cfr-0.151.jar java7_jar.jar --outputdir D:/Java/tmp
java -jar cfr-0.150.jar Client.class
cfr还有大量的参数可以让我们灵活的设置java -jar cfr-0.150.jar --help
--aexagg (boolean)--aexagg2 (boolean)--aggressivedoextension (boolean)--aggressivesizethreshold (int >= 0) default: 15000--allowcorrecting (boolean) default: true--analyseas (One of [DETECT, JAR, WAR, CLASS])--arrayiter (boolean) default: true if class file from version 49.0 (Java 5) or greater--caseinsensitivefs (boolean) default: true--clobber (boolean)--collectioniter (boolean) default: true if class file from version 49.0 (Java 5) or greater--commentmonitors (boolean) default: false--comments (boolean) default: true--decodeenumswitch (boolean) default: true if class file from version 49.0 (Java 5) or greater去除switch对枚举支持的语法糖 --decodeenumswitch false--decodefinally (boolean) default: true--decodelambdas (boolean) default: true if class file from version 52.0 (Java 8) or greater去除lambda表达式的语法糖 --decodelambdas false--decodestringswitch (boolean) default: true if class file from version 51.0 (Java 7) or greater--dumpclasspath (boolean) default: false--eclipse (boolean) default: true--elidescala (boolean) default: false--extraclasspath (string)--forbidanonymousclasses (boolean) default: false--forbidmethodscopedclasses (boolean) default: false--forceclassfilever (string, specifying either java version as 'j6', 'j1.0', or classfile as '56', '56.65535')--forcecondpropagate (boolean)--forceexceptionprune (boolean)--forcereturningifs (boolean)--forcetopsort (boolean)--forcetopsortaggress (boolean)--forcetopsortnopull (boolean)--forloopaggcapture (boolean)--hidebridgemethods (boolean) default: true--hidelangimports (boolean) default: true--hidelongstrings (boolean) default: false--hideutf (boolean) default: true--ignoreexceptions (boolean) default: false--ignoreexceptionsalways (boolean) default: false--importfilter (string)--innerclasses (boolean) default: true--instanceofpattern (boolean) default: true if class file from version 58.0 (Java 14) or greater, or experimental in 58.0 (Java 14)--j14classobj (boolean) default: false if class file from version 49.0 (Java 5) or greater--jarfilter (string)--labelledblocks (boolean) default: true--lenient (boolean) default: false--liftconstructorinit (boolean) default: true--lomem (boolean) default: false--methodname (string)--obfuscationpath (string)--outputdir (string)结果输出目录--outputpath (string)--override (boolean) default: true if class file from version 50.0 (Java 6) or greater--previewfeatures (boolean) default: true--pullcodecase (boolean) default: false--recordtypes (boolean) default: true if class file from version 58.0 (Java 14) or greater, or experimental in 58.0 (Java 14)--recover (boolean) default: true--recovertypeclash (boolean)--recovertypehints (boolean)--relinkconststring (boolean) default: true--removebadgenerics (boolean) default: true去除泛型的语法糖 --removebadgenerics false--removeboilerplate (boolean) default: true--removedeadconditionals (boolean)--removedeadmethods (boolean) default: true--removeinnerclasssynthetics (boolean) default: true--rename (boolean) default: false--renamedupmembers (boolean) default: Value of option 'rename'--renameenumidents (boolean) default: Value of option 'rename'--renameillegalidents (boolean) default: Value of option 'rename'--renamesmallmembers (int >= 0) default: 0--showinferrable (boolean) default: false if class file from version 51.0 (Java 7) or greater--showversion (boolean) default: true--silent (boolean) default: false--skipbatchinnerclasses (boolean) default: true--staticinitreturn (boolean) default: true--stringbuffer (boolean) default: false if class file from version 49.0 (Java 5) or greater--stringbuilder (boolean) default: true if class file from version 49.0 (Java 5) or greater--stringconcat (boolean) default: true if class file from version 53.0 (Java 9) or greater--sugarasserts (boolean) default: true--sugarboxing (boolean) default: true去除自动装箱和拆箱的语法糖 --sugarboxing false--sugarenums (boolean) default: true if class file from version 49.0 (Java 5) or greater去除枚举的语法糖 --sugarenums false--switchexpression (boolean) default: true if class file from version 57.0 (Java 13) or greater, or experimental in 56.0 (Java 12)--tidymonitors (boolean) default: true--tryresources (boolean) default: true if class file from version 51.0 (Java 7) or greater--usenametable (boolean) default: true--usesignatures (boolean) default: true--help (string)
修改Jar包工具
jclasslib bytecode viewer
jclasslib bytecode viewer 是一个可以可视化已编译Java类文件和所包含的字节码的工具。 另外,它还提供一个库,可以让开发人员读写Java类文件和字节码。
编辑
所有常量池条目都可以编辑。引用的常量池条目可以直接从属性和常量池条目的“编辑”按钮显示的上下文菜单中进行编辑。
Jar包签名
某些Jar包中包含代码签名,修改Jar包后需要重新签名,需要用到JDK自带工具keytool
若不重新签名,会出现JarVerifier错误。
原理
签名:
认证:
签名步骤
用java的keytool生成密钥对,用java的jarsigner做签名
生成密钥对
keytool -genkey -keystore ijvmkeys.keystore -keyalg RSA -validity 10000 -alias friend.keystore
查看密钥文件
keytool -list -v -keystore ijvmkeys.keystore
签名Jar包
jarsigner -verbose -keystore ijvmkeys.keystore friend.jar friend.keystore

FRIEND_K.SF文件:
Signature-Version: 1.0SHA1-Digest-Manifest-Main-Attributes: QHukAYw2MtCop4vlrhjJDDro1fQ=Created-By: 1.6.0_12 (Sun Microsystems Inc.)SHA1-Digest-Manifest: YePdyFc1+FVdY1PIcj6WVuTJAFE=Name: com/yfq/test/friend/Friend$1.classSHA1-Digest: mj79V3+YKsRAzxGHpyFGhOdY4dU=Name: com/yfq/test/friend/Friend.classSHA1-Digest: tqPfF2lz4Ol8eJ3tQ2IBvvtduj0=
它包含了签名的版本,签名者,还有被签名的类名,以及这个类的hash摘要,第四行是整个本文件的摘要,用于jar包的校验
Jar验证
jarsigner -verify friend.jar和jarsigner -verify stranger.jar
参考: https://www.cnblogs.com/Gandy/p/7290069.html https://blog.csdn.net/yangxt/article/details/1796965 https://www.cnblogs.com/jixp/articles/10731726.html
JCE(加密)供应商的相关Jar包
是JCE供应商(provider)的相关Jar,有可能报JCE cannot authenticate the provider BC。
这是由于JCE供应商相关Jar包,必须签名两次,第一次必须是Oracle,第二次是CA。
必须由JDK环境认证证书的签名,即必须由Oracle 进行JCE提供商认证签名,需要申请。
官方说明:https://www.oracle.com/java/technologies/javase/getcodesigningcertificate.html
参考: https://stackoverflow.com/questions/13721579/jce-cannot-authenticate-the-provider-bc-in-java-swing-application https://stackoverflow.com/questions/1756801/how-to-sign-a-custom-jce-security-provider https://stackoverflow.com/questions/20998124/jar-file-manifest-does-not-contain-permission-attribute https://www.oracle.com/java/technologies/javase/getcodesigningcertificate.html https://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/HowToImplAProvider.html#Step6
绕过Oracle签名
使用OpenJDK,没有Oracle JDK导致的相关签名问题,经验证,修改的Jar包可以直接使用运行。
安装OpenJDK
下载地址:https://adoptopenjdk.net/?variant=openjdk8&jvmVariant=hotspot
需要本地设置环境变量JAVA_HOME
即可在该环境下使用
IDEA配置:
系统配置:Maven Importing -> JDK for importer 修改为openjdk
工程配置:project -> project SDK 改为openjdk
modules -> Dependencies -> Module SDK 改为openjdk
集成到java工程
JDK使用openjdk
工程下目录/lib 增加demo.jar
pom依赖配置:
<dependency><groupId>demo</groupId><artifactId>demo</artifactId><version>1.0.0</version><scope>system</scope><systemPath>${project.basedir}/lib/demo.jar</systemPath></dependency>
构建插件:
<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><includeSystemScope>true</includeSystemScope></configuration></plugin>

