hiktools’ documentation!

Features

  • “Native” interface on sending and receiving SADP packets

  • Client for XML based UDP communication on port 37020

  • Generation of old reset code

  • Hikvision firmware inspector and extractor

  • Wireshark dissector written in Lua for Search Active Devices Protocol (SADP)

  • Disassebled C/C++ code snippets for checksum algorithm and packet building

Note

Previos versions of hiktools were unstable in terms of working with firmware files, but since 1.2.2 the while codebase has been refactored to be more robust.

Usage

Installation

git clone https://github.com/MatrixEditor/hiktools.git
cd hiktools/ && pip install .

Build the docs:

cd docs/
pip install -U sphinx
sphinx-build -b html source build

Install dissector

Open up wireshark go to Help > About Wireshark > search for “Global Lua Plugins” and copy the location.

$LOCATION="..."
# on unix
cp hiktools/lua/sadp.lua $LOCATION/sadp.lua
# on windows
copy "hiktools\lua\sadp.lua" "$LOCATION\sadp.lua"

Basic Usage

  • Firmware inspection and extraction

from hiktools import fmod

# Open the resource at the specified path (loading is done automatically)
# or manually decrypt the firmware file.
with fmod.DigiCap('filename.dav') as dcap:
   # Iterate over all files stored in the DigiCap object
   for file_info in dcap:
      print('> File name="%s", size=%d, pos=%d, checksum=%d' % file_info)

   # get file amount and current language
   print("Files: %d, Language: %d" % (dcap.head.files, dcap.head.language))

   # save all files stored in <filename.dav>
   fmod.export(dcap, "outdir/")
  • Native interface on sending raw packets (only LINUX)

from hiktools import csadp

# Because the following module requires root priviledges it has to be
# imported directly
from hiktools.csadp import CService

sock = CService.l2socket('wlan0')
counter = 2855

# Building an inquiry packet
packet = csadp.packet(
   'src_mac', 'src_ip', 0x03, counter,
   checksum=csadp.from_counter(counter),
   payload='\x00'*28
)

# If you want to have the packet as an object use parse()
packet_obj = csadp.parse(packet)

sock.send(packet) # or sock.send(bytes(packet_obj))
response = csadp.parse(sock.recv(1024))
  • Interact with the device through UDP broadcast

from hiktools import sadp
from uuid import uuid4

# create a packet from a simple dict object
inquiry = sadp.fromdict({
   'Uuid': str(uuid4()).upper(),
   'MAC': 'ff-ff-ff-ff-ff-ff',
   'Types': 'inquiry'
})

# Open up a client to communicate over broadcast
with sadp.SADPClient() as client:
   # send the inquiry packet
   client.write(inquiry)

   # iterate over all received packets (None is returned on error)
   for response in client:
      if response is None: break
      # initiate the response
      message = sadp.unmarshal(response.toxml())

      # message objects contain a dict-like implementation
      for property_name in message:
         print(message[property_name])

      # e.g.
      print('Device at', message['IPv4Address'])

Indices and tables