自定义类加载器例子(对 class 文件进行解密操作)

本贴最后更新于 1541 天前,其中的信息可能已经渤澥桑田

摘抄自 https://xz.aliyun.com/t/9002#toc-16

案例

  • 首先创建一个需要加密的 测试类
package cn.lacknb.test.classloader; /** * @Desc: cypher 密码 * 自定义 类加载器: 将此 的 class文件进行加密,然后使用自定义的 * 类加载器 进行加载。 * @Author: gitsilence * @Date: 2021/2/16 */ public class CypherTest { public static void main(String[] args) { System.out.println("This experiment test is successful"); } }
  • 通过上面的类生成 class 文件。
  • 创建一个用来加密 class 文件的类,其实就是 进行按位 异或操作。
package cn.lacknb.test.classloader; import java.io.*; /** * @Desc: 加密 类 ,使用逐位 和 1111 1111(0xff) 进行异或。 * @Author: gitsilence * @Date: 2021/2/16 */ public class Encryption { private static final String CLASS_PATH = "/media/gitsilence/nie475/javaProject/Java_Thread/01-Threadhello/target/classes/cn/lacknb/test/classloader/CypherTest.class"; public static void main(String[] args) { encode(new File(CLASS_PATH), new File("/media/gitsilence/nie475/javaProject/Java_Thread/01-Threadhello/src/main/java/cn/lacknb/test/classloader/CypherTest.class")); } public static void encode (File src, File dest) { FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream(src); fos = new FileOutputStream(dest); int temp = -1; // 读取 一个 字节 while ((temp = fis.read()) != -1) { // 0xff 为16进制、 二进制为:1111 1111 // 按位 进行 异或 运算, 再进行有一次异或 恢复。 fos.write(temp ^ 0xff); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } } System.out.println("current class is encoded successfully!"); } }
  • 执行 对 class 文件的加密后,自定义 一个类加载器,在加载前进行 解密操作。
package cn.lacknb.test.classloader; import java.io.*; /** * @Desc: 自定义 类加载器,解密class * 将Decryption 继承 ClassLoader类,之后覆盖findClass方法, * 并且 在findClass方法中调用defineClass()方法使用,最后加载我们自定义 * getClassData 方法进行 解密操作。 * @Author: gitsilence * @Date: 2021/2/16 */ public class Decryption extends ClassLoader { private String rootDir; public Decryption (String rootDir) { this.rootDir = rootDir; } /** * 重写覆盖 findClass * @param name * @return * @throws ClassNotFoundException */ @Override protected Class<?> findClass(String name) throws ClassNotFoundException { // 先从 已加载的类中 查找 是否已经加载。 Class<?> clzz = findLoadedClass(name); if (clzz != null) { return clzz; } else { ClassLoader parent = this.getParent(); try { clzz = parent.loadClass(name); } catch (ClassNotFoundException e) { System.out.println("父类无法加载你的class,捕获异常,继续运行。"); } if (clzz != null) { System.out.println("父类加载成功"); return clzz; } else { // 读取文件 转化为 字节数组 byte[] classData = getClassData(name); if (classData == null) { throw new ClassNotFoundException("not found class : " + name); } else { // 调用 defineClass方法 clzz = defineClass(name, classData, 0, classData.length); return clzz; } } } } /** * 解密字节码 文件的内容 * @param className * @return */ public byte[] getClassData (String className) { String path = rootDir + "/" + className.replace(".", "/") + ".class"; // 将流中的数据 转换为字节数组 InputStream is = null; ByteArrayOutputStream baso = new ByteArrayOutputStream(); try { is = new FileInputStream(path); byte[] buffer = new byte[1024]; int temp = -1; while ((temp = is.read()) != -1) { // 与 二进制 1111 1111 进行 异或运算。 baso.write(temp ^ 0xff); } return baso.toByteArray(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); baso.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } }
  • 测试
package cn.lacknb.test.classloader; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @Desc: 测试 加载 加密 后的class文件。 * @Author: gitsilence * @Date: 2021/2/16 */ public class ClassLoaderDemo { public static void main(String[] args) { // 解密加载器。 Decryption decryption = new Decryption("/media/gitsilence/nie475/javaProject/Java_Thread/01-Threadhello/src/main/java/"); try { // 加载已经解密的 class文件 Class<?> clzz = decryption.findClass("cn.lacknb.test.classloader.CypherTest"); System.out.println("class is : " + clzz); // 通过反射 获取main方法 Method main = clzz.getMethod("main", String[].class); // JDK1.4以后 把整个数组 作为一个参数 // 按照1.4的语法,是数组中的每个元素对应一个参数 // 1.5 必须兼容1.4,因此字符串数组会被拆分为 若干个单独的参数 // 因此在给main方法传递参数时,不能使用代码 main.invoke(null, new String[]{"1", "2"}); // javac 会按照1.4的语法进行编译,会出现参数数量不匹配的问题。 main.invoke(null, (Object)new String[]{"1", "2"}); // 解决办法:对我们要传的字符数组进行一次包装,把它包装到一个Object数组 // 中,这时拆开后,得到唯一参数 就是字符串数组。 } catch (ClassNotFoundException | NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }

最后打印结果。

父类加载成功
class is : class cn.lacknb.test.classloader.CypherTest
This experiment test is successful

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3200 引用 • 8216 回帖
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 411 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    345 引用 • 747 回帖 • 1 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    6 引用 • 26 回帖 • 545 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    56 引用 • 85 回帖
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖 • 1 关注
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    180 引用 • 408 回帖 • 484 关注
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 114 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    298 引用 • 763 回帖
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    162 引用 • 1096 回帖
  • sts
    2 引用 • 2 回帖 • 228 关注
  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 635 关注
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 8 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 497 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    730 引用 • 1280 回帖 • 5 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 726 关注
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    15 引用 • 7 回帖 • 1 关注
  • Office

    Office 现已更名为 Microsoft 365. Microsoft 365 将高级 Office 应用(如 Word、Excel 和 PowerPoint)与 1 TB 的 OneDrive 云存储空间、高级安全性等结合在一起,可帮助你在任何设备上完成操作。

    5 引用 • 34 回帖
  • danl
    164 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 291 关注
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 556 关注
  • V2Ray
    1 引用 • 15 回帖
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    227 引用 • 476 回帖
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 29 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 507 关注
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖 • 1 关注