This commit is contained in:
novice.li 2023-11-25 14:55:08 +08:00
commit e060f1c114
29 changed files with 740 additions and 0 deletions

63
jetbra-agent/pom.xml Normal file
View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>win.novice</groupId>
<artifactId>jetbra</artifactId>
<version>0.0.1</version>
</parent>
<groupId>win.novice.li</groupId>
<artifactId>jetbra-agent</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.14.8</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>1.14.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifestEntries>
<Premain-Class>win.novice.li.AgentMain</Premain-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,50 @@
package win.novice.li;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatchers;
import java.lang.instrument.Instrumentation;
import java.util.Set;
public class AgentMain {
public static void premain(String agentArgs, Instrumentation inst) throws Exception {
printLogo();
AgentBuilder agentBuilder = newAgentBuilder();
agentBuilder.type(ElementMatchers.named("java.security.cert.PKIXBuilderParameters"))
.transform((builder, typeDescription, classLoader, module, protectionDomain) -> builder
.visit(Advice.to(PKIXBuilderParameters.class)
.on(ElementMatchers.isConstructor().and(ElementMatchers.takesArgument(0, Set.class)))))
.asTerminalTransformation()
.type(ElementMatchers.named("sun.net.www.http.HttpClient"))
.transform((builder, typeDescription, classLoader, module, protectionDomain) -> builder
.visit(Advice.to(HttpClientAdvice.class)
.on(ElementMatchers.named("openServer"))))
.asTerminalTransformation()
.type(ElementMatchers.named("java.lang.System"))
.transform((builder, typeDescription, classLoader, module, protectionDomain) -> builder
.visit(Advice.to(SystemAdvice.class)
.on(ElementMatchers.named("getProperty"))))
.asTerminalTransformation()
.installOn(inst);
agentBuilder.installOn(inst);
}
static AgentBuilder newAgentBuilder() {
return new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
.with(AgentBuilder.TypeStrategy.Default.REDEFINE)
.ignore(ElementMatchers.nameStartsWith("net.bytebuddy."));
}
static void printLogo() {
System.out.println(" _ _ _ \n" +
" | | ___| |_| |__ _ __ __ _ \n" +
" _ | |/ _ \\ __| '_ \\| '__/ _` |\n" +
"| |_| | __/ |_| |_) | | | (_| |\n" +
" \\___/ \\___|\\__|_.__/|_| \\__,_|");
}
}

View file

@ -0,0 +1,14 @@
package win.novice.li;
import net.bytebuddy.asm.Advice;
import java.net.SocketTimeoutException;
public class HttpClientAdvice {
@Advice.OnMethodExit
public static void intercept(@Advice.This Object x) throws Exception {
if (x.toString().contains("validateKey.action")){
throw new SocketTimeoutException();
}
}
}

View file

@ -0,0 +1,24 @@
package win.novice.li;
import net.bytebuddy.asm.Advice;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.cert.TrustAnchor;
import java.util.HashSet;
import java.util.Set;
public class PKIXBuilderParameters {
@Advice.OnMethodEnter
@SuppressWarnings("unchecked")
public static void intercept(@Advice.Argument(value = 0, readOnly = false) Set<TrustAnchor> trustAnchors) throws Exception {
Class<?> clazz = Class.forName("win.novice.li.TrustAnchorHolder", true, ClassLoader.getSystemClassLoader());
Method method = clazz.getDeclaredMethod("loadTrustAnchors");
Set<TrustAnchor> loadedTrustAnchors = (Set<TrustAnchor>)method.invoke(null);
HashSet<TrustAnchor> newTrustAnchors = new HashSet<>(trustAnchors);
newTrustAnchors.addAll(loadedTrustAnchors);
trustAnchors = newTrustAnchors;
}
}

View file

@ -0,0 +1,29 @@
package win.novice.li;
import net.bytebuddy.asm.Advice;
public class SystemAdvice {
// System.getProperty
@Advice.OnMethodExit
public static void intercept(@Advice.Argument(0) Object x, @Advice.Return(readOnly = false) String r) throws Exception {
if (x.toString().equals("jb.vmOptionsFile")) {
RuntimeException exception = new RuntimeException();
int nullCnt = 0;
boolean hasReflect = false;
for (StackTraceElement element : exception.getStackTrace()) {
if (element.getFileName() == null) {
nullCnt += 1;
continue;
}
if (element.getFileName().equals("Method.java")) {
hasReflect = true;
}
}
if (nullCnt >= 3 && hasReflect) {
r = null;
}
}
}
}

View file

@ -0,0 +1,66 @@
package win.novice.li;
import java.io.File;
import java.io.FileInputStream;
import java.net.URI;
import java.net.URL;
import java.nio.file.Paths;
import java.security.cert.CertificateFactory;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.HashSet;
import java.util.Set;
public class TrustAnchorHolder {
public static Set<TrustAnchor> TRUST_ANCHORS;
public static Set<TrustAnchor> loadTrustAnchors() throws Exception {
if (TRUST_ANCHORS != null) {
return TRUST_ANCHORS;
}
TRUST_ANCHORS = new HashSet<>();
String certDir;
if (System.getenv("JB_HOME") != null) {
certDir = System.getenv("JB_HOME");
} else {
URI jarURI = getJarURI();
if (jarURI == null) {
return TRUST_ANCHORS;
}
certDir = Paths.get(jarURI).getParent().resolve("trust-crt").toString();
}
System.out.println("load crt from " + certDir);
File dir = new File(certDir);
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
for (File item : files) {
if (item.getName().endsWith(".crt")) {
X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(new FileInputStream(item));
TRUST_ANCHORS.add(new TrustAnchor(cert, null));
}
}
}
}
System.out.println("loaded " + TRUST_ANCHORS.size() + " crts");
return TRUST_ANCHORS;
}
public static URI getJarURI() throws Exception {
URL url = TrustAnchorHolder.class.getProtectionDomain().getCodeSource().getLocation();
if (null != url) {
return url.toURI();
}
String resourcePath = "/jarLocation.txt";
url = TrustAnchorHolder.class.getResource(resourcePath);
if (null == url) {
return null;
}
String path = url.getPath();
path = path.substring(0, path.length() - resourcePath.length() - 1);
return new URI(path);
}
}