BuringStraw

BuringStraw

不動のjarファイルを使用して、Javaクラスを変更するために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 つのチームだけでした。私たちは修正できなかったため、4 位に終わりました(幸いにも kali には jadx-gui がありますが、なぜ jadx-gui は見るだけで変更できないのでしょうか!)。

調査した結果、Java エージェントというものを見つけました。これはフックのような効果を持つことができます(xposed よりも効果がないように感じますが)。ただし、環境に関してはいくつかの落とし穴があるようなので、メモしておきます。

まず、最も重要でないコードの部分は、ここを参考にしています。関数のオーバーロードに対して精確な検索を追加しました(Java エージェントの紹介はこちらも参照できます):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);

                // バイトコードを返し、CtClassオブジェクトをdetachします
                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 を使用していますが、依存関係をパッケージに含める方法が見つからなかったため、ant を使用しました。

私は Netbeans を使用しています。Libraries で右クリックして jar を追加することができます。

マニフェストの変更は、次のリンクを参考にしてください: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.propertiesmanifest.file=manifest.mfmanifest.file=MANIFEST.MFに変更する必要があります。

マニフェストには、Premain-ClassAgent-Class以外にも 2 行追加する必要があります(彼が書いた乱雑な属性はすべて削除することを忘れないでください):

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

ant は依存関係をパッケージに含めていないため、実行できますが、manifest に classpath の属性を書き込むために lib ディレクトリを作成しました。

そして、起動コマンドはjava -javaagent:'/home/zfn/NetBeansProjects/agent2/dist/agent2.jar' -jar awd.jarです。

以上です。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。