Need some help with my Script This works want Mac info as well

Any major updates coming, Upcoming Software, General Security advice for others and topics alike Post them here so other users can chat with you.
User avatar
Revo2Maxx
Site Admin
Posts: 6726
Joined: Sat Jun 15, 2019 3:05 pm

Need some help with my Script This works want Mac info as well

Post by Revo2Maxx »

So I am trying to get some things worked out for my cameras to add to a data base print out that offers info about my cameras for my kin when it is time for me to pass. Right now I have it where it will give data about the camera and I can use any of the Passwords I might use but one thing that I want to add to my script is the ability to get the Mac address for the cameras as well in my print out.. Right now I am just setting the script I will add in the output later. Right now have it setup to let me use multi passwords, I have it setup to show pass1 or pass2 etc as what one works rather then showing the password it self.. Crazy thing is my 4216-E1 shows that it is a 4232-E1 lol. All others show the right things..

Code: Select all

import os
import requests
from requests.auth import HTTPDigestAuth
import ipaddress
import sys

# Replace with your camera's username
USERNAME = "admin"  # Replace with your actual username

# List of possible passwords to try
PASSWORDS = [
    "password1!",  # First password to try
    "password2@",  # Second password to try
    # Add more passwords here if needed
]

# Define the network range (e.g., 192.168.1.0/24)
NETWORK_RANGE = "192.168.1.0/24"

# Function to check if a camera is online and accessible
def check_camera(camera_ip):
    for i, password in enumerate(PASSWORDS, 1):  # Enumerate to get index (1-based)
        try:
            # CGI command to get system info
            CAMERA_URL = f"http://{camera_ip}/cgi-bin/magicBox.cgi?action=getSystemInfo"
            
            # Make a request to the camera using Digest Authentication
            response = requests.get(CAMERA_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

            if response.status_code == 200:
                print(f"Camera found at {camera_ip}. Authentication successful with pass{i}. System Information:")
                print(response.text.strip())  # Print the system info once
                return  # Exit the loop if a password worked
            elif response.status_code == 401:
                print(f"Authentication failed for camera at {camera_ip} using pass{i}.")
            else:
                print(f"Camera at {camera_ip} returned an error: {response.status_code}")
        
        except requests.exceptions.RequestException as e:
            print(f"Error connecting to camera at {camera_ip}: {e}")

    print(f"Failed to authenticate with any password for camera at {camera_ip}.")

# Function to ping a single camera to check if it’s reachable
def ping_camera(camera_ip):
    response = os.system(f"ping -c 1 {camera_ip} > /dev/null 2>&1")  # Suppress output
    return response == 0

# Scan the network and check for reachable devices
def scan_network():
    # Generate the list of IP addresses in the network range
    network = ipaddress.IPv4Network(NETWORK_RANGE, strict=False)
    
    print(f"Scanning network range: {NETWORK_RANGE}...\n")
    
    # Iterate through all IP addresses in the network range
    for ip in network.hosts():
        camera_ip = str(ip)
        
        # Ping the camera
        if ping_camera(camera_ip):
            print(f"\nFound camera at {camera_ip}.")
            check_camera(camera_ip)  # Attempt to get system info from the camera
        else:
            print(f"No camera at {camera_ip}.")

# Main function to run the scan
if __name__ == "__main__":
    try:
        scan_network()
    except KeyboardInterrupt:
        print("\n\nScan aborted by user. Exiting script gracefully...")
        sys.exit(0)  # Exit the script cleanly
so I would like to add in the Mac addresses and I am not able to figure it out lol I know it is something I am over looking so this is the code that I have working so far.

The Output is and I will take out some of the Data that I don't want to share but enough to see what the output is..

Code: Select all

No camera at 10.0.0.33.

Found camera at 10.0.0.34.
Camera found at 10.0.0.34. Authentication successful with pass1. System Information:
appAutoStart=true
deviceType=IP2M-841B
hardwareVersion=1.00
processor=S2LM
serialNumber=AMC000FXXXXXXXXXX
updateSerial=IPC-AW25W-V2-Amcrest
updateSerialCloudUpgrade=IPC-AW25W-V2-Amcrest:0XXXXXXXXXXXXXXXXXXXXXXXXXXX02:00:00:00:00:00:00:100
No camera at 10.0.0.35.

Found camera at 10.0.0.36.
Authentication failed for camera at 10.0.0.36 using pass1.
Camera found at 10.0.0.36. Authentication successful with pass2. System Information:
appAutoStart=true
deviceType=N43AN52
hardwareVersion=1.00
processor=DH7300
serialNumber=7E03XXXXXXXXXXX
updateSerial=IPC-HDBW3441F-AS-M-DZ
updateSerialCloudUpgrade=IPC-HDBW3441F-AS-M-DZ:XXXXXXXXXXXXXXXXXXXXXXXXX00:00:00:00:00:01:00:00:200
No camera at 10.0.0.37.
Be Safe.
User avatar
Revo2Maxx
Site Admin
Posts: 6726
Joined: Sat Jun 15, 2019 3:05 pm

Re: Need some help with my Script This works want Mac info as well

Post by Revo2Maxx »

So I thought I would update the info I have about my script that I was using to try and get Mac info as well. All I get is this info..

Code: Select all

Camera found at 10.0.0.34. Authentication successful with pass1. System Information:
appAutoStart=true
deviceType=IP2M-841B
hardwareVersion=1.00
processor=S2LM
serialNumber=AMC000Fxxxxxxxxxxxxxx
updateSerial=IPC-AW25W-V2-Amcrest
updateSerialCloudUpgrade=IPC-AW25W-V2-Amcrest:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2:00:00:00:00:00:00:100
MAC Address not found for camera at 10.0.0.34.
No camera at 10.0.0.35.

Found camera at 10.0.0.36.
Authentication failed for camera at 10.0.0.36 using pass1.

Camera found at 10.0.0.36. Authentication successful with pass2. System Information:
appAutoStart=true
deviceType=N43AN52
hardwareVersion=1.00
processor=DH7300
serialNumber=7E0348xxxxxxxxxxxxxxx
updateSerial=IPC-HDBW3441F-AS-M-DZ
updateSerialCloudUpgrade=IPC-HDBW3441F-AS-M-DZ:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00:00:00:01:00:00:200
MAC Address not found for camera at 10.0.0.36.
So this is the code I am using for getting this data.

Code: Select all

import os
import requests
from requests.auth import HTTPDigestAuth
import ipaddress
import sys

# Replace with your camera's username
USERNAME = "admin"  # Replace with your actual username

# List of possible passwords to try
PASSWORDS = [
    "password1!",  # First password to try
    "password2@",  # Second password to try
    # Add more passwords here if needed
]

# Define the network range (e.g., 192.168.1.0/24)
NETWORK_RANGE = "192.168.1.0/24"

# Function to get the MAC address from the camera's network config
def get_mac_address(camera_ip, password):
    try:
        # Send a request to get the network configuration, including MAC address
        NETWORK_URL = f"http://{camera_ip}/cgi-bin/configManager.cgi?action=getConfig&name=Network"
        response = requests.get(NETWORK_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

        if response.status_code == 200:
            # Parse the MAC address from the response content
            mac_start = response.text.find("macAddress")
            if mac_start != -1:
                mac_address = response.text[mac_start:mac_start + 100].split('=')[1].split('<')[0].strip()
                return mac_address
            else:
                return None
        else:
            print(f"Failed to retrieve MAC address for camera at {camera_ip}.")
            return None

    except requests.exceptions.RequestException as e:
        print(f"Error connecting to camera at {camera_ip} to retrieve MAC address: {e}")
        return None

# Function to check if a camera is online and accessible
def check_camera(camera_ip):
    for i, password in enumerate(PASSWORDS, 1):  # Enumerate to get index (1-based)
        try:
            # CGI command to get system info
            CAMERA_URL = f"http://{camera_ip}/cgi-bin/magicBox.cgi?action=getSystemInfo"
            
            # Make a request to the camera using Digest Authentication
            response = requests.get(CAMERA_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

            if response.status_code == 200:
                print(f"\nCamera found at {camera_ip}. Authentication successful with pass{i}. System Information:")
                print(response.text.strip())  # Print the system info once

                # Now get the MAC address
                mac_address = get_mac_address(camera_ip, password)
                if mac_address:
                    print(f"MAC Address: {mac_address}")
                else:
                    print(f"MAC Address not found for camera at {camera_ip}.")
                
                return  # Exit the loop if a password worked
            elif response.status_code == 401:
                print(f"Authentication failed for camera at {camera_ip} using pass{i}.")
            else:
                print(f"Camera at {camera_ip} returned an error: {response.status_code}")
        
        except requests.exceptions.RequestException as e:
            print(f"Error connecting to camera at {camera_ip}: {e}")

    print(f"Failed to authenticate with any password for camera at {camera_ip}.")

# Function to ping a single camera to check if it’s reachable
def ping_camera(camera_ip):
    response = os.system(f"ping -c 1 {camera_ip} > /dev/null 2>&1")  # Suppress output
    return response == 0

# Scan the network and check for reachable devices
def scan_network():
    # Generate the list of IP addresses in the network range
    network = ipaddress.IPv4Network(NETWORK_RANGE, strict=False)
    
    print(f"Scanning network range: {NETWORK_RANGE}...\n")
    
    # Iterate through all IP addresses in the network range
    for ip in network.hosts():
        camera_ip = str(ip)
        
        # Ping the camera
        if ping_camera(camera_ip):
            print(f"\nFound camera at {camera_ip}.")
            check_camera(camera_ip)  # Attempt to get system info from the camera
        else:
            print(f"No camera at {camera_ip}.")

# Main function to run the scan
if __name__ == "__main__":
    try:
        scan_network()
    except KeyboardInterrupt:
        print("\n\nScan aborted by user. Exiting script gracefully...")
        sys.exit(0)  # Exit the script cleanly
If I run the CGI without being in my script I get a return

Code: Select all

table.Network.DefaultInterface=eth0
table.Network.Domain=dauha
table.Network.Hostname=IPC
table.Network.eth0.DefaultGateway=10.0.0.1
table.Network.eth0.DhcpEnable=true
table.Network.eth0.DnsServers[0]=10.0.0.1
table.Network.eth0.DnsServers[1]=0.0.0.0
table.Network.eth0.EnableDhcpReservedIP=false
table.Network.eth0.IPAddress=10.0.0.34
table.Network.eth0.MTU=1500
table.Network.eth0.PhysicalAddress=4c:11:bf:xx:xx:xx
table.Network.eth0.SubnetMask=255.255.255.0
table.Network.eth2.DefaultGateway=192.168.0.1
table.Network.eth2.DhcpEnable=true
table.Network.eth2.DnsServers[0]=8.8.8.8
table.Network.eth2.DnsServers[1]=8.8.4.4
table.Network.eth2.EnableDhcpReservedIP=false
table.Network.eth2.IPAddress=192.168.0.108
table.Network.eth2.MTU=1500
table.Network.eth2.PhysicalAddress=4c:11:bf:xx:xx:xx
table.Network.eth2.SubnetMask=255.255.255.0
Be Safe.
User avatar
Revo2Maxx
Site Admin
Posts: 6726
Joined: Sat Jun 15, 2019 3:05 pm

Re: Need some help with my Script This works want Mac info as well

Post by Revo2Maxx »

OK well I got it working somewhat lol. I mean maybe in the mind it is better then the real results. Took a good few tries and being locked out of some of my cameras before I got it working to a degree that I like it enough. First I setup using only 1 password, then thought well that won't work seeing I have cameras that has more then 1 so setup having multi passwords. Found out that passwords and script wasn't happy so I had to make it so I could put in the specials and different ones seeing I have a few different passwords with !@#$%)+

Some how I knocked out one of my Dahua cameras in all this testing of my script, I got locked out, used one of my other computers to reboot the camera and it never came back online. So I logged into the POE Switch it was connected to and rebooted that. All my other cameras came back online, but some reason it won't come up. It is all good The camera faces an area with little to no traffic.

If you happen to do scripts can you take a look at this and see what I can do to clean it up a little? Also if you are reading this and would like to have a version that won't have to scan the whole network range I could post a little change in the code that will only scan a set number of IP addresses rather then the whole network.

Code: Select all

import os
import requests
from requests.auth import HTTPDigestAuth
import ipaddress
import sys

# Replace with your camera's username
USERNAME = "admin"  # Replace with your actual username

# List of possible passwords to try
PASSWORDS = [
    "password1!",  # First password to try
    "password2@",  # Second password to try
    # Add more passwords here if needed
]

# Define the network range (e.g., 192.168.1.0/24)
NETWORK_RANGE = "192.168.1.0/24"

# Function to get the MAC address of the camera
def get_mac_address(camera_ip, password):
    try:
        # URL to fetch the network info, including the MAC address
        NETWORK_URL = f"http://{camera_ip}/cgi-bin/configManager.cgi?action=getConfig&name=Network"
        response = requests.get(NETWORK_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

        if response.status_code == 200:
            # Extract MAC address from the response
            mac_start = response.text.find("PhysicalAddress=")
            if mac_start != -1:
                mac_address = response.text[mac_start + 16:mac_start + 33].strip()
                return mac_address
            else:
                print(f"MAC Address not found in response from {camera_ip}.")
        else:
            print(f"Failed to retrieve MAC address for camera at {camera_ip}. Status code: {response.status_code}")

    except requests.exceptions.RequestException as e:
        print(f"Error retrieving MAC address for camera at {camera_ip}: {e}")
    return None

# Function to check if a camera is online and accessible
def check_camera(camera_ip):
    # Try each password independently
    for i, password in enumerate(PASSWORDS, 1):  # Enumerate to get index (1-based)
        try:
            # CGI command to get system info
            CAMERA_URL = f"http://{camera_ip}/cgi-bin/magicBox.cgi?action=getSystemInfo"
            
            # Make a request to the camera using Digest Authentication
            response = requests.get(CAMERA_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

            if response.status_code == 200:
                print(f"Camera found at {camera_ip}. Authentication successful with pass{i}. System Information:")
                print(response.text.strip())  # Print the system info once
                
                # Get the MAC address if authentication succeeded
                mac_address = get_mac_address(camera_ip, password)
                if mac_address:
                    print(f"MAC Address for camera at {camera_ip}: {mac_address}")
                
                return  # Exit after successful authentication (either pass1 or pass2)

            elif response.status_code == 401:
                print(f"Authentication failed for camera at {camera_ip} using pass{i}.")
            else:
                print(f"Camera at {camera_ip} returned an error: {response.status_code}")
        
        except requests.exceptions.RequestException as e:
            print(f"Error connecting to camera at {camera_ip}: {e}")

    print(f"Failed to authenticate with any password for camera at {camera_ip}.")

# Function to ping a single camera to check if it’s reachable
def ping_camera(camera_ip):
    response = os.system(f"ping -c 1 {camera_ip} > /dev/null 2>&1")  # Suppress output
    return response == 0

# Scan the network and check for reachable devices
def scan_network():
    # Generate the list of IP addresses in the network range
    network = ipaddress.IPv4Network(NETWORK_RANGE, strict=False)
    
    print(f"Scanning network range: {NETWORK_RANGE}...\n")
    
    # Iterate through all IP addresses in the network range
    for ip in network.hosts():
        camera_ip = str(ip)
        
        # Ping the camera
        if ping_camera(camera_ip):
            print(f"\nFound camera at {camera_ip}.")
            check_camera(camera_ip)  # Attempt to get system info from the camera
        else:
            print(f"No camera at {camera_ip}.")

# Main function to run the scan
if __name__ == "__main__":
    try:
        scan_network()
    except KeyboardInterrupt:
        print("\n\nScan aborted by user. Exiting script gracefully...")
        sys.exit(0)  # Exit the script cleanly
Be Safe.
User avatar
Revo2Maxx
Site Admin
Posts: 6726
Joined: Sat Jun 15, 2019 3:05 pm

Re: Need some help with my Script This works want Mac info as well

Post by Revo2Maxx »

So I will admit I have not worked on this much but I did get a result that I am happy with.. You can find the script below if you wanted to also do something like it. I have a few different types of these script in place and seeing I have it worked out in my head well enough now I can make changes if I need. However trying to get more data will require messing with things so that might not be as easy..

So after some time I was able to get it to search my network and list devices. Then I wanted to update so it would only list devices that will be printed. However after making that change from showing each ping to just saying that it is doing a scan and then it just sits there and waits until it ran the whole range. I thought ok lets make it so I can watch as it goes but didn't post any device info until the end. Then just as I thought that is good enough I added another camera to my setup lol. I was like man I don't want to have to wait until it scans the whole range again so I went in and added the ability to just scan 1 ip if I wanted to this way I can add in new cameras added after setting up the list for my records...

So this end result is a script that will scan my network using in my case 2 different passwords and then printing out to screen the list of devices. Again running the script it will ask if you want to do 1 or the whole network..

Changes you will need to make. 1 if your network isn't setup on 10.0.0.xxx then you will need to change the code where I have my network range added. Also you will have to change the passwords. Because of the way passwords work or fail I have added to the script the ability to do special Charactars as well..
I am not a script guy so this I am sure isn't going to be perfect. I am sure there are things that I could have done that made this smaller to easier but it works for what I want and having the ability to have some info about each of my cameras 1 in print form seeing I have also printed out the list. I can put in a 3 ring binder and keep info in arms reach.

This does Dahua and Amcrest cameras. If I feel like it at some point I might add in the ability to also get info from Hikvision cameras. Seeing most of my cameras are Dahua or OEM of such I didn't try much with hikvision before I just kept it Dahua Based..

Code: Select all

import os
import requests
from requests.auth import HTTPDigestAuth
import ipaddress
import sys
import time

# Replace with your camera's username
USERNAME = "admin"  # Replace with your actual username

# List of possible passwords to try
PASSWORDS = [
    "Password1",  # First password to try
    "Password2",  # Second password to try
    # Add more passwords here if needed
]

# Define the network range (e.g., 192.168.1.0/24)
NETWORK_RANGE = "10.0.0.0/24"

discovered_cameras = []  # Store discovered camera information

# Function to get the MAC address of the camera
def get_mac_address(camera_ip, password):
    try:
        NETWORK_URL = f"http://{camera_ip}/cgi-bin/configManager.cgi?action=getConfig&name=Network"
        response = requests.get(NETWORK_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

        if response.status_code == 200:
            mac_start = response.text.find("PhysicalAddress=")
            if mac_start != -1:
                mac_address = response.text[mac_start + 16:mac_start + 33].strip()
                return mac_address
    except requests.exceptions.RequestException:
        pass
    return None

# Function to check if a camera is online and accessible
def check_camera(camera_ip):
    for i, password in enumerate(PASSWORDS, 1):
        try:
            CAMERA_URL = f"http://{camera_ip}/cgi-bin/magicBox.cgi?action=getSystemInfo"
            response = requests.get(CAMERA_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

            if response.status_code == 200:
                mac_address = get_mac_address(camera_ip, password)
                discovered_cameras.append({
                    "ip": camera_ip,
                    "password_used": f"pass{i}",
                    "system_info": response.text.strip(),
                    "mac_address": mac_address
                })
                print(f"\n[✓] Camera authenticated at {camera_ip} using pass{i}")
                return
        except requests.exceptions.RequestException:
            pass
    print(f"[✗] No valid authentication found for {camera_ip}")

# Function to ping a single camera
def ping_camera(camera_ip):
    return os.system(f"ping -c 1 {camera_ip} > /dev/null 2>&1") == 0

# Function to scan a single IP
def scan_single_ip(ip_address):
    print(f"Checking single IP: {ip_address}...")
    if ping_camera(ip_address):
        print(f"[!] Device responded at {ip_address}, checking credentials...")
        check_camera(ip_address)
    else:
        print(f"[-] No response from {ip_address}")

# Scan the network and check for reachable devices
def scan_network():
    network = ipaddress.IPv4Network(NETWORK_RANGE, strict=False)
    total_ips = sum(1 for _ in network.hosts())
    checked_ips = 0
    
    print(f"Scanning network range: {NETWORK_RANGE}...\n")
    for ip in network.hosts():
        camera_ip = str(ip)
        checked_ips += 1
        print(f"[{checked_ips}/{total_ips}] Checking {camera_ip}...")  # Progress feedback
        time.sleep(0.1)  # Small delay for better output readability
        if ping_camera(camera_ip):
            print(f"[!] Device responded at {camera_ip}, checking credentials...")
            check_camera(camera_ip)
        else:
            print(f"[-] No response from {camera_ip}")

# Main function to run the scan
if __name__ == "__main__":
    try:
        mode = input("Run full network scan or single IP scan? (full/single): ").strip().lower()
        if mode == "single":
            single_ip = input("Enter the IP address to scan: ").strip()
            scan_single_ip(single_ip)
        else:
            scan_network()
        
        print("\nScan complete. Discovered devices:")
        for cam in discovered_cameras:
            print(f"\nCamera IP: {cam['ip']}\nPassword Used: {cam['password_used']}\nMAC Address: {cam['mac_address']}\nSystem Info:\n{cam['system_info']}")
    except KeyboardInterrupt:
        print("\n\nScan aborted by user. Exiting script gracefully...")
        sys.exit(0)
Be Safe.
User avatar
Revo2Maxx
Site Admin
Posts: 6726
Joined: Sat Jun 15, 2019 3:05 pm

Re: Need some help with my Script This works want Mac info as well

Post by Revo2Maxx »

Ok so I thought I would make another change..

Rather then having to type out if I wanted single or full I added in the ability to pick 1 or 2 much easier then having to type.. Then rather then watching it waste a bunch of space on the screen while it scans each IP.. I added in a Throbber instead lol.. While it isn't as cool as the one from years past it is still the idea of the spinning line lol. It is not that long but is longer then the last one I posted.. Extra functions require extra lines..

Code: Select all

import os
import requests
from requests.auth import HTTPDigestAuth
import ipaddress
import sys
import threading
import time

# Replace with your camera's username
USERNAME = "admin"  # Replace with your actual username

# List of possible passwords to try
PASSWORDS = [
    "password1",  # First password to try
    "password2",  # Second password to try
    # Add more passwords here if needed
]

# Define the network range (e.g., 192.168.1.0/24)
NETWORK_RANGE = "10.0.0.0/24"

discovered_cameras = []  # Store discovered camera information
scanning = False  # Flag to control the throbber

def throbber():
    while scanning:
        for char in "|/-\\":
            print(f"\rScanning... {char}", end="", flush=True)
            time.sleep(0.1)
    print("\rScan complete!   ")

# Function to get the MAC address of the camera
def get_mac_address(camera_ip, password):
    try:
        NETWORK_URL = f"http://{camera_ip}/cgi-bin/configManager.cgi?action=getConfig&name=Network"
        response = requests.get(NETWORK_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

        if response.status_code == 200:
            mac_start = response.text.find("PhysicalAddress=")
            if mac_start != -1:
                mac_address = response.text[mac_start + 16:mac_start + 33].strip()
                return mac_address
    except requests.exceptions.RequestException:
        pass
    return None

# Function to check if a camera is online and accessible
def check_camera(camera_ip):
    for i, password in enumerate(PASSWORDS, 1):
        try:
            CAMERA_URL = f"http://{camera_ip}/cgi-bin/magicBox.cgi?action=getSystemInfo"
            response = requests.get(CAMERA_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

            if response.status_code == 200:
                mac_address = get_mac_address(camera_ip, password)
                discovered_cameras.append({
                    "ip": camera_ip,
                    "password_used": f"pass{i}",
                    "system_info": response.text.strip(),
                    "mac_address": mac_address
                })
                return
        except requests.exceptions.RequestException:
            pass

# Function to ping a single camera
def ping_camera(camera_ip):
    return os.system(f"ping -c 1 {camera_ip} > /dev/null 2>&1") == 0

# Scan the network and check for reachable devices
def scan_network():
    global scanning
    network = ipaddress.IPv4Network(NETWORK_RANGE, strict=False)
    scanning = True
    throbber_thread = threading.Thread(target=throbber)
    throbber_thread.start()
    
    for ip in network.hosts():
        camera_ip = str(ip)
        if ping_camera(camera_ip):
            check_camera(camera_ip)
    
    scanning = False
    throbber_thread.join()

# Scan a single IP
def scan_single_ip(single_ip):
    global scanning
    scanning = True
    throbber_thread = threading.Thread(target=throbber)
    throbber_thread.start()
    
    if ping_camera(single_ip):
        check_camera(single_ip)
    
    scanning = False
    throbber_thread.join()

# Main function to run the scan
if __name__ == "__main__":
    try:
        mode = input("Enter '1' to scan a single IP or '2' to scan the full range: ")
        if mode == '1':
            single_ip = input("Enter the IP address to scan: ")
            scan_single_ip(single_ip)
        else:
            scan_network()
        
        print("\nScan complete. Discovered devices:")
        for cam in discovered_cameras:
            print(f"\nCamera IP: {cam['ip']}\nPassword Used: {cam['password_used']}\nMAC Address: {cam['mac_address']}\nSystem Info:\n{cam['system_info']}")
    except KeyboardInterrupt:
        scanning = False
        print("\n\nScan aborted by user. Exiting script gracefully...")
        sys.exit(0)
Be Safe.
ultimatecodewarrior
Posts: 26
Joined: Mon Jan 13, 2025 3:04 pm

Re: Need some help with my Script This works want Mac info as well

Post by ultimatecodewarrior »

My remix with up to 256 threads in parallel for a less than 15 second complete scan of your IP range.

Code: Select all

import os
import requests
from requests.auth import HTTPDigestAuth
import ipaddress
import sys
import threading
import time

# Replace with your camera's username
USERNAME = "admin"  # Replace with your actual username

# List of possible passwords to try
PASSWORDS = [
    "admin",  # First password to try
    "admin",  # Second password to try
    # Add more passwords here if needed
]

# Define the network range (e.g., 192.168.1.0/24)
NETWORK_RANGE = "192.168.0.1/24"

discovered_cameras = []  # Store discovered camera information
scanning = False  # Flag to control the throbber

# Function to get the MAC address of the camera
def get_mac_address(camera_ip, password):
    try:
        NETWORK_URL = f"http://{camera_ip}/cgi-bin/configManager.cgi?action=getConfig&name=Network"
        response = requests.get(NETWORK_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

        if response.status_code == 200:
            mac_start = response.text.find("PhysicalAddress=")
            if mac_start != -1:
                mac_address = response.text[mac_start + 16:mac_start + 33].strip()
                return mac_address
    except requests.exceptions.RequestException:
        pass
    return None

# Function to check if a camera is online and accessible
def check_camera(camera_ip):
    for i, password in enumerate(PASSWORDS, 1):
        try:
            CAMERA_URL = f"http://{camera_ip}/cgi-bin/magicBox.cgi?action=getSystemInfo"
            response = requests.get(CAMERA_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

            if response.status_code == 200:
                mac_address = get_mac_address(camera_ip, password)
                discovered_cameras.append({
                    "ip": camera_ip,
                    "password_used": f"pass{i}",
                    "system_info": response.text.strip(),
                    "mac_address": mac_address
                })
                return
        except requests.exceptions.RequestException:
            pass

# Function to ping a single camera
def ping_camera(camera_ip):
    return os.system(f"ping -c 1 {camera_ip} > /dev/null 2>&1") == 0

def check_ip(ip):
    #print(ip)
    camera_ip = str(ip)
    if ping_camera(camera_ip):
        check_camera(camera_ip)

def throbber():
    while scanning:
        for char in "|/-\\":
            print(f"\rScanning... {char}", end="", flush=True)
            time.sleep(0.1)
    print("\rScan complete!   ")


# Scan the network and check for reachable devices
def scan_network():
    ts = time.time()
    global scanning
    network = ipaddress.IPv4Network(NETWORK_RANGE, strict=False)
    scanning = True

    threads = []
    ct=0
    for ip in network.hosts():
      ip_thread = threading.Thread(target=check_ip, args=(ip,))
      ip_thread.start()
      threads.append(ip_thread)
      ct+=1

    print(f"[{ct}] Scanning threads launched in parallel, be patient for roughly 15 seconds give or take...")


    throbber_thread = threading.Thread(target=throbber)
    throbber_thread.start()

    for t in threads:
      t.join()
    print(f"\r\n[{ct}] Threads finished locating  {len(discovered_cameras)} cameras in {round(time.time()-ts)} seconds flat....")
    scanning = False

    # Wait for all threads to finish
 
 
# Main function to run the scan
if __name__ == "__main__":
    try:
 
        scan_network()
        
        print("\nScan complete. Discovered devices:")
        for cam in discovered_cameras:
            print(f"\nCamera IP: {cam['ip']}\nPassword Used: {cam['password_used']}\nMAC Address: {cam['mac_address']}\nSystem Info:\n{cam['system_info']}")
    except KeyboardInterrupt:
     
        print("\n\nScan aborted by user. Exiting script gracefully...")
        sys.exit(0)



 
User avatar
Revo2Maxx
Site Admin
Posts: 6726
Joined: Sat Jun 15, 2019 3:05 pm

Re: Need some help with my Script This works want Mac info as well

Post by Revo2Maxx »

Wow So that is back to like the full without option of range or 1 ip and I don't remember I might have made that change and not uploaded that part.. But wow I am not coder lol I wonder what my last code would look like with the right coding.. I mean the last scan I did of my full system took 20 min lol.. Now I will admit I have not looked at your script, Just did a once over and ran it and sure enough took about 12 seconds to print out 32 devices.. Only thing I don't understand is why they are being output out of order.. I mean 99 is being output before 86 and 177 is being output after 225, 232 and not listed in order of the 2-254? Besides that it was very fast?

Again have not looked at the code but in mine it only gets some trash from one of my Switches where with your code 3 of my switches output trash in the output.. I spent little time yesterday adding some things to skip that output from the switches.. Here is just a part of what it sends out from yours.. There is about 200 plus lines of text just a sample lol..

Code: Select all

amera IP: 10.0.0.170
Password Used: pass1
MAC Address: None
System Info:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>

<head>
<title>Authentication Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<LINK href="../css/cisco.css" type=text/css rel=STYLESHEET>
<script src="../js/common_functions.js"></script>
<script src="../js/cookies.js"></script>
<script src="../js/String.js"></script>
<script language="JavaScript">
<!-- Beginng of JavaScript Applet
var formele;
if (((top.location==self.location)&&(!opener))|| top.location.pathname!="/config/authentication_page.htm")
top.location.href="../config/authentication_page.htm";
visible = false;
function formSubmit()
{
username = document.forms[0].elements['userName$query'].value;
var expdate = new Date();
expdate.setMinutes(expdate.getMinutes()+1);
set_cookie("username",username,expdate,"/");
SendLoginXML();
}
var xmlhttp;
function SendLoginXML()
So this is my updated code and wow taking 20 min to run but isn't 100% because there are still a few cameras that are not listing because of being older FW and so I have been trying to make that adjustment to get all the cameras listed.. Right now my older 850EB gives an error do to the Auth type. The newer FW 850EB that has newer fw with removed functions give the good output..

So I just ran my last output and oddly did something that has chnaged the IP to being numbered lol. So this is the last update to my script before I changed to try to scan older FW Dahua and Amcrest camera.. This one lets me pick from 3 different full, single or a range of IPs.. In my last one I have 4 options the 3 here in the code below and 4th for Amcrest older and after 5 tries I get it to do only older Amcrest and fails all newer FW cameras and or it will do the new and not older and in the last one it is back to only doing the newer FW ones but no longer submits the IP it just outputs some numbered output so must have missed something in one of the lines text.. Normally I put on some dance music and mess around until I had enough lol.. Anyway the code below works just isn't able to show older Amcrest fw details and has to do with Auth issues.

Code: Select all

import os
import requests
from requests.auth import HTTPDigestAuth
import ipaddress
import sys
import time
import itertools
import threading

USERNAME = "admin"
PASSWORDS = ["admin", "password"]
discovered_cameras = []
stop_spinner = False

# Spinner animation
def spinner():
    for frame in itertools.cycle(['|', '/', '-', '\\']):  # Fixed string literal
        if stop_spinner:
            break
        print(f'\rScanning... {frame}', end='', flush=True)
        time.sleep(0.1)
    print('\r', end='', flush=True)

# Get MAC address
def get_mac_address(camera_ip, password):
    try:
        response = requests.get(
            f"http://{camera_ip}/cgi-bin/configManager.cgi?action=getConfig&name=Network",
            auth=HTTPDigestAuth(USERNAME, password), timeout=5)
        if response.status_code == 200:
            mac_start = response.text.find("PhysicalAddress=")
            return response.text[mac_start + 16:mac_start + 33].strip() if mac_start != -1 else None
    except requests.RequestException:
        pass
    return None

# Check camera
def check_camera(camera_ip):
    for i, password in enumerate(PASSWORDS, 1):
        try:
            response = requests.get(
                f"http://{camera_ip}/cgi-bin/magicBox.cgi?action=getSystemInfo",
                auth=HTTPDigestAuth(USERNAME, password), timeout=5)
            if response.status_code == 200:
                discovered_cameras.append({
                    "ip": camera_ip,
                    "password_used": f"pass{i}",
                    "mac_address": get_mac_address(camera_ip, password),
                    "system_info": response.text.strip()
                })
                return
        except requests.RequestException:
            pass

# Ping camera
def ping_camera(camera_ip):
    return os.system(f"ping -c 1 {camera_ip} > /dev/null 2>&1") == 0

# Scan IPs
def scan_ips(ip_list):
    global stop_spinner
    spinner_thread = threading.Thread(target=spinner)
    spinner_thread.start()
    
    for camera_ip in ip_list:
        if ping_camera(camera_ip):
            check_camera(camera_ip)
    
    stop_spinner = True
    spinner_thread.join()

# Main Function
if __name__ == "__main__":
    choice = input("Choose scanning mode:\n1) Single IP\n2) Custom IP Range\n3) Full Network Range\nEnter your choice: ")
    
    if choice == '1':
        single_ip = input("Enter the single IP to scan: ")
        scan_ips([single_ip])
    elif choice == '2':
        start_ip = ipaddress.IPv4Address(input("Enter the start IP: "))
        end_ip = ipaddress.IPv4Address(input("Enter the end IP: "))
        ip_range = [str(ipaddress.IPv4Address(ip)) for ip in range(int(start_ip), int(end_ip) + 1)]
        scan_ips(ip_range)
    elif choice == '3':
        network = ipaddress.IPv4Network("10.0.0.0/24", strict=False)
        scan_ips([str(ip) for ip in network.hosts()])
    else:
        print("Invalid choice.")
    
    print("\nDiscovered devices:")
    for cam in discovered_cameras:
        print(f"\nIP: {cam['ip']}\nPassword Used: {cam['password_used']}\nMAC: {cam['mac_address']}\nSystem Info:\n{cam['system_info']}")
Be Safe.
User avatar
Revo2Maxx
Site Admin
Posts: 6726
Joined: Sat Jun 15, 2019 3:05 pm

Re: Need some help with my Script This works want Mac info as well

Post by Revo2Maxx »

Ok I changed it so it will output in IP order again I have not added back my options yet but really don't need to do range and all that now that it is so fast seeing your setup is using multi thread design..

Code: Select all

import os
import requests
from requests.auth import HTTPDigestAuth
import ipaddress
import sys
import threading
import time

# Replace with your camera's username
USERNAME = "admin"  

# List of possible passwords to try
PASSWORDS = [
    "admin",  
    "password",  
]

# Define the network range
NETWORK_RANGE = "10.0.0.0/24"

discovered_cameras = []  
scanning = False  

# Function to get the MAC address of the camera
def get_mac_address(camera_ip, password):
    try:
        response = requests.get(
            f"http://{camera_ip}/cgi-bin/configManager.cgi?action=getConfig&name=Network",
            auth=HTTPDigestAuth(USERNAME, password), timeout=5
        )
        if response.status_code == 200:
            mac_start = response.text.find("PhysicalAddress=")
            if mac_start != -1:
                return response.text[mac_start + 16:mac_start + 33].strip()
    except requests.exceptions.RequestException:
        pass
    return None

# Function to check if a camera is online and accessible
def check_camera(camera_ip):
    for i, password in enumerate(PASSWORDS, 1):
        try:
            response = requests.get(
                f"http://{camera_ip}/cgi-bin/magicBox.cgi?action=getSystemInfo",
                auth=HTTPDigestAuth(USERNAME, password), timeout=5
            )
            if response.status_code == 200:
                mac_address = get_mac_address(camera_ip, password)
                discovered_cameras.append({
                    "ip": camera_ip,
                    "password_used": f"pass{i}",
                    "system_info": response.text.strip(),
                    "mac_address": mac_address
                })
                return
        except requests.exceptions.RequestException:
            pass

# Function to ping a single camera
def ping_camera(camera_ip):
    return os.system(f"ping -c 1 {camera_ip} > /dev/null 2>&1") == 0

def check_ip(ip):
    camera_ip = str(ip)
    if ping_camera(camera_ip):
        check_camera(camera_ip)

def throbber():
    while scanning:
        for char in "|/-\\":
            print(f"\rScanning... {char}", end="", flush=True)
            time.sleep(0.1)
    print("\rScan complete!   ")

# Scan the network and check for reachable devices
def scan_network():
    global scanning
    ts = time.time()
    network = ipaddress.IPv4Network(NETWORK_RANGE, strict=False)
    scanning = True

    threads = []
    for ip in network.hosts():
        ip_thread = threading.Thread(target=check_ip, args=(ip,))
        ip_thread.start()
        threads.append(ip_thread)

    print(f"[{len(threads)}] Scanning threads launched in parallel, be patient...")

    throbber_thread = threading.Thread(target=throbber)
    throbber_thread.start()

    for t in threads:
        t.join()

    scanning = False
    print(f"\r\nScan completed in {round(time.time()-ts)} seconds.")

# Main function to run the scan
if __name__ == "__main__":
    try:
        scan_network()
        
        # Sort discovered cameras by IP before displaying
        discovered_cameras.sort(key=lambda cam: ipaddress.IPv4Address(cam['ip']))
        
        print("\nDiscovered Devices (Sorted by IP):")
        for cam in discovered_cameras:
            print(f"\nCamera IP: {cam['ip']}\nPassword Used: {cam['password_used']}\nMAC Address: {cam['mac_address']}\nSystem Info:\n{cam['system_info']}")
    
    except KeyboardInterrupt:
        print("\n\nScan aborted by user. Exiting script gracefully...")
        sys.exit(0)
Be Safe.
User avatar
Revo2Maxx
Site Admin
Posts: 6726
Joined: Sat Jun 15, 2019 3:05 pm

Re: Need some help with my Script This works want Mac info as well

Post by Revo2Maxx »

OK I need help lol So I wanted to list the output in connection with same Processor just so I knew.. So yeah as it printed in terminal in color with same color to same CPU, Then I setup so it would save to a text file but forgot that it won't save in color that format so I thought ok will just do something in HTML format and well you can see what I really want in the first picture but then I went over board and the output to html is worse lol I mean sure I could do screen shots but that is just to much.. Right now have some of my devices behind VLan so they are not showing up as these are the ones in my current PC vlan.. Once I gert it to an output I like I would like to open my network do the scan and then do a full list.. Plus need to work out something in future that will let me add in my POE NVRs connected cameras as well lol. Covered the SN and Mac address into in the pictures don't want trolls lol.. I know I need to make some changes in my colors as well lol.. In terminal output looks fine for most part.. Geez need to take a break lol..
Screenshot from 2025-02-19 07-20-41.png
Screenshot from 2025-02-19 07-20-41.png (150.59 KiB) Viewed 1014 times
Screenshot from 2025-02-19 07-09-45.png
Screenshot from 2025-02-19 07-09-45.png (589.34 KiB) Viewed 1014 times
Be Safe.
ultimatecodewarrior
Posts: 26
Joined: Mon Jan 13, 2025 3:04 pm

Re: Need some help with my Script This works want Mac info as well

Post by ultimatecodewarrior »

Running the script will :
-Scan for the Cameras
-Create HTML table with dynamically sortable columns, just click on the column heading to sort asc/desc
-Startup a small webserver
-Launch your browser to load the HTML file.
-Don't forget to change the passwords/ip range

Code: Select all

import os
import requests
from requests.auth import HTTPDigestAuth
import ipaddress
import sys
import threading
import time
import json
import webbrowser
from http.server import SimpleHTTPRequestHandler, HTTPServer

# Replace with your camera's username
USERNAME = "admin"  # Replace with your actual username

# List of possible passwords to try
PASSWORDS = [
    "admin",  # First password to try
    "admin",  # Second password to try
    # Add more passwords here if needed
]

# Define the network range (e.g., 192.168.0.1/24)
NETWORK_RANGE = "192.168.0.1/24"

discovered_cameras = []  # Store discovered camera information
scanning = False  # Flag to control the throbber

# Function to get the MAC address of the camera
def get_mac_address(camera_ip, password):
    try:
        NETWORK_URL = f"http://{camera_ip}/cgi-bin/configManager.cgi?action=getConfig&name=Network"
        response = requests.get(NETWORK_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

        if response.status_code == 200:
            mac_start = response.text.find("PhysicalAddress=")
            if mac_start != -1:
                mac_address = response.text[mac_start + 16:mac_start + 33].strip()
                return mac_address
    except requests.exceptions.RequestException:
        pass
    return None

# Function to check if a camera is online and accessible
def check_camera(camera_ip):
    for i, password in enumerate(PASSWORDS, 1):
        try:
            CAMERA_URL = f"http://{camera_ip}/cgi-bin/magicBox.cgi?action=getSystemInfo"
            response = requests.get(CAMERA_URL, auth=HTTPDigestAuth(USERNAME, password), timeout=5)

            if response.status_code == 200:
                mac_address = get_mac_address(camera_ip, password)
                system_info = response.text.strip()

                # Parse the response text to extract the specified fields
                fields = {
                    "appAutoStart": None,
                    "deviceType": None,
                    "hardwareVersion": None,
                    "processor": None,
                    "serialNumber": None,
                    "updateSerial": None,
                    "updateSerialCloudUpgrade": None
                }

                for line in system_info.splitlines():
                    key, sep, value = line.partition('=')
                    if key in fields:
                        fields[key] = value.strip()

                if fields["serialNumber"] is not None:
                    system_info = "Camera Detected"

                discovered_cameras.append({
                    "ip": camera_ip,
                    "password_used": f"pass{i}",
                    "mac_address": mac_address,
                    "processor": fields["processor"],                    
                    "deviceType": fields["deviceType"],
                    "serialNumber": fields["serialNumber"],
                    "system_info": system_info,

                })

                '''
                "hardwareVersion": fields["hardwareVersion"],              
                "updateSerial": fields["updateSerial"],
                "updateSerialCloudUpgrade": fields["updateSerialCloudUpgrade"],
                "appAutoStart": fields["appAutoStart"]
                '''

                return
        except requests.exceptions.RequestException:
            pass

# Function to ping a single camera
def ping_camera(camera_ip):
    return os.system(f"ping -c 1 {camera_ip} > /dev/null 2>&1") == 0

threads_left = 0

def check_ip(ip):
    global threads_left
    camera_ip = str(ip)
    if ping_camera(camera_ip):
        check_camera(camera_ip)
    threads_left -= 1

def throbber():
    global threads_left
    while scanning:
        for char in "|/-\\":
            print(f"\rScanning waiting for {threads_left} threads to finish... {char}", end="", flush=True)
            time.sleep(0.1)
    print("\rScan complete!   ")

# Scan the network and check for reachable devices
def scan_network():
    global threads_left
    ts = time.time()
    global scanning
    network = ipaddress.IPv4Network(NETWORK_RANGE, strict=False)
    scanning = True

    threads = []
    ct = 0
    for ip in network.hosts():
        ip_thread = threading.Thread(target=check_ip, args=(ip,))
        ip_thread.start()
        threads.append(ip_thread)
        threads_left += 1
        ct += 1

    print(f"[{ct}] Scanning threads launched in parallel, be patient for roughly 15 seconds give or take...")

    throbber_thread = threading.Thread(target=throbber)
    throbber_thread.start()

    for t in threads:
        t.join()
    print(f"\r\n[{ct}] Threads finished locating {len(discovered_cameras)} cameras in {round(time.time() - ts)} seconds flat....")
    scanning = False

    # Save discovered cameras to a JSON file
    with open('discovered_cameras.json', 'w') as json_file:
        json.dump(discovered_cameras, json_file, indent=4)

    # Launch the browser to display the HTML file
    webbrowser.open('http://localhost:8000')

    # Wait for all threads to finish

# HTML content to display the discovered cameras
HTML_CONTENT = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Discovered Cameras</title>
    <style>
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            padding: 8px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }
        th {
            cursor: pointer;
        }
        th.sort-asc::after {
            content: " ▲";
        }
        th.sort-desc::after {
            content: " ▼";
        }
        tr:nth-child(even) {
            background-color: #f2f2f2;
        }
        tr:hover {
            background-color: #ddd;
        }
    </style>
</head>
<body>
    <h1>Discovered Cameras</h1>

    <!--
                <th onclick="sortTable(7)">Hardware Version</th>
                <th onclick="sortTable(8)">Update Serial</th>
                <th onclick="sortTable(9)">Update Serial Cloud Upgrade</th>
                <th onclick="sortTable(10)">App Auto Start</th>
    -->

    <table id="cameraTable">
        <thead>
            <tr>
                <th onclick="sortTable(0)">IP Address</th>
                <th onclick="sortTable(1)">Password Used</th>
                <th onclick="sortTable(2)">MAC Address</th>
                <th onclick="sortTable(3)">Processor</th>
                <th onclick="sortTable(4)">Device Type</th>
                <th onclick="sortTable(5)">Serial Number</th>
                <th onclick="sortTable(6)">System Info</th>

            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>

    <script>


        //<td>${camera.hardwareVersion}</td>
        /// <td>${camera.updateSerial}</td>
        // <td>${camera.updateSerialCloudUpgrade}</td>
        //  <td>${camera.appAutoStart}</td>
        document.addEventListener('DOMContentLoaded', function() {
            fetch('discovered_cameras.json')
                .then(response => response.json())
                .then(data => {
                    const tableBody = document.querySelector('#cameraTable tbody');
                    data.forEach(camera => {
                        const row = document.createElement('tr');
                        row.innerHTML = `
                            <td>${camera.ip}</td>
                            <td>${camera.password_used}</td>
                            <td>${camera.mac_address}</td>
                            <td>${camera.processor}</td>
                            <td>${camera.deviceType}</td>
                            <td>${camera.serialNumber}</td>
                            <td>${camera.system_info}</td>
                        `;
                        tableBody.appendChild(row);
                    });
                    sortTable(0, true); // Default sort by IP Address descending
                });
        });

        function sortTable(columnIndex, descending = false) {
            const table = document.getElementById('cameraTable');
            const tbody = table.tBodies[0];
            const rows = Array.from(tbody.rows);
            const th = table.tHead.rows[0].cells[columnIndex];

            rows.sort((a, b) => {
                const aText = a.cells[columnIndex].textContent.trim();
                const bText = b.cells[columnIndex].textContent.trim();
                return aText.localeCompare(bText, undefined, {numeric: true});
            });

            if (descending) {
                rows.reverse();
            }

            rows.forEach(row => tbody.appendChild(row));

            Array.from(th.parentNode.cells).forEach(cell => cell.classList.remove('sort-asc', 'sort-desc'));
            th.classList.add(descending ? 'sort-desc' : 'sort-asc');
        }
    </script>
</body>
</html>
"""

class CustomHandler(SimpleHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write(HTML_CONTENT.encode('utf-8'))
        elif self.path == '/discovered_cameras.json':
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            with open('discovered_cameras.json', 'r') as json_file:
                self.wfile.write(json_file.read().encode('utf-8'))
        else:
            self.send_error(404, "File not found")

def run_server():
    server_address = ('', 8000)
    httpd = HTTPServer(server_address, CustomHandler)
    print("Serving on port 8000...")
    httpd.serve_forever()

# Main function to run the scan
if __name__ == "__main__":
    try:
        scan_network()
        
        print("\nScan complete. Discovered devices:")
        for cam in discovered_cameras:
            print(f"\nCamera IP: {cam['ip']}\nPassword Used: {cam['password_used']}\nMAC Address: {cam['mac_address']}\nSystem Info:\n{cam['system_info']}")

        # Run the server to display the HTML content
        run_server()
    except KeyboardInterrupt:
        print("\n\nScan aborted by user. Exiting script gracefully...")
        sys.exit(0)

-
Post Reply