BuringStraw

BuringStraw

不動jar文件,通過java agent來修改java類

遼寧省賽線下 awd,出了那麼一道 java 題:

@PostMapping({"/cmd"})
@ResponseBody
public String cmd(@RequestParam String command) throws Exception {
    Base64.getDecoder();
    StringBuffer sb = new StringBuffer("");
    String[] c = {"/bin/bash", "-c", command};
    Process p = Runtime.getRuntime().exec(c);
    CopyInputStream(p.getInputStream(), sb);
    CopyInputStream(p.getErrorStream(), sb);
    return sb.toString();
}

遺憾的是:只有 3 個隊伍會修。而我們正因為不會修,屈居第四(還好 kali 上有個 jadx-gui,但是為什麼 jadx-gui 只能看不能改啊!!)。

研究了一下,發現了 java agent 這個東西,可以弄出類似 hook 的效果(感覺不如。。xposed),但是感覺有很多坑,環境方面,所以記錄一下。

首先最不重要的代碼部分是從這裡參考的,加了點針對函數重載的精確搜索(關於 java agent 的介紹也可以看這裡):https://www.cnblogs.com/rickiyang/p/11368932.html

package agent2;

import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import javassist.*;

public class PreMainAgent {

    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("agentArgs : " + agentArgs);
        inst.addTransformer(new DefineTransformer(), true);
    }

    static class DefineTransformer implements ClassFileTransformer {

        @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
            if (!"com/example/ezjava/controller/EvilController".equals(className)) {
                return null;
            }
            System.out.println("premain load Class:" + className);
            try {
                System.out.println("trying!");
                final ClassPool classPool = ClassPool.getDefault();
                final CtClass clazz = classPool.get("com.example.ezjava.controller.EvilController");
                final CtClass str_class = classPool.get("java.lang.String");
                System.out.println(str_class);
                CtMethod cmd = clazz.getDeclaredMethod("cmd", new CtClass[]{str_class});
                //這裡對 java.util.Date.convertToAbbr() 方法進行了改寫,在 return之前增加了一个 打印操作
                String methodBody = "{return \"stupid!\";}";
                System.out.println("Setting body!");
                cmd.setBody(methodBody);

                // 返回字節碼,並且detachCtClass對象
                byte[] byteCode = clazz.toBytecode();
                //detach的意思是將內存中曾經被javassist加載過的Date對象移除,如果下次有需要在內存中找不到會重新走javassist加載
                clazz.detach();
                System.out.println("returning!");
                return byteCode;
            } catch (IOException | CannotCompileException | NotFoundException e) {
                System.out.println("Error!");
                System.out.println(e);
                return null;
            }
        }
    }
}

坑部分:

下載javassist.jar

然後他用的是 maven 來改 manifest,但是我一直沒有找到把依賴打進包里的辦法,就改用 ant 了。

IDE 我用的 netbeans。可以直接在 Libraries 上右鍵添加 jar。

修改 manifest 參考這個鏈接:https://www.javaxt.com/wiki/Tutorials/Netbeans/How_to_Add_Version_Information_to_a_Jar_File_with_Netbeans

但是,其中的這部分不太對

First, you must update your Netbeans "project.properties" file found in the "nbproject" directory. Add the following line to the file:

manifest.file=manifest.mf

應該是把project.properties里的manifest.file=manifest.mf改成manifest.file=MANIFEST.MF

manifest 里除了Premain-ClassAgent-Class以外還要再加兩行(記得把他寫的亂七八糟的屬性都刪掉):

<attribute name="Can-Redefine-Classes" value="true"/>
<attribute name="Can-Retransform-Classes" value="true"/>

雖然 ant 也沒把依賴打進包里,但他創建了個 lib 目錄並在 manifest 里寫入了 classpath 的屬性,所以可以跑起來。

然後啟動命令是java -javaagent:'/home/zfn/NetBeansProjects/agent2/dist/agent2.jar' -jar awd.jar

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。