跳到主要内容

解密 ClassFinal 加密的 Java Jar 包

· 阅读需 3 分钟

ClassFinal 是一款java class文件安全加密工具,支持直接加密jar包或war包,无需修改任何项目代码,兼容spring-framework;可避免源码泄漏或字节码被反编译。

要点

  • 拿到 password
    • 可能内置了
      • META-INF/.classes/org.springframework.config.Pass
    • 可能需要通过外部方式获取
      • 命令行参数或者环境变量或者拦截 Class 加载
    • 总的来说比较容易获取
  • 将 jar 添加到 classpath - 方便直接调用 net.roseboy.classfinal 内内容
    • 通过 IDE 或者通过命令行参数
  • 解压 jar 到当前 目录 tmp
package main;

import net.roseboy.classfinal.JarDecryptor;
import net.roseboy.classfinal.util.EncryptUtils;
import net.roseboy.classfinal.util.StrUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class DecryptClassFinal {
public static void main(String[] args) throws IOException {
String src =System.getProperty("user.dir") + "/tmp/META-INF/.classes";
String dst = System.getProperty("user.dir") + "/src/main/class";

File srcDir = new File(src);
JarDecryptor.getInstance();
// 默认 password 位置
String pass = Files.readString(Path.of(src+"/org.springframework.config.Pass"));
char[] password = EncryptUtils.md5(pass.toCharArray());

System.out.printf("src:%s\n", src);
System.out.printf("dst:%s\n", dst);
System.out.printf("password:%s\n", pass);

if (srcDir.isDirectory()) {
for (File file : srcDir.listFiles()) {
String fp = file.getName();
if (fp.startsWith("org.springframework")) {
continue;
}

byte[] fileBytes = Files.readAllBytes(file.toPath());
byte[] out = dec(password, fp, fileBytes);

String[] split = fp.split("[.]");
String fn = split[split.length-1];

String p = dst+"/"+ fp.substring(0, fp.lastIndexOf('.')).replaceAll("[.]", "/");
new File(p).mkdirs();
String f = p+"/"+ fn +".class";

System.out.println("Write to: "+f+" Len:"+out.length);
Files.write(new File(f).toPath(), out);
}
}

}

public static byte[] dec(char[] password, String fileName, byte[] bytes){
char[] pass;
pass = StrUtils.merger(new char[][]{password, fileName.toCharArray()});
return EncryptUtils.de(bytes, pass, 1);
}
}

运行 main 后 src/main/class 目录下会生成解密后的 class 文件。

反编译 class 为 java

# 假设是 macOS 安装的 IDEA
# IDEA 自带的反编译工具解密即可
java -cp ~/Applications/IntelliJ\ IDEA\ Ultimate.app/Contents/plugins/java-decompiler/lib/java-decompiler.jar \
org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler \
-dgs=true \
src/main/class/ src/main/java/

执行后 src/main/java 目录下会生成反编译后的 java 文件。

提示

解压得到的 lib 目录(sprint-boot 的 jar),可以直接加入到 classpath 中,然后即可直接在代码中调用 jar 或者直接运行 Application。

我记录思考的方式简单总结

· 阅读需 6 分钟
  1. README 涉足或者了解一个新的领域,需要先对一个领域有基础的理解
  2. GLOSSARY 记录过程中遇到的各种术语,通过术语能够快速了解一个领域
  3. AWESOME 了解和整理一个领域的资源,能够快速找到一个领域的优秀资源
  4. FAQ 记录过程中的各种常见问题,常见问题能带来非常的价值,展现了一定的思考
  5. DESIGN 总结结论,统一自己的思考方式,得出自己的设计模式
  6. Write in Public
    • 理解和表达自己的思考、沉淀自己的思考、分享自己的思考
    • 如果记录过程是 Public 的状态,那么就会更加注重质量

如何用记笔记来索引知识

2022-07-21 的一些思考

  1. 工作 是重复的任务 - Job is recurring work
  2. 经验 是解决重复问题的方案 - Experience is solution for recurring situation
  3. 知识 是重用经验 - Knowledge is about reusing experience
  4. 记笔记 是重用获取知识的时间 - Noting is about reusing time used to acquire the knowledge

要完成任务,只需了解一点点知识。知识是积累、演变和时间的结果,由小片段组成。条条大路通罗马,你必须找到自己的那条。

通过记笔记,首先做一组标记,然后深入挖掘,最终形成一个知识池。

索引知识

  • 大脑容量有限(字面意义上的)
  • 索引是为了直达重点
  • 重点如:列表、表格、代码 这样的表现方式
  • 记录内容是关于:上下文、背景、原因、关系、为什么、注意事项 等

重点可能非常简单,例如 Next.js 不支持 ESM,这就足够做出决策。 但如果你想了解更多,你将花费更多时间得出结论,是的,它还没准备好,但是...

不要浪费5分钟选择技术,使用你已经足够了解的无聊技术。

Thoughts

  • 体系结构和设计 - 选择是关键,你最好了解它们。
  • 不要在同一块石头上绊倒两次。
  • 记笔记是为了自己,写文章和博客是为了别人阅读。
  • 记笔记可以释放大脑压力,就像将思维分散到另一个地方。

记笔记是思考的反映,就像散点图,索引将其变成有向图,这是我们建模知识的方式。 写作就像绘画,试图在说服你一个观点,这个观点在在标题或第一段中已经提出,其余的文字都是在证明“我早就告诉过你了”。

为什么选择 Alpine Linux?

· 阅读需 4 分钟

Small. Simple. Secure.

Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox.

Alpine Linux 是一个基于 musl libc 和 busybox, 面向安全, 轻量级的 Linux 发布版.

恢复群晖数据盘

· 阅读需 6 分钟

Recover Synology

  • Recover Synology from AlpineLinux
  • btrfs report I/O Error

问题

群晖的盘搞的很复杂

  • mdraid -> lvm -> btrfs

只看到 btrfs 报错(I/O Error),无法使用,没看到具体的磁盘错误,只能逐级排查。

主要目的是挂载 btrfs 恢复数据。

CRM 实现经历

· 阅读需 11 分钟
vdate
v12019.11 - 2021.01
v22020.01 - 2020.06
v32020.11 - 2022.07
v42022.06 - 2022.11
v52022.11 - 2023.03
v62023.03 -

:::tips Choose

  • FE
    • React
    • Vite
    • tailwindcss
    • daisyui
    • headlessui
    • floatingui
    • GraphQL + urlq + CodeGen
    • react-hook-form
    • zustand
  • BE
    • PostgreSQL
    • mikro-orm
    • type-graphql
    • NestJS
    • Hono
    • swc+esbuild -> single bundle
    • ts-node+swc -> faster dev
  • 不要选择
    • andt
    • trpc

:::

v1

  • 后端 - Java - 2019.11 - 2021.01
  • 前端 - NextJS v9 + Antd - 2019.11 - 2021.3
    • @reduxjs/toolkit
总结

非常简单的尝试,很快就失败了,目标并不明确。 对 CRM 并不了解,过于盲目。 堆砌了一些基础前端组件。前端开发能力尚不成熟。

大师之路

· 阅读需 1 分钟

幼儿园小朋友的画和自由派名画师的话没什么区别,小学生作文和名作家的文章也没什么区别。它们在形式和内容上都是差不多的。