Initial implementation of ssl-wrapped socket

This commit is contained in:
Caleb Stewart 2021-06-13 22:09:41 -04:00
parent 2691f77c76
commit 2c9a1dbc71
5 changed files with 44 additions and 7 deletions

View File

@ -581,7 +581,10 @@ def create(protocol: Optional[str] = None, **kwargs) -> Channel:
or kwargs["host"] == "0.0.0.0"
or kwargs["host"] is None
):
protocols.append("bind")
if "certfile" in kwargs or "keyfile" in kwargs:
protocols.append("ssl-bind")
else:
protocols.append("bind")
else:
protocols.append("connect")
else:
@ -600,8 +603,10 @@ from pwncat.channel.ssh import Ssh # noqa: E402
from pwncat.channel.bind import Bind # noqa: E402
from pwncat.channel.socket import Socket # noqa: E402
from pwncat.channel.connect import Connect # noqa: E402
from pwncat.channel.ssl_bind import SSLBind # noqa: E402
register("socket", Socket)
register("bind", Bind)
register("connect", Connect)
register("ssh", Ssh)
register("ssl-bind", SSLBind)

View File

@ -51,6 +51,8 @@ class Bind(Socket):
self._socket_connected(client)
except KeyboardInterrupt:
raise ChannelError(self, "listener aborted")
except socket.error as exc:
raise ChannelError(self, str(exc))
finally:
self.server.close()

View File

@ -15,6 +15,7 @@ utilize this class to instantiate a session via an established socket.
manager.interactive()
"""
import os
import ssl
import errno
import fcntl
import socket
@ -91,11 +92,14 @@ class Socket(Channel):
while written < len(data):
try:
written += self.client.send(data[written:])
except BlockingIOError:
except (BlockingIOError, ssl.SSLWantWriteError, ssl.SSLWantReadError):
pass
except BrokenPipeError as exc:
self._connected = False
raise ChannelClosed(self) from exc
except (ssl.SSLEOFError, ssl.SSLSyscallError, ssl.SSLZeroReturnError):
self._connected = False
raise ChannelClosed(self) from exc
return len(data)
@ -124,6 +128,11 @@ class Socket(Channel):
try:
data = data + self.client.recv(count)
return data
except ssl.SSLWantReadError:
return data
except (ssl.SSLEOFError, ssl.SSLSyscallError, ssl.SSLZeroReturnError):
self._connected = False
raise ChannelClosed(self) from exc
except socket.error as exc:
if exc.args[0] == errno.EAGAIN or exc.args[0] == errno.EWOULDBLOCK:
return data

View File

@ -0,0 +1,22 @@
#!/usr/bin/env python3
import ssl
from pwncat.channel import ChannelError
from pwncat.channel.bind import Bind
class SSLBind(Bind):
def __init__(self, certfile: str = None, keyfile: str = None, **kwargs):
super().__init__(**kwargs)
self.context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
self.context.load_cert_chain(certfile, keyfile)
self.server = self.context.wrap_socket(self.server)
def connect(self):
try:
super().connect()
except ssl.SSLError as exc:
raise ChannelError(self, str(exc))

View File

@ -19,12 +19,11 @@ with pwncat.manager.Manager("data/pwncatrc") as manager:
# session = manager.create_session("windows", host="192.168.56.10", port=4444)
# session = manager.create_session("windows", host="192.168.122.11", port=4444)
# session = manager.create_session("linux", host="pwncat-ubuntu", port=4444)
session = manager.create_session("linux", host="127.0.0.1", port=4444)
# session = manager.create_session("linux", host="127.0.0.1", port=4444)
session = manager.create_session(
"linux", certfile="/tmp/cert.pem", keyfile="/tmp/cert.pem", port=4444
)
# session.platform.powershell("amsiutils")
with open("/tmp/random", "rb") as source:
with session.platform.open("/tmp/random", "wb") as destination:
shutil.copyfileobj(source, destination)
manager.interactive()