Skip to content

Commit

Permalink
add start of hijacker
Browse files Browse the repository at this point in the history
  • Loading branch information
ElNiak committed Jan 3, 2024
1 parent bd4fafd commit 2969333
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 5 deletions.
88 changes: 88 additions & 0 deletions py-ssh3/http3/http3_hijacker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import asyncio
from aioquic.asyncio import QuicConnectionProtocol
from aioquic.asyncio.protocol import QuicStreamHandler
from aioquic.quic.events import StreamDataReceived, StreamReset, ConnectionTerminated
from aioquic.quic.connection import QuicConnection

class HTTPStreamer:
"""
Allows taking over a HTTP/3 stream. This is a simplified version that
assumes the stream is already established.
"""
def __init__(self, stream_reader, stream_writer):
self.stream_reader = stream_reader
self.stream_writer = stream_writer

async def read(self, size):
return await self.stream_reader.read(size)

async def write(self, data):
self.stream_writer.write(data)
await self.stream_writer.drain()

def close(self):
self.stream_writer.close()

class StreamCreator:
"""
This class represents an entity capable of creating QUIC streams.
"""
def __init__(self, protocol: QuicConnectionProtocol):
self.protocol = protocol

async def open_stream(self) -> HTTPStreamer:
reader, writer = await self.protocol._quic.create_stream()
return HTTPStreamer(reader, writer)

async def open_uni_stream(self) -> HTTPStreamer:
reader, writer = await self.protocol._quic.create_unidirectional_stream()
return HTTPStreamer(reader, writer)

def local_addr(self):
return self.protocol._quic._local_endpoint

def remote_addr(self):
return self.protocol._quic._peer_endpoint

def connection_state(self):
return self.protocol._quic._state

class Hijacker:
"""
Allows hijacking of the stream creating part of a QuicConnectionProtocol.
"""
def __init__(self, protocol: QuicConnectionProtocol):
self.protocol = protocol

def stream_creator(self) -> StreamCreator:
return StreamCreator(self.protocol)

class Body:
"""
The body of a HTTP Request or Response.
"""
def __init__(self, stream: HTTPStreamer):
self.stream = stream
self.was_hijacked = False

async def read(self, size) -> bytes:
return await self.stream.read(size)

def http_stream(self) -> HTTPStreamer:
self.was_hijacked = True
return self.stream

async def close(self):
self.stream.close()

# Example usage
# async def main():
# # Example usage - this will vary depending on how you establish your QUIC connection.
# # Replace with actual connection and protocol setup.
# protocol = QuicConnectionProtocol(QuicConnection(...))
# stream_creator = StreamCreator(protocol)
# http_stream = await stream_creator.open_stream()
# # Now you can read from or write to http_stream as needed.

# if __name__ == "__main__":
# asyncio.run(main())
3 changes: 2 additions & 1 deletion py-ssh3/http3/http3_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from aioquic.quic.logger import QuicFileLogger
from aioquic.tls import SessionTicket
import util.globals as glob

from http3.http3_hijacker import *
try:
import uvloop
except ImportError:
Expand Down Expand Up @@ -332,6 +332,7 @@ def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._handlers: Dict[int, Handler] = {}
self._http: Optional[HttpConnection] = None
self.hijacker = Hijacker(self)

def http_event_received(self, event: H3Event) -> None:
log.debug("HTTP event received: %s", event)
Expand Down
3 changes: 2 additions & 1 deletion py-ssh3/linux_server/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from ssh3.version import *
from starlette.responses import PlainTextResponse, Response
from aioquic.tls import *

from http3.http3_hijacker import *
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

Expand All @@ -29,6 +29,7 @@
class AuthHttpServerProtocol(HttpServerProtocol):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.hijacker = Hijacker(self)

def http_event_received(self, event: H3Event) -> None:
for header, value in event.headers:
Expand Down
3 changes: 2 additions & 1 deletion py-ssh3/server_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,8 @@ def handle_session_channel():
session_ticket_handler=glob.SESSION_TICKET_HANDLER,
)

ssh3Server = SSH3Server(30000,quic_server._create_protocol, 10, conversation_handler=handle_conv)

ssh3Server = SSH3Server(30000,quic_server._protocols, 10, conversation_handler=handle_conv)
ssh3Handler = ssh3Server.get_http_handler_func()

glob.ENABLE_PASSWORD_LOGIN = args.enablePasswordLogin
Expand Down
9 changes: 7 additions & 2 deletions py-ssh3/ssh3/ssh3_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from ssh3.channel import *
from starlette.responses import PlainTextResponse, Response
from aioquic.quic.connection import NetworkAddress, QuicConnection

log = logging.getLogger(__name__)

class SSH3Server:
Expand All @@ -26,7 +25,7 @@ def __init__(self, max_packet_size,
self.conversation_handler = conversation_handler
self.lock = asyncio.Lock()
log.debug("SSH3Server initialized")
self.h3_server._stream_handler = self.stream_hijacker
#self.h3_server._stream_handler = self.stream_hijacker

def stream_hijacker(frame_type, stream_id, data, end_stream):
# Your stream hijacking logic
Expand Down Expand Up @@ -167,6 +166,12 @@ async def handler(authenticated_username, new_conv, request):
log.debug(f"request.url: {request.url}")
if request.method == "CONNECT" and request.headers.get("protocol", None) == "ssh3": # request.url.scheme == "ssh3": TODO
# Assuming that request_handler can act as a hijacker

protocols_keys = list(glob.QUIC_SERVER._protocols.keys())
prot = glob.QUIC_SERVER._protocols[protocols_keys[-1]]

hijacker = prot.hijacker #self.h3_server.hijacker
stream_creator = hijacker.stream_creator()
# stream_creator =QuicConnection(
# configuration=glob.CONFIGURATION,
# session_ticket_handler=glob.SESSION_TICKET_HANDLER
Expand Down

0 comments on commit 2969333

Please sign in to comment.