1
0
mirror of synced 2024-12-23 19:34:49 +01:00
bemaniutils/bemani/utils/bemanishark.py

108 lines
3.7 KiB
Python

from typing import Optional
import argparse
from bemani.sniff import Sniffer
from bemani.protocol import EAmuseProtocol, EAmuseException
from bemani.common import HTTP
def mainloop(
address: Optional[str] = None, port: int = 80, verbose: bool = False
) -> None:
"""
Main loop of BEMANIShark. Starts an instance of Sniffer and EAmuseProtocol and does a
lazy job of banging them together with the above HTTP.parse. Will loop trying to decode
packets forever.
Arguments:
address - A string representing an IP of interest
port - An integer representing a port of interest
"""
sniffer = Sniffer(address=address, port=port)
parser = EAmuseProtocol()
while True:
packets = sniffer.recv_stream()
inbound = HTTP.parse(packets["inbound"], request=True)
outbound = HTTP.parse(packets["outbound"], response=True)
if inbound is not None:
if inbound["data"] is None:
in_req = None
else:
try:
in_req = parser.decode(
inbound["headers"].get("x-compress"),
inbound["headers"].get("x-eamuse-info"),
inbound["data"],
)
except EAmuseException:
in_req = None
print(
f"Inbound request (from {packets['source_address']}:{packets['source_port']} to {packets['destination_address']}:{packets['destination_port']}):"
)
if verbose:
print(f"HTTP {inbound['method']} request for URI {inbound['uri']}")
print(f"Compression is {inbound['headers'].get('x-compress', 'none')}")
print(
f"Encryption key is {inbound['headers'].get('x-eamuse-info', 'none')}"
)
if in_req is None:
print("Inbound request was not parseable")
else:
print(in_req)
if outbound is not None:
if outbound["data"] is None:
out_req = None
else:
try:
out_req = parser.decode(
outbound["headers"].get("x-compress"),
outbound["headers"].get("x-eamuse-info"),
outbound["data"],
)
except EAmuseException:
out_req = None
print(
f"Outbound response (from {packets['destination_address']}:{packets['destination_port']} to {packets['source_address']}:{packets['source_port']}):"
)
if verbose:
print(f"Compression is {outbound['headers'].get('x-compress', 'none')}")
print(
f"Encryption key is {outbound['headers'].get('x-eamuse-info', 'none')}"
)
if out_req is None:
print("Outbound response was not parseable")
else:
print(out_req)
def main() -> None:
parser = argparse.ArgumentParser(
description="A utility to sniff packets and decode them as eAmusement packets. Should probably be run as root."
)
parser.add_argument(
"-p", "--port", help="Port to sniff on. Defaults to 80", type=int, default=80
)
parser.add_argument(
"-a",
"--address",
help="Address to sniff on. Defaults to all addresses",
type=str,
default=None,
)
parser.add_argument(
"-v", "--verbose", help="Show extra packet information", action="store_true"
)
args = parser.parse_args()
mainloop(address=args.address, port=args.port, verbose=args.verbose)
if __name__ == "__main__":
main()