From 44da75f2c7a60b66a5c886d9f2fe23255bee8b60 Mon Sep 17 00:00:00 2001
From: Tim W <timrlw@gmail.com>
Date: Fri, 3 Jul 2020 13:49:51 +0800
Subject: [PATCH] rebase fix java stderr output in cmd_exec

---
 .../com/metasploit/meterpreter/Channel.java   | 19 +++++++---
 .../meterpreter/ProcessChannel.java           | 37 ++++++++++---------
 2 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Channel.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Channel.java
index f9113ae1..8c831773 100644
--- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Channel.java
+++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Channel.java
@@ -32,16 +32,21 @@ public class Channel {
         this.id = meterpreter.registerChannel(this);
         this.in = in;
         this.out = out;
-        new InteractThread(in).start();
+        if (in != null) {
+            new InteractThread(in, true).start();
+        }
     }
 
     /**
      * Close this channel and deregister it from the meterpreter.
      */
     public synchronized void close() throws IOException {
-        in.close();
-        if (out != null)
+        if (in != null) {
+            in.close();
+        }
+        if (out != null) {
             out.close();
+        }
         meterpreter.channelClosed(id);
         active = false;
         closed = true;
@@ -160,9 +165,11 @@ public class Channel {
      */
     protected class InteractThread extends Thread {
         private final InputStream stream;
+        private final boolean handleClose;
 
-        public InteractThread(InputStream stream) {
+        public InteractThread(InputStream stream, boolean handleClose) {
             this.stream = stream;
+            this.handleClose = handleClose;
         }
 
         public void run() {
@@ -176,7 +183,9 @@ public class Channel {
                     System.arraycopy(buffer, 0, data, 0, len);
                     handleInteract(data);
                 }
-                handleInteract(null);
+                if (handleClose) {
+                    handleInteract(null);
+                }
             } catch (Throwable t) {
                 t.printStackTrace(meterpreter.getErrorStream());
             }
diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/ProcessChannel.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/ProcessChannel.java
index 20f14764..2a288268 100644
--- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/ProcessChannel.java
+++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/ProcessChannel.java
@@ -12,6 +12,7 @@ import java.io.PrintStream;
 public class ProcessChannel extends Channel {
 
     private final Process process;
+    private final InputStream inputStream;
     private final InputStream err;
 
     /**
@@ -21,10 +22,13 @@ public class ProcessChannel extends Channel {
      * @param process     Process of the channel
      */
     public ProcessChannel(Meterpreter meterpreter, Process process) {
-        super(meterpreter, process.getInputStream(), process.getOutputStream());
-        this.process = process;
+        super(meterpreter, null, process.getOutputStream());
+        this.inputStream = process.getInputStream();
         this.err = process.getErrorStream();
-        new StderrThread(err, meterpreter.getErrorStream()).start();
+        this.process = process;
+        Thread stdinThread = new InteractThread(this.inputStream, false);
+        Thread stderrThread = new InteractThread(this.err, false);
+        new CloseThread(stdinThread, stderrThread).start();
     }
 
     /**
@@ -48,30 +52,27 @@ public class ProcessChannel extends Channel {
 
     public void close() throws IOException {
         process.destroy();
+        inputStream.close();
         err.close();
         super.close();
     }
 
-    class StderrThread extends Thread {
-        private final InputStream inputStream;
-        private final PrintStream outputStream;
+    class CloseThread extends Thread {
+        private final Thread stdinThread;
+        private final Thread stderrThread;
 
-        public StderrThread(InputStream inputStream, PrintStream outputStream) {
-            this.inputStream = inputStream;
-            this.outputStream = outputStream;
+        public CloseThread(Thread stdinThread, Thread stderrThread) {
+            this.stdinThread = stdinThread;
+            this.stderrThread = stderrThread;
         }
 
         public void run() {
             try {
-                byte[] buffer = new byte[1024*1024];
-                int len;
-                while ((len = inputStream.read(buffer)) != -1) {
-                    if (len == 0)
-                        continue;
-                    byte[] data = new byte[len];
-                    System.arraycopy(buffer, 0, data, 0, len);
-                    handleInteract(data);
-                }
+                stdinThread.start();
+                stderrThread.start();
+                stdinThread.join();
+                stderrThread.join();
+                handleInteract(null);
             } catch (Throwable t) {
                 t.printStackTrace(this.outputStream);
             }