View Javadoc
1   package com.jsql.view.swing.terminal;
2   
3   import com.jsql.util.LogLevelUtil;
4   import org.apache.commons.lang3.StringUtils;
5   import org.apache.logging.log4j.LogManager;
6   import org.apache.logging.log4j.Logger;
7   
8   import java.io.BufferedReader;
9   import java.io.DataOutputStream;
10  import java.io.IOException;
11  import java.io.InputStreamReader;
12  import java.net.Socket;
13  
14  public class ServerInputConnection {
15  
16      private static final Logger LOGGER = LogManager.getRootLogger();
17  
18      private final BufferedReader bufferedReader;
19      private final Socket clientSocket;
20      private final ServerInput serverInput;
21      private final ExploitReverseShell exploitReverseShell;
22      private boolean running = true;
23      private String command;
24  
25      public ServerInputConnection(ExploitReverseShell exploitReverseShell, Socket clientSocket, ServerInput serverInput) throws IOException {
26          this.clientSocket = clientSocket;
27          this.exploitReverseShell = exploitReverseShell;
28          this.serverInput = serverInput;
29          LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "Reverse established by {}", clientSocket);
30          LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Type 'exit' in reverse shell to close the connection");
31          this.bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
32      }
33  
34      public void run() throws IOException {
35          try (DataOutputStream dataOutputStream = new DataOutputStream(this.clientSocket.getOutputStream())) {
36              Thread readerThread = new Thread(() -> {
37                  try {
38                      this.handleSocketReading();
39                  } catch (IOException e) {
40                      LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Error reading from socket: {}", e.getMessage());
41                  } finally {
42                      this.closeResources();
43                  }
44              });
45              readerThread.start();
46  
47              while (this.running) {
48                  this.processAndSendCommand(dataOutputStream);
49              }
50  
51              try {
52                  readerThread.join(2000);
53              } catch (InterruptedException e) {
54                  Thread.currentThread().interrupt();
55                  LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Reader thread interrupted");
56              }
57          }
58      }
59  
60      private void processAndSendCommand(DataOutputStream dataOutputStream) throws IOException {
61          if (StringUtils.isNotEmpty(this.command)) {
62              var commandWithoutPrompt = this.command.replaceAll("[^$]*\\$\\s*", "");
63              this.command = null;
64              dataOutputStream.writeBytes(commandWithoutPrompt + "\n");
65          }
66      }
67  
68      private void handleSocketReading() throws IOException {
69          int length = 1024;
70          char[] buffer = new char[length];
71          int charsRead;
72          while (this.running) {
73              charsRead = this.bufferedReader.read(buffer, 0, length);
74              if (charsRead != -1) {
75                  String result = new String(buffer, 0, charsRead);  // discard unused chars from buffer
76                  this.exploitReverseShell.append(result.matches("\\$$") ? result +" " : result);  // space after internal prompt
77                  this.exploitReverseShell.reset(false);
78              } else {
79                  break;
80              }
81          }
82      }
83  
84      private void closeResources() {
85          try {
86              LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Reverse connection closed");
87              this.running = false;
88              this.serverInput.close();
89          } catch (IOException e) {
90              LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Error closing resources: {}", e.getMessage());
91          }
92      }
93  
94      public void setCommand(String command) {
95          this.command = command;
96      }
97  }