summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2019-05-15 00:42:25 +0200
committerBjørn Mork <bjorn@mork.no>2019-05-15 00:42:25 +0200
commit1d4577ccfa932255656db76e7f8b8cf4334a730f (patch)
tree98a688411ce58983b841a788c5e2b56d87c367b5
parente45eee8546e64a4a34e017479638bfca060babfb (diff)
docs finished
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--dcs8000lh.md1646
1 files changed, 833 insertions, 813 deletions
diff --git a/dcs8000lh.md b/dcs8000lh.md
index 9be7261..4dfa584 100644
--- a/dcs8000lh.md
+++ b/dcs8000lh.md
@@ -1,73 +1,452 @@
# D-Link DCS-8000LH
-## Hardware spec
+These are random notes descibing how I changed my D-Link DCS-8000LH
+from a cloud camera to a locally managed IP camera, streaming H.264
+MPEG-TS over HTTP and HTTPS. Some of the tools and ideas might work
+for other cameras too, given some model specific adaptation.
- *
- *
+Complete defogging requires modifying one of the file systems in the
+camera. This implies a slight risk of ending up with a brick. You
+have now been warned...
-No ethernet. No USB. No memory card slot.
+This is tested and developed on firmware versions v2.01.03 and
+v2.02.02 only. The final complete procedure has only been tested with
+v2.02.02. It should work fine with v2.01.03 and other versions, in
+theory, but could fail like anything untested. Please let me know if
+you have an original v2.01.03 firmware update from D-Link, or any
+other version for that matter, or know where firmware updates can be
+downloaded.
-Currently unsupported by OpenWrt.
+The v2.02.02 update is available from
+https://mydlinkmpfw.auto.mydlink.com/DCS-8000LH/DCS-8000LH_Ax_v2.02.02_3014.bin
+at the time of writing. But I assume this link stops working as soon
+as there is a newer version available.
-## Foggy business
+## Problem
-Bummer. Got a new camera with firmware version 2.01.03. This version
-is locked to a app/cloud service. It does not run a local NIPCA
-compatible web API, and it does not stream video in a fashion we can
-easily access. And there is no way to downgrade the firmware either.
-In fact, there is no easy way to install any firmware image
+Got a new D-Link DCS-8000LH with firmware version 2.01.03 from factory.
+This firmware is locked to the "mydlink" app/cloud service. It does
+not provide a local NIPCA compatible HTTP API or similar, and it does
+not stream video over HTTP, HTTPS or RTSP.
+Additionally, there is no way to downgrade the firmware. In fact,
+there is no documented way to install any firmware image at all,
+except trusting the "mydlink" cloud service to do it for you.
-## Serial console
-Despite the above, I gotta love D-Link for this one.
+## Solution
-Started opening the case, which is pretty simple: Remove the two
-screws behind the bottom label, remove the top and bottom "lids".
-Split the two cylinder halves.
+#### Primary goals achieved:
-But I didn't finish opening the case, because I discovered that the
-serial console is accessible from the outside! There is a 2 mm, 4
-hole, female header in the bottom of the camera. This header is
-accessible via 4 tiny holes in the case behind the bottom
-label. Simply mate it with a 3 (or 4) pin male 2 mm connector, and you
-have console!
+* configuration of network and admin password via Bluetooth LE, without
+ registering with D-Link or using the "mydlink" app at all
+* streaming MPEG-TS directly from camera over HTTP and HTTPS
+* HTTP API based configuration of most settings, like LED, nightmode, etc
+
+#### And some extra goodies which came for free
+
+* Firmware upgrades and downgrades via HTTP API
+* telnet server with a root account (admin/PIN Code)
+* easy access to serial console, using the same root account
+* running arbitrary commands on the camera using Bluetooth
+
+Read on for all the gory details...
+
+
+### Requirements
+
+ * a Linux PC with a Bluetooth controller
+ * python3 with the **bluepy** library: https://ianharvey.github.io/bluepy-doc/index.html
+ * WiFi network with WPA2-PSK and a known password
+ * mksquashfs from the squashfs-tools package
+ * a tftp server or web server accepting file uploads (for backups)
+ * guts :-)
+
+Most recent Linux distros will probably do. The bluepy library can be
+installed using pip if it is not available as a distro package. Other
+types of WiFi networks might work, but has not been tested with the
+provided tools. The squashfs-tools are only necessary if you want to
+rebuild the "mydlink" alternative file system. I assume you can even
+run the tools without installing Linux, by using a Linux "Live"
+CD/DVD/USB stick.
+
+This was developed and tested on Debian Buster.
+
+
+
+### Camera configuration using the Bluetooth LE GATT API
+
+The "mydlink" app uses Bluetooth LE for camera setup, authenticated by
+the camera pincode. This repo includes an alternative python script
+with a few extra goodies, but needing a better name:
+**dcs8000lh-configure.py**.
+
+(Why not an Android app? Because it would take me much more time to
+write. Should be fairly easy to do though, for anyone with enough
+interest. You can find all the necessary protocol details here and in
+the python code. Please let me know if you are interested)
+
+The script does not support scanning for the simple reason that this
+would require root access for not real gain. You have to provide the
+**PIN Code** from the camera label anyway. Reading the **MAC** as
+well is simple enough.
+
+The command line *address* paramenter should be formatted as
+**01:23:45:67:89:AB**, and not like the **0123456789AB** format
+printed on the label.
+
+Current script help text at the time of writing shows what the script
+can do:
+
+```
+$ ./dcs8000lh-configure.py -h
+usage: dcs8000lh-configure.py [-h] [--essid ESSID] [--wifipw WIFIPW]
+ [--survey] [--netconf] [--sysinfo]
+ [--command COMMAND] [--telnetd] [--lighttpd]
+ [--unsignedfw] [--attrs] [-V]
+ address pincode
+
+IPCam Bluetooth configuration tool.
+
+positional arguments:
+ address IPCam Bluetooth MAC address (01:23:45:67:89:AB)
+ pincode IPCam PIN Code (6 digits)
+
+optional arguments:
+ -h, --help show this help message and exit
+ --essid ESSID Connect to this WiFi network
+ --wifipw WIFIPW Password for ESSID
+ --survey List WiFi networks seen by the IPCam
+ --netconf Print current network configuration
+ --sysinfo Dump system configuration
+ --command COMMAND Run command on IPCam
+ --telnetd Start telnet server on IPCam
+ --lighttpd Start web server on IPCam
+ --unsignedfw Allow unsigned firmware
+ --attrs Dump IPCam GATT characteristics
+ -V, --version show program's version number and exit
+```
+
+
+#### Real session excample after a clean upgrade to firmware v2.02.02, followed by factory reset
+
+1. Start by making sure the camera can see our WiFi network. This
+ also verifies that we can connect and authenticate against the
+ Bluetooth LE IPCam service, without making any changes to any
+ camera settings:
+
+```
+$ ./dcs8000lh-configure.py B0:C5:54:AA:BB:CC 123456 --survey
+Connecting to B0:C5:54:AA:BB:CC...
+Verifying IPCam service
+Connected to 'DCS-8000LH-BBCC'
+DCS-8000LH-BBCC is scanning for WiFi networks...
+{'I': 'AirLink126FD4', 'M': '0', 'C': '11', 'S': '4', 'E': '2', 'P': '47'}
+{'I': 'Antiboks', 'M': '0', 'C': '11', 'S': '4', 'E': '2', 'P': '73'}
+{'I': 'ASV17', 'M': '0', 'C': '11', 'S': '4', 'E': '2', 'P': '47'}
+{'I': 'ASV17-dlink', 'M': '0', 'C': '6', 'S': '4', 'E': '2', 'P': '57'}
+{'I': 'DIRECT-33-HP%20ENVY%205000%20series', 'M': '0', 'C': '1', 'S': '4', 'E': '2', 'P': '46'}
+{'I': 'fjorde123', 'M': '0', 'C': '1', 'S': '4', 'E': '2', 'P': '55'}
+{'I': 'JOJ', 'M': '0', 'C': '11', 'S': '4', 'E': '2', 'P': '48'}
+{'I': 'Kjellerbod', 'M': '0', 'C': '11', 'S': '4', 'E': '2', 'P': '75'}
+{'I': 'Landskap_24', 'M': '0', 'C': '11', 'S': '4', 'E': '2', 'P': '46'}
+{'I': 'mgmt', 'M': '0', 'C': '1', 'S': '4', 'E': '2', 'P': '72'}
+{'I': 'Rindedal', 'M': '0', 'C': '11', 'S': '4', 'E': '2', 'P': '68'}
+{'I': 'risikovirus', 'M': '0', 'C': '1', 'S': '4', 'E': '2', 'P': '45'}
+{'I': 'risikovirus%20WIFI', 'M': '0', 'C': '11', 'S': '4', 'E': '2', 'P': '45'}
+{'I': 'Stavik2014', 'M': '0', 'C': '6', 'S': '4', 'E': '2', 'P': '47'}
+{'I': 'TomterNett1', 'M': '0', 'C': '6', 'S': '4', 'E': '2', 'P': '44'}
+{'I': 'VIF', 'M': '0', 'C': '11', 'S': '4', 'E': '2', 'P': '47'}
+Done.
+```
+
+2. We're going to use the 'Kjellerbod' network, so that looks good.
+ Select it and give the associated WiFi password to the camera:
+
+```
+$ ./dcs8000lh-configure.py B0:C5:54:AA:BB:CC 123456 --essid Kjellerbod --wifipw redacted
+Connecting to B0:C5:54:AA:BB:CC...
+Verifying IPCam service
+Connected to 'DCS-8000LH-BBCC'
+DCS-8000LH-BBCC is scanning for WiFi networks...
+Will configure: M=0;I=Kjellerbod;S=4;E=2;K=redacted
+Done.
+```
+
+3. Verify that the camera connected to the Wifi network and got an
+ address. If not, go back and try again, making sure you are using
+ the correct WiFi password:
+
+```
+$ ./dcs8000lh-configure.py B0:C5:54:AA:BB:CC 123456 --netconf
+Connecting to B0:C5:54:AA:BB:CC...
+Verifying IPCam service
+Connected to 'DCS-8000LH-BBCC'
+wifi link is Up
+wifi config: {'M': '0', 'I': 'Kjellerbod', 'S': '4', 'E': '2'}
+ip config: {'I': '192.168.2.37', 'N': '255.255.255.0', 'G': '192.168.2.1', 'D': '148.122.16.253'}
+Done.
+```
+
+
+WARNING: You must make a backup of your device at this point if you
+haven't done so already. See the backup section below. I only skipped it
+in this example because I already had made a complete backup.
+
+
+
+4. We need HTTP NIPCA API for the remaining tasks, so temporarily
+ start lighttpd on the camera:
+
+```
+$ ./dcs8000lh-configure.py B0:C5:54:AA:BB:CC 123456 --lighttpd
+Connecting to B0:C5:54:AA:BB:CC...
+Verifying IPCam service
+Connected to 'DCS-8000LH-BBCC'
+Attempting to run '[ $(tdb get HTTPServer Enable_byte) -eq 1 ] || tdb set HTTPServer Enable_byte=1' on DCS-8000LH-BBCC by abusing the 'set admin password' request
+Attempting to run '/etc/rc.d/init.d/extra_lighttpd.sh start' on DCS-8000LH-BBCC by abusing the 'set admin password' request
+Done.
+```
+
+Note that this implicitly changes a couple of settings which are
+stored in the "db" NVRAM partition, and therefore will persist until
+the next factory reset:
+ * extra_lighttpd.sh will exit without doing anything unless
+ **HTTPServer Enable** is set
+ * the admin password is set both because we're abusing that BLE
+ request, and because we need it for the HTTP API access. The
+ script only supports setting the password to the **PIN Code**.
+
+(This password restriction is because I'm lazy - there is nothing in
+the camera or protocol preventing the password from being set to
+something else. But the script would then need the new password as
+an additional input parameter for most commands)
+
+
+5. Disable firmware signature verification. Only firmwares signed by
+ D-Link are accepted by default. This feature can be disabled by
+ changing a variable in the "db" NVRAM partition:
+
+```
+$ ./dcs8000lh-configure.py B0:C5:54:AA:BB:CC 123456 --unsignedfw
+Connecting to B0:C5:54:AA:BB:CC...
+Verifying IPCam service
+Connected to 'DCS-8000LH-BBCC'
+Attempting to run 'tdb set SecureFW _TrustLevel_byte=0' on DCS-8000LH-BBCC by abusing the 'set admin password' request
+Done.
+```
+
+6. The final step is the dangerous one. It replaces the file system
+ on the **userdata** partition with our home cooked one. The D-Link
+ firmware uses this partition exclusively for the "mydlink" cloud
+ tools, which we don't need. The rest of the system is not touched
+ by our firmware update. The camera will therefore run exactly the
+ same kernel and rootfs as before the update, whatever version they
+ were. I.e., the firmware version does not change - only the
+ "mydlink" version.
+```
+$ curl --http1.0 -u admin:123456 --form upload=@fw.tar http://192.168.2.37/config/firmwareupgrade.cgi
+upgrade=ok
+```
+
+The **firmwareupgrade.cgi** script running in the camera isn't much
+smarter than the rest of the system, so there are a few important
+things to note here. These are found by trial-and-error:
+ * HTTP/1.1 might not work - the firmwareupgrade.cgi script does not support **100 Continue** AFAICS
+ * The firmware update image should be provided as a **file** input field from a form
+ * The field name must be **upload**.
+
+Using the exact curl command as provided above, replcaing the PIN Code
+and IP address with the correct vaules for your camera, should
+work. Anything else might not.
+
+The camera will reboot automatically after a sucessful upgrade. But
+from now both telnetd and lighttpd is automatically started on every
+boot. And there will also be an **admin:PIN Code** account for both.
+
+
+#### unexpected errors during firmware update via HTTP
+
+The camera must be manually rebooted by removing power or pressing
+reset if the firmware upgrade fails for any reason. The
+**firmwareupgrade.cgi** script stops most processes, inluding the
+Bluetooth handler, and fails to restart them on errors.
+
+There will be no permanent harm if the upload fails. But note that
+you have to repeat the **--lighttpd** step after rebooting the camera,
+before you can retry. It does not start automatically until we've
+installed our modified "mydlink" alternative.
+
+The contents of the fw.tar file must obviously be a valid, encrypted,
+firmware update intended for the specified hardware. It must also be
+signed. But the signing key can be unknown to the camera provided the
+previous **--unsignedfw** request above was successful.
+
+The **Makefile** provided here shows how to build a valid firmware
+update, but for the DCS-8000LH only! It does not support any other
+model. It will create a new throwaway signing key if it canæt find a
+real one, and include the associated public key in the archive in case
+you want to verify the signature manually.
+
+Note that the encryption key might be model specific. I do not know
+this as I have no other model to look at. Please let me know if you
+have any information on this topic.
+
+The encryption key is part ot the **pib** partition, and can be
+read from a shell using
+```
+pibinfo PriKey
+```
+Or you can simply look at your partition backup. The key is stored as
+a plain text *RSA PRIVATE KEY* PEM blob, so it is easy to spot.
+
+
+### Backup
+
+Create a backup of everything *before* you mess up. Restoring will be
+hard anyway, so don't rely on that. But you can forget about
+restoring at all unless you have a backup, so make it anyway.
+
+Note that the **pib** partition contains data which are specific to
+**your** camera, and cannot be restored from any other source! This
+includes
+ * model number
+ * hardware revision
+ * mac address
+ * feature bits
+ * private keys, pincode and passwords
+
+Well, OK, we can restore most of the **pib** using information from
+the camera label, but it's better to avoid having to do that...
+
+A backup is also useful for analyzing the file systems offline.
+
+Making a backup without networking is inconvenient, so setup
+networking first. In theory, you could dump the flash to the serial
+console. But this would be very time consuming and tiresome.
+
+The D-Link firmware provides a selection of network file transfer
+tools. Pick anyone you like:
+ * tftp
+ * wget
+ * curl
+ * ...and probably more
+
+
+I've been using tftp for my backups because it is simple. You'll
+obviously need a tftp server for this. Google for instructions on
+setting that up. You could alternatively set up a web server and use
+wget or curl to post the files there, but this is more complx to set
+up IMHO.
+
+Here is one example of how to enable temporary telnet access and
+copying all camera flash partitions to a tftp server:
+
+```
+$ ./dcs8000lh-configure.py B0:C5:54:AA:BB:CC 123456 --telnetd
+Connecting to B0:C5:54:AA:BB:CC...
+Verifying IPCam service
+Connected to 'DCS-8000LH-BBCC'
+Adding the 'admin' user as an alias for 'root'
+Attempting to run 'grep -Eq ^admin: /etc/passwd||echo admin:x:0:0::/:/bin/sh >>/etc/passwd' on DCS-8000LH-BBCC by abusing the 'set admin password' request
+Setting the 'admin' user password to '123456'
+Attempting to run 'grep -Eq ^admin:x: /etc/passwd&&echo admin:123456|chpasswd' on DCS-8000LH-BBCC by abusing the 'set admin password' request
+Starting telnetd
+Attempting to run 'pidof telnetd||telnetd' on DCS-8000LH-BBCC by abusing the 'set admin password' request
+
+
+Attempting to run '[ $(tdb get HTTPServer Enable_byte) -eq 1 ] || tdb set HTTPServer Enable_byte=1' on DCS-8000LH-BBCC by abusing the 'set admin password' request
+Attempting to run '/etc/rc.d/init.d/extra_lighttpd.sh start' on DCS-8000LH-BBCC by abusing the 'set admin password' request
+Done.
+
+
+$ telnet 192.168.2.37
+Trying 192.168.2.37...
+Connected to 192.168.2.37.
+Escape character is '^]'.
+localhost login: admin
+Password:
+
+
+BusyBox v1.22.1 (2019-02-14 17:06:35 CST) built-in shell (ash)
+Enter 'help' for a list of built-in commands.
+
+
+# for i in 0 1 2 3 4 5 6 7 8; do tftp -l /dev/mtd${i}ro -r mtd$i -p 192.168.2.1; done`
+```
+
+Change 192.168.2.37 to the address of your camera and 192.168.2.1 to
+the address of your tftp server. Note that most tftp servers require
+existing and writable destination files. Refer to your tftp server docs
+for details.
+
+
+
+## All the gory details
+
+
+### Restoring original D-Link firmware
+
+The D-Link firmware, including the mydlink tools in the **userdata**
+partition, can be restored by doing a manual firmware upgrade
+providing a firmware update from D-Link. Real example, going back to
+v2.02.02:
+
+```
+$ curl --http1.0 -u admin:123456 --form upload=@DCS-8000LH_Ax_v2.02.02_3014.bin http://192.168.2.37/config/firmwareupgrade.cgi
+curl: (52) Empty reply from server
+```
+
+I don't know why I got that *Empty reply* warning instead of the
+expected *upgrade=ok*, but update went fine so I guess it can safely
+be ignored. Might be a side effect of rewriting the root file system,
+which the firmwareupgrade.cgi script is running from.
+
+
+### Serial console
+
+Entirely optional. The defogging procedure does not require console
+access, but it can be very useful when debugging problems related to
+network configuration etc.
+
+There is a 4 hole female header with 2 mm spacing in the bottom of the
+camera. This header is easily accessible without opening the case at
+all. But you will need to remove the bottom label to find it. Take a
+picure, or save the information somewhere else, first, in case you
+make the label unreadable.
+
+Mate with a 3 (or 4) pin male 2 mm connector, or use sufficiently
+solid wires. The pins need to be 6-10 mm long.
The pinout seen from center to edge of camera is:
| GND | RX | TX | 3.3V |
-You obviously need a 3.3V TTL adapter for this. I use a cheap PL2303
-based USB adapter from eBay. Look at the generic OpenWrt console
-instructions for guidance.
+You obviously need a 3.3V TTL adapter for this, Look at for example
+at the generic OpenWrt console instructions if you need guidance.
The serial port parameters are 57600 8N1
-## U-Boot
+### U-Boot
-The camera came with
+My DCS-8000LH came with this boot loader:
`U-Boot 2014.01-rc2-V1.1 (Jun 06 2018 - 03:44:37)`
-
-without too much vendor added mess AFIACS. There is one minor issue
-though: Access to the prompt is password protected.
-
-Still, even if this might provoke some bad thoughts, I just have to
-love D-Link for making the password readily available in their GPL
-package :-)
-
-From `DCS-8000LH-GPL/configs/gpl_defconfig`:
+But it is patched/configured to require a password for access to the
+U-Boot prompt. Fortunately, D-Link makes the password readily
+available in their GPL package :-) It is found in the file
+`DCS-8000LH-GPL/configs/gpl_defconfig`:
`ALPHA_FEATURES_UBOOT_LOGIN_PASSWORD="alpha168"`
-Enter this password when you see
+Enter **alpha168** password when you see
`Press ESC to abort autoboot in 3 seconds`
-And you'll get a `rlxboot#` prompt :
+and you'll get a `rlxboot#` prompt, with access to these U-Boot commands :
```
rlxboot# ?
@@ -110,11 +489,12 @@ update - update image
version - print monitor, compiler and linker version
```
-Using this for image manipulation is hard since there is no ethernet,
-USB or removable flash. It is probably possible to load an image over
-serial, but I don't have the patience for that....
+Using the boot loader for image manipulation will be hard though,
+since the camera has no ethernet, USB or removable flash and the boot
+loader has no WiFi driver. It is probably possible to load an image
+over serial, but I don't have the patience for that...
-The environment is pretty clean too:
+The environment is fixed and pretty clean:
```
rlxboot# printenv
=3
@@ -135,100 +515,36 @@ stdout=serial
Environment size: 533/131068 bytes
```
-No need to dwell on the weirdness of ethernet settings here. Modifying
-the command line is more than enough for our purpose:
-
-`rlxboot# setenv bootargs ${bootargs} init=/bin/sh`
+So we can get ourselves a root shell:
-Then continue to boot normally:
-`rlxboot# ${bootcmd}`
+```
+rlxboot# setenv bootargs ${bootargs} init=/bin/sh
+rlxboot# ${bootcmd}
+```
-This will provide a temporary root shell, without making any permanent
-changes to the system. But /sbin/init is skipped altogether, which
-means that nothing is mounted etc. Not even /sys and /proc. The
-simplest way to both have the root shell and a normal system, is by
-running
+Nothing is mounted or started since /sbin/init is skipped altogether
+in this case. Not even /sys and /proc. We can emulate a semi-normal
+system by running
`/etc/rc.d/rcS`
-in that root shell. You might also want to run
+as the first command. And then run for example
`telnetd -l /bin/sh`
-so you can telnet into the camera instead of/in addition to the shell
-on the serial console. Only if you set up networking, using the mydlink
-app, first, of course.
-
-## Configuring the camera using the mydlink app
-
-We need networking for the remaining parts. Which means that you have
-to configure the camera, either using the mydlink app, or by using
-Bluetooth GATT commands as described below.
+to enable temporary passwordless telnet into the camera instead of/in
+addition to the serial console. This is futile unless you have
+networking of course. I will not go into details on how to do that
+from the shell. Use the much simpler Bluetooth procedure described
+above. Or the "mydlink" app if you prefer.
-### Automatic firmware upgrades
-
-Remember to disable automatic firmware upgrades before changing any of
-the installed file systems.
-
-The file systems will be replaced on every firmware upgrade, so any
-local changes will be lost if the camera is upgraded. Let the system
-upgrade to the latest version before making the changes, if you want
-the most recent firmware.
-
-Note that I've only tested the procedure with firmware versions
-*2.01.03* and *2.02.02*. A different set of modifications could be
-necessary to make this work with other versions.
-
-
-## Backing up
-
-Create a backup of everything *before* you mess up. Restoring will be
-hard anyway, so don't rely on that. But you can forget about
-restoring at all unless you have the backup, so make it anyway.
-
-Note that the "pib" partition contains device specific data which
-cannot be restored from any other source than your device:
- * model number
- * hardware revision
- * mac address
- * feature bits
- * private keys and passwords
-
-The backup is also useful for analyzing the system offline.
-
-You will need networking. In theory, you could dump the flash to the
-console and save it from the terminal, but that would be very time
-consuming and tiresome.
-
-There are several network transfer tools in the original firmware:
- * tftp
- * wget
- * curl
- * ...and probably more
-
-
-I've been using tftp becuase it is simple. You'll obviously need a
-tftp server for this. Google for instructions on setting that up. You
-could alternatively set up a web server to use wget or curl.
-
-Copying out all flash partitions is as easy as for example:
-
-`for i in 0 1 2 3 4 5 6 7 8; do tftp -l /dev/mtd${i}ro -r mtd$i -p 192.168.2.1; done`
-
-Change 192.168.2.1 to the address of your tftp server. Some tftp
-servers might require existing and writable destination files. Refer
-to the tftp server docs.
-
-
-FIXME: check out /usr/bin/flash_erase and /usr/bin/flashcp
-
### Partitions
-The partitions are:
+The D-Link DCS-8000LH partitions are:
```
# cat /proc/mtd
dev: size erasesize name
@@ -258,148 +574,156 @@ Creating 9 MTD partitions on "m25p80":
0x0000004e0000-0x000000fe0000 : "rootfs"
```
-Partition usage summary:
+Partition usage:
- | number | name | start | end | size | fstype | contents |
- | 0 | "boot" | 0x000000 | 0x040000 | 0x40000 | boot | U-Boot |
- | 1 | "pib" | 0x040000 | 0x060000 | 0x20000 | raw | device info |
- | 2 | "userdata" | 0x060000 | 0x160000 | 0x100000 | squashfs | mydlink (/opt) |
- | 3 | "db" | 0x160000 | 0x180000 | 0x20000 | tar.gz | dynamic data |
- | 4 | "log" | 0x180000 | 0x1a0000 | 0x20000 | raw? | empty |
- | 5 | "dbbackup" | 0x1a0000 | 0x1c0000 | 0x20000 | tar.gz | copy of "db" |
- | 6 | "logbackup" | 0x1c0000 | 0x1e0000 | 0x20000 | raw? | empty |
- | 7 | "kernel" | 0x1e0000 | 0x4e0000 | 0x300000 | uImage | Linux 3.10 |
- | 8 | "rootfs" | 0x4e0000 | 0xfe0000 | 0xb00000 | squashfs | rootfs (/) |
+ | number | name | start | end | size | fstype | contents |
+ | 0 | "boot" | 0x000000 | 0x040000 | 0x40000 | boot | U-Boot |
+ | 1 | "pib" | 0x040000 | 0x060000 | 0x20000 | raw | device info |
+ | 2 | "userdata" | 0x060000 | 0x160000 | 0x100000 | squashfs | mydlink (/opt) |
+ | 3 | "db" | 0x160000 | 0x180000 | 0x20000 | tar.gz | non-volatile data |
+ | 4 | "log" | 0x180000 | 0x1a0000 | 0x20000 | raw? | empty |
+ | 5 | "dbbackup" | 0x1a0000 | 0x1c0000 | 0x20000 | tar.gz | copy of "db" |
+ | 6 | "logbackup" | 0x1c0000 | 0x1e0000 | 0x20000 | raw? | empty |
+ | 7 | "kernel" | 0x1e0000 | 0x4e0000 | 0x300000 | uImage | Linux 3.10 |
+ | 8 | "rootfs" | 0x4e0000 | 0xfe0000 | 0xb00000 | squashfs | rootfs (/) |
-Firmware upgrades replace the "userdata", "kernel" and "rootfs"
-partitions, but leave all(?) other partitions unmodified. I imagine
-that the "boot" partition could be upgraded too if necessary. But it
-was not touched when going from 2.01.03 to 2.02.02, FWIW.
+The D-Link firmware updates I have looked at will replace the
+"userdata", "kernel" and "rootfs" partitions, but leave other
+partitions unchanged. I imagine that the "boot" partition might be
+upgraded too if deemed necessary by D-Link. But it was not touched
+when going from 2.01.03 to 2.02.02.
The "log" and "logbackup" appear to be currently unused. But I am
reluctant trusting this, given their names. I guess they could be
-cleaned and overwritten anytime.
+cleaned and overwritten anytime. They are too small to be very useful
+anyway. You can't put any writable file system om them with only two
+erase blocks.
-### Backup up dynamic data
+### Backing up dynamic data
This is not necessary for system operation as any non-volatile data is
-saved in the "db" partition anyway. But it can still be useful
-to have a copy of the system state for offline studying, so I also
-like to save a working copy of /tmp:
+saved in the **db** partition anyway. But it can still be useful to
+have a copy of the system state for offline studying, so I also like
+to save a working copy of /tmp:
```
tar zcvf /tmp/tmp.tgz /tmp/
tftp -l /tmp/tmp.tgz -r tmp.tgz -p 192.168.2.1
```
-## Making the NIPCA webserver start automatically
+### Why can we run the NIPCA webserver before we modify the firmware?
+
+D-Link left all the webserver parts in the firmware, including all the
+NIPCA CGI tools. The only change they made was disabling the startup
+script.
+
+The webserver can be enabled and started manually from the shell by
+running:
-The good news is that D-Link left all the webserver parts in the
-firmware, including all the NIPCA CGI tools. You can start it from the
-shell by running:
```
tdb set HTTPServer Enable_byte=1
/etc/rc.d/init.d/extra_lighttpd.sh start
```
-Changing the `HTTPServer Enable_byte` is only necessary the first
-time. The setting is stored in the non-volatile "db" partition.
-
-The bad news is that I haven't found a way to re-enable the webserver
-startup by simply making changes to the non-volatile variables. Making
-the webserver start automatically requires changes to a file system in
-either the "userdata" or "rootfs" partition. I have chosen to modify
-the "userdata" file system because it only contains the mydlink
-applications mounted on /opt, and messing with it is therefore much
-simpler than messing with the root filesystem.
-
-
-### Creating a modified "userdata" file system
-
-This is done on a separate Linux system, using the backup we made of
-mtd2 ("userdata"). The necessary tools are unsquashfs and mksquashfs,
-found in the squashfs-tools package on Debian.
+This is precisely what our Bluetooth tool does when it is called with
+the **--lighttpd** option.
+
+The `HTTPServer Enable_byte` is persistent, so setting is only
+necessary once. Unless you do a factory reset.
+
+
+### The "userdata" file system
+
+The **userdata** you backed up as **mtd2** contains a xz compressed
+squasfs file system, with most of the mydlink cloud tools. The file
+system can be unpacked on a Linux system using unsquashfs:
+```
+$ unsquashfs mtd2
+Parallel unsquashfs: Using 4 processors
+15 inodes (22 blocks) to write
+
+[=============================================================================================================================================================================================================|] 22/22 100%
+
+created 12 files
+created 1 directories
+created 3 symlinks
+created 0 devices
+created 0 fifos
+$ ls -la squashfs-root/
+total 1156
+drwxr-xr-x 2 bjorn bjorn 340 Feb 14 10:58 .
+drwxrwxrwt 41 root root 2280 May 13 15:13 ..
+-rwxr-xr-x 1 bjorn bjorn 13184 Feb 14 10:58 ca-refresh
+-rwxr-xr-x 1 bjorn bjorn 273692 Feb 14 10:58 cda
+lrwxrwxrwx 1 bjorn bjorn 9 May 13 15:13 cert -> /tmp/cert
+-rwxr-xr-x 1 bjorn bjorn 5991 Feb 14 10:58 client-ca.crt.pem
+lrwxrwxrwx 1 bjorn bjorn 7 May 13 15:13 config -> /tmp/db
+-rwxr-xr-x 1 bjorn bjorn 436428 Feb 14 10:58 da_adaptor
+-rwxr-xr-x 1 bjorn bjorn 4 Feb 14 10:58 dcp_version
+-rwxr-xr-x 1 bjorn bjorn 814 Feb 14 10:58 device.cfg
+lrwxrwxrwx 1 bjorn bjorn 17 May 13 15:13 lib -> /var/libevent/lib
+-rwxr-xr-x 1 bjorn bjorn 5 Feb 14 10:58 m2m
+-rwxr-xr-x 1 bjorn bjorn 6220 Feb 14 10:58 mydlink_watchdog.sh
+-rwxr-xr-x 1 bjorn bjorn 1034 Feb 14 10:58 opt.local
+-rwxr-xr-x 1 bjorn bjorn 171828 Feb 14 10:58 sa
+-rwxr-xr-x 1 bjorn bjorn 242028 Feb 14 10:58 strmsvr
+-rwxr-xr-x 1 bjorn bjorn 10 Feb 14 10:58 version
+```
+
+The primary entry point here is the **opt.local** init-script. This
+is also the only required file. The **version** file is read by the
+Bluetooth API, and reported as the mydlink version, which makes it
+useful for verifying a modified camera. Our alternate **userdata**
+file system contains only these two files. But one could imagine
+including a number of other useful tools, like tcpdump, a ssh server etc.
+
+It is also possible to keep all the D-Link files, if that's
+wanted. The original **opt.local** script can be modified to leave
+mydlink support running while still starting other features. We could
+even add our own non-volatile setting to choose one or the other, or
+both, and making it a configuration thing. Fantasy is the only
+limiting factor.
+
+Repacking the files into a camera compatible squashfs file system:
```
-cd /tmp
-unsquashfs mtd2
-vi squashfs-root/webenable
-chmod 755 squashfs-root/webenable
-sed -i -e '/check_alive strmsvr/i \
- check_alive webenable' squashfs-root/mydlink_watchdog.sh
mksquashfs squashfs-root mtd2.new -all-root -comp xz
```
-You can put whatever you want into the webenable script. But make sure
-it works, and doesn't exit, since the mydlink_watchdog we use to start
-it might barf otherwise.
+Note that **xz** compression is required. No other compression is
+supported AFAIK.
-webenable script example, creating a new root user named "foo" and
-starting telnetd as well:
-```
-#!/bin/sh
-
-echo "Doing local fixups..."
-killall -TERM telnetd
-grep -Eq ^foo: /etc/passwd || echo "foo:x:0:0::/:/bin/sh" >> /etc/passwd && echo "foo:$(pibinfo Pincode)" | chpasswd -m
-[ "$(tdb get HTTPServer Enable_byte)" -eq "1" ] || tdb set HTTPServer Enable_byte=1
-[ -n "$(tdb get HTTPAccount AdminPasswd_ss)" ] || tdb set HTTPAccount AdminPasswd_ss=$(pibinfo Pincode)
-/etc/rc.d/init.d/extra_lighttpd.sh start
-telnetd -F
-```
+There are simpler ways to write the new file system to the camera than
+creating a firmware update package, if you just want to test it. One
+example:
-You might want to upload this script to the /tmp ramfs and test it a
-few times before writing it to flash. When you are satisfied, then do
-something like this in the camera shell:
```
tftp -r mtd2.new -l /tmp/mtd2.new -g 192.168.2.1
-umount /opt
-```
-
-The `umount` will likely fail. If so, then do not continue, but look
-for any processing keeping files in /opt open, kill them, and retry. For example
-
-```
-# ps w|grep /mydlink
- 800 root 1432 S {mydlink_watchdo} /bin/sh /mydlink/mydlink_watchdog.
- 1133 root 17936 S /mydlink/strmsvr
- 1422 root 18896 S /mydlink/cda
- 1455 root 4464 S < /mydlink/sa
- 2299 root 26076 S /mydlink/da_adaptor -s mdb
-19627 root 1416 S grep /mydlink
-# kill -TERM 800 1133 1422 1455 2299
-umount /opt
-```
-
-After successfully unmounting:
-```
cat /tmp/mtd2.new >/dev/mtdblock2
-mount /dev/mtdblock2 /opt
```
-You should now see your script as `/opt/webenable`, and it will start
-automatically after booting. This change is permanent until the next
-firmware upgrade, after which the process must be repeated from the
-beginning. So you'll want to disable automatic upgrades unless you
-enjoy using the serial console.
+But DON'T do that unless you both have a backup and know what you are
+doing...
+You should reboot the camera after doing this, unless you make sure
+you stop any process running from the previous /opt system and remount
+it properly.
### Using NIPCA to manage the camera
The local web server provides a direct camera management API, but not
-a web GUI application. And all commands require authentication. By
-default there is a single admin user, using the pincode from the
-camera label as passord. I believe you can add more users using the
-API, but I haven't tested this.
-
-Google a NIPCA reference, or look at the script names under /var/www
-and try them out. Some examples:
+a web GUI application. All API requests require authentication. We
+have added a single admin user, using the pincode from the camera
+label as passord. More users can be adding if necessary, even by
+using the API itself.
+Google for the NIPCA reference spec, or look at the script names under
+/var/www and try them out. Some examples:
```
-$ curl -u admin:012345 'http://dcs8000lh.mork.no/config/datetime.cgi'
+$ curl -u admin:123456 'http://192.168.2.37/config/datetime.cgi'
method=1
timeserver=ntp1.dlink.com
timezone=1
@@ -413,9 +737,10 @@ offset=01:00
starttime=3.2.0/02:00:00
stoptime=11.1.0/02:00:00
-$ curl -u admin:012345 http://dcs8000lh.mork.no/config/led.cgi?led=off
+$ curl -u admin:123456 http://192.168.2.37/config/led.cgi?led=off
led=off
```
+There are lots of settings which can be controlled using this API.
### Streaming video locally
@@ -424,57 +749,45 @@ The whole point of all this... We can now stream directly from the
camera using for example:
```
-vlc https://192.168.2.99/video/mpegts.cgi
-vlc https://192.168.2.99/video/flv.cgi
+vlc https://192.168.2.37/video/mpegts.cgi
+vlc https://192.168.2.37/video/flv.cgi
```
-...of course replacing 192.168.2.99 with the address of your camera.
-Use the same admin user and pincode to authenticate.
-
+Again using the same admin/PIN Code user for authentication.
-## Bluetooth
+### Bluetooth LE GATT API
-The mydlink app use Bluetooth LE GATT commands for the initial setup,
-like selecting and configuring a Wireless network. It is possible to
-do this manually too, if you have a Linux system with a modern
-Bluetooth controller. Most laptops with Linux will do.
+The Bluetooth service is in a "locked" mode by default. This is
+controlled by the "Ble Mode" persistent setting stored in the **db**
+partition. If true ("1"), then most of the Bluetooth commands are
+rejected. But changing the setting manually will not help much, since
+the system automatically enter lock mode 180 seconds after the last
+Bluetooth client disconnected.
-The Bluetooth service is in "locked" mode by default, This is
-controlled by the "Ble Mode" setting in the "db". If true ("1"), then
-most of the Bluetooth commands are rejected. The system will
-automatically enter lock mode 180 seconds after the last client
-disconnected.
+The challenge -> response unlock method described below is much more
+useful.
-There are multiple ways to unlock the Bluetooth service, like for
-example running `tdb set Ble Mode_byte=0` in a shell. But the
-obviously most useful unlock method is using the challenge -> response
-method described below
+#### Converting the PIN Code to a Bluetooth unlock key
-### Convert pincode to session key
-
-Most of the Bluetooth commands are protected when locked. They can be
-unlocked by using the pincode printed on the camera label. This
-pincode is not sent directly over the air though. Instead it is
-combined with a random challenge.
+Most Bluetooth commands are rejected when locked. Access to the full
+Bluetooth API can be unlocked by using the PIN Code printed on the
+camera label. This code is not sent directly over the air
+though. Instead it is combined with a random challenge.
Both the random challenge and the matching key are generated by the
application `sbin/gen_bt_config` on the camera side. The key is
-calculated by taking the first 16 bytes of the base64 encoded md5sum
-of the concatination of
- * model string
- * '-'
- * four last uppercase digits of the mac address
- * pincode
- * challenge.
+calculated by taking the first 16 bytes of the base64 encoded md5
+digest of
-The first part., before the pincode, happens to be identical to the
-Bluetooth device name. So an application can simply use this.
+ * model string + '-' four last mac digits (or Bluetooth device name?)
+ * PIN Code
+ * challenge.
-Note that this application depend on bluetooth libraries, which are
-not in /lib. So we have to set LD\_LIBRARY\_PATH to run it:
+Note that this application depends on bluetooth libraries, which are
+not in /lib. So we have to set LD\_LIBRARY\_PATH to run it manually:
```
# LD_LIBRARY_PATH=/var/bluetooth/lib sbin/gen_bt_config update_key_only
@@ -501,23 +814,23 @@ b2gaescrbldchnik
jrtY6nONQ5rV+2Ph
```
-Yes, it does actually use tdb for the first one and mdb for the
-second. I have absolutely no idea why,... It is possible to read the key using tdb too:
+Yes, the D-Link code does actually use tdb for the first one and mdb
+for the second. I have absolutely no idea why,... It is possible to
+read the key using tdb too:
```
# tdb get Ble Key_ss
jrtY6nONQ5rV+2Ph
```
-Generating the key by hand on a Linux system, without the final
-truncation to 16 bytes:
+Generating the same key by hand on a Linux system is simple:
```
$ echo -n 'DCS-8000LH-CDEF012345b2gaescrbldchnik' | md5sum | xxd -r -p | base64 | cut -c-16
jrtY6nONQ5rV+2Ph
```
-### GATT API
+#### Characteristic UUIDs
D-Link is using the GATT BlueZ example plugin, patching it to add
their camera specific endpoints. This means that we can find all the
@@ -525,7 +838,7 @@ API "documentation" in the
`DCS-8000LH-GPL/package/bluez_utils/feature-patch/5.28/customized-mydlink.patch`
file in the GPL archive.
-They use a number of 16bit UUIDs with nonsense names:
+This defines a number of 16bit UUIDs with mostly nonsense names:
```
+#define IPCAM_UUID 0xD001
+#define A000_UUID 0xA000
@@ -546,39 +859,43 @@ They use a number of 16bit UUIDs with nonsense names:
`IPCAM_UUID` is registered as the `GATT_PRIM_SVC_UUID`, which means
-that it shows up as a primary GATT service we can scan for.
+that it shows up as a primary GATT service we can look for when
+looking for a supported camera.
-The rest of the UUIDs are characteristics of the primary service.
+The rest of the UUIDs are characteristics of this primary service. The
+API is based on reading or writing these characteristics.
-#### data formatting
+#### Data formatting
-Both input and output parameters are sent as ascii strings with
-key=value pairs joined by `;`. The keys are single upper case
-characters. Key names are reused, so the meaning depend on the
-endpoint.
+Both input and output parameters are sent as ascii strings using
+key=value pairs joined by `;`, with an exception for the nested KV
+pairs in the WiFi survey results. All keys are single upper case
+characters. Key names are somewhat reused, so the exact meaning depend
+on the characteristic.
-Values are either integers, including boolean 0/1, or a consist of a
-restricted set of ascii text.
+Values are either integers, including boolean 0/1, or some set of
+ascii text.
-Examples:
+Three real examples, read from 0xA001, 0xA200 and 0xA104:
```
M=1;C=b2gaescrbldchnik
N=DCS-8000LH;P=1;T=1557349762;Z=CET-1CEST,M3.5.0,M10.5.0/3;F=2.01.03;H=A1;M=B0C554ABCDEF;V=3.0.0-b71
I=192.168.2.37;N=255.255.255.0;G=192.168.2.1;D=148.122.16.253
```
-#### Endpoints
-
-FIXME: /sbin/save_wireless_info decodes S and E values into wpa_supplicant.conf settings. How?
+#### Listing characteristics
-FIXME: figure out the wlan survey format. It splits pages, and numbers them.
-L=I=AirLink126FD4,M=0,C=11,S=4,E=2,P=46&L=I=Antiboks,M=0,C=1,S=4,E=2,P=88&L=I=ASV17,M=0,C=11,S=4,E=2,P=48&L=I=ASV17-dlink,M=0,C=6,S=4,E=2,P=72&L=I=fjorde123,M=0,C=1,S=4,E=2,P=48&L=I=Getbox-2B797A,M=0,C=1,S=4,E=2,P=46&L=I=JOJ,M=0,C=11,S=4,E=2,P=56&L=I=Kjellerbod,M=0,C=1,S=4,E=2,P=75&L=I=mgmt,M=0,C=1,S=4,E=2,P=88&L=I=Rindedal,M=0,C=11,S=4,E=2,P=64&L=I=VIF,M=0,C=11,S=4,E=2,P=46
-
-Real example:
-
-[B0:C5:54:4C:CC:73][LE]> characteristics 0x0011
+The **gattool** Linux command line tool is useful for exploring
+Bluetooth LE devices. You can look for primary services and list
+associated characteristics of a service:
+```
+[B0:C5:54:AA:BB:CC][LE]> primary
+attr handle: 0x0001, end grp handle: 0x0008 uuid: 00001800-0000-1000-8000-00805f9b34fb
+attr handle: 0x0010, end grp handle: 0x0010 uuid: 00001801-0000-1000-8000-00805f9b34fb
+attr handle: 0x0011, end grp handle: 0x002e uuid: 0000d001-0000-1000-8000-00805f9b34fb
+[B0:C5:54:AA:BB:CC][LE]> characteristics 0x0011
handle: 0x0012, char properties: 0x12, char value handle: 0x0013, uuid: 0000a000-0000-1000-8000-00805f9b34fb
handle: 0x0015, char properties: 0x0a, char value handle: 0x0016, uuid: 0000a001-0000-1000-8000-00805f9b34fb
handle: 0x0017, char properties: 0x02, char value handle: 0x0018, uuid: 0000a100-0000-1000-8000-00805f9b34fb
@@ -593,38 +910,20 @@ handle: 0x0027, char properties: 0x02, char value handle: 0x0028, uuid: 0000a301
handle: 0x0029, char properties: 0x08, char value handle: 0x002a, uuid: 0000a302-0000-1000-8000-00805f9b34fb
handle: 0x002b, char properties: 0x08, char value handle: 0x002c, uuid: 0000a303-0000-1000-8000-00805f9b34fb
handle: 0x002d, char properties: 0x02, char value handle: 0x002e, uuid: 0000a304-0000-1000-8000-00805f9b34fb
+```
+It is also possible to read and write characteristics using this tool,
+but this can be a bit cumbersome unless you are fluent in ASCII coding
+;-)
-FIXME: what are the provisioning parameters?
-
-example:
-
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x0028
-Characteristic value/descriptor: 4e 3d 3b 54 3d 3b 55 3d
-
-bjorn@miraculix:/usr/local/src/git/DCS-8000LH-GPL$ decode-ascii.pl 4e 3d 3b 54 3d 3b 55 3d
-N=;T=;U=
-
-
-FIXME: the mydlink register commands operate on /tmp/mydlink/reg_st and /tmp/mydlink/reg_info files
-
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x002e
-Characteristic value/descriptor: 53 3d 31 31 3b 45 3d 30
-bjorn@miraculix:/usr/local/src/git/DCS-8000LH-GPL$ decode-ascii.pl 53 3d 31 31 3b 45 3d 30
-S=11;E=0
-
-after factory reset:
-
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x002e
-Characteristic value/descriptor: 45 3d 30 3b 53 3d 30
-bjorn@miraculix:/usr/local/src/git/DCS-8000LH-GPL$ decode-ascii.pl 45 3d 30 3b 53 3d 30
-E=0;S=0
+#### Description of the IPCam characteristics
+Guessing the meaning of each characteristic, based on the source code
+and some trial and error:
-The characteristics are mapped to system commands or data as follows::
| UUID | op | description | format | keys |
| A000 | read | last status | C=%d;A=%d;R=%d | C: uuid, A: mode, R: state |
@@ -639,7 +938,7 @@ The characteristics are mapped to system commands or data as follows::
| A104 | read | ip config | I=%s;N=%s;G=%s;D=%s | I: address, N: netmask, G: gateway, D: DNS-server |
| A200 | read | system info | N=%s;P=%d;T=%d;Z=%s;F=%s;H=%s;M=%s;V=%s | N: devicename, P: haspin (0/1), T: time (unix epoch), Z: timezone, F: fwver, H: hwver, M: macaddr, V:mydlinkver |
| A200 | write | name and time | N=%s;T=%d;Z=%s | N: devicename, T: time (unix epoch), Z: timezone |
- | A201 | write | admin password | P=%s;N=%s | P: current password (pincode), N: new password |
+ | A201 | write | admin password | P=%s;N=%s | P: current password, N: new password |
| A300 | read | reg state | G=%d | G: registration state (0/1) |
| A300 | write | reg state | G=%d | G: registration state (0/1) |
| A301 | read | provisioning | N=%s;T=%s;U=%s | N: username, T: footprint, U: portal |
@@ -648,37 +947,57 @@ The characteristics are mapped to system commands or data as follows::
| A304 | read | register | S=%d;E=%d | S: , E: (cat /tmp/mydlink/reg_st) |
+The UUIDs from 0xA300 to 0xA304 are all related to the mydlink cloud
+service, and therefore not of much use to us. I haven't bothered
+trying to figure out exactly how they are used.
+
+We could in theory use the 0xA303 request which simply calls
+**/opt/opt.local restart**. But with the gaping 0xA201 hole,
+allowing **any** command, there isn't much need for this one...
+
+A few more details on the more complex characteristics:
+
+
+##### A000
+
+The only characteristic sent as notifications. But it can also be
+read directly for syncronous operations.
+
+The value is the state to the last Bluetooth action:
+
+ "C=%d;A=%d;R=%d", last_action_status.uuid, last_action_status.mode, last_action_status.state
+
##### A100
The wifi survey scan results are split in 128 byte "pages", where each
page starts with the total number of pages and the current page
number. The characteristic value must be read as many times as the
-given total to restrieve all pages.
+given total.
For example, reading 3 pages:
```
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x0018
+[B0:C5:54:AA:BB:CC][LE]> char-read-hnd 0x0018
Characteristic value/descriptor: 4e 3d 33 3b 50 3d 31 3b 4c 3d 49 3d 41 6e 74 69 62 6f 6b 73 2c 4d 3d 30 2c 43 3d 36 2c 53 3d 34 2c 45 3d 32 2c 50 3d 36 32 26 4c 3d 49 3d 41 53 56 31 37 2c 4d 3d 30 2c 43 3d 31 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 34 36 26 4c 3d 49 3d 41 53 56 31 37 2d 64 6c 69 6e 6b 2c 4d 3d 30 2c 43 3d 36 2c 53 3d 34 2c 45 3d 32 2c 50 3d 36 38 26 4c 3d 49 3d 66 6a 6f 72 64 65 31 32 33 2c 4d 3d 30
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x0018
+[B0:C5:54:AA:BB:CC][LE]> char-read-hnd 0x0018
Characteristic value/descriptor: 4e 3d 33 3b 50 3d 32 3b 2c 43 3d 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 35 38 26 4c 3d 49 3d 4a 4f 4a 2c 4d 3d 30 2c 43 3d 31 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 34 37 26 4c 3d 49 3d 4b 6a 65 6c 6c 65 72 62 6f 64 2c 4d 3d 30 2c 43 3d 36 2c 53 3d 34 2c 45 3d 32 2c 50 3d 36 32 26 4c 3d 49 3d 6d 67 6d 74 2c 4d 3d 30 2c 43 3d 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 37 34 26 4c 3d 49 3d 52 69
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x0018
+[B0:C5:54:AA:BB:CC][LE]> char-read-hnd 0x0018
Characteristic value/descriptor: 4e 3d 33 3b 50 3d 33 3b 6e 64 65 64 61 6c 2c 4d 3d 30 2c 43 3d 31 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 36 32
```
-The strings are decoded to:
+These strings are decoded as:
```
N=3;P=1;L=I=Antiboks,M=0,C=6,S=4,E=2,P=62&L=I=ASV17,M=0,C=11,S=4,E=2,P=46&L=I=ASV17-dlink,M=0,C=6,S=4,E=2,P=68&L=I=fjorde123,M=0
N=3;P=2;,C=1,S=4,E=2,P=58&L=I=JOJ,M=0,C=11,S=4,E=2,P=47&L=I=Kjellerbod,M=0,C=6,S=4,E=2,P=62&L=I=mgmt,M=0,C=1,S=4,E=2,P=74&L=I=Ri
N=3;P=3;ndedal,M=0,C=11,S=4,E=2,P=62
```
-Which, when joined after removing the paging info, becomes::
+Which, when joined after removing the N/P paging info, becomes::
```
L=I=Antiboks,M=0,C=6,S=4,E=2,P=62&L=I=ASV17,M=0,C=11,S=4,E=2,P=46&L=I=ASV17-dlink,M=0,C=6,S=4,E=2,P=68&L=I=fjorde123,M=0,C=1,S=4,E=2,P=58&L=I=JOJ,M=0,C=11,S=4,E=2,P=47&L=I=Kjellerbod,M=0,C=6,S=4,E=2,P=62&L=I=mgmt,M=0,C=1,S=4,E=2,P=74&L=I=Rindedal,M=0,C=11,S=4,E=2,P=62
```
-After splitting the list on &, the final result is:
+And after splitting this on & we get the final result:
```
L=I=Antiboks,M=0,C=6,S=4,E=2,P=62
L=I=ASV17,M=0,C=11,S=4,E=2,P=46
@@ -700,8 +1019,14 @@ So each L entry is made up of the same set of keys:
* P: relative signal. Higher is better. dBm + 100?
Still need to figure out the mapping of the M,S,E keys to
-wpa_supplicant config settings. The setting `M=0;I=Kjellerbod;S=4;E=2`
-is mapped to this configuration:
+wpa_supplicant config settings. I assume they represent enums. But we
+can simply treat them as opaque values since we only use the survey
+data to help setup WiFi anyway. We copy these to the setup request,
+and do not need to know what they mean.
+
+
+FWIW, my example setting `M=0;I=Kjellerbod;S=4;E=2`
+is mapped to this wpa_supplicant configuration:
```
# cat /tmp/wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant
@@ -721,157 +1046,122 @@ network={
}
```
-##### A303
+##### A201
-The two strings S and M are url decoded, checked for special characters, and then fed into
-```
- snprintf(cmdbuf, sizeof(cmdbuf), "echo \"S=%s;M=%s\" > /tmp/mydlink/reg_info", S_str, M_str);
- generic_run_cmd(cmdbuf);
- generic_run_cmd("kill -USR1 `pidof da_adaptor`");
-```
-It is pretty safe to assume that this provides some registration info
-to the mydlink system, allowing it to connect to the cloud service.
+This write request allows setting an admin password, used for example
+by the webserver. It takes the old and new passwords as unencoded
+input, verifies that the old password matches, and then change the
+admin password to the provided new one.
+
+The initial password is empty, which prevents webserver
+authentication. Simply provide an empty string for the old password in
+the first request: **P=;N=newpassword**
+
+But this request is much more useful in other ways.... The new passord
+(N_str) is processed like this (after slight compression of the
+interesting code lines):
-The set of allowed characters is rather interesting:
```
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
+ snprintf(cmd, sizeof(cmd), "mdb set admin_passwd %s", N_str);
+ snprintf(cmdbuf, sizeof(cmdbuf), "%s > %s 2>&1", cmd, p_name);
+ fp = popen(cmdbuf, "r");
```
+You don't have to be a security expert to see the problem here. But
+one mans bug is another mans feature :-)
-This should open up a hole or two....
-
-for example: set S to
-`S=">/dev/null; echo -e "#!/bin/sh\ntouch /tmp/foo" >/tmp/kwh2; chmod 755 /tmp/kwh2; /tmp/kwh2; echo "S=x`
+##### A303
-Try this:
+The two strings S and M are url decoded and checked for special
+characters. Then the **orginal** url encoded strings are written to
+**/tmp/mydlink/reg_info** and SIGUSR1 is sent to the **da_adaptor**
+process. Presumably triggering it to reread the reg_info file.
- 1. add an admin:pincode account to /tmp/passwd
- 2. start telnetd
- 3. add an admin:pincode account to the web htdigest file
- 4. start web server
+It is pretty safe to assume that this provides some registration info
+to the mydlink system, allowing it to connect to the cloud service.
-urlencode S in this:
+The set of allowed characters is rather interesting:
```
-S=">/dev/null;echo "admin:x:0:0::/:/bin/sh">>/tmp/passwd&&echo admin:pincode|chpasswd;telnetd -p 1057;echo "S=;M=
-
-S=">/dev/null;echo "admin:x:0:0::/:/bin/sh">>/tmp/passwd&&echo admin:pincode|chpasswd;telnetd -p 1057;echo "S=;M=
-
-S=">/dev/null;echo "admin:x:0:0::/:/bin/sh">>/tmp/passwd;echo "S=;M=
-S=">/dev/null;echo admin:pincode|chpasswd;telnetd -p 1057;echo "S=;M=
-
-
-S=">/dev/null;echo "admin:x:0:0::/:/bin/sh">>/tmp/passwd&&echo admin:pincode|chpasswd;telnetd -p 1057;echo "S=;M=
-
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
```
-#### Notifications
+Which initially made me think that this was an obvious security hole,
+since I missed the point that it's the url encoded strings that are
+used on the command line.
-The camera sends `last_action` notifications as an alternative to readding lots of A000 requests:
+But given the quality of the rest of the code here, I would be very
+surprised if there isn't an issue or ten in the da_adaptor code
+allowing this to be abused. It's just a bit harder to figure out
+without the source code.
- "C=%d;A=%d;R=%d", last_action_status.uuid, last_action_status.mode, last_action_status.state
+### Firmware updates
+There are at least two shell scripts providing a firmware update
+service in the D-Link firmware:
+ * /var/www/config/firmwareupgrade.cgi
+ * /sbin/fwupdate
-#### Sample Bluetooth network configuration
+They are both pretty similar and obviously come from the same source.
+The main difference is that firmwareupgrade.cgi provides the NIPCA
+firmwareupgrade service, while fwupdate is a command line tool.
- 1. find camera: LE scan (should be limited to devices announcing 0000d001-0000-1000-8000-00805f9b34fb?)
- 2. connect to device (input: selection): LE connect
- 3. find the announced services: GATT primary
- 4. get attributes for our service: GATT characteristics for UUID 0000d001-0000-1000-8000-00805f9b34fb
- 5. read challenge: GATT read UUID 0000a001-0000-1000-8000-00805f9b34fb => M=1;C=b2gaescrbldchnik
- 6. authenticate and unlock (input: pincode): GATT write UUID 0000a001-0000-1000-8000-00805f9b34fb <= M=0;K=jrtY6nONQ5rV+2Ph
- 7. check current wifi settings: GATT read UUID 0000a101-0000-1000-8000-00805f9b34fb => M=0;I=;S=0;E=0
- 8. scan for wifi networks (repeat until P=N, and then concat the results without N and P)
- a. GATT read UUID 0000a100-0000-1000-8000-00805f9b34fb => N=3;P=1;L=I=Antiboks,M=0,C=1,S=4,E=2,P=70&L=I=ASV17,M=0,C=11,S=4,E=2,P=57&L=I=ASV17-dlink,M=0,C=6,S=4,E=2,P=71&L=I=fjorde123,M=0
- b. GATT read UUID 0000a100-0000-1000-8000-00805f9b34fb => N=3;P=2;,C=1,S=4,E=2,P=58&L=I=Kjellerbod,M=0,C=1,S=4,E=2,P=74&L=I=mgmt,M=0,C=1,S=4,E=2,P=74&L=I=noramaja_2G,M=0,C=11,S=4,E=2,P=4
- c. GATT read UUID 0000a100-0000-1000-8000-00805f9b34fb => N=3;P=3;6&L=I=Rindedal,M=0,C=11,S=4,E=2,P=60
- 9. select wifi network (input: password): GATT write UUID 0000a101-0000-1000-8000-00805f9b34fb <= M=0;I=Kjellerbod;S=4;E=2;K=redeacted
- 10. commit wifi setting: GATT write UUID 0000a102-0000-1000-8000-00805f9b34fb <= C=1
- 11. check wifi settings again: GATT read UUID 0000a101-0000-1000-8000-00805f9b34fb => M=0;I=Kjellerbod;S=4;E=2
- 12. check ip config: GATT read UUID 0000a104-0000-1000-8000-00805f9b34fb => I=192.168.2.37;N=255.255.255.0;G=192.168.2.1;D=148.122.16.253
- 13. end session by locking: GATT write UUID 0000a001-0000-1000-8000-00805f9b34fb <= M=1;K=jrtY6nONQ5rV+2Ph
-
+The web service is most interesting for us, providing both the upload
+and upgrade in one simple tool. The fwupdate tool is used by the
+mydlink cloud tool **da_adaptor** , via an fw_upgrade symlink.
-```
-root@miraculix:/tmp# hcitool -i hci0 lescan
-LE Scan ...
-CC:B1:1A:1A:C6:A1 (unknown)
-B0:C5:54:4C:CC:73 (unknown)
-B0:C5:54:4C:CC:73 DCS-8000LH-CC73
-16:E6:00:43:3E:EA (unknown)
-^C
-root@miraculix:/tmp# gatttool -b B0:C5:54:4C:CC:73 -I
-[B0:C5:54:4C:CC:73][LE]> connect
-Attempting to connect to B0:C5:54:4C:CC:73
-Connection successful
-[B0:C5:54:4C:CC:73][LE]> primary
-attr handle: 0x0001, end grp handle: 0x0008 uuid: 00001800-0000-1000-8000-00805f9b34fb
-attr handle: 0x0010, end grp handle: 0x0010 uuid: 00001801-0000-1000-8000-00805f9b34fb
-attr handle: 0x0011, end grp handle: 0x002e uuid: 0000d001-0000-1000-8000-00805f9b34fb
-[B0:C5:54:4C:CC:73][LE]> characteristics 0x0011
-handle: 0x0012, char properties: 0x12, char value handle: 0x0013, uuid: 0000a000-0000-1000-8000-00805f9b34fb
-handle: 0x0015, char properties: 0x0a, char value handle: 0x0016, uuid: 0000a001-0000-1000-8000-00805f9b34fb
-handle: 0x0017, char properties: 0x02, char value handle: 0x0018, uuid: 0000a100-0000-1000-8000-00805f9b34fb
-handle: 0x0019, char properties: 0x0a, char value handle: 0x001a, uuid: 0000a101-0000-1000-8000-00805f9b34fb
-handle: 0x001b, char properties: 0x08, char value handle: 0x001c, uuid: 0000a102-0000-1000-8000-00805f9b34fb
-handle: 0x001d, char properties: 0x02, char value handle: 0x001e, uuid: 0000a103-0000-1000-8000-00805f9b34fb
-handle: 0x001f, char properties: 0x02, char value handle: 0x0020, uuid: 0000a104-0000-1000-8000-00805f9b34fb
-handle: 0x0021, char properties: 0x0a, char value handle: 0x0022, uuid: 0000a200-0000-1000-8000-00805f9b34fb
-handle: 0x0023, char properties: 0x08, char value handle: 0x0024, uuid: 0000a201-0000-1000-8000-00805f9b34fb
-handle: 0x0025, char properties: 0x0a, char value handle: 0x0026, uuid: 0000a300-0000-1000-8000-00805f9b34fb
-handle: 0x0027, char properties: 0x02, char value handle: 0x0028, uuid: 0000a301-0000-1000-8000-00805f9b34fb
-handle: 0x0029, char properties: 0x08, char value handle: 0x002a, uuid: 0000a302-0000-1000-8000-00805f9b34fb
-handle: 0x002b, char properties: 0x08, char value handle: 0x002c, uuid: 0000a303-0000-1000-8000-00805f9b34fb
-handle: 0x002d, char properties: 0x02, char value handle: 0x002e, uuid: 0000a304-0000-1000-8000-00805f9b34fb
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x0016
-Characteristic value/descriptor: 4d 3d 31 3b 43 3d 62 32 67 61 65 73 63 72 62 6c 64 63 68 6e 69 6b
-[B0:C5:54:4C:CC:73][LE]> char-write-req 0x0016 4d3d303b4b3d6a727459366e4f4e513572562b325068
-Characteristic value was written successfully
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x001a
-Characteristic value/descriptor: 4d 3d 30 3b 49 3d 3b 53 3d 30 3b 45 3d 30
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x0018
-Characteristic value/descriptor: 4e 3d 33 3b 50 3d 31 3b 4c 3d 49 3d 41 6e 74 69 62 6f 6b 73 2c 4d 3d 30 2c 43 3d 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 37 30 26 4c 3d 49 3d 41 53 56 31 37 2c 4d 3d 30 2c 43 3d 31 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 35 37 26 4c 3d 49 3d 41 53 56 31 37 2d 64 6c 69 6e 6b 2c 4d 3d 30 2c 43 3d 36 2c 53 3d 34 2c 45 3d 32 2c 50 3d 37 31 26 4c 3d 49 3d 66 6a 6f 72 64 65 31 32 33 2c 4d 3d 30
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x0018
-Characteristic value/descriptor: 4e 3d 33 3b 50 3d 32 3b 2c 43 3d 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 35 38 26 4c 3d 49 3d 4b 6a 65 6c 6c 65 72 62 6f 64 2c 4d 3d 30 2c 43 3d 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 37 34 26 4c 3d 49 3d 6d 67 6d 74 2c 4d 3d 30 2c 43 3d 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 37 34 26 4c 3d 49 3d 6e 6f 72 61 6d 61 6a 61 5f 32 47 2c 4d 3d 30 2c 43 3d 31 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 34
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x0018
-Characteristic value/descriptor: 4e 3d 33 3b 50 3d 33 3b 36 26 4c 3d 49 3d 52 69 6e 64 65 64 61 6c 2c 4d 3d 30 2c 43 3d 31 31 2c 53 3d 34 2c 45 3d 32 2c 50 3d 36 30
-[B0:C5:54:4C:CC:73][LE]> char-write-req 0x001a 4d3d303b493d4b6a656c6c6572626f643b533d343b453d323b4b3d7265646163746564
-Characteristic value was written successfully
-[B0:C5:54:4C:CC:73][LE]> char-write-req 0x001c 433d31
-Characteristic value was written successfully
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x001a
-Characteristic value/descriptor: 4d 3d 30 3b 49 3d 4b 6a 65 6c 6c 65 72 62 6f 64 3b 53 3d 34 3b 45 3d 32
-[B0:C5:54:4C:CC:73][LE]> char-read-hnd 0x0020
-Characteristic value/descriptor: 49 3d 31 39 32 2e 31 36 38 2e 32 2e 33 37 3b 4e 3d 32 35 35 2e 32 35 35 2e 32 35 35 2e 30 3b 47 3d 31 39 32 2e 31 36 38 2e 32 2e 31 3b 44 3d 31 34 38 2e 31 32 32 2e 31 36 2e 32 35 33
-[B0:C5:54:4C:CC:73][LE]> char-write-req 0x0016 4d3d313b4b3d6a727459366e4f4e513572562b325068
-Characteristic value was written successfully
-[B0:C5:54:4C:CC:73][LE]> disconnect
-```
+#### Signed and encrypted
+Looking at the contents of a firmware update from D-Link can be
+demotivating at the beginning:
+```
+$ tar xvf DCS-8000LH_Ax_v2.02.02_3014.bin
+update.bin.aes
+update.aes
+aes.key.rsa
+certificate.info
+sign.sha1.rsa
+$ file *
+aes.key.rsa: data
+certificate.info: ASCII text
+sign.sha1.rsa: data
+update.aes: data
+update.bin.aes: data
+$ ls -l
+total 10956
+-rw-r--r-- 1 bjorn bjorn 128 Feb 14 10:58 aes.key.rsa
+-rw-r--r-- 1 bjorn bjorn 130 Feb 14 10:58 certificate.info
+-rw-r--r-- 1 bjorn bjorn 128 Feb 14 10:58 sign.sha1.rsa
+-rw-r--r-- 1 bjorn bjorn 10268368 Feb 14 10:58 update.aes
+-rw-r--r-- 1 bjorn bjorn 936464 Feb 14 10:58 update.bin.aes
+```
-## Ultimate automated control
-
-
-Loose plan:
-
- 1. configure networking
- 2. enable telnetd
- 3. optional backup
- 4. replace /opt with our prebaked version, having mostly /opt/opt.local and /opt/version (reported as mydlink version by both bluetooth and mdns - can be useful)
-
-
+So all the interesting stuff is AES encrypted, and the AES key is RSA
+encrypted. The only directly readable file is this one, and it
+doesn't tell us much:
-Note that var/www/config/firmwareupgrade.cgi is a shell script.... We might abuse that.
+```
+$ cat certificate.info
+Publisher:DMdssdFW1
+Supported Models:DCS-8000LH,DCS-8000LH
+Firmware Version:1.0.0
+Target:update.bin
+Build No:3014
+Contents:update
+```
-Useful info indeed:
+Not much we can do about this then. Or so it seems... Until we look
+at **firmwareupgrade.cgi**, or **fwupdate** which has almost the same
+code:
+```
verifyFirmware() {
result=uploadSign
#tar tf "$UPLOADBIN" > /dev/null 2> /dev/null || return 1
@@ -885,416 +1175,146 @@ decryptFirmware() {
fw_decrypt.sh $dir/decrypt.key $out > /dev/null 2> /dev/null || return 1
return 0
}
+```
+Can it be that simple? Yes, it is.
-Also note:
-
-fw-2.02.02/root/tmp/download/version_info:{"code": 0, "fw_ver_type": "REGULAR", "process_time": 210, "main_board": {"url": "https://mydlinkmpfw.auto.mydlink.com/DCS-8000LH/DCS-8000LH_Ax_v2.02.02_3014.bin", "fw_version": "2.02.02", "md5": "97c46e5b998df42c3363866e895aa11b"}, "release_version": "3.1.0-b03", "device_id": "B0C5544CCC73"}
-
-
-Wow! The decryptkey is loaded into the pib!
-
-# pibinfo PriKey
------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-----
-
-
-Helpful hint here https://stackoverflow.com/questions/34304570/how-to-resolve-the-evp-decryptfinal-ex-bad-decrypt-during-file-decryption :
-
-Default digest has changed between those versions from md5 to
-sha256. One can specify the default digest on the command line as -md
-sha256 or -md md5 respectively
-
-
+Looking further at the **fw_sign_verify.sh** and **fw_decrypt.sh**,
+used by both update tools, confirms it. The firmware is verified by
+using the RSA public key in **/etc/db/verify.key** to decrypt the hash
+in **sign.sha1.rsa**. Then it is decrypted using a key from the
+factory data **pib** partition.
-And this works!!!
+#### Further unpacking the firmware update
-openssl rsautl -decrypt -in aes.key.rsa -inkey ~/docs/hardware/dlink/dcs8000lh/PriKey.pem -out aes.key
-password=`cat aes.key`
+So we have the keys and the hashing algorithms we need to both verify
+and decrypt this firmware. We can run the commands found in
+**fw_decrypt.sh** to get the real contents (slightly adapted to modern
+openssl versions):
+```
+$ openssl rsautl -decrypt -in aes.key.rsa -inkey decrypt.key -out aes.key
-bjorn@miraculix:/tmp/update2$ openssl aes-128-cbc -v -md md5 -kfile aes.key -nosalt -d -in update.bin.aes -out update.bin
+$ openssl aes-128-cbc -v -md md5 -kfile aes.key -nosalt -d -in update.bin.aes -out update.bin
bufsize=8192
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
bytes read : 936464
bytes written: 936454
-
-bjorn@miraculix:/tmp/update$ openssl aes-128-cbc -v -md md5 -kfile aes.key -nosalt -d -in update.bin.aes -out update.bin
+$ openssl aes-128-cbc -v -md md5 -kfile aes.key -nosalt -d -in update.aes -out update
bufsize=8192
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
-bytes read : 936416
-bytes written: 936413
-
-
-
-Note that update.bin also is a shell script!
-
-
-
-bjorn@miraculix:/tmp/update$ sh update.bin info
-MECH_SIGN="QPAT"
-MECH_VERSION="1.0"
-MECH_APP="doUpdate"
-HWBOARD="r8000lh"
-HWVERSION="1.0.0"
-MODEL="DCS-8000LH"
-PRODUCT="Internet Camera"
-OEM="D-Link"
-VENDOR="Alphanetworks"
-VERSION="1.0.0-1515"
-DESCRIPT="A full update image."
-PACKAGE=""
-bjorn@miraculix:/tmp/update$ sh update.bin brief
-
-This is a full update image.
-It will update following, ...
- 1. boot script.
- 2. kernel.
- 3. root system.
-And after it is updated, the system will reboot in 1 second.
-
-
-
-
-This is extremely useful:
-
-```
-change_root() {
- mkdir -p /tmp/root
- mount --bind /tmp/root /tmp/root
- cd /tmp/root/
- mkdir -p bin sbin usr/bin lib sys proc mnt var dev media tmp
- cd /bin
- cp -arf busybox ash ln vi sh mount umount sync grep openssl tar cp mv ls cat sleep mkdir rmdir rm kill chmod ps /tmp/root/bin/
- cp -af /sbin/pivot_root /tmp/root/sbin/
- cp -af /sbin/reboot /tmp/root/sbin/
- cp -af /usr/bin/flash_erase /tmp/root/usr/bin/
- cp -af /usr/bin/free /tmp/root/usr/bin/
- cp -af /usr/bin/cut /tmp/root/usr/bin/
- cp -af /usr/bin/expr /tmp/root/usr/bin/
- cd /lib
- cp -arf libssl.so* libcrypt* ld-uClibc* libgcc* libuClibc-0.9.33.so libpthread* libc.* libm-* libm.* libmtd.so libdl* /tmp/root/lib/
-
- /bin/mount -o noatimve,move /proc /tmp/root/proc
- /sbin/pivot_root /var/tmp/root /var/tmp/root/mnt
- cp -arf /mnt/dev/* /dev/
- ln -sf /bin/busybox /usr/bin/[
- ln -sf /bin/busybox /usr/bin/[[
- ln -sf /bin/busybox /usr/bin/]
- mkdir -p /etc/openssl/
- cp -f /mnt/etc/openssl/openssl.cnf /etc/openssl/
- mount --bind /mnt/tmp /tmp
- /bin/umount -l /mnt
- echo 3 > /proc/sys/vm/drop_caches
- /bin/sync
- cd /
- busybox killall dbd
- busybox killall lighttpd
- busybox killall watchDog
- #exec /bin/busybox sh
-}
+bytes read : 10268368
+bytes written: 10268355
+
+$ file update.bin update
+update.bin: POSIX shell script, ASCII text executable
+update: data
```
+OK, the **update** file is still in an unknown format, but at least
+we have the tool used to write it to the system. And it is a shell
+script, so we have the source to look at too! But 936454 bytes is a
+hell of a shell script, and this is of course because most of it is an
+uuencoded binary. So we don't know exactly what that does. But it is
+named ddPack so a fair guess is that it is a tool for dd'ing multiple
+file systems or other images packed as a single file. That's really
+enough info.
+binwalk shows that the **update** file is just two squashfs systems
+and a kernel, with a 1024 header of some sort. The header presumably
+tells ddPack how it should apply these three images:
+```
+$ binwalk update
-Note that update.bin is almost identical in the two sample archives - the ddPack binary is exactly the same:
+DECIMAL HEXADECIMAL DESCRIPTION
+--------------------------------------------------------------------------------
+1024 0x400 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 338755 bytes, 16 inodes, blocksize: 131072 bytes, created: 2019-02-14 09:58:28
+340992 0x53400 uImage header, header size: 64 bytes, header CRC: 0x675F081D, created: 2019-02-14 09:31:53, image size: 1661571 bytes, Data Address: 0x804D4960, Entry Point: 0x804D4960, data CRC: 0x73083021, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: none, image name: "linux_3.10"
+2002627 0x1E8EC3 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 8265620 bytes, 2145 inodes, blocksize: 131072 bytes, created: 2019-02-14 09:58:45
+```
+But we can easily guess that without knowing anything about the
+header. There is only one alternative:
+ * The kernel goes into the **kernel** partition
+ * The 8265620 bytes squasfs system goes into the **rootfs** partition
+ * The remaining squasfs system goes into the **userdata** partition
-```
-bjorn@miraculix:/tmp$ diff -u update{,2}/update.bin|less
---- update/update.bin 2019-05-10 15:02:35.722407365 +0200
-+++ update2/update.bin 2019-05-10 15:02:18.802296356 +0200
-@@ -5,7 +5,7 @@
- OEM="D-Link"
- MODEL="DCS-8000LH"
- PRODUCT="Internet Camera"
--VERSION="1.0.0-1515"
-+VERSION="1.0.0-3014"
- PACKAGE=""
- WIRELESS_MODULE="RTL8723BU"
- # the DESCRIPT must be xml encoded.
-@@ -24,7 +24,7 @@
- "
- }
-
--MD5SUM="f91196794237bd39bd7040919d65cbdf"
-+MD5SUM="ca8aab5cda35beaab74ce9fdad65f909"
-
- MECH_SIGN="QPAT"
- MECH_VERSION="1.0"
-@@ -52,7 +52,7 @@
- }
-
- extract_ddpack() {
-- head -n 15453 $1 | tail -n +165 | uudecode -o /tmp/ddPack
-+ head -n 15454 $1 | tail -n +166 | uudecode -o /tmp/ddPack
- }
-
- dumpPibSettings() {
-@@ -124,6 +124,7 @@
- cp -arf libssl.so* libcrypt* ld-uClibc* libgcc* libuClibc-0.9.33.so libpthread* libc.* libm-* libm.* libmtd.so libdl* /tmp/root/lib/
-
- /bin/mount -o noatimve,move /proc /tmp/root/proc
-+ /bin/mount -t sysfs sysfs /tmp/root/sys
- /sbin/pivot_root /var/tmp/root /var/tmp/root/mnt
- cp -arf /mnt/dev/* /dev/
- ln -sf /bin/busybox /usr/bin/[
-```
+So there is no need to analyze ddPack. We have the necessary entry
+points for **fwupdate** or **firmwareupgrade.cgi** in the
+**update.bin** script, and that's what we needed to know for the next
+step:
+#### Creating our own firmware updates
+We do have shell access, so we can simply write the file systems we
+want to flash as shown earlier. We don't need to use the D-Link
+scripts. But where's the fun in that?
-```
-bjorn@miraculix:/tmp/update$ hexdump -C update |head -16
-00000000 53 b6 3b 76 d5 56 dc a3 fb 82 ff 82 31 1c 8e f4 |S.;v.V......1...|
-00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 75 70 64 61 74 65 2d 67 65 6e 65 72 69 63 5f 31 |update-generic_1|
-00000030 2e 30 2e 30 5f 33 36 32 35 2e 62 69 6e 00 00 00 |.0.0_3625.bin...|
-00000040 03 00 00 00 ff 00 00 00 00 00 06 00 00 60 02 00 |.............`..|
-00000050 00 00 00 00 f2 10 f1 bf ff 00 00 00 00 00 1e 00 |................|
-00000060 9e 5b 19 00 00 00 00 00 bb 1e e8 0a ff 00 00 00 |.[..............|
-00000070 00 00 4e 00 00 50 80 00 00 00 00 00 12 6c ad 99 |..N..P.......l..|
-00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-*
-00000400 68 73 71 73 0d 00 00 00 07 42 0b 5a 00 00 02 00 |hsqs.....B.Z....|
-00000410 02 00 00 00 04 00 11 00 e0 00 01 00 04 00 00 00 |................|
-00000420 91 01 00 00 00 00 00 00 a0 5c 02 00 00 00 00 00 |.........\......|
-00000430 98 5c 02 00 00 00 00 00 ff ff ff ff ff ff ff ff |.\..............|
-00000440 48 5a 02 00 00 00 00 00 3a 5b 02 00 00 00 00 00 |HZ......:[......|
-00000450 24 5c 02 00 00 00 00 00 8a 5c 02 00 00 00 00 00 |$\.......\......|
+There is one challenge here: The D-Link tools are expecting signed and
+encrypted firmware updates. They will run their verifyFirmware() and
+decryptFirmware() functions, and fail the update if any of the returns
+an error.
-bjorn@miraculix:/tmp/update$ binwalk update
+But bailing out on verification errors is only the default setting, as
+illustrated by this code from **fwupdate** (there is code with similar
+functionality in **firmwareupgrade.cgi**):
-DECIMAL HEXADECIMAL DESCRIPTION
---------------------------------------------------------------------------------
-1024 0x400 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 154784 bytes, 13 inodes, blocksize: 131072 bytes, created: 2017-11-14 19:20:39
-156672 0x26400 uImage header, header size: 64 bytes, header CRC: 0x63BA4812, created: 2017-11-14 18:53:33, image size: 1661790 bytes, Data Address: 0x804D4960, Entry Point: 0x804D4960, data CRC: 0xAF348ADF, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: none, image name: "linux_3.10"
-1818526 0x1BBF9E Squashfs filesystem, little endian, version 4.0, compression:xz, size: 8408112 bytes, 2142 inodes, blocksize: 131072 bytes, created: 2017-11-14 19:21:12
+
+```
+ TrustLevel=`tdb get SecureFW _TrustLevel_byte`
+ verifyFirmware
+ ret=$?
+ case $ret in
+ 2)
+ sign="not_signed"
+ ;;
+ 0)
+ sign="trust"
+ ;;
+ *)
+ sign="untrust"
+ ;;
+ esac
+ if [ "$do_up" = "1" -a "$ret" != "0" -a "$TrustLevel" = "1" ]; then
+ echo "3"
+ return 1
+ fi
```
+So we don't need to sign the firmware if we change the **SecureFW
+_TrustLevel** setting. Or we can even sign it with a key unknown to
+the camera if we like. Which can be useful if we ever replace the
+**rootfs**, since it will allow us to install our own verification
+key and use it with D-Links tools.
+But what about the encryption? This cannot be disabled. This gets
+even better: The decrypting key so graciously provided to us in the
+**pib** partition is an RSA private key. So not only can we decrypt
+the firmware with it, but we can also encrypt! Nice.
-```
-bjorn@miraculix:/tmp/update2$ hexdump -C update |head -16
-00000000 84 dd 19 a9 dc 69 0b 10 1b 6d 72 09 43 04 f7 f4 |.....i...mr.C...|
-00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 75 70 64 61 74 65 2d 67 65 6e 65 72 69 63 5f 31 |update-generic_1|
-00000030 2e 30 2e 30 5f 33 36 32 35 2e 62 69 6e 00 00 00 |.0.0_3625.bin...|
-00000040 03 00 00 00 ff 00 00 00 00 00 06 00 00 30 05 00 |.............0..|
-00000050 00 00 00 00 8e 91 0e 7e ff 00 00 00 00 00 1e 00 |.......~........|
-00000060 c3 5a 19 00 00 00 00 00 0e 5b d0 18 ff 00 00 00 |.Z.......[......|
-00000070 00 00 4e 00 00 20 7e 00 00 00 00 00 f4 2f 3c fb |..N.. ~....../<.|
-00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-*
-00000400 68 73 71 73 10 00 00 00 c4 3b 65 5c 00 00 02 00 |hsqs.....;e\....|
-00000410 02 00 00 00 04 00 11 00 e0 00 01 00 04 00 00 00 |................|
-00000420 05 02 00 00 00 00 00 00 43 2b 05 00 00 00 00 00 |........C+......|
-00000430 3b 2b 05 00 00 00 00 00 ff ff ff ff ff ff ff ff |;+..............|
-00000440 78 28 05 00 00 00 00 00 96 29 05 00 00 00 00 00 |x(.......)......|
-00000450 b7 2a 05 00 00 00 00 00 2d 2b 05 00 00 00 00 00 |.*......-+......|
-bjorn@miraculix:/tmp/update2$ binwalk update
+The **Makefile** in this repo has examples of how to use this to
+create firmware update images which are accepted by the **fwupdate**
+and **firmwareupgrade.cgi** tools. It uses an alternatative
+**update.bin** made to modify only the **userdata** partition. This
+way we can install our own code in the camera, but still leave the
+D-Link camera OS unmodified.
+
+
+## Contact
-DECIMAL HEXADECIMAL DESCRIPTION
---------------------------------------------------------------------------------
-1024 0x400 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 338755 bytes, 16 inodes, blocksize: 131072 bytes, created: 2019-02-14 09:58:28
-340992 0x53400 uImage header, header size: 64 bytes, header CRC: 0x675F081D, created: 2019-02-14 09:31:53, image size: 1661571 bytes, Data Address: 0x804D4960, Entry Point: 0x804D4960, data CRC: 0x73083021, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: none, image name: "linux_3.10"
-2002627 0x1E8EC3 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 8265620 bytes, 2145 inodes, blocksize: 131072 bytes, created: 2019-02-14 09:58:45
-
-bjorn@miraculix:/tmp/update2$ cmp _update.extracted/400.squashfs ~/docs/hardware/dlink/dcs8000lh/fw-2.02.02/mtd/mtd2
-_update.extracted/400.squashfs /home/bjorn/docs/hardware/dlink/dcs8000lh/fw-2.02.02/mtd/mtd2 differ: byte 339969, line 1341
-
-
-
-bjorn@miraculix:/tmp/update2$ hexdump -C ~/docs/hardware/dlink/dcs8000lh/fw-2.02.02/mtd/mtd2 |tail -20
-00052a70 00 02 00 01 00 73 61 c1 01 09 00 02 00 06 00 73 |.....sa........s|
-00052a80 74 72 6d 73 76 72 e5 01 0a 00 02 00 06 00 76 65 |trmsvr........ve|
-00052a90 72 73 69 6f 6e 20 80 d4 be 04 00 00 00 00 00 a4 |rsion ..........|
-00052aa0 69 00 00 00 00 00 00 ec 47 04 00 00 00 00 00 e8 |i.......G.......|
-00052ab0 76 00 00 00 00 00 00 95 2a 05 00 00 00 00 00 6c |v.......*......l|
-00052ac0 00 fd 37 7a 58 5a 00 00 01 69 22 de 36 03 c0 31 |..7zXZ...i".6..1|
-00052ad0 80 01 21 01 02 00 00 00 00 d5 63 7a 58 e0 00 7f |..!.......czX...|
-00052ae0 00 29 5d 00 02 80 8c c2 fd 03 13 13 bd 99 05 db |.)].............|
-00052af0 e5 85 88 7a 67 d4 1e 28 ef a3 03 b2 03 4e 9e c5 |...zg..(.....N..|
-00052b00 54 57 16 26 a7 2a 6b c0 71 9a 2b c4 e0 00 00 00 |TW.&.*k.q.+.....|
-00052b10 00 13 b2 2b 6f 00 01 45 80 01 00 00 00 f5 98 9a |...+o..E........|
-00052b20 95 3e 30 0d 8b 02 00 00 00 00 01 59 5a bf 2a 05 |.>0........YZ.*.|
-00052b30 00 00 00 00 00 04 80 00 00 00 00 35 2b 05 00 00 |...........5+...|
-00052b40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-*
-00053000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-*
-00060000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-*
-00100000
-
-
-
-bjorn@miraculix:/tmp/update2$ hexdump -C _update.extracted/400.squashfs |egrep '^0005(2[b-f]|30)'
-00052b00 54 57 16 26 a7 2a 6b c0 71 9a 2b c4 e0 00 00 00 |TW.&.*k.q.+.....|
-00052b10 00 13 b2 2b 6f 00 01 45 80 01 00 00 00 f5 98 9a |...+o..E........|
-00052b20 95 3e 30 0d 8b 02 00 00 00 00 01 59 5a bf 2a 05 |.>0........YZ.*.|
-00052b30 00 00 00 00 00 04 80 00 00 00 00 35 2b 05 00 00 |...........5+...|
-00052b40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00053000 27 05 19 56 67 5f 08 1d 5c 65 35 89 00 19 5a 83 |'..Vg_..\e5...Z.|
-00053010 80 4d 49 60 80 4d 49 60 73 08 30 21 05 05 02 00 |.MI`.MI`s.0!....|
-00053020 6c 69 6e 75 78 5f 33 2e 31 30 00 00 00 00 00 00 |linux_3.10......|
-00053030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00053040 21 80 80 00 21 88 a0 00 21 90 c0 00 21 98 e0 00 |!...!...!...!...|
-00053050 67 80 04 3c f0 a3 84 24 a7 80 06 3c 00 c4 c6 24 |g..<...$...<...$|
-00053060 00 00 80 ac fe ff c4 14 04 00 84 24 67 80 04 3c |...........$g..<|
-00053070 00 a4 84 24 a7 80 1d 3c 00 c4 bd 27 4d 80 1f 3c |...$...<...'M..<|
-00053080 b4 49 ff 27 4d 80 1a 3c 4c 4c 5a 27 08 00 40 03 |.I.'M..<LLZ'..@.|
-00053090 00 00 00 00 21 20 00 02 21 28 20 02 21 30 40 02 |....! ..!( .!0@.|
-000530a0 21 38 60 02 3c 80 1a 3c e0 98 5a 37 08 00 40 03 |!8`.<..<..Z7..@.|
-000530b0 00 00 00 00 ff ff 00 10 00 00 00 00 00 00 00 00 |................|
-000530c0 03 00 81 04 67 80 18 3c 08 00 e0 03 21 10 00 00 |....g..<....!...|
-000530d0 fc a3 02 8f 05 00 40 14 fc ff 03 24 67 80 02 3c |......@....$g..<|
-000530e0 f4 a3 42 8c fc a3 02 af fc a3 02 8f 03 00 42 24 |..B...........B$|
-000530f0 24 10 43 00 21 20 82 00 fc a3 04 af 67 80 18 3c |$.C.! ......g..<|
-
-
-bjorn@miraculix:/tmp/update2$ hexdump -C ~/docs/hardware/dlink/dcs8000lh/fw-2.02.02/mtd/mtd2 |egrep '^0005(2[b-f]|300)'
-00052b00 54 57 16 26 a7 2a 6b c0 71 9a 2b c4 e0 00 00 00 |TW.&.*k.q.+.....|
-00052b10 00 13 b2 2b 6f 00 01 45 80 01 00 00 00 f5 98 9a |...+o..E........|
-00052b20 95 3e 30 0d 8b 02 00 00 00 00 01 59 5a bf 2a 05 |.>0........YZ.*.|
-00052b30 00 00 00 00 00 04 80 00 00 00 00 35 2b 05 00 00 |...........5+...|
-00052b40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00053000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-
-
-bjorn@miraculix:/tmp/update2$ hexdump -C _update.extracted/400.squashfs |tail -20
-000ffed0 31 a7 7c a3 ec 78 cf 09 b4 e3 e3 72 c4 00 99 70 |1.|..x.....r...p|
-000ffee0 92 a3 5b 89 1a 7a ad 0e b8 0b 37 5f b1 a6 d9 3b |..[..z....7_...;|
-000ffef0 46 ad ad 8f 16 21 94 c3 a9 39 94 f6 c6 2a 42 8e |F....!...9...*B.|
-000fff00 c5 56 27 af a4 b9 3f 8b 52 1d 05 a3 7e 3f d3 c1 |.V'...?.R...~?..|
-000fff10 9b e0 e5 5c a3 cd b6 e8 9a 5f 8c 3c b6 8b 0f e7 |...\....._.<....|
-000fff20 17 2f e9 ed ce 9e b8 97 6d 7c a0 44 6f 42 a0 d0 |./......m|.DoB..|
-000fff30 29 de 24 34 46 1c a6 98 a1 92 39 68 cf 99 e9 4f |).$4F.....9h...O|
-000fff40 e7 b3 df 76 40 5a e4 80 ac 38 bc 80 fb b6 f9 4e |...v@Z...8.....N|
-000fff50 87 fb da 3c 47 a7 65 ff f4 94 f2 71 3f a0 59 80 |...<G.e....q?.Y.|
-000fff60 86 22 db bb a6 15 13 51 07 8d b0 50 70 b7 85 a9 |.".....Q...Pp...|
-000fff70 08 97 54 ee 93 3f 96 b3 22 b3 7b 1d 74 cb b1 00 |..T..?..".{.t...|
-000fff80 c6 d1 4f 25 d7 cd 86 8f 7d a2 6a c7 12 2f 6d 65 |..O%....}.j../me|
-000fff90 6e 14 ae 2f 75 02 9c be 25 e5 82 e8 24 70 4c 45 |n../u...%...$pLE|
-000fffa0 4c 39 24 a4 f9 0c 5f 48 21 9d de 71 8d 30 cd 6e |L9$..._H!..q.0.n|
-000fffb0 50 75 8f 28 14 1f 00 e3 5a d4 24 e5 50 4d 21 c1 |Pu.(....Z.$.PM!.|
-000fffc0 f1 fd b9 ed e8 c4 42 5e b4 6a 2f 96 12 86 21 78 |......B^.j/...!x|
-000fffd0 b7 12 11 1c 51 cb a9 21 33 0b 7c 96 4e 0b 6e c4 |....Q..!3.|.N.n.|
-000fffe0 61 cc d2 0a 61 30 67 2c d3 d4 0f ee 7b 3a 8e 80 |a...a0g,....{:..|
-000ffff0 dd af 1b d1 1d 29 db 84 82 45 f5 32 8d 44 6a 4c |.....)...E.2.DjL|
-00100000
-
-```
-
-
-Note that there are lots of compressed 00 byte lines between 00052b40
-and 00053000 above. And 0x53000 is 339968.
-
-
-
-While the rootfs seems to be just big enough, and there has no extra data:
-
-```
-bjorn@miraculix:/tmp/update2$ hexdump -C _update.extracted/1E8EC3.squashfs|tail -20
-007e1e80 bd 80 eb 69 d2 14 8c 15 2b b7 02 f7 9e dc f4 f6 |...i....+.......|
-007e1e90 5d fb b1 a5 64 4b 98 0a 40 68 c8 70 13 c7 52 55 |]...dK..@h.p..RU|
-007e1ea0 59 42 7e 72 f8 ab d8 c1 4e 7c 8b ea d5 65 aa 47 |YB~r....N|...e.G|
-007e1eb0 59 a4 b9 40 43 c1 6a f7 58 b3 cd bb 4e c1 68 26 |Y..@C.j.X...N.h&|
-007e1ec0 37 22 35 a0 05 19 42 3c 48 c0 08 95 89 19 51 9d |7"5...B<H.....Q.|
-007e1ed0 e6 d8 87 4c c5 39 ef e7 6e ad fb 24 ca b1 1b 5f |...L.9..n..$..._|
-007e1ee0 b3 c9 e4 c3 c3 d3 b0 a3 43 48 e6 26 e1 80 ad f9 |........CH.&....|
-007e1ef0 95 38 36 dd 1a b4 ab 59 03 ee e3 1e 9b f5 64 43 |.86....Y......dC|
-007e1f00 ce 44 1c 20 6e e7 77 23 ed 20 9c 90 4b 00 d5 01 |.D. n.w#. ..K...|
-007e1f10 1e 1c dd c4 7b 96 f2 1d 47 ae 2e e0 5c 51 6c 54 |....{...G...\QlT|
-007e1f20 9b e7 92 66 5e 33 98 00 e0 79 b9 3c f8 01 38 d5 |...f^3...y.<..8.|
-007e1f30 82 1b 11 48 66 be 0a 7c b7 19 c3 7c 0d be 91 27 |...Hf..|...|...'|
-007e1f40 95 32 0b 13 78 6a 49 dd f6 f4 a1 3f e3 00 a1 63 |.2..xjI....?...c|
-007e1f50 86 16 00 01 84 02 88 06 00 00 15 33 d4 10 3e 30 |...........3..>0|
-007e1f60 0d 8b 02 00 00 00 00 01 59 5a 08 0d 7e 00 00 00 |........YZ..~...|
-007e1f70 00 00 d2 15 7e 00 00 00 00 00 40 1e 7e 00 00 00 |....~.....@.~...|
-007e1f80 00 00 08 80 75 00 00 00 7d 00 00 00 82 1f 7e 00 |....u...}.....~.|
-007e1f90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-*
-007e2000
-
-
-bjorn@miraculix:/tmp/update2$ hexdump -C ~/docs/hardware/dlink/dcs8000lh/fw-2.02.02/mtd/mtd8 |tail -22
-007e1e80 bd 80 eb 69 d2 14 8c 15 2b b7 02 f7 9e dc f4 f6 |...i....+.......|
-007e1e90 5d fb b1 a5 64 4b 98 0a 40 68 c8 70 13 c7 52 55 |]...dK..@h.p..RU|
-007e1ea0 59 42 7e 72 f8 ab d8 c1 4e 7c 8b ea d5 65 aa 47 |YB~r....N|...e.G|
-007e1eb0 59 a4 b9 40 43 c1 6a f7 58 b3 cd bb 4e c1 68 26 |Y..@C.j.X...N.h&|
-007e1ec0 37 22 35 a0 05 19 42 3c 48 c0 08 95 89 19 51 9d |7"5...B<H.....Q.|
-007e1ed0 e6 d8 87 4c c5 39 ef e7 6e ad fb 24 ca b1 1b 5f |...L.9..n..$..._|
-007e1ee0 b3 c9 e4 c3 c3 d3 b0 a3 43 48 e6 26 e1 80 ad f9 |........CH.&....|
-007e1ef0 95 38 36 dd 1a b4 ab 59 03 ee e3 1e 9b f5 64 43 |.86....Y......dC|
-007e1f00 ce 44 1c 20 6e e7 77 23 ed 20 9c 90 4b 00 d5 01 |.D. n.w#. ..K...|
-007e1f10 1e 1c dd c4 7b 96 f2 1d 47 ae 2e e0 5c 51 6c 54 |....{...G...\QlT|
-007e1f20 9b e7 92 66 5e 33 98 00 e0 79 b9 3c f8 01 38 d5 |...f^3...y.<..8.|
-007e1f30 82 1b 11 48 66 be 0a 7c b7 19 c3 7c 0d be 91 27 |...Hf..|...|...'|
-007e1f40 95 32 0b 13 78 6a 49 dd f6 f4 a1 3f e3 00 a1 63 |.2..xjI....?...c|
-007e1f50 86 16 00 01 84 02 88 06 00 00 15 33 d4 10 3e 30 |...........3..>0|
-007e1f60 0d 8b 02 00 00 00 00 01 59 5a 08 0d 7e 00 00 00 |........YZ..~...|
-007e1f70 00 00 d2 15 7e 00 00 00 00 00 40 1e 7e 00 00 00 |....~.....@.~...|
-007e1f80 00 00 08 80 75 00 00 00 7d 00 00 00 82 1f 7e 00 |....u...}.....~.|
-007e1f90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-*
-007e2000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-*
-00b00000
-```
-
-Experiment:
-
-```
-# flash_erase -j /dev/mtd4 0 2
-Erasing 64 Kibyte @ 0 -- 0 % complete flash_erase: Cleanmarker written at 0
-Erasing 64 Kibyte @ 10000 -- 50 % complete flash_erase: Cleanmarker written at 10000
-Erasing 64 Kibyte @ 10000 -- 100 % complete
-
-# mount -t jffs2 /dev/mtdblock4 /mnt
-mount: mounting /dev/mtdblock4 on /mnt failed: Invalid argument
-# dmesg|tail
-rtk_btcoex: update_profile_connection: btrtl_coex.profile_refcount[6] = 0
-rtk_btcoex: update_profile_connection: btrtl_coex.profile_refcount[7] = 0
-rtk_btcoex: rtk_notify_profileinfo_to_fw: BufferSize 2
-rtk_btcoex: rtk_notify_profileinfo_to_fw: NumberOfHandles 0
-rtk_btcoex: rtk_notify_profileinfo_to_fw: profile_status 0x00
-rtk_btcoex: rtk_vendor_cmd_to_fw: opcode 0xfc19
-rtk_btusb: hci0 evt 2
-rtk_btusb: btusb_notify : hci0 evt 2
-jffs2: Too few erase blocks (2)
-jffs2: Too few erase blocks (2)
-
-```
-
-
-
-
-THIS WORKED:
-
-bjorn@miraculix:/tmp/update2$ perl -e 'print unpack("(H2 )*", shift),"\n"' 'P=123947;N=123947&&(echo "gg::0:0::/:/bin/sh">>/tmp/passwd)&'
-503d3132333934373b4e3d3132333934372626286563686f202267673a3a303a303a3a2f3a2f62696e2f7368223e3e2f746d702f7061737377642926
+Please contact me on bjorn@mork.no if you have questions, comments or
+just want to say hi.
-bjorn@miraculix:/tmp/update2$ perl -e 'print unpack("(H2 )*", shift),"\n"' 'P=123947;N=123947&&(telnetd -p 1099)&'
-503d3132333934373b4e3d31323339343726262874656c6e657464202d7020313039392926
+But please note that I won't be able to provide any support for this.
+I am making this information available for educational purposes. If
+you find it useful, then great! If you brick a camera, then I am
+truly sorry about that. But there isn't much I can do about it....