BuringStraw

BuringStraw

Do not move the jar file, modify the Java class through a Java agent.

During the offline AWD competition in Liaoning Province, there was a Java question:

@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();
}

Unfortunately, only three teams were able to solve it. We ranked fourth because we didn't know how to fix it. Luckily, we had jadx-gui on Kali, but why can we only view it and not modify it?

After some research, I discovered Java Agent, which can achieve a similar effect to hooking (although it doesn't seem as good as Xposed). However, there are many pitfalls and environmental issues, so I decided to document the process.

First, the least important part of the code was referenced from here, with some modifications for precise searching of overloaded functions (you can also refer to this link for an introduction to 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});
                // Here, the java.util.Date.convertToAbbr() method is modified by adding a print operation before the return statement
                String methodBody = "{return \"stupid!\";}";
                System.out.println("Setting body!");
                cmd.setBody(methodBody);

                // Return the bytecode and detach the CtClass object
                byte[] byteCode = clazz.toBytecode();
                // Detach means removing the Date object that was previously loaded by Javassist from memory. If it is not found in memory next time, Javassist will load it again.
                clazz.detach();
                System.out.println("returning!");
                return byteCode;
            } catch (IOException | CannotCompileException | NotFoundException e) {
                System.out.println("Error!");
                System.out.println(e);
                return null;
            }
        }
    }
}

Pitfalls:

Download javassist.jar.

He used Maven to modify the manifest, but I couldn't find a way to include dependencies in the package, so I switched to Ant.

I used NetBeans as my IDE. You can directly right-click on Libraries and add the jar.

Refer to this link for modifying the manifest: https://www.javaxt.com/wiki/Tutorials/Netbeans/How_to_Add_Version_Information_to_a_Jar_File_with_Netbeans

However, this part is incorrect:

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

Instead, you should change manifest.file=manifest.mf in project.properties to manifest.file=MANIFEST.MF.

In addition to Premain-Class and Agent-Class, two more lines need to be added to the manifest (remember to remove the unnecessary properties):

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

Although Ant didn't include the dependencies in the package, it created a lib directory and added the classpath attribute to the manifest, so it can still run.

The command to start is java -javaagent:'/home/zfn/NetBeansProjects/agent2/dist/agent2.jar' -jar awd.jar

Good.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.