javaweb-codereview 學習記錄-5

1.關於URLConnection

 應用程序利用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

2.關於java agent

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庫

Instrumentation

java提供的監測jvm程序的api,利用Instrumentation咱們能夠實現

1.動態添加Transformer(addTransformer),上面的例子就是

2.動態修改classpath(appendToBootstrapClassLoaderSearch、appendToSystemClassLoaderSearch)

3.動態獲取全部JVM已經加載的類(getAllLoadedClasses)

4.動態獲取某個類加載器已經實例化的全部類(getInitiatedClasses)

5.直接修改已加載的類的字節碼

6.動態設置JNI前綴(setNativeMethodPrefix)

7.重加載指定類字節碼(retransformClasses)

ClassFileTransformer

轉換類文件的代理接口,拿到Instrumentation後能夠調用addTransformer方法添加自定義的類文件轉換器,上面的例子實際上就自定義了

一個Transformer,此時transform(類名,類加載器,類字節碼等)方法就包含了咱們要修改的目標類的一些信息,修改完再返回字節碼,jvm對字節碼進行驗證後將決定是否加載。

這裏簡單記錄一下,後面有機會再深刻學習。

相關文章
相關標籤/搜索