BuringStraw

BuringStraw

Do not move the jar file, modify the Java class through the 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 (thankfully, we had jadx-gui on Kali, but why can we only view it and not modify it?!).

After some research, I found out about this thing called Java Agent, which can achieve a similar effect to hooking (although it doesn't seem as good as Xposed). However, there seem to be many pitfalls and environmental issues, so I decided to document it.

First, the least important part of the code was referenced from here, with some modifications for precise searching of overloaded functions (you can also find an introduction to Java Agent here): 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 reload it.
                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.

Then, he used Maven to modify the manifest, but I couldn't find a way to include the 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.

To modify the manifest, refer to this link: https://www.javaxt.com/wiki/Tutorials/Netbeans/How_to_Add_Version_Information_to_a_Jar_File_with_Netbeans

However, this part is not quite right:

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 delete all the messy properties he wrote):

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

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

The startup command 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.