Dahua CCTV cameras use proprietary protocol, replying on TCP port 37777.
Here are absent server or NAS or NVR/DVR[1] (I use a fake server Python script instead of it) and working Dahua CCTV camera. Here is Dahua camera tries to connect to a (fake) server/NAS/NVR/DVR, to auth and to upload video.
The user is 'admin' and the password (I knew beforehand) is 'Admin12345'.
Camera to (fake) server: 00000000: A0 05 00 60 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000010: 00 00 00 00 00 00 00 00 04 02 00 01 00 00 00 00 ................ (Fake) server to camera: 00000000: B0 01 00 78 46 00 00 00 01 0E 10 00 00 00 00 00 ...xF........... 00000010: 00 00 00 00 01 00 00 00 06 00 F9 00 00 00 00 02 ................ 00000020: 52 65 61 6C 6D 3A 4C 6F 67 69 6E 20 74 6F 20 30 Realm:Login to 0 00000030: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000 00000040: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0D 000000000000000. 00000050: 0A 52 61 6E 64 6F 6D 3A 31 32 33 34 35 36 37 38 .Random:12345678 00000060: 39 30 0D 0A 0D 0A 90.... Camera to (fake) server: 00000000: A0 05 00 60 47 00 00 00 00 00 00 00 00 00 00 00 ....G........... 00000010: 00 00 00 00 00 00 00 00 04 02 00 08 00 00 A1 AA ................ 00000020: 61 64 6D 69 6E 26 26 31 30 45 34 30 39 33 39 32 admin&&10E409392 00000030: 38 39 32 34 41 38 39 45 37 37 38 44 42 45 31 38 8924A89E778DBE18 00000040: 41 46 42 36 44 38 42 38 37 36 31 31 37 33 32 33 AFB6D8B876117323 00000050: 44 31 37 45 32 37 32 46 34 32 43 32 43 44 31 35 D17E272F42C2CD15 00000060: 34 30 45 44 44 32 44 40EDD2D First half: 10E4093928924A89E778DBE18AFB6D8B Second half: 876117323D17E272F42C2CD1540EDD2D
And this is a fake server Python code:
#!/usr/bin/env python3
import socket, hexdump, sys
to_send=b""
to_send+=b"\xb0\x01\x00\x78\x46\x00\x00\x00\x01\x0e\x10\x00\x00\x00\x00\x00"
to_send+=b"\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\xf9\x00\x00\x00\x00\x02"
to_send+=b"Realm:Login to 00000000000000000000000000000000\x0d\x0a"
to_send+=b"Random:1234567890\x0d\x0a\x0d\x0a"
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('0.0.0.0', 37777))
serversocket.listen(5) # become a server socket, maximum 5 connections
while True:
connection, address = serversocket.accept()
buf = connection.recv(1024)
if len(buf) > 0:
print ("recv:")
hexdump.hexdump(buf)
print ("send:")
hexdump.hexdump(to_send)
connection.send(to_send)
buf=connection.recv(1024)
print ("recv:")
hexdump.hexdump(buf)
break
What is second half (32 nibbles or 16 bytes), I don't know. But the first half is calculated as:
str_upper(hex(md5(username:random:str_upper(hex(md5(username:realm:password))))))
This formula is similar to RTSP, but somewhat different, and string uppercase operation is also used. Also, the 'Random' term is used instead of 'nonce'.
The code to calculate this hash:
#!/usr/bin/env python3
import hashlib
username="admin"
password="Admin12345"
def hashed_password(random, realm):
h = hashlib.md5(f"{username}:{realm}:{password}".encode("utf-8")).hexdigest().upper()
return hashlib.md5(f"{username}:{random}:{h}".encode("utf-8")).hexdigest().upper()
realm="Login to 00000000000000000000000000000000"
random="1234567890"
print (hashed_password(random, realm))
It will print: 10E4093928924A89E778DBE18AFB6D8B.
I couldn't find a way to run Hashcat for this auth. Maybe in future it will be available.
[1] DVR - digital video recorder; NVR - network video recorder.
