Skip to main content
BloodCat uses intelligent banner detection to automatically identify camera brands and apply brand-specific configurations during penetration tests. This eliminates manual configuration and optimizes brute-force efficiency.

Detection Process

The detection process occurs in the Execute_Cam.run() method (lib/camlib.py:166-225) and follows these steps:
1

RTSP Banner Retrieval

BloodCat sends an RTSP OPTIONS request to the target camera and extracts the Server header from the response.
2

Banner Analysis

The server banner is converted to lowercase and checked against known brand identifiers.
3

Configuration Selection

Based on the detected brand, BloodCat loads the appropriate users and RTSP paths from the CamLib class.
4

Fallback Handling

If no brand is detected, BloodCat uses a comprehensive default path list for unknown or clone devices.
The __get_rtsp_banner() method (lib/camlib.py:228-250) retrieves the RTSP server banner:
def __get_rtsp_banner(self, ip: str, port=554):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(5)
        sock.connect((ip, port))
        request = (
            f"OPTIONS rtsp://{ip}:{port}/ RTSP/1.0\r\n"
            "CSeq: 1\r\n"
            "\r\n"
        )
        sock.send(request.encode())
        response = sock.recv(4096).decode(errors='ignore')
        sock.close()
        print("[*] Authentication required detected, preparing to brute-force.")
        match = re.search(r"Server:\s*(.+)", response)
        if match:
            server = match.group(1).strip()
        else:
            server = 'N/A'
        return (ip, server)
    
    except Exception as e:
        return (None, None)
The method sends a standard RTSP OPTIONS request and parses the Server: header using regex. A 5-second timeout prevents hanging on unresponsive targets.

Brand Matching Logic

The run() method performs case-insensitive banner matching:
def run(self, ip: str, port=554):
    print(f"[+] Testing target: {ip}:{port}")
    _, banner = self.__get_rtsp_banner(ip, port)
    if banner is None:
        print("[...] Skip")
        return
    else:
        # Default fallback configuration
        default_paths = [
            'live.sdp',
            'stream1',
            'stream2',
            'h264',
            'h265',
            'videoMain',
            'videoSub',
            'media/video1',
            'media/video2',
            'ch0_0.h264',
            'ch1_0.h264',
            'user=admin_password=123456_channel=1_stream=0.sdp',
            'live/ch00_0',
            '0',
            '1',
            '11',
            '12',
            'h264Preview_01_main',
            'h264Preview_01_sub',
        ]
        users = ['admin']
        
        # Brand detection
        banner_lower = banner.lower()
        if 'hikvision' in banner_lower:
            print("[+] Hikvision detected")
            users, default_paths = self.Hikvision()
        elif 'dahua' in banner_lower:
            print("[+] Dahua detected")
            users, default_paths = self.Dahua()
        elif 'uniview' in banner_lower:
            print("[+] Uniview detected")
            users, default_paths = self.Uniview()
        elif 'axis' in banner_lower:
            print("[+] Axis detected")
            users, default_paths = self.Axis()
        elif 'sony' in banner_lower:
            print("[+] Sony detected")
            users, default_paths = self.Sony()
        elif 'vivotek' in banner_lower:
            print("[+] Vivotek detected")
            users, default_paths = self.Vivotek()
        elif 'reolink' in banner_lower:
            print("[+] Reolink detected")
            users, default_paths = self.Reolink()
        elif 'tvt' in banner_lower:
            print("[+] TVT detected")
            users, default_paths = self.TVT()
        elif 'milesight' in banner_lower:
            print("[+] Milesight detected")
            users, default_paths = self.Milesight()
        else:
            print("[+] Unknown or clone device detected")
        
        self.__rtsp_path_bruteforce(ip, port, default_paths, users)

Detection Flow Diagram

Successful Detection

  1. RTSP OPTIONS request sent
  2. Server banner extracted
  3. Brand keyword matched (e.g., “hikvision”)
  4. Brand-specific config loaded
  5. Optimized brute-force begins

Unknown Device

  1. RTSP OPTIONS request sent
  2. Server banner extracted
  3. No brand keyword matched
  4. Default path list used (19 paths)
  5. Generic brute-force begins

Fallback Behavior

When BloodCat encounters an unknown or clone device, it uses a comprehensive fallback configuration:
users = ['admin']
Only the admin username is tested for unknown devices to reduce brute-force time.
default_paths = [
    'live.sdp',
    'stream1',
    'stream2',
    'h264',
    'h265',
    'videoMain',
    'videoSub',
    'media/video1',
    'media/video2',
    'ch0_0.h264',
    'ch1_0.h264',
    'user=admin_password=123456_channel=1_stream=0.sdp',
    'live/ch00_0',
    '0',
    '1',
    '11',
    '12',
    'h264Preview_01_main',
    'h264Preview_01_sub',
]
This list aggregates common paths across multiple manufacturers and clone devices.
The fallback behavior is triggered when:
  • The RTSP server banner doesn’t contain any known brand keywords
  • The camera is a clone device using generic firmware
  • The manufacturer deliberately obscures their server banner
Typical RTSP server banners that BloodCat detects:
BrandExample Server Banner
HikvisionRTSP Server/Hikvision-RtspServer
DahuaRTSP Server/1.0 (Dahua IP Camera)
AxisAXIS Communications/1.0
UnknownRTSP Server/1.0 or N/A

Detection Efficiency

By detecting the camera brand, BloodCat significantly reduces brute-force time:
  • Hikvision: 3 users × 6 paths × 33 passwords = 594 total combinations
  • Unknown device: 1 user × 19 paths × 33 passwords = 627 total combinations
  • Without detection: Would need to test all possible combinations across all brands
Brand detection allows BloodCat to use brand-specific usernames (like supervisor for Hikvision or system for Dahua), which increases success rates.
BloodCat tests 33 common default passwords including admin, 123456, password, 12345678, and others commonly found in IoT devices. See lib/camlib.py:130-164 for the complete password list.

Error Handling

If banner retrieval fails (network timeout, closed port, etc.), BloodCat skips the target:
if banner is None:
    print("[...] Skip")
    return
This prevents wasted time on non-responsive or non-camera targets during mass scanning operations.

Build docs developers (and LLMs) love