1. new feature: global transformer

2. new feature: native method transform
This commit is contained in:
pengzhile 2022-01-14 19:53:31 +08:00
parent 9ae61fbeff
commit be4d4fa72f
7 changed files with 54 additions and 5 deletions

View File

@ -1,4 +1,4 @@
# ja-netfilter v2.1.0
# ja-netfilter v2.1.1
### A javaagent framework
@ -10,8 +10,8 @@
* some apps support the `JVM Options file`, you can add as a line of the `JVM Options file`.
* **WARNING: DO NOT put some unnecessary whitespace characters!**
* edit your plugin config files: `${lower plugin name}.conf` file in the `conf` dir where `ja-netfilter.jar` is located.
* the `conf` and `plugins` directory can be specified through **the javaagent args**.
* edit your plugin config files: `${lower plugin name}.conf` file in the `config` dir where `ja-netfilter.jar` is located.
* the `config` and `plugins` directory can be specified through **the javaagent args**.
* eg: `-javaagent:/path/to/ja-netfilter.jar=appName`, your config and plugins directories will be `config-appname` and `plugins-appname`.
* if no javaagent args, they default to `config` and `plugins`.
* this mechanism will avoid extraneous and bloated `config` and `plugins`.

View File

@ -6,7 +6,7 @@
<groupId>com.ja-netfilter</groupId>
<artifactId>ja-netfilter</artifactId>
<version>2.1.0</version>
<version>2.1.1</version>
<name>ja-netfilter</name>
<description>A javaagent framework</description>
@ -85,6 +85,7 @@
<Main-Class>com.janetfilter.core.Launcher</Main-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
<Can-Set-Native-Method-Prefix>true</Can-Set-Native-Method-Prefix>
</manifestEntries>
</archive>
<descriptorRefs>

View File

@ -11,9 +11,15 @@ import java.util.*;
public final class Dispatcher implements ClassFileTransformer {
private final Set<String> classSet = new TreeSet<>();
private final Map<String, List<MyTransformer>> transformerMap = new HashMap<>();
private final List<MyTransformer> globalTransformers = new ArrayList<>();
public synchronized void addTransformer(MyTransformer transformer) {
String className = transformer.getHookClassName();
if (null == className) {
globalTransformers.add(transformer);
return;
}
classSet.add(className.replace('/', '.'));
List<MyTransformer> transformers = transformerMap.computeIfAbsent(className, k -> new ArrayList<>());
@ -56,6 +62,10 @@ public final class Dispatcher implements ClassFileTransformer {
int order = 0;
try {
for (MyTransformer transformer : globalTransformers) {
classFileBuffer = transformer.transform(className, classFileBuffer, order++);
}
for (MyTransformer transformer : transformers) {
classFileBuffer = transformer.transform(className, classFileBuffer, order++);
}

View File

@ -9,6 +9,7 @@ public final class Environment {
private final File agentFile;
private final File configDir;
private final File pluginsDir;
private final String nativePrefix;
public Environment(File agentFile) {
this(agentFile, null);
@ -26,6 +27,8 @@ public final class Environment {
configDir = new File(baseDir, "config-" + app);
pluginsDir = new File(baseDir, "plugins-" + app);
}
nativePrefix = StringUtils.randomMethodName(15) + "_";
}
public File getBaseDir() {
@ -44,6 +47,10 @@ public final class Environment {
return pluginsDir;
}
public String getNativePrefix() {
return nativePrefix;
}
@Override
public String toString() {
return "Environment: {" +
@ -51,6 +58,7 @@ public final class Environment {
", \n\tagentFile=" + agentFile +
", \n\tconfigDir=" + configDir +
", \n\tpluginsDir=" + pluginsDir +
", \n\tnativePrefix=" + nativePrefix +
"\n}";
}
}

View File

@ -14,6 +14,7 @@ public class Initializer {
new PluginManager(inst, dispatcher, environment).loadPlugins();
inst.addTransformer(dispatcher, true);
inst.setNativeMethodPrefix(dispatcher, environment.getNativePrefix());
Set<String> classSet = dispatcher.getHookClassNames();
for (Class<?> c : inst.getAllLoadedClasses()) {

View File

@ -9,17 +9,25 @@ import java.net.URL;
import java.util.jar.JarFile;
public class Launcher {
private static final String VERSION = "v2.1.0";
private static final String VERSION = "v2.1.1";
private static boolean loaded = false;
public static void main(String[] args) {
printUsage();
}
public static void premain(String args, Instrumentation inst) {
if (loaded) {
DebugInfo.output("WARN: You have multiple `ja-netfilter` as -javaagent.");
return;
}
printUsage();
URI jarURI;
try {
loaded = true;
jarURI = getJarURI();
} catch (Throwable e) {
DebugInfo.output("ERROR: Can not locate ja-netfilter jar file.", e);

View File

@ -1,7 +1,28 @@
package com.janetfilter.core.utils;
import java.util.Random;
public class StringUtils {
private static final String METHOD_NAME_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$_0123456789";
public static boolean isEmpty(String str) {
return null == str || str.isEmpty();
}
public static String randomMethodName(int length) {
int i = 0;
if (i == length) {
return "";
}
char[] buffer = new char[length];
Random rnd = new Random();
buffer[i++] = METHOD_NAME_CHARS.charAt(rnd.nextInt(54));
while (i < length) {
buffer[i++] = METHOD_NAME_CHARS.charAt(rnd.nextInt(64));
}
return new String(buffer);
}
}