package org.test.remotecmd;
public class JavaClassExecuter {
public static String execute(byte[] classByte) {
HackSystem.clearBuffer();
ClassModifier cm = new ClassModifier(classByte);
byte[] modiBytes = cm.modifyUTF8Constant("java/lang/System",
"org/test/remotecmd/HackSystem");
HotSwapClassloader loader = new HotSwapClassloader();
Class<?> clazz = loader.loadByte(modiBytes);
try {
Method method = clazz.getMethod("main",
new Class[] { String.class });
method.invoke(null, (Object[]) new String[] { null });
} catch (Throwable e) {
e.printStackTrace(HackSystem.out);
}
return HackSystem.getBufferString();
}
}
public class HotSwapClassloader extends ClassLoader {
public HotSwapClassloader() {
super(HotSwapClassloader.class.getClassLoader());
}
public Class<?> loadByte(byte[] classByte) {
return defineClass(null, classByte, 0, classByte.length);
}
}
public class HackSystem {
public final static InputStream in = System.in;
private static ByteArrayOutputStream buffer = new ByteArrayOutputStream();
public final static PrintStream out = new PrintStream(buffer);
public final static PrintStream err = out;
public static String getBufferString() {
return buffer.toString();
}
public static void clearBuffer() {
buffer.reset();
}
public static void setSecurityManager(final SecurityManager s) {
System.setSecurityManager(s);
}
public static SecurityManager getSecurityManager() {
return System.getSecurityManager();
}
public static long currentTimeMillis() {
return System.currentTimeMillis();
}
public static void arraycopy(Object src, int srcPos, Object dest,
int destPos, int len) {
System.arraycopy(src, srcPos, dest, destPos, len);
}
public static int indentityHashCode(Object x) {
return System.identityHashCode(x);
}
// 下面所有的方法都与java.lang.System的名称一样,因版面原因,省略了其他方法
}
public class ByteUtils {
public static int bytes2Int(byte[] b, int start, int len) {
int sum = 0;
int end = start + len;
for (int i = start; i < end; i++) {
int n = ((int) b[i]) & 0xff;
n <<= (--len) * 8;
sum = n + sum;
}
return sum;
}
public static byte[] int2Bytes(int value, int len) {
byte[] b = new byte[len];
for (int i = 0; i < len; i++) {
b[len - i - 1] = (byte) ((value >> 8 * i) & 0xff);
}
return b;
}
public static String bytes2String(byte[] b, int start, int len) {
return new String(b, start, len);
}
public static byte[] string2Bytes(String str) {
return str.getBytes();
}
public static byte[] bytesReplace(byte[] origBytes, int offset, int len,
byte[] replaceBytes) {
byte[] newBytes = new byte[origBytes.length
+ (replaceBytes.length - len)];
System.arraycopy(origBytes, 0, newBytes, 0, offset);
System.arraycopy(replaceBytes, 0, newBytes, offset, replaceBytes.length);
System.arraycopy(origBytes, offset + len, newBytes, offset
+ replaceBytes.length, origBytes.length - offset - len);
return newBytes;
}
}
public class ClassModifier {
/**
* Class文件中常量池的起始偏移
*/
private static final int CONSTANT_POOL_INDEX = 8;
/**
* CONSTANT_Utf8_info常量的tag标志
*/
private static final int CONSTANT_Utf8_info = 1;
/**
* 常量池中11种常量所占的长度,CONSTANT_Utf8_info型常量除外,因为它不是定长的
*/
private static final int[] CONSTANT_ITEM_LEN = { -1, -1, 5, -1, 5, 9, 9, 3,
3, 5, 5, 5, 5 };
private static final int u1 = 1;
private static final int u2 = 2;
private byte[] classByte;
public ClassModifier(byte[] classByte) {
this.classByte = classByte;
}
public byte[] modifyUTF8Constant(String oldStr, String newStr) {
int cpc = getConstantPoolCount();
int offset = CONSTANT_POOL_INDEX + u2;
for (int i = 0; i < cpc; i++) {
int tag = ByteUtils.bytes2Int(classByte, offset, u1);
if (tag == CONSTANT_Utf8_info) {
int len = ByteUtils.bytes2Int(classByte, offset + u1, u2);
offset += (u1 + u2);
String str = ByteUtils.bytes2String(classByte, offset, len);
if (str.equalsIgnoreCase(oldStr)) {
byte[] strBytes = ByteUtils.string2Bytes(newStr);
byte[] strLen = ByteUtils.int2Bytes(newStr.length(), u2);
classByte = ByteUtils.bytesReplace(classByte, offset - u2,
u2, strLen);
classByte = ByteUtils.bytesReplace(classByte, offset, len,
strBytes);
return classByte;
} else {
offset += len;
}
} else {
offset += CONSTANT_ITEM_LEN[tag];
}
}
return classByte;
}
public int getConstantPoolCount() {
return ByteUtils.bytes2Int(classByte, CONSTANT_POOL_INDEX, u2);
}
}
Remote CMD to Java App
最新推荐文章于 2023-12-07 11:43:39 发布