java运行库一键修复_在运行时修补Java
java運(yùn)行庫一鍵修復(fù)
本文將重點(diǎn)介紹如何解決與第三方庫相關(guān)的問題- 不能被規(guī)避
- 難以排除/繞過/更換
- 只需不提供錯(cuò)誤修正
在這種情況下,解決問題仍然是一項(xiàng)艱巨的任務(wù)。
作為這種情況的誘因,請考慮對“哈希索引”數(shù)據(jù)結(jié)構(gòu)的攻擊,例如java.util.Hashtable和java.util.HashMap (對于不熟悉此類攻擊的人,我建議查看以下內(nèi)容28C3: 對Web應(yīng)用程序進(jìn)行拒絕服務(wù)攻擊變得容易( )。
長話短說,核心問題是使用非加密哈希函數(shù)(在其中查找沖突很容易)。 根本原因隱藏在java.lang.String.hashCode()函數(shù)中。 顯而易見的方法是修補(bǔ)java.lang.String類,這很困難,原因有兩個(gè):
第一點(diǎn)將迫使我們修補(bǔ)體系結(jié)構(gòu)和特定于OS的庫,我們應(yīng)該在可能的情況下規(guī)避這些庫。 第二點(diǎn)是正確的,但它會更靈活一些,我們將在下面看到。
好的,讓我們重新考慮:修補(bǔ)本機(jī)很臟,我們不急于采用這種方式–我們必須為不愿意修復(fù)其代碼的其他人(在本例中為SDK SDK庫)做一些工作。
嘗試:
哈希問題涉及類java.util.Hashtable和java.util.HashMap ,它們不使用任何本機(jī)代碼。 修補(bǔ)這些類要容易得多,因?yàn)闉樗畜w系結(jié)構(gòu)和OS提供一個(gè)已編譯的類就足夠了。
我們可以使用提供的錯(cuò)誤解決方案之一,并用固定版本調(diào)整(或替換)原始類。 困難在于在不接觸核心庫的情況下修補(bǔ)VM –我想如果用戶必須更改其JVM安裝的一部分,或者更糟糕的是,我們的應(yīng)用程序在安裝過程中自動執(zhí)行此操作,用戶將非常失望。 在某些情況下,進(jìn)一步引入新的自定義類加載器可能會很困難。
我們需要的是一種動態(tài)修補(bǔ)單個(gè)應(yīng)用程序的解決方案–替換有問題的類,不要碰其他任何東西。 如果我們透明地執(zhí)行此操作,則其他軟件部分甚至都不會識別任何更改(最好),并保持與類的接口,而無需進(jìn)行任何修改。
可以通過濫用Java Instrumentation API輕松地完成此操作。 引用JavaDoc :
“提供允許Java編程語言代理檢測運(yùn)行在JVM上的程序的服務(wù)?!?這正是我們所需要的!
概念證明
首先,我們需要一個(gè)示例應(yīng)用程序來演示該概念:
運(yùn)行此類時(shí),它僅輸出:A
應(yīng)用我們的“補(bǔ)丁”之后,我們將獲得以下輸出:已補(bǔ)丁
“修補(bǔ)的代碼如下所示:
public class A {public static String shout() {return "Apatched";} }進(jìn)一步,我們需要一個(gè)“代理”來管理所使用的類并修補(bǔ)正確的類:
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 {...} }不用擔(dān)心–我不會打擾您實(shí)現(xiàn)細(xì)節(jié),因?yàn)檫@只是PoC代碼,遠(yuǎn)非美觀,巧妙,快速而簡潔。 除了我因?yàn)榇藭r(shí)太懶而捕獲 Exception以外,我沒有過濾輸入,構(gòu)建深拷貝(防御性編程作為流行語),這實(shí)際上不應(yīng)該被視為生產(chǎn)代碼。
公共PatchingAgent()
初始化代理(在這種情況下,將獲取修補(bǔ)的A.class文件的字節(jié)。修補(bǔ)的類已編譯并存儲在我們可以訪問它的位置。
公共靜態(tài)無效premain(…)
在JVM初始化并準(zhǔn)備代理后,將調(diào)用此方法。
公共字節(jié)[]變換(…)
每當(dāng)定義了一個(gè)類時(shí)(例如,通過ClassLoader.defineClass (…)),該函數(shù)都會被調(diào)用,并且可以轉(zhuǎn)換已處理的類字節(jié) []( classfileBuffer )。 可以看出,我們將為stringchanger包中的A類執(zhí)行此操作。 您不受限制如何轉(zhuǎn)換類(只要它仍然是有效的Java 類 )–例如,您可以利用字節(jié)碼修改框架…–為使事情變得簡單,我們假設(shè)我們將舊字節(jié) []替換為修補(bǔ)類之一(通過將完整的修補(bǔ)A.class文件簡單地緩存到字節(jié) []中)。
這就是修補(bǔ)程序編碼部分的全部內(nèi)容……最后,我們必須使用一個(gè)特殊的manifest.mf文件構(gòu)建一個(gè)jar容器,該文件告訴JVM如何調(diào)用該代理。
清單版本:1.0
X-COMMENT:Main-Class將通過構(gòu)建自動添加
Premain-Class:stringchanger.PatchingAgent
構(gòu)建完這個(gè)jar之后,我們可以嘗試PoC應(yīng)用程序。 首先,我們將在沒有調(diào)用代理的必要JVM參數(shù)的情況下調(diào)用它:
跑:
一個(gè)
建立成功(總時(shí)間:0秒)
它的行為符合預(yù)期,并輸出未修補(bǔ)類定義的輸出。
現(xiàn)在,我們將使用神奇的JVM參數(shù)來嘗試調(diào)用代理-javaagent:StringChanger.jar:
跑:
初始化熱修補(bǔ)程序…
讀取修補(bǔ)文件。 修補(bǔ)…換弦器/ A 已分配 建立成功(總時(shí)間:0秒)
Voilà,該代碼已成功進(jìn)行了實(shí)時(shí)修補(bǔ)!
如我們所見,有可能動態(tài)地對JVM進(jìn)行熱補(bǔ)丁而不用觸摸交付的代碼。 必須做的是開發(fā)修補(bǔ)程序和修補(bǔ)的類。 目前,我還不了解性能評估數(shù)據(jù)。 因此,我不確定該解決方案對生產(chǎn)系統(tǒng)的實(shí)用性以及對應(yīng)用程序性能的影響程度。
明確地說,這不是一個(gè)優(yōu)雅的解決方案–至少它很臟! 最好的方法是修補(bǔ)根本原因,但只要沒有供應(yīng)商修復(fù)程序,開發(fā)人員就可以通過熱修補(bǔ)來防止其軟件運(yùn)行,而無需重寫使用易受攻擊類的每一行。
最后,我希望提出意見,改進(jìn)或只是更好的解決方案。 非常感謝Juraj Somorovsky與我在這個(gè)問題上共同努力。
參考: JCG合作伙伴 在運(yùn)行時(shí)修補(bǔ)Java ? Christopher Meyer討論了Java安全性和相關(guān)主題 。
翻譯自: https://www.javacodegeeks.com/2012/02/patching-java-at-runtime.html
java運(yùn)行庫一鍵修復(fù)
總結(jié)
以上是生活随笔為你收集整理的java运行库一键修复_在运行时修补Java的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS触摸事件全面解析
- 下一篇: Java调用容联云通讯短信验证码API接