java运行库一键修复_在运行时修补Java

java运行库一键修复

本文将重点介绍如何解决与第三方库相关的问题
  • 不能被规避
  • 难以排除/绕过/更换
  • 只需不提供错误修正

在这种情况下,解决问题仍然是一项艰巨的任务。

作为这种情况的诱因,请考虑对“哈希索引”数据结构的攻击,例如java.util.Hashtable和java.util.HashMap (对于不熟悉此类攻击的人,我建议查看以下内容28C3: 对Web应用程序进行拒绝服务攻击变得容易( )。

长话短说,核心问题是使用非加密哈希函数(在其中查找冲突很容易)。 根本原因隐藏在java.lang.String.hashCode()函数中。 显而易见的方法是修补java.lang.String类,这很困难,原因有两个:

  1. 它包含本机代码
  2. 它属于Java核心类,它们随Java安装一起提供,因此不受我们的控制

第一点将迫使我们修补体系结构和特定于OS的库,我们应该在可能的情况下规避这些库。 第二点是正确的,但它会更灵活一些,我们将在下面看到。

好的,让我们重新考虑:修补本机很脏,我们不急于采用这种方式–我们必须为不愿意修复其代码的其他人(在本例中为SDK SDK库)做一些工作。

尝试:
哈希问题涉及类java.util.Hashtablejava.util.HashMap ,它们不使用任何本机代码。 修补这些类要容易得多,因为为所有体系结构和OS提供一个已编译的类就足够了。
我们可以使用提供的错误解决方案之一,并用固定版本调整(或替换)原始类。 困难在于在不接触核心库的情况下修补VM –我想如果用户必须更改其JVM安装的一部分,或者更糟糕的是,我们的应用程序在安装过程中自动执行此操作,用户将非常失望。 在某些情况下,进一步引入新的自定义类加载器可能会很困难。

我们需要的是一种动态修补单个应用程序的解决方案–替换有问题的类,不要碰其他任何东西。 如果我们透明地执行此操作,则其他软件部分甚至都不会识别任何更改(最好),并保持与类的接口,而无需进行任何修改。

可以通过滥用Java Instrumentation API轻松地完成此操作。 引用JavaDoc

“提供允许Java编程语言代理检测运行在JVM上的程序的服务。”

这正是我们所需要的!

概念证明
首先,我们需要一个示例应用程序来演示该概念:

public class StringChanger {public static void main(String[] args) {System.out.println(A.shout());}}public class A {public static String shout() {return "A";}
}

运行此类时,它仅输出:A
应用我们的“补丁”之后,我们将获得以下输出:已补丁

“修补的代码如下所示:

public class A {public static String shout() {return "Apatched";}
}

进一步,我们需要一个“代理”来管理所使用的类并修补正确的类:

final public class PatchingAgent implements ClassFileTransformer {private static byte[] PATCHED_BYTES;private static final String PATH_TO_FILE = "Apatched.class";private static final String CLASS_TO_PATCH = "stringchanger/A";public PatchingAgent() throws FileNotFoundException, IOException {if (PATCHED_BYTES == null) {PATCHED_BYTES = readPatchedCode(PATH_TO_FILE);}}public static void premain(String agentArgument,final Instrumentation instrumentation) { System.out.println("Initializing hot patcher...");PatchingAgent agent = null;try {agent = new PatchingAgent();} catch(Exception e) {System.out.println("terrible things happened....");}instrumentation.addTransformer(agent);}@Overridepublic byte[] transform(final ClassLoader loader, String className,final Class classBeingRedefined, final ProtectionDomain protectionDomain,final byte[] classfileBuffer) throws IllegalClassFormatException {byte[] result = null;if (className.equals(CLASS_TO_PATCH)) {System.out.println("Patching... " + className);result = PATCHED_BYTES;}return result;}private byte[] readPatchedCode(final String path)throws FileNotFoundException, IOException {...}
}

不用担心–我不会打扰您实现细节,因为这只是PoC代码,远非美观,巧妙,快速而简洁。 除了我因为此时太懒而捕获 Exception以外,我没有过滤输入,构建深拷贝(防御性编程作为流行语),这实际上不应该被视为生产代码。

公共PatchingAgent()
初始化代理(在这种情况下,将获取修补的A.class文件的字节。修补的类已编译并存储在我们可以访问它的位置。

公共静态无效premain(…)
在JVM初始化并准备代理后,将调用此方法。

公共字节[]变换(…)
每当定义了一个类时(例如,通过ClassLoader.defineClass (…)),该函数都会被调用,并且可以转换已处理的类字节 []( classfileBuffer )。 可以看出,我们将为stringchanger包中的A类执行此操作。 您不受限制如何转换类(只要它仍然是有效的Java )–例如,您可以利用字节码修改框架…–为使事情变得简单,我们假设我们将旧字节 []替换为修补类之一(通过将完整的修补A.class文件简单地缓存到字节 []中)。

这就是修补程序编码部分的全部内容……最后,我们必须使用一个特殊的manifest.mf文件构建一个jar容器,该文件告诉JVM如何调用该代理。

清单版本:1.0
X-COMMENT:Main-Class将通过构建自动添加
Premain-Class:stringchanger.PatchingAgent

构建完这个jar之后,我们可以尝试PoC应用程序。 首先,我们将在没有调用代理的必要JVM参数的情况下调用它:

跑:
一个
建立成功(总时间:0秒)

它的行为符合预期,并输出未修补类定义的输出。

现在,我们将使用神奇的JVM参数来尝试调用代理-javaagent:StringChanger.jar:

跑:
初始化热修补程序…
读取修补文件。 修补…换弦器/ A 已分配 建立成功(总时间:0秒)

Voilà,该代码已成功进行了实时修补!

如我们所见,有可能动态地对JVM进行热补丁而不用触摸交付的代码。 必须做的是开发修补程序和修补的类。 目前,我还不了解性能评估数据。 因此,我不确定该解决方案对生产系统的实用性以及对应用程序性能的影响程度。

明确地说,这不是一个优雅的解决方案–至少它很脏! 最好的方法是修补根本原因,但只要没有供应商修复程序,开发人员就可以通过热修补来防止其软件运行,而无需重写使用易受攻击类的每一行。

最后,我希望提出意见,改进或只是更好的解决方案。 非常感谢Juraj Somorovsky与我在这个问题上共同努力。

参考: JCG合作伙伴 在运行时修补Java   Christopher Meyer讨论了Java安全性和相关主题 。


翻译自: https://www.javacodegeeks.com/2012/02/patching-java-at-runtime.html

java运行库一键修复

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356559.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用LinkedList模拟一个堆栈或者队列数据结构

使用LinkedList模拟一个堆栈或者队列数据结构。 堆栈:先进后出 如同一个杯子。 队列:先进先出 如同一个水管。 import java.util.LinkedList;public class DuiLie {private LinkedList link;public DuiLie() {link new LinkedList();}public void m…

k40游戏增强版服务器维护中,Redmi K40 游戏增强版发布,第四台 K40 出现了

原标题:Redmi K40 游戏增强版发布,第四台 K40 出现了今晚 Redmi 发布了旗下的新款游戏手机 —— Redmi K40 游戏增强版,这也是K40、K40 Pro、K40 Pro 之后的又一款 K40 产品,主打的是专游戏功能和轻薄设计。Redmi K40 游戏增强版使…

mpvue微信小程序动画_入门微信小程序

为何现在的微信小程序还是高温不退?主要原因如下:无需安装、不占内存、易传播。废话不多说,开始进入开发!-----------小程序环境搭建-----------------------------------账号注册百度搜索 "微信公众平台"官网地址&…

瀑布流式布局

今天终于搞懂了瀑布流式布局,哈哈,总结下 瀑布流式布局分为两种类型:1、每一列都限定宽度不限定高度的布局(使用浮动)2、宽度不是写死的,是根据页面的放大缩小变化的(定位布局) 瀑布…

Spock VW:编写自定义的Spock框架扩展

Spock框架具有多个内置扩展 ,这些扩展支持许多核心功能,例如Ignore和Timeout批注。 但更重要的是,鼓励开发人员编写自己的扩展。 例如, SpringExtension很好地将Spock与Spring框架集成在一起。 编写自定义扩展没有很好的文档记录。…

物理服务器备份系统,物理备份和逻辑备份区别

物理备份和逻辑备份区别 内容精选换一换可能这份面试题还不足以包含所有Java问题,但有了它,我相信你一定不会“败”的很惨,有了它,足以应对目前市面上绝大部分的Java面试了,因为这些问题不论是从深度还是广度上来讲&am…

dd命令iso linux_BootISO:从 ISO 文件中创建一个可启动的 USB 设备

今天,我们将讨论名为 BootISO 的实用程序类似工具。它是一个简单的 bash 脚本,允许用户来从 ISO 文件中创建一个可启动的 USB 设备。-- Prakash Subramanian(作者)为了安装操作系统,我们中的大多数人(包括我)经常从 ISO 文件中创建一个可启动…

java基础-接口

转载于:https://www.cnblogs.com/ceshi2016/p/6025027.html

Python之路,day4-Python基础

1.集合2.元组 只读列表,只有count,index2个方法3.字典key-value对 1.特性 2.查询速度快,比列表快python中的hash在同一程序下值相同python字典中的hash只有key是hash的hash之后二分查找,劈半劈半注:只有unicode有…

gwt入门和进阶_GWT入门

gwt入门和进阶GWT是Google Web Development Kit的缩写,可让程序员使用Java开发Ajax Web应用程序。 GWT编译器将Java代码转换为JavaScript和html代码。 GWT应用程序称为模块,并且使用xml文件描述模块,假设该模块名称为xml文件的“ mymodule”名…

workbook加载文件路径_通过Workbook.XML 修复Excel自定义名称

小伙伴们经常想求助IT 提升打开Excel的速度, 标准回答是:重启。其实Excel 中影响打开速度的几个因素:1. 公式 2. 链接 3. 自定义名称 自定义名称常常被人忽视,里面经常隐藏着众多错误,而且有很多的名称是隐藏的&#x…

将IDE检查应用于自定义Java批注

J2SE 5中注释的引入改变了我们编写和处理Java的方式。 除了Java SE的预定义注释外 ,框架,IDE和工具包还引入了自己的自定义注释 。 Checker框架提供了一些示例,说明如何使用自定义注释在Java中增加类型安全性 。 在本文中,我着眼于…

有什么用_app用什么软件编写

自己咋开发APP这得看你的学习程度了,如果你学了安卓开发那么久按照教程来吧,如果没有学过,那么就看看我的回答是不是贴题意的。比较快的开发app方式。接入任意后台,通过HBuilder封装成app。2.使用MUI,借用官方的组件代…

java函数的笔记

java函数的笔记 java中,函数即方法。也就是实现某个功能的办法。 函数的格式 修饰符 返回值类型 函数名(参数类型 参数) { 逻辑处理; return 处理结果; // return关键字是用于结束该函数的,并将处理结果返回给调用者。void类型可以省略return&#xff0…

jquery手写轮播图_15个超强的jQuery/HTML5图片轮播插件

最近我们为大家分享过不少基于jQuery的图片轮播插件,当然也有很多使用了HTML5和CSS3的相关技术,让整个图片播放器显得更加美观,动画效果显得更加炫酷。这次我们特意为大家筛选了一些最新的jQuery/HTML5图片轮播插件,每一个的功能都…

NLOG配置

<?xml version"1.0" encoding"utf-8" ?><nlog xmlns"http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"> <!-- See https://github.com/nlog/nlog/wiki/Config…

gwt格式_GWT –利弊

gwt格式我喜欢JavaScript。 随着jQuery和Mootools的出现&#xff0c;我对JavaScript的热爱倍增 。 如果有选择&#xff0c;我将对开发的任何Web应用程序使用上述任一框架。 但是进入服务行业后&#xff0c;我不得不一次次屈服于客户的压力&#xff0c;并在他们选择技术的过程中…

sap获取系统时间_获取系统当前时间

NSString *appKey(){// // 获取系统当前时间// NSDate * date [NSDate date];// NSTimeInterval sec [date timeIntervalSinceNow];// NSDate * currentDate [[NSDate alloc] initWithTimeIntervalSinceNow:sec];//// //设置时间输出格式&#xff1a;// NSDateFormatter * d…

Git 初始化版本库

创建带工作区的版本库 在开始一个新项目时&#xff0c;首先就要创建并初始化代码库。如果是在本机的工作目录中&#xff0c;那么&#xff1a; $ git init 也就够用了。如果想要初始化的版本库不在当前目录&#xff0c;需要为 git init 命令指定版本库所在的目录&#xff1a; $ …

Spring中的值注释中的占位符支持

Value批注中的${...}占位符用于访问在PropertySource注册的属性。 这对于Spring应用程序中的Configuration bean非常有用&#xff0c;但不仅如此。 为确保可行&#xff0c; PropertySourcesPlaceholderConfigurer必须存在于所有需要占位符解析的应用程序上下文中。 在此博客文…