應用程序利用url與遠程通訊的全部類的超類java
jdk1.8中支持的協議包括以上這些,gopher在jdk8中取消了。api
java中默認對(http|https)作了一些事情,好比:
默認啓用了透明NTLM認證
默認跟隨跳轉
httpURLconnection可能jdk7低版本可能在win機器上致使ntlmrelay攻擊https://zhuanlan.zhihu.com/p/64889695數組
使用URLconnection的子類可能只適合http|https,對ssrf也有必定的限制app
HttpURLConnection
HttpClient
Request
okhttp
Java中
Instrumentation(Java Agent API)
和JVMTI(JVM Tool Interface)
功能,容許JVM
在加載某個class文件
以前對其字節碼進行修改,同時也支持對已加載的class(類字節碼)
進行從新加載(Retransform
),rsap和iast都基於這個功能實現動態修改java字節碼來插入檢測代碼jvm
java agent的兩種運行模式:
函數
1.直接在命令添加運行參數 -javaagent(Instrumentation API實現方式)或-agentpath/ -agentlib(JVMTI的實現方式)學習
2.attach方式,直接將agent加到對應的java進程測試
helloWorld.javaurl
public class helloWorld { public static void main(String[] args){ System.out.println("hello world"); } }
好比就上面一段簡單的代碼,編譯後取修改器字節碼讓其輸出hello world,想一下hello world在編譯後存儲在class文件中,那麼此時已經編譯成字節碼,要輸出的字符串確定也是以字節碼存儲着,那麼此時能夠直接替換獲取編譯好的字節碼進行修改spa
testagent.java
import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; import java.security.ProtectionDomain; import java.util.Arrays; public class testagent { private static byte[] relaceBytes(String classname,byte[] classbuffer) { String bufferStr = Arrays.toString(classbuffer).replace("[","").replace("]",""); System.out.println("classname:"+classname); System.out.println("byes:"+ bufferStr); byte[] findBytes = "hello world".getBytes(); String findStr = Arrays.toString(findBytes).replace("[","").replace("]",""); System.out.println("world"+findStr); byte[] replaceBytes = "hello agent".getBytes(); String replaceStr = Arrays.toString(replaceBytes).replace("[","").replace("]",""); System.out.println("agent"+replaceStr); bufferStr = bufferStr.replace(findStr,replaceStr); System.out.println(bufferStr); String[] bytearr = bufferStr.split("\\s*,\\s*"); byte[] bytes = new byte[bytearr.length]; for(int i=0;i < bytearr.length;i++) { bytes[i] = Byte.parseByte((bytearr[i])); } System.out.println("new byte :"+Arrays.toString(bytes)); return bytes; } public static void premain(String args,final Instrumentation inst){ inst.addTransformer(new ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { className = className.replace("/","."); if(className.equals("helloWorld")){ return relaceBytes(className,classfileBuffer); } return classfileBuffer; } },true); } }
這裏的classfileBuffer就是要修改字節碼的class文件,這裏替換字節的函數能夠自定義,只要返回一個字節數組便可
測試的時候testagent.java編譯後要包含MANIFEST.MF,聲明premain-class
而後使用jar命令打包
jar -cvfm agent.jar MANIFEST.MF *.class
以後再到helloWorld.class的目錄運行agent便可
java -javaagent:agent.jar helloWorld
這裏通常修改字節碼用ASM庫
java提供的監測jvm程序的api,利用Instrumentation咱們能夠實現
1.動態添加Transformer(addTransformer),上面的例子就是
2.動態修改classpath(appendToBootstrapClassLoaderSearch、appendToSystemClassLoaderSearch)
3.動態獲取全部JVM已經加載的類(getAllLoadedClasses)
4.動態獲取某個類加載器已經實例化的全部類(getInitiatedClasses)
5.直接修改已加載的類的字節碼
6.動態設置JNI前綴(setNativeMethodPrefix)
7.重加載指定類字節碼(retransformClasses)
轉換類文件的代理接口,拿到Instrumentation後能夠調用addTransformer方法添加自定義的類文件轉換器,上面的例子實際上就自定義了
一個Transformer,此時transform(類名,類加載器,類字節碼等)方法就包含了咱們要修改的目標類的一些信息,修改完再返回字節碼,jvm對字節碼進行驗證後將決定是否加載。
這裏簡單記錄一下,後面有機會再深刻學習。