mirror of
https://github.com/AlexGustafsson/dlink-dcs-reversing.git
synced 2025-12-08 21:54:37 +01:00
Initial commit
This commit is contained in:
commit
3233091d32
6 changed files with 205 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.DS_Store
|
||||
firmware
|
||||
dump
|
||||
73
README.md
Normal file
73
README.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# D-Link DCS reversing
|
||||
### An effort to simplify firmware analysis and firmware updating on D-Link's DCS line of products
|
||||
***
|
||||
|
||||
## Project goal
|
||||
|
||||
The short-term goal of this project is to provide the necessary tools to easily analyze and modify D-Link's firmware for its DCS line of products (such as their network cameras).
|
||||
|
||||
A long-term goal is to be able to provide an alternative firmware with only the bare essentials to use the camera in order to fully disable all cloud aspects of the camera and to potentially make it HomeKit-compatible.
|
||||
|
||||
## What's in the box
|
||||
|
||||
### Scripts
|
||||
|
||||
#### Firmware
|
||||
|
||||
The `./scripts/download-firmware.sh` script downloads the firmware for a specific product. For example, one can download the latest firmware for the DCS-936L like so:
|
||||
|
||||
```sh
|
||||
./scripts/download-firmware.sh <model> <output directory> [firmware index]
|
||||
./scripts/download-firmware.sh dcs-936l firmware 1
|
||||
```
|
||||
|
||||
The `./scripts/unpack-firmware.sh` script decrypts, unpacks and carves date from the firmware file. It can be used like so:
|
||||
|
||||
```sh
|
||||
./scripts/unpack-firmware.sh <path to firmware> <output directory>
|
||||
./scripts/unpack-firmware.sh firmware/DCS-936L_fw_revA1_1-07-04_eu_multi_20180918.zip dump
|
||||
```
|
||||
|
||||
Example (shallow) directory structure for the unpacking script:
|
||||
|
||||
```
|
||||
❯ tree -L 4 -d dump/
|
||||
dump/
|
||||
├── carved
|
||||
│ └── _update.extracted
|
||||
│ ├── squashfs-root
|
||||
│ └── squashfs-root-0
|
||||
│ ├── empty -> /tmp
|
||||
│ ├── lib -> /tmp
|
||||
│ ├── lock -> /tmp
|
||||
│ ├── log -> /tmp
|
||||
│ ├── run -> /tmp
|
||||
│ ├── shares
|
||||
│ ├── tmp -> /tmp
|
||||
│ └── www
|
||||
└── extracted
|
||||
```
|
||||
|
||||
### Tools
|
||||
|
||||
The `./tools` directory contains dockerized tools such as Binwalk. The tools can be built and used using the following script:
|
||||
|
||||
```sh
|
||||
./tools/build.sh
|
||||
docker run -it binwalk
|
||||
```
|
||||
|
||||
## Previous art
|
||||
|
||||
https://github.com/bmork/defogger
|
||||
|
||||
## Contributing
|
||||
|
||||
Any contribution is welcome. If you're not able to code it yourself, perhaps someone else is - so post an issue if there's anything on your mind.
|
||||
|
||||
### Development
|
||||
|
||||
Clone the repository:
|
||||
```
|
||||
git clone https://github.com/AlexGustafsson/dlink-dcs-reversing && cd dlink-dcs-reversing
|
||||
```
|
||||
48
scripts/download-firmware.sh
Executable file
48
scripts/download-firmware.sh
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
model="$1"
|
||||
output_directory="$2"
|
||||
firmware_index="$3"
|
||||
|
||||
function search() {
|
||||
query="$1"
|
||||
curl -s "https://eu.dlink.com/uk/en/search/suggestions?mode=ajax&q=$query" | grep -e 'item-listing.*href' | sed 's/.*href="\([^"]\+\)".*/\1/'
|
||||
}
|
||||
|
||||
function find_firmware() {
|
||||
page="$1"
|
||||
curl -s "https://eu.dlink.com$page" | grep "href" | sed 's/.*href="\([^"]\+\)".*/\1/' | grep ".zip"
|
||||
}
|
||||
|
||||
function find_all_firmware() {
|
||||
while read -r page; do
|
||||
find_firmware "$page"
|
||||
done
|
||||
}
|
||||
|
||||
search_result="$(search "$model")"
|
||||
if [[ -z "$search_result" ]]; then
|
||||
echo "Unable to find any matching model"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
all_firmware="$(echo "$search_result" | find_all_firmware)"
|
||||
if [[ -z "$all_firmware" ]]; then
|
||||
echo "Unable to find any firmware for that model"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$firmware_index" ]]; then
|
||||
echo "Found firmware the following firmware"
|
||||
echo "$all_firmware" | nl -w1 -s' '
|
||||
echo -ne "\nWhich firmware do you want to download? "
|
||||
read firmware_index
|
||||
fi
|
||||
|
||||
firmware="$(echo "$all_firmware" | sed -n "${firmware_index}p")"
|
||||
if [[ -z "$firmware" ]]; then
|
||||
echo "No such firmware"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wget --directory-prefix="$output_directory" "$firmware"
|
||||
67
scripts/unpack-firmware.sh
Executable file
67
scripts/unpack-firmware.sh
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
USE_DOCKER="${USE_DOCKER:-1}"
|
||||
|
||||
# The input firmware zip file as downloaded from D-Link's website
|
||||
firmware_zip="$1"
|
||||
|
||||
# Output directory
|
||||
output="$2"
|
||||
|
||||
# The RSA private key dumped from the device using the following command:
|
||||
# pibinfo PriKey
|
||||
private_key="$(cat << EOF
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQC87QYtji6c0odxDs5SON+lpP0WE52WMK4OuRo8mHL0HWi0bZe0
|
||||
dyDcJ6IO6EwKuIn0sJi5oY8/P0g3PAp4TTlZm6WBiwZ8XaPwnGY8Kd2lrcRvPR+0
|
||||
UJ07hQ4RvhfFmanN8KEhe/myKkMldO/reyW8nwRRJwc2OHEvZ81KfAppWwIDAQAB
|
||||
AoGAKGeIqrV9woxD6yn/dhYzvnlKpy4KxdQjZYKw2cTA0PR5MB1AFJhlrq/LOOT1
|
||||
XlWZK3uZLhofSKeAClAM7S2W1fTbxmM8y/3g6c5Z3LbpNsvwVTWNp5ErbKMMeR+q
|
||||
CnUA+NQ47f65EwUUyTIWhMcgINLjZT33Eg0DOPUVIoiDEgECQQDta5ehRLQQN8Tr
|
||||
5OROwFrJA3qL4g+qmcnUrVfgDE/ro1zxcYluleg8ZCAJbhBgju7Y75voRlrZITkF
|
||||
2dGFZq4PAkEAy7Xowx+az4ZU6Iw/AGmbv801digR9345UKZZNRLffLh0Hda2mPM+
|
||||
25whWWTMiPcY0ty9/MZovZvVyuYuxzHb9QJBAJlbEgpdMmH3Y/9rTf2ASiPlV1bb
|
||||
onrz82aowUY7LbRrRTG/wKHpuqSnl/n/WhzEtorx2qbiKvRtfUPGOowMkwkCQGgi
|
||||
n9BPcbYwd2tBdlthoUrVPkUeisC399iwkN2+vhxltoYiYsmhXzqof6vRCXXiyv/P
|
||||
9Bcp3hU/enT0YmlVpZkCQQDmsui42t0uup3hj6ITZa2JRkCCUI7qyU0HrE65lj88
|
||||
s4IoUXr0RWUtnEbeDUbw2GtQVHNoldXVXSh30SDb6El7
|
||||
-----END RSA PRIVATE KEY-----
|
||||
EOF
|
||||
)"
|
||||
|
||||
# Temporary directory used throughtout the unpacking
|
||||
temp_directory="$(mktemp -d)"
|
||||
|
||||
# First unzip the file which contains a single tar file
|
||||
unzip -p "$firmware_zip" > "$temp_directory/firmware.tar"
|
||||
|
||||
# Untar the file
|
||||
tar --extract --directory="$temp_directory" --file="$temp_directory/firmware.tar"
|
||||
rm "$temp_directory/firmware.tar"
|
||||
|
||||
# Decrypt the AES encryption key
|
||||
echo "$private_key" > "$temp_directory/rsa.key"
|
||||
openssl rsautl -decrypt -in "$temp_directory/aes.key.rsa" -out "$temp_directory/aes.key" -inkey "$temp_directory/rsa.key"
|
||||
|
||||
# Decrypt the update itself
|
||||
openssl aes-128-cbc -v -nosalt -md md5 -d -in "$temp_directory/update.aes" -out "$temp_directory/update" -kfile "$temp_directory/aes.key"
|
||||
openssl aes-128-cbc -v -nosalt -md md5 -d -in "$temp_directory/update.bin.aes" -out "$temp_directory/update.bin" -kfile "$temp_directory/aes.key"
|
||||
|
||||
# Move the firmware to the target directory
|
||||
mkdir -p "$output/extracted"
|
||||
mv "$temp_directory/update" "$output/extracted"
|
||||
mv "$temp_directory/update.bin" "$output/extracted"
|
||||
|
||||
# Remove the temporary directory
|
||||
rm -r "$temp_directory"
|
||||
|
||||
# Unpack the base64 encoded binary within update.bin
|
||||
mkdir -p "$output/carved"
|
||||
cat "$output/extracted/update.bin" | tr -d '\n' | sed 's!.*=== ddPack Boundary ===begin-base64 755 /dev/stdout!!' | rev | cut -c 5- | rev | base64 -d > "$output/carved/payload"
|
||||
|
||||
# Extract files from the update payload
|
||||
if [[ "$USE_DOCKER" -eq 1 ]]; then
|
||||
docker run --rm -it -v "$(realpath "$output"):/output" binwalk --extract --directory "/output/carved" "/output/extracted/update"
|
||||
else
|
||||
binwalk --extract --directory "$output/carved" "$output/extracted/update"
|
||||
fi
|
||||
11
tools/Dockerfile.binwalk
Normal file
11
tools/Dockerfile.binwalk
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
FROM debian:buster-slim
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y python3 git squashfs-tools python3-pip && \
|
||||
git clone https://github.com/ReFirmLabs/binwalk.git && \
|
||||
cd binwalk && \
|
||||
python3 setup.py install
|
||||
|
||||
VOLUME /output
|
||||
|
||||
ENTRYPOINT ["binwalk"]
|
||||
3
tools/build.sh
Executable file
3
tools/build.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
docker build -t binwalk -f tools/Dockerfile.binwalk .
|
||||
Loading…
Add table
Reference in a new issue