Compare commits

...
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

9 Commits

  1. 4
      python/Lab10/requirements.txt
  2. 0
      python/Lab10/sniffer/__init__.py
  3. 35
      python/Lab10/sniffer/__main__.py
  4. 27
      python/Lab10/sniffer/arp.py
  5. 39
      python/Lab10/sniffer/ethernet.py
  6. 2
      python/Lab10/sniffer/ip/__init__.py
  7. 35
      python/Lab10/sniffer/ip/ip.py
  8. 29
      python/Lab8/http_proxy.py
  9. 121
      python/Lab8/socks5_proxy.py
  10. 5
      python/Lab9/README.md
  11. 0
      python/Lab9/lab9/__init__.py
  12. 18
      python/Lab9/lab9/__main__.py
  13. 30
      python/Lab9/lab9/client.py
  14. 52
      python/Lab9/lab9/proto.py
  15. 82
      python/Lab9/lab9/server.py

4
python/Lab10/requirements.txt

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
colorama==0.4.4
commonmark==0.9.1
Pygments==2.9.0
rich==10.4.0

0
python/Lab10/sniffer/__init__.py

35
python/Lab10/sniffer/__main__.py

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
import socket
from typing import Protocol
from rich.console import Console
from .ethernet import EthernetFrame, EthernetProtoType
from .ip import Ipv4Packet
from .arp import ArpPacket
console = Console()
class Printable(Protocol):
def print(self, console: Console):
pass
def print_packet(frame: EthernetFrame) -> None:
if frame.frame_type == EthernetProtoType.IPV4:
Ipv4Packet.decode(frame.data).print(console)
elif frame.frame_type == EthernetProtoType.ARP:
ArpPacket.decode(frame.data).print(console)
else:
frame.print(console)
def main():
conn = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.ntohs(3))
while True:
raw_data, _ = conn.recvfrom(65536)
ethernet_frame = EthernetFrame.decode(raw_data)
print_packet(ethernet_frame)
if __name__ == "__main__":
main()

27
python/Lab10/sniffer/arp.py

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
import struct
from dataclasses import dataclass
from rich.console import Console
@dataclass()
class ArpPacket:
operation: int
@classmethod
def decode(cls, data: bytes) -> "ArpPacket":
operation = struct.unpack("!H", data[6:8])[0]
return cls(operation=operation)
def _describe_operaion(self) -> str:
if self.operation == 1:
return "request"
elif self.operation == 2:
return "response"
else:
return "unknown"
def print(self, console: Console):
console.print("[ARP]", style="bold blue", end=" ")
console.print("operation", self._describe_operaion())

39
python/Lab10/sniffer/ethernet.py

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
import struct
import binascii
from dataclasses import dataclass
from enum import Enum
from rich.console import Console
def format_mac(mac_addr: str) -> str:
return ":".join(mac_addr[i:i+2] for i in range(0, len(mac_addr), 2))
class EthernetProtoType(int, Enum):
IPV4 = 0x0800
ARP = 0x0806
@dataclass()
class EthernetFrame:
src: str
dst: str
frame_type: int
data: bytes
@classmethod
def decode(cls, data: bytes) -> "EthernetFrame":
eth_header = struct.unpack("!6s6sH", data[0:14])
dst_mac = binascii.hexlify(eth_header[0]).decode("ascii")
src_mac = binascii.hexlify(eth_header[1]).decode("ascii")
proto = eth_header[2]
return cls(src=src_mac, dst=dst_mac, frame_type=proto, data=data[14:])
def print(self, console: Console):
console.print("[Ethernet]", style="bold blue", end=" ")
console.print(f"from {self.src} to {self.dst} transfered {len(self.data)} bytes")
console.print(
" " + binascii.hexlify(self.data).decode('ascii'),
style="bright_black", crop=True, no_wrap=True, overflow="ellipsis",
)

2
python/Lab10/sniffer/ip/__init__.py

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
from .ip import Ipv4Packet, IpProto

35
python/Lab10/sniffer/ip/ip.py

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
import struct
import binascii
from dataclasses import dataclass
from enum import Enum
from rich.console import Console
class IpProto(str, Enum):
IPV4 = "ipv4"
IPV6 = "ipv6"
UNKNOWN = "unknown"
@dataclass()
class Ipv4Packet:
ttl: int
proto: int
src: str
dst: str
data: bytes
@classmethod
def decode(cls, data: bytes) -> "Ipv4Packet":
ttl, proto, src, dst = struct.unpack("!8xBB2x4s4s", data[:20])
fmt_ip = lambda addr: ".".join(map(str, addr))
return cls(ttl=ttl, proto=proto, src=fmt_ip(src), dst=fmt_ip(dst), data=data[20:])
def print(self, console: Console):
console.print("[IPV4]", style="bold blue", end=" ")
console.print(f"from {self.src} to {self.dst} transfered {len(self.data)} bytes")
console.print(
" " + binascii.hexlify(self.data).decode('ascii'),
style="bright_black", crop=True, no_wrap=True, overflow="ellipsis",
)

29
python/Lab8/http_proxy.py

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
import requests
from http.server import BaseHTTPRequestHandler, HTTPServer
REMOTE_URL = "https://0x73.ru"
class ProxyHandler(BaseHTTPRequestHandler):
def proxy_request(self) -> None:
resp = requests.request(
method=self.command,
url=REMOTE_URL + self.path,
headers=self.headers,
)
self.send_response(resp.status_code)
for k, v in resp.headers.items():
self.send_header(k, v)
self.end_headers()
self.wfile.write(resp.raw.read(-1))
def do_GET(self):
self.proxy_request()
def do_POST(self):
self.proxy_request()
if __name__ == "__main__":
HTTPServer(("", 8080), ProxyHandler).serve_forever()

121
python/Lab8/socks5_proxy.py

@ -0,0 +1,121 @@ @@ -0,0 +1,121 @@
import socket
import struct
class SocksServer:
def __init__(self):
self._ports_pool = list(range(30000, 31000))
def is_supported_version(self, version: int) -> bool:
return version == 5
def choose_auth_method(self) -> int:
return 0x02
def auth_client(self, *_) -> bool:
return True
def pop_port(self) -> int:
return self._ports_pool.pop()
def serve_conn(self, remote_ip: str, remote_port: int, local_port: int):
try:
self._serve_remote_conn(remote_ip, remote_port, local_port)
finally:
self._ports_pool.append(local_port)
@staticmethod
def _serve_remote_conn(remote_ip: str, remote_port: int, local_port: int):
local_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
local_sock.bind(("", local_port))
local_sock.listen(1)
client_conn, _ = local_sock.accept()
remote_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_sock.connect((remote_ip, remote_port))
while True:
data = client_conn.recv(1)
remote_sock.send(data)
class SocksHandler:
def __init__(self, host: str, port: int, server: SocksServer) -> None:
self.host = host
self.port = port
self._srv = server
def _handle_greeting(self, conn: socket.socket):
version, auth_methods_count = struct.unpack("BB", conn.recv(2))
conn.recv(auth_methods_count)
if not self._srv.is_supported_version(version):
conn.send(bytes([0xFF]))
raise ConnectionAbortedError()
auth_method = self._srv.choose_auth_method()
conn.send(bytes([0x05, auth_method]))
def _handle_creds_auth(self, conn: socket.socket):
_, username_len = struct.unpack("BB", conn.recv(2))
username = conn.recv(username_len).decode("ascii")
password_len = struct.unpack("B", conn.recv(1))[-1]
password = conn.recv(password_len).decode("ascii")
if not self._srv.auth_client(username, password):
conn.send(bytes([0x01, 0xff]))
raise ConnectionAbortedError()
conn.send(bytes([0x01, 0x00]))
def _handle_conn_request(self, conn: socket.socket):
_, cmd = struct.unpack("BBx", conn.recv(3))
if cmd != 0x01:
conn.send(bytes([0x05, 0x07, 0x00]))
raise ConnectionAbortedError()
remote_host = self._recv_host(conn)
remote_port = struct.unpack(">H", conn.recv(2))[-1]
local_port = self._srv.pop_port()
resp = bytes([
0x05, 0x00, 0x00, 0x01,
0x01, 127, 0, 0, 1,
local_port >> 8 & 0xff, local_port & 0xff,
])
conn.send(resp)
self._srv.serve_conn(remote_host, remote_port, local_port)
@staticmethod
def _recv_host(conn: socket.socket) -> str:
address_type = struct.unpack("B", conn.recv(1))[-1]
if address_type == 0x01:
addr = conn.recv(4)
return ".".join(str(i) for i in addr)
elif address_type == 0x03:
raise Exception("что ты такое?")
elif address_type == 0x04:
name_len = struct.unpack("B", conn.recv(1))[-1]
return conn.recv(name_len).decode("ascii")
else:
raise ValueError("unknown address family")
def _handle(self, conn: socket.socket):
try:
self._handle_greeting(conn)
print("Greeting passed")
self._handle_creds_auth(conn)
print("Client authenticated")
self._handle_conn_request(conn)
except ConnectionAbortedError:
pass
def serve(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((self.host, self.port))
s.listen(1)
while True:
conn, _ = s.accept()
self._handle(conn)
finally:
s.close()
if __name__ == "__main__":
server = SocksServer()
handler = SocksHandler("", 1080, server)
handler.serve()

5
python/Lab9/README.md

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
# Lab9
Start server: `python3 -m lab9 server`
Start client: `python3 -m lab9 client`

0
python/Lab9/lab9/__init__.py

18
python/Lab9/lab9/__main__.py

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
import sys
from . import client, server
def main():
if len(sys.argv) < 2:
print("...")
print(sys.argv)
if sys.argv[1] == "client":
client.main()
elif sys.argv[1] == "server":
server.main()
if __name__ == "__main__":
main()

30
python/Lab9/lab9/client.py

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
import socket
import time
from .proto import ClientRegisterEvent, NewTaskEvent, SolveResultEvent
SERVER_ADDR = ("127.0.0.1", 30030)
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 30031))
hello_packet = ClientRegisterEvent("127.0.0.1", 30031)
sock.sendto(hello_packet.to_bytes(), SERVER_ADDR)
while True:
data = sock.recv(1024)
message_type = data[0]
if message_type == 1:
event = NewTaskEvent.from_bytes(data)
print("New task recieved:", event.expression)
time.sleep(0.5)
result = eval(event.expression)
print(f"Task {event.identifier} solved. Result: {result}")
solve_event = SolveResultEvent(
identifier=event.identifier, result=str(result).encode("utf-8"),
)
sock.sendto(solve_event.to_bytes(), SERVER_ADDR)
if __name__ == "__main__":
main()

52
python/Lab9/lab9/proto.py

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
import struct
from dataclasses import dataclass
@dataclass()
class ClientRegisterEvent:
remote_addr: str
remote_port: int
@classmethod
def from_bytes(cls, data: bytes) -> "ClientRegisterEvent":
addr_len, data = data[1], data[2:]
addr = data[:addr_len].decode("utf-8")
port = struct.unpack("H", data[-2:])
return cls(remote_addr=addr, remote_port=port[0])
def to_bytes(self) -> bytes:
addr = self.remote_addr.encode("utf-8")
return bytes([0]) + struct.pack(f"B{len(addr)}sH", len(addr), addr, self.remote_port)
@dataclass()
class NewTaskEvent:
identifier: int
expression: str
@classmethod
def from_bytes(cls, data: bytes) -> "NewTaskEvent":
identifier = struct.unpack("I", data[1:5])
expression = data[5:]
return cls(identifier=identifier[-1], expression=expression.decode("utf-8"))
def to_bytes(self) -> bytes:
return bytes([1]) + struct.pack("I", self.identifier) + self.expression.encode("utf-8")
@dataclass()
class SolveResultEvent:
identifier: int
result: bytes
@classmethod
def from_bytes(cls, data: bytes) -> "SolveResultEvent":
data = data[1:]
struct_fmt = "I"
header_len = struct.calcsize(struct_fmt)
identifier, data = struct.unpack("I", data[:header_len]), data[header_len:]
return cls(identifier=identifier[0], result=data)
def to_bytes(self) -> bytes:
return bytes([2]) + struct.pack("I", self.identifier) + self.result

82
python/Lab9/lab9/server.py

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
import socket
from pprint import pprint
from typing import List, Tuple
from .proto import ClientRegisterEvent, NewTaskEvent, SolveResultEvent
Matrix = List[List[int]]
def make_tasks(matrix_1: Matrix, matrix_2: Matrix) -> List[NewTaskEvent]:
result: List[NewTaskEvent] = []
for i in range(0, len(matrix_1)):
row_1, row_2 = matrix_1[i], matrix_2[i]
eval_str = ", ".join(f"{a} + {b}" for a, b in zip(row_1, row_2))
eval_str = f"[{eval_str}]"
result.append(NewTaskEvent(identifier=len(result), expression=eval_str))
return result
def build_result(solves: List[SolveResultEvent]) -> Matrix:
solves = sorted(solves, key=lambda x: x.identifier)
result: Matrix = []
for solve in solves:
solve_text = solve.result.decode("utf-8")
s = eval(solve_text)
result.append(s)
return result
def sum_matrix(sock: socket.socket, matrix_1: Matrix, matrix_2: Matrix) -> Matrix:
tasks = make_tasks(matrix_1, matrix_2)
pending_tasks_count = len(tasks)
results: List[SolveResultEvent] = []
clients: List[Tuple[str, int]] = []
def send_task(remote_addr: str, remote_port: int):
if len(tasks) == 0:
return
task = tasks.pop()
sock.sendto(task.to_bytes(), (remote_addr, remote_port))
print(f"Task #{task.identifier} sent")
while True:
message, client = sock.recvfrom(1024)
message_type = message[0]
if message_type == 0:
event = ClientRegisterEvent.from_bytes(message)
print(f"New client {event.remote_addr}:{event.remote_port}")
clients.append((event.remote_addr, event.remote_port))
send_task(event.remote_addr, event.remote_port)
elif message_type == 2:
event = SolveResultEvent.from_bytes(message)
results.append(event)
pending_tasks_count += -1
print(f"Solve for task #{event.identifier} received. Result: {event.result.decode('utf-8')}")
send_task(*client)
if pending_tasks_count == 0:
return build_result(results)
def main():
input_matrix_1 = [
[0, 2, 0],
[1, 0, 1],
[0, 1, 0],
]
input_matrix_2 = [
[1, 0, 1],
[0, 1, 0],
[1, 0, 1],
]
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp.bind(("0.0.0.0", 30030))
print("Handle 0.0.0.0:30030")
result = sum_matrix(udp, input_matrix_1, input_matrix_2)
pprint(result)
if __name__ == "__main__":
main()