- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| doc | ||
| src | ||
| .gitignore | ||
| LICENSE | ||
| README.md | ||
| requirements.txt | ||
hikextractor-gui
Script to parse HIKVISION DVR hard drives and export the footage
This script was written as an effort to extract footage from a specific DVR (JFL TradeMark, model DHD-2104N). It's HD contained strings that identify it as HIKVISION, version HIK.2011.03.08. This script was written based on the following paper: Paper.
The format found in the HD was not the same as the described in the paper, but the overall structure was the same (maybe a different version).
The script has also been successfully tested on the HDD from a DS-7208HQHI-SH/A DVR model, that had the real-time clock fail due to age and was recording with semi-random timestamps due to multiple power failures. For this use case the --physical-order option was added, to retrieve video data in the order it was stored on the HD (with the hope that the recording just reuses the same storage area over and over, while leaving timestamps run out of order).
It was tested on windows and linux, using a DD image of the HD as input. It uses FFmpeg to mux the video into MP4 files, so FFmpeg should be in the os search path (ffmpeg.exe in the same folder as the script is enough). You can get a copy of FFmpeg here: FFmpeg. For linux, you can use your package manager to install it.
The script was tested using python 3.9 and python 3.13, but any version from 3.7 on should work.
The HD Image can be created using dd (from linux), any forensic imager (FTK Imager, for instance). You can also use the HDD Raw Copy Tool from HDDGURU: HDD Raw Copy Tool. Direct usage on an actual HDD is not recommended, even if it has been successfully tested.
Usage examples
Use
python hikextractor.py -h
to view available options and a short description for each.
Decode master block (CLI)
In the folder containing the file hikextractor.py:
python hikextractor.py -i <INPUT_IMAGE.DD> -m
List available footage (CLI)
In the folder containing the file hikextractor.py:
python hikextractor.py -i <INPUT_IMAGE.DD> -l
Run Graphical User Interface (GUI) 🖥️
For a user-friendly, visual experience, run the dedicated GUI script. This simplifies selecting the input image and output directory.
In the folder containing the file hikextractor-gui.py:
python hikextractor-gui.py
- A window will open, allowing you to select the HD raw image and the output folder.
- FFmpeg must still be accessible for the extraction process to work.
Extract all footage (CLI)
In the folder containing the file hikextractor.py and ffmpeg.exe:
python hikextractor.py -i <INPUT_IMAGE.DD> -o <OUTPUT_DIR>
INPUT_IMAGE.DD: HD raw image file.OUTPUT_DIR: Output folder where the MP4 videos will be saved.
Extract all footage to raw h264 Stream (CLI)
If FFmpeg cannot mux the H264 stream to an MP4 file, you can export the raw H264 stream instead. It can be played using the VLC Media Player.
winget install --id=Gyan.FFmpeg -e
In the folder containing the file hikextractor.py and ffmpeg.exe:
python hikextractor.py -i <INPUT_IMAGE.DD> -o <OUTPUT_DIR> -r
INPUT_IMAGE.DD: HD raw imageOUTPUT_DIR: Output folder where the mp4 videos will be saved to
Extract all footage in physical order
python hikextractor.py -i <INPUT_IMAGE.DD> -o <OUTPUT_DIR> --physical-order
Extract all footage for just one channel
python hikextractor.py -i <INPUT_IMAGE.DD> -o <OUTPUT_DIR> -c <CHANNEL_NUMBER>
Changes for direct drive reading and time filtering
A few things were added on top of the original script:
Read straight from the DVR disk on Windows
-i also accepts a physical drive now, so the .dd image step can be skipped:
python hikextractor.py -i PHYSICALDRIVE9 -o <OUTPUT_DIR>
\\.\PHYSICALDRIVE9, PHYSICALDRIVE9 and plain 9 all work. The drive is opened read-only over ctypes, no extra packages needed, but the terminal has to run as admin. The drive number can change between reboots, check it in Disk Management first.
Export only a timeframe
python hikextractor.py -i PHYSICALDRIVE9 -o <OUTPUT_DIR> --from "2026-09-02 10:00" --to "2026-09-02 18:00"
--from and --to take a date or date and time. Only footage blocks that overlap the range get exported, works together with -c and --physical-order and also in list mode with -l. Blocks still being recorded have no trustworthy timestamps and are always included.
The drive size bug ("Wrong HIKBTREE Signature")
Reading a real drive kept failing with Wrong HIKBTREE Signature while the same disk as a .dd image worked. The cause: the script got the drive size from the CHS geometry values (cylinders * tracks * sectors * bytes-per-sector). That math reports less than the real capacity on modern drives, on the 2 TB test disk it was about 2.4 MiB short. The HIK index tree is stored in exactly that last gap at the end of the disk, so every read into it came back empty and the parser never saw the HIKBTREE signature.
The fix: the size now comes from IOCTL_DISK_GET_LENGTH_INFO, which returns the exact byte size of the disk. If the master block reports a bigger capacity than that, the readable range is widened to match. The tree offsets are printed with the master block info now, which is what made the missing data visible in the first place.
One more Windows quirk worth knowing: device handles cannot be memory mapped, so when the input is a drive the script reads it in 1 MiB chunks through a plain buffer instead of mmap.