Quantcast
Channel: Sergei's incoherrent ramblings
Viewing all 58 articles
Browse latest View live

Dynamic HTML5 video page generator

$
0
0

Not sure if this is optimal, as I am not a “web” developer, here is a dynamically generated simple HTML5 page:


<!DOCTYPE html>
<html>
  <script type="text/javascript">
function sVideo(){
    d = new Date();
    var streams = ["stream1","steam2","steam3","streamN","streamN+1"];
    var l = streams.length;
    for (var i = 0; i < l; i++){

        var vDiv = document.createElement("div");
        vDiv.style.position="relative";
        vDiv.style.cssFloat="left";
        vDiv.style.display="table-row";

        var vVideo = document.createElement("video");
        vVideo.id = streams[i];
        var source = document.createElement('source');
        source.src = 'http://example.com/video/'+streams[i]+'?t='+ d.getTime();
        source.type = 'video/webm'
        vVideo.appendChild(source);

        vVideo.play();
        vVideo.removeAttribute("controls");

        vDiv.appendChild(vVideo);

        var aDiv = document.getElementById("anchor");
        aDiv.appendChild(vDiv);
   }
}
  </script>
  <body onload="sVideo()">
    <div id="anchor" style="position:relative; float:left; display:table">
    </div>
  </body>
</html>

Here what it does:

For every stream in the list ‘streams’ it generates a div (the divs are arranged in a table), into which it places video block with stream source and type.

This page does not work with iOS because it does not support webm. On other hand it works perfectly fine on a shitty $50 android device. Actually it works everywhere except iOS (Linux, Windows, Android, FreeBSD and OSX).


Protected: HKE451

$
0
0

This content is password protected. To view it please enter your password below:

ILDVR INC-MH40D06

$
0
0

ILDVR INC-MH40D06

A 4MP dome IP camera (this particular has 2.8mm lens) ordered from ildvr.com, somewhat unknown company between western IP camera enthusiasts (although it is known in Russian circles). I have stumbled up when researching new cameras on some Russian website.

Made an enquiry on ildvr.com expecting to have usual “go away” response (as in: “contact our useless resellers, that will not sell you anyway”). To my surprise I got a very quick reply with all my questioned answered.

The retail price of this camera is around $100USD (they charge extra for their windows software, in which I was not interested).

From hardware perspective this camera is similar to Dahua IPC-HDBW4300E.

It has metal construction with plastic dome. Biggest difference is that the Dahua has PoE circuit on the base, while ILDVR has it on the camera body.

The camera came in a cubic box which contained another box padded by thin layer of foam. One issue with packaging I had is that the bag containing the mounting screws was not sealed properly and spilled the screws. One of the screws managed to leave a scratch on the dome. This scratch is not a huge issue is that it is unlikely it will ever be in field of view.

INC-MH40D06_box

INC-MH40D06_box1

The warranty sticker is a nice touch:
INC-MH40D06_box2

INC-MH40D06_box3

The ILDVR letters are bunch of stickers (I will probably remove them as they are a bit tacky):
INC-MH40D06_camera

Second warranty sticker on camera itself:
INC-MH40D06_camera1

INC-MH40D06_camera2

Note the string preventing the dome from falling. The screws are also captive and of torx type (a bit nicer than usual hex screws).
INC-MH40D06_camera3

INC-MH40D06_camera4

A close up of the scratch (nothing to really worry about):
INC-MH40D06_scratch

The box contained a Torx “L” wrench, template, mounting screws/dowels and ethernet jack seal kit.
Note: there was no CD (normally containing crappy windows software) or manual.

An interesting feature is the ethernet status LEDs on the connector:
INC-MH40D06_jack

The cable itself is about 40cm long.

Technical details

Most of this stuff I discovered poking around while waiting for technical details from ILDVR.
I will fill in once I have more details.

With no help from ILDVR I managed to get shell on it.

ARMv7 Processor rev 5 (v7l)
128MB RAM
16MB Flash (MX25L128XX)

/proc/cpuinfo

Processor       : ARMv7 Processor rev 5 (v7l)
BogoMIPS        : 1196.85
Features        : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc07
CPU revision    : 5

Hardware        : hi3516a
Revision        : 0000
Serial          : 0000000000000000

free -m

             total         used         free       shared      buffers
Mem:           121           64           57            0            0
-/+ buffers:                 64           57
Swap:            0            0            0

load hovers around 3 (less than Dahua and Hikvision).

uname -a

Linux ipc 3.4.35 #5 Fri May 8 10:31:07 CST 2015 armv7l GNU/Linux

df -h

Filesystem                Size      Used Available Use% Mounted on
/dev/root                 2.0M      2.0M         0 100% /
tmpfs                    30.0M     19.9M     10.1M  66% /dev
tmpfs                    30.0M     19.9M     10.1M  66% /tmp
tmpfs                    30.0M     19.9M     10.1M  66% /dev
tmpfs                    30.0M     19.9M     10.1M  66% /var
tmpfs                    30.0M     19.9M     10.1M  66% /tmp
tmpfs                    30.0M     19.9M     10.1M  66% /dev
tmpfs                    30.0M     19.9M     10.1M  66% /var
/dev/mtdblock3           11.0M      8.5M      2.5M  77% /mnt/flash
tmpfs                    30.0M     19.9M     10.1M  66% /mnt/flash/Server
tmpfs                    30.0M     19.9M     10.1M  66% /usr/lib
tmpfs                    30.0M     19.9M     10.1M  66% /etc
tmpfs                    30.0M     19.9M     10.1M  66% /root

cat /mnt/flash/productinfo/deviceid.txt

DEVICEID V6202IR-OV4689

I found actual manufacturer of the board:
http://www.hankvision.com/chanpin/wangluomozu/512.html

In case link goes away here is the screenshot:
hankvision_HC-9402A

They claim it is Hi3516D chipset.

The webUI.

Default username and password is admin.
I was hoping for a more modern interface, the one without ActiveX/Windows only crap…
As usual the viewer is useless without ActiveX plugin, even if mjpeg is selected there is a bug where it only shows two frames.
The Video and Camera settings are useless again due lack of plugin.
This webUI is on par on crappiness with Hikvision and Dahua.
One day we will have platform independent HTML5 interface… I hope.

Epic fail with activeX:
ildvr_activeX_crap

ildvr_camera_settings_plugin_fail

MJPEG stream preview is a bit buggy (not really visible here):
ildvr_mjpeg_fail

Various settings:
ildvr_settings_page

ildvr_video_settings

The most important feature that is missing is Telnet/SSH control (I would rather turn off Telnet). The telnet is on all the time (I have enquired about telnet access).
There is also no control regarding password protecting streams.

It took me a while to figure out the streams, due to misleading Dahua style URL working somewhat. This will work rtsp://192.168.1.200:554/cam/realmonitor?channel=0&subtype=0 but it disregards the channel or subtype selection and only gives sub stream (“minor” in ILDVR terms). That URL is not correct.
Below are correct urls (I lifted them off the javascript in the webUI).

Main stream (aka “major”):

rtsp://192.168.1.200:554/1/h264major

Sub stream (aka “minor”):

rtsp://192.168.1.200:554/1/h264minor

Snapshot URL:

http://admin:admin@192.168.1.200/jpgimage/1/image.jpg

Not sure what is the correct URL for mjpeg stream…

Interesting that the camera supports H265/HEVC. I am yet to test it (need to compile ffmpeg with h265 support).

The resolution selection goes all the way up to 2592×1944 (“2K”) on the “major” stream.

As typical there are stream errors with UDP stream (TCP stream is OK).

In general Web UI is very crappy and not tailored to the camera. It does not even get the camera model correctly.
There is a special clause in javascript for hi3518E chip (for whatever reason?).

I have spent a few hours pocking around the camera I noticed a few issues with webUI. I could crash (in a minor way) the camera with malformed fields when setting the time (via curl POST) as the validation happens in the javascript.
The smtp,ftp and alarm settings don’t work. The motion detect is useless without ftp/smtp or alarm settings.

The following quirks I found:

/form/, /cgi/ and /cgi-bin/ are all the same paths.
There is a “form” validation which does not allow arbitrary /cgi-bin/ script execution.
The simple path traversal exploit does not work.
Various little hack failed (command execution, remote inclusion, etc.), but I haven’t tried hard enough (I don’t normally hack things).
Any URL ending with image.jpg will result of attempting to get a snapshot from camera.
The ones that dont match jpgimage/1/image.jpg result in following output:

HTTP/1.0 200 OK
Content-Type: text/html

Image error

 

This potentially could be exploited (I don’t know how yet).

A lot of validation is happening in javascript. It is possible to set IP address, create username or almost any other field to any test string. I am currently trying to exploit this “feature”.

There are also a few places in javascript that has hard-coded “admin/admin” username and password:

document.getElementById("replay").SetLoginParam(srcIP,'admin','admin');		//justin changed 2013.6.27
document.getElementById("replay").SetLoginParamEx(srcIP,'admin','admin',$("#httpPort").val(),$("#rtspPort").val());		//2014.04.12

and:

player.RunPlayEx(ipAddr.toString(),0,"0.0.0.0",2,90,0,"admin","admin");

 

There are a lot of references to “justin” all over the place.

The onvif located at http://192.168.1.200:8999/onvif/
The onvif is not password protected!!!! (I can add remove users, reboot camera, change passwords, etc).

The server headers are very similar to Hikvision (only it is “Hankvision”, lol WTF?):

HTTP/1.1 200 Data follows
Server: Hankvision-Webs
Date: Thu Dec 24 12:44:27 2015
Pragma: no-cache
Cache-Control: no-cache
Content-Type: text/html

 

Digging more around I found that OMEGA-21P22-12 has same firmware (I googled the firmware version number out of desperation).

Basically I am thinking of getting serial port hooked up the board as the manufacturer is silent regarding telnet/shell access and I do not trust this firmware at all.

Here are the innards (the simplest way to remove the board is to unclip IR cover from front using two clips on the side):

INC-MH40D06_module_back

PoE module:
INC-MH40D06_PoE

SoC board (unfortunately cannot tell the model of SoC due to heatsink, looks like Hisilicon, possibly Hi3516D):
INC-MH40D06_SoC

Lens:
INC-MH40D06_lens

Sensor (I assume it is OV4689):
INC-MH40D06_sensor

Conclusion.

It started all promising (communication, pricing and delivery). Hardware is great. Firmware is the show stopper.

I am thinking of putting off buying ILDVR cameras due to “secrecy” regarding firmware and telnet access (not unless I can flash them with generic Hivision firmware).

I’ll probably stick to Dahua, as at least I have shell access on those (and I can hack firmware to fix/address whatever issues arise). Even though Dahua does not want to deal with me directly…

Update: I managed to get shell on it, more info here.

ILDVR INC-MH40D06 or hacking cheap chinese camera

$
0
0

Continuation of ILDVR INC-MH40D06

Since manufacturer will not divulge the super secret telnet password, and not having ability to turn off the telnet from web ui, I have decided to get access to camera via more brute method.

This involves opening the camera, soldering a pin header/wires to RS232 pads on the SoC board:

ildvr_rs232_pads_labels

ildvr_1.27mm_rs232

ildvr_1.27mm_to_2.54mm_rs232

ildvr_1.27mm_rs232_2

ildvr_usb_rs232

The RS232 is connected to a 3.3V (NOT 5V!) USB RS232 TTL adapter (a few bucks on ebay). BTW the ebay sourced USB adapter did not come with instruction/pin-out. It is in fact the following:

Red - 3.3V
Green - TX
White - RX
Black - GND

The pin spacing is 1.27mm. I could not find the connector that would fit so I botched 1.27mm->2.54mm header adapter (since the USB adapter came with 2.54mm sockets):

I disconnected the 3.3V pin as the SoC was using that for power and would not reboot when PoE was disconnected.
I used minicom with following settings:

115200 8N1
ttyUSB0

Once power is applied immediately press any key to interrupt the boot process and get uBoot prompt:

U-Boot 2010.06 (May 18 2015 - 09:40:27)

Check spi flash controller v350... Found
Spi(cs1) ID: 0xC2 0x20 0x18 0xC2 0x20 0x18
Spi(cs1): Block:64KB Chip:16MB Name:"MX25L128XX"
In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0 
hisilicon #

To find out correct boot parameters run printenv:

hisilicon # printenv 
bootcmd=sf probe 0;sf read 0x82000000 0x50000 0x2b0000;bootm 0x82000000
bootdelay=1
baudrate=115200
ethaddr=00:00:23:34:45:66
ipaddr=192.168.6.99
serverip=192.168.6.10
netmask=255.255.252.0
bootfile="uImage"
board=hi3516d
bootargs=mem=128M console=ttyAMA0,115200 root=/dev/mtdblock2 rootfstype=jffs2 mtdparts=hi_sfc:320K(boot),2752K(kernel),2M(rootfs),11M(data)
stdin=serial
stdout=serial
stderr=serial
verify=n
ver=U-Boot 2010.06 (May 18 2015 - 09:40:27)

To get root you will need to modify the bootargs variable:

setenv bootargs mem=128M console=ttyAMA0,115200 root=/dev/mtdblock2 rootfstype=jffs2 mtdparts=hi_sfc:320K(boot),2752K(kernel),2M(rootfs),11M(data) init=/bin/sh

It is pretty much exactly the same as original bootargs from printenv except the init is changed to shell (/bin/sh).

To boot, simply run the values from bootcmd variable from printenv:

sf probe 0;sf read 0x82000000 0x50000 0x2b0000;bootm 0x82000000

To continue with boot (to get rest of the mounts and things up and running) run following:

/etc/init.d/rcS

At this stage you can change the root password (via passwd). This will not stick, to make it stick modify Server.tar.xz with desired etc/passwd entry (see below).

Horrible stuff below.
Everything runs as root!

The point of interest is /mnt/flash/Server.tar.xz, I believe init script unpacks it into /mnt/flash/.
It is possible to get the whole file without using tfpt or any other trickery by simply copying it accross into accessible area from webui:

cp /mnt/flash/Server.tar.xz /mnt/flash/web/browse/


From there you can simply type http://${camera_ip}/browse/Server.tar.xz and download the whole thing.

Examining the "server" binary I discovered major security flaw. Specifically in Server/LINUX/webs there are following strings:

name=HANKVISION
password=HANKVISION

I tested it against web ui, and to my horror these credentials allowed me to log in (with admin right nevertheless).

Here is the Server.tar.xz for curious types.

Other things.

The /etc/passwd contained the following:

root:$1$EnVGPLqH$OmqpejDjDsF8NQkcwH/og.:0:0::/root:/bin/sh


I am using JTR with Cuda (on GTX970) against it (at this stage alpha 4-8), but I doubt I will get anywhere. I need to find an exploit to change /etc/passwd without using serial.

The /etc/passwd- contained the following:

root:$1$y3A1TsGe$n7RvgOkNPb1PhGPGnh9v5.:0:0::/root:/bin/sh

There are a lot of references to Justin and paths like /home/zhangxq/

Since you can get Server.tar.xz and there is wget, you can modify Server.tar.xz and replace modified version via wget, which opens to plenty of possibilities.

mini0806 internal cable issue

$
0
0

So, Why my second mini0806 was always crashing?
Turns out to be it was the internal cable after all.

Here is the fix:
mini0806_cable_fix

mini0806_cable_fix1

hot glue for a good measure:
mini0806_cable_fix2

The original cable:
IMG_20150807_132408

I used some telephone/Cat5 cable due to lack of better alternative, it works good now.

I also noticed a peculiar thing: card slot A and slot B have different read/write speeds.

ILDVR INC-MH40D06 security nightmare

$
0
0

So here I am poking at ILDVR INC-MH40D06 only to discover more and more security issues.

Security issue #1

WebUI hardcoded username and password (HANKVISION/HANKVISION).

Security issue #2

Apparently beyond “standard” webs binary running as webserver there is a separate instance of httpd running on the camera.
It runs on port 10081 and uses /mnt/flash/data as homedir.
The /mnt/flash/data contains a lot of config files (or status files to be exact):

/mnt/flash/data # ls -la

total 49
drwxrwxrwx    2 root     root             0 Aug  5  2013 .
drwxrwxrwx    8 root     root             0 Feb  8 16:13 ..
-rwx------    1 root     root           596 Dec 30 14:21 AlarmInfo
-rwx------    1 root     root            26 Dec 30 14:19 AudioConfig.txt
-rwx------    1 root     root           204 Dec 29 17:15 Auth8021xInfo
-rwx------    1 root     root            72 Dec 30 14:17 CameraInfo
-rwx------    1 root     root            64 Dec 29 17:15 ConfigScopeData
-rwx------    1 root     root           204 Dec 29 17:15 DDnsInfo
-rwx------    1 root     root            50 Aug  5  2013 DhcpFile.txt
-rwx------    1 root     root            50 Dec 29 17:15 DhcpSFile.txt
-rw-r--r--    1 root     root            64 Aug  5  2013 FilterInfo
-rwx------    1 root     root           632 Dec 29 17:15 FtpInfo
-rwx------    1 root     root            48 Dec 29 17:15 IgmpInfo
-rwx------    1 root     root           608 Dec 30 14:19 IvpathInfo
-rw-r--r--    1 root     root            80 Dec 30 14:19 MDScopeInfo
-rw-------    1 root     root          2384 Dec 30 14:05 MOTO_PresetPoint
-rw-r--r--    1 root     root             8 Aug  5  2013 MobileInfo
-rwx------    1 root     root           356 Dec 29 17:15 MotionInfo
-rwx------    1 root     root            64 Feb  8 15:47 NetInfo
-rwx------    1 root     root            64 Dec 29 17:15 NetInfo_BSD
-rwx------    1 root     root            64 Dec 29 17:15 NetInfo_HK
-rwx------    1 root     root           148 Dec 30 14:07 NtpInfo
-rwx------    1 root     root           328 Dec 30 14:19 OsdInfo
-rw-r--r--    1 root     root            18 Aug  5  2013 OwnUserInfo.txt
-rwx------    1 root     root            68 Dec 29 17:15 PppoeInfo
-rwx------    1 root     root           356 Dec 30 14:19 PrivacyInfo
-rwx------    1 root     root           480 Dec 29 17:15 ProfileData
-rwx------    1 root     root         17132 Dec 30 14:20 PtzConfigInfo
-rwx------    1 root     root            11 Dec 30 14:21 SDInfo
-rw-------    1 root     root            26 Dec 29 17:15 ShaInfo
-rwx------    1 root     root           492 Dec 29 17:26 SipInfo
-rw-r--r--    1 root     root            28 Aug  5  2013 SjkdInfo
-rwx------    1 root     root           800 Feb  8 14:14 SmtpInfo
-rw-r--r--    1 root     root           280 Aug  5  2013 SnmpInfo
-rwx------    1 root     root           320 Aug  5  2013 SysInfo
-rw-r--r--    1 root     root            36 Aug  5  2013 TutkInfo
-rwx------    1 root     root          4328 Feb  8 14:13 UserInfo
-rwx------    1 root     root            46 Dec 29 17:15 UuidData
-rwx------    1 root     root            15 Dec 29 17:15 Version.txt
-rwx------    1 root     root            36 Dec 30 14:20 VideoInfo
-rw-r--r--    1 root     root            12 Aug  5  2013 WifiBitrateInfo
-rw-r--r--    1 root     root           112 Aug  5  2013 WifiInfo
-rwx------    1 root     root           312 Dec 30 14:17 cameramode
-rwx------    1 root     root           312 Dec 29 17:15 cameramode_default
-rw-------    1 root     root            10 Dec 29 17:15 device_model.txt
-rw-------    1 root     root             2 Dec 29 17:15 hik.txt
-rw-r--r--    1 root     root             0 Jan  1  1970 hisi_ipc
-rwx------    1 root     root            18 Dec 29 17:15 ppcnCfg.txt
---------x    1 root     root           320 Dec 30 14:20 profiledata
-rwx------    1 root     root            14 Dec 30 14:14 sensor.cfg
-rwx------    1 root     root            13 Dec 29 17:19 uluCfg.cfg

These will contain plain text ftp settings and smtp settings among other this. There is no hint of auth.

ILDVR INC-MH40D06 or hacking cheap chinese camera part 2

$
0
0

ILDVR INC-MH40D06 or hacking cheap chinese camera part 2 (or unbricking the camera via uBoot).

While was poking around, I managed to brick the camera.
I tried to change the /etc/password on rootfs, unfortunately due to nature jffs2 small changes to file system are not quiet possible if there is not enough space of erase block size increment (in this case it was 64k).
I moved away udevadm to be able to change /etc/passwd only to find I could not move it back or change the /etc/password anyway.
Any attempt led to No space left on device. I put this to my lack of experience with jffs2. At that stage I knew camera was bricked. I saved udevadm binary which I moved away via wget (I moved it to the /mnt/flash/web/browse/ which made it accessible via http). I confirmed it was bricked after reboot (no networking due to unable to mount the flash partitions, as udev was not setting up the block devices in /dev).

Now, I knew that not everything was lost, since I still had uBoot working.
Specifically there was tftp tool to upload/download memory chunks to tftp server.

Since I am using Ubuntu I installed tftp server:

apt-get install tftpd-hpa

It took me awhile to figure out how to read and write to flash (the give away was sf probe 0;sf read 0x82000000 0x50000 0x2b0000;bootm 0x82000000 as bootcmd).

To map the flash memory into a specific address in RAM of specific offset of flash memory (flash address) and specific length (flash partition size):

sf read $MEMORY_ADDRESS $FLASH_OFFSET $SIZE

I use the default address of 0x82000000 (no idea how it is determined normally, I guess it is high enough not to interfere with uBoot?).
For Flash Offset and size I used data from cat /proc/mtd

If these things are unknown I guess it is possible to infer them from bootcmd or by dumping the whole flash and then binwalk (I haven't tried this).

the /proc/mtd looked like this:

dev:    size   erasesize  name
mtd0: 00050000 00010000 "boot"
mtd1: 002b0000 00010000 "kernel"
mtd2: 00200000 00010000 "rootfs"
mtd3: 00b00000 00010000 "data"

Rest is simple arithmetic:

The partition I was after was mtd2 (rootfs), so the offset worked out to 0x50000+0x2b0000=0x300000 (mtd0 + mtd1) the size is 0x20000.

To map the mtd2 to memory I ran following:

sf probe 0
sf read 0x82000000 0x300000 0x200000


Note: sf probe 0 needed to initialise flash.

I changed the ip address/netmask and tftp server address via this command (my tftp server is on 192.168.1.2):

set env ipaddr 192.168.1.200
set env serverip 192.168.1.2
set env netmask 255.255.255.0

Then I put the mapped flash via tftp to the tftp server:

tftp 0x82000000 rootfs 0x200000

Once I had the image I loaded into mtd device emulation on local machine. This is where erasesize comes handy (found in /proc/mtd earlier): 0x10000 = 64KiB.
To setup mtd device on a linux box you need to do the following:

modprobe mtdram total_size=2048 erase_size=64
modprobe mtdblock
modprobe jffs2
dd if=/var/lib/tftp/rootfs of=/dev/mtdblock0
mkdir /tmp/target
mount -t jffs2 /dev/mtdblock0 /tmp/target/

You might need to install mtd and jffs2 related packages: apt-get install mtd-utils
If it complains about "wrong superblock" while attempting to mount jffs2 most likely you got size/offset wrong when you ran sf read.

Once you have file system mounted copy it into a directory for future manipulations.
In the copy I fixed the /etc/passwd. I copied in the udevadm binary that I moved away.
Then I repacked the directory back into jffs2 image:

mkfs.jffs2 -r ~/rootfs_ipcam -e 64 -n -m size -o /var/lib/tftpboot/rootfs_fixed

Only to find out that the image turned out to be larger then the target size of 2MiB. I guess they used proprietary tools to build their jffs2 to cram it right into 2MiB. I was off by 140KiB or so. I managed to reclaim space by removing mkfs.fat and e2fsck (since this particular camera does not have physical SD-Card slot). Alternative was getting all partitions and re-shuffling the layout (relatively easy, but tedious).

Once I had the image built I confirmed that was OK by mounting the same way as original image.

The final step was downloading new image via tftp and flashing it:

tftp 0x82000000 rootfs_fixed
sf erase 0x300000 0x200000
sf write 0x82000000 0x300000 0x200000

WARNING: Don't get the size/offset wrong as you will have bad times!

Reverse engineering Hikvision SADP Tool

$
0
0

I got couple of Hikvision cameras that needed to have their passwords reset.

Instead of reset-to-factory default button these cameras have very elaborate password reset process.

Officially one must download SADP tool, get the serial number off the camera, fetch it to the Hikvision support, then they generate you a reset code that you plug in into the camera.

The unreliable Hikvision support can be bypassed with this tool (more details here).

I feel very dirty because I had to install the SADP in a Windows virtual machine (it does not work under Linux).
Interesting that the tool is build around QT and libpcap so technically it should not be too difficult to port it to Linux.

Looking at traffic captures the tool discovers the camera via multicast (239.255.255.250, udp port 37020) with this payload:

<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>13A888A9-F1B1-4020-AE9F-05607682D23B</Uuid><Types>inquiry</Types></Probe>

The camera responds to with this:

<?xml version="1.0" encoding="UTF-8"?>
<ProbeMatch><Uuid>FC25924E-AFE2-49E6-ACC9-F84A6859054D</Uuid>
<Types>inquiry</Types>
<DeviceType>38930</DeviceType>
<DeviceDescription>DS-2CD2432F-IW</DeviceDescription>
<DeviceSN>DS-2CD2432F-IW20150126CCCH502126167</DeviceSN>
<CommandPort>8000</CommandPort>
<HttpPort>80</HttpPort>
<MAC>c0-56-e3-fe-42-92</MAC>
<IPv4Address>10.1.1.251</IPv4Address>
<IPv4SubnetMask>255.255.255.0</IPv4SubnetMask>
<IPv4Gateway>10.1.1.1</IPv4Gateway>
<IPv6Address>::</IPv6Address>
<IPv6Gateway>::</IPv6Gateway>
<IPv6MaskLen>64</IPv6MaskLen>
<DHCP>false</DHCP>
<AnalogChannelNum>0</AnalogChannelNum>
<DigitalChannelNum>1</DigitalChannelNum>
<SoftwareVersion>V5.2.5build 141201</SoftwareVersion>
<DSPVersion>V5.0, build 140714</DSPVersion>
<BootTime>2016-03-06 09:18:17</BootTime>
</ProbeMatch>

This is all nice and easy to replicate, except when discovering that when resetting the password the tool talks to camera directly via ethernet frames:

Reset packet:

12:14:16.063953 52:54:00:db:ae:e4 > XX:XX:XX:XX:XX:XX, ethertype Unknown (0x8033), length 80: 
        0x0000:  2102 0142 0000 173a 0604 0a00 ba54 5254  !..B...:.....TRT
        0x0010:  00db aee4 0a01 0102 XXXX XXXX XXXX 0a01  ........XXXXXX..
        0x0020:  01fb ffff ff00 5252 5364 5264 6572 6439  ......RRSdRderd9
        0x0030:  0000 a100 0000 0000 0000 0000 0000 0000  ................
        0x0040:  0000                                     ..

Response packet:

12:14:16.094857 XX:XX:XX:XX:XX:XX > 52:54:00:db:ae:e4, ethertype Unknown (0x8033), length 260: 
        0x0000:  2101 01f6 0000 173a 0604 0b01 8a3b XXXX  !......:.....;XX
        0x0010:  XXXX XXXX 0a01 01fb ffff ffff ffff 0000  XXXX............
        0x0020:  0000 ffff ff00 4453 2d32 4344 3234 3332  ......DS-2CD2432
        0x0030:  462d 4957 3230 3135 3031 3236 4343 4348  F-IW20150126CCCH
        0x0040:  XXXX XXXX XXXX XXXX XX00 0000 0000 0000  XXXXXXXXX.......
        0x0050:  0000 0000 0000 0000 9812 0000 1f40 0000  .............@..
        0x0060:  0001 0000 0000 5635 2e32 2e35 6275 696c  ......V5.2.5buil
        0x0070:  6420 3134 3132 3031 0000 0000 0000 0000  d.141201........
        0x0080:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0090:  0000 0000 0000 5635 2e30 2c20 6275 696c  ......V5.0,.buil
        0x00a0:  6420 3134 3037 3134 0000 0000 0000 0000  d.140714........
        0x00b0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00c0:  0000 0000 0000 3230 3136 2d30 332d 3036  ......2016-03-06
        0x00d0:  2030 393a 3138 3a31 3700 0000 0000 0000  .09:18:17.......
        0x00e0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00f0:  0000 0000 0000                           ......

Now looking further it appears that discovery as well as expected UDP communication there is also ethernet frame type of communication going on in parallel:

Broadcast:

12:13:29.539493 52:54:00:db:ae:e4 > ff:ff:ff:ff:ff:ff, ethertype Unknown (0x8033), length 80: 
        0x0000:  2102 0142 0000 1739 0604 0300 80b6 5254  !..B...9......RT
        0x0010:  00db aee4 0a01 0102 ffff ffff ffff 0000  ................
        0x0020:  0000 0000 0000 fe80 0000 0000 0000 889f  ................
        0x0030:  720d 7c8f 8429 0000 0000 0000 0000 0000  r.|..)..........
        0x0040:  0000                                     ..

Response:

12:13:29.555356 XX:XX:XX:XX:XX:XX > 52:54:00:db:ae:e4, ethertype Unknown (0x8033), length 416: 
        0x0000:  2101 01f6 0000 1739 0604 0400 8c42 XXXX  !......9.....BXX
        0x0010:  XXXX XXXX 0a01 01fb ffff ffff ffff 0000  XXXX............
        0x0020:  0000 ffff ff00 4453 2d32 4344 3234 3332  ......DS-2CD2432
        0x0030:  462d 4957 3230 3135 3031 3236 4343 4348  F-IW20150126CCCH
        0x0040:  XXXX XXXX XXXX XXXX XX00 0000 0000 0000  XXXXXXXXX.......
        0x0050:  0000 0000 0000 0000 9812 0000 1f40 0000  .............@..
        0x0060:  0001 0000 0000 5635 2e32 2e35 6275 696c  ......V5.2.5buil
        0x0070:  6420 3134 3132 3031 0000 0000 0000 0000  d.141201........
        0x0080:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0090:  0000 0000 0000 5635 2e30 2c20 6275 696c  ......V5.0,.buil
        0x00a0:  6420 3134 3037 3134 0000 0000 0000 0000  d.140714........
        0x00b0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00c0:  0000 0000 0000 3230 3136 2d30 332d 3036  ......2016-03-06
        0x00d0:  2030 393a 3138 3a31 3700 0000 0000 0000  .09:18:17.......
        0x00e0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00f0:  0000 0000 0000 029c 5648 0a01 0101 0000  ........VH......
        0x0100:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0110:  0000 0000 0000 0000 0000 0000 0000 0007  ................
        0x0120:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0130:  0000 0000 0000 0000 0000 0000 0000 0050  ...............P
        0x0140:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0150:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0160:  0000 4453 2d32 4344 3234 3332 462d 4957  ..DS-2CD2432F-IW
        0x0170:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0180:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0190:  0000

So theoretically it is possible to create a tool based on the reset password code generator to completely cut out middle man.
This is the way I see it working:

1) Discover camera and get serial number and camera ip
2) Get camera date/time via simple GET to port 80.
3) Generate reset code with camera serial number and date/time
4) send magic packet to reset camera.

I found some examples of the traffic that does not contain fe80 0000…XXXX…0000 bit at the end (looks like previous version of SADP Tool didn’t append that crap). I successfully replayed that packet.
I have noticed that the checksum does not include the source (header) of the packet, so as long as the MAC address matches in the body the header can be spoofed.

I have changed the mac address on VM where SADP Tool was running and looks like4 bytes between Source MAC and Destination MAC in the body changes. As well as 2x 2 bytes surrounding 06040300.

If I increment any number by one and decrement @ 0x0018 the packet gets response. This implies that the check sum is only 2 bytes long.

So far I figured out the check sum for older type of discovery packet (without crap at the end of the packet).

the check sum is located here:
0x0010: 00db aee4 0a01 0102 ffff ffff ffff 0000
In this example it is 0102.
Actually the check sum is 0201 (reversed order).
The check sum algorithm is 16-bit one’s complement.
The trick (which was given away by comparing sequential packets) is to ignore the header, and to reverse order in these two bytes:
0x0000: 2102 0142 0000 1739 0604 0300 80b6 5254
in example above they are check-summed as b680.

Next step is to see if I can apply the same method to the password reset packet….

At this stage I solved the following: discovery via frames, discovery via UDP, generate reset code and reset the camera via frame.

There is a potential problem to get camera time reliably (in case it is not configured in same subnet).

After poking around Sadp.dll I found these interesting XML strings:

<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>%s</Uuid><Types>inquiry</Types></Probe>
<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>%s</Uuid><Types>update</Types><MAC>%s</MAC><Password>%s</Password><IPv4Address>%s</IPv4Address><CommandPort>%d</CommandPort><HttpPort>%d</HttpPort><IPv4SubnetMask>%s</IPv4SubnetMask><IPv4Gateway>%s</IPv4Gateway><IPv6Address>%s</IPv6Address><IPv6Gateway>%s</IPv6Gateway><IPv6MaskLen>%d</IPv6MaskLen><DHCP>%s</DHCP></Probe>
<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>%s</Uuid><MAC>%s</MAC><Types>reset</Types><Code>%s</Code></Probe>
<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>%s</Uuid><MAC>%s</MAC><Types>reset</Types><Code>%s</Code><Password>%s</Password></Probe>
<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>%s</Uuid><MAC>%s</MAC><Types>reset</Types><SyncIPCPassword>true</SyncIPCPassword ><Code>%s</Code><Password>%s</Password></Probe>
<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>%s</Uuid><MAC>%s</MAC><Types>getcode</Types></Probe>
<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>%s</Uuid><MAC>%s</MAC><Types>exchangecode</Types><Code>%s</Code></Probe>
<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>%s</Uuid><MAC>%s</MAC><Types>activate</Types><Password>%s</Password></Probe>
<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>%s</Uuid><MAC>%s</MAC><Types>getencryptstring</Types></Probe>

None of that proved to be useful of extracting local time (except inquiry).

See this post for actual script.


JDM GRB STI: Rear diffrential – which type?

$
0
0

After conflicting information on the net I finally purchased el-cheapo endoscope camera and took some snaps of the differential.

Pictures are crap but enough to confirm that the diff is Torsen:

GRB_Diff00

GRB_Diff01

What you see is the helical gear shafts (I also confirmed that by spinning the wheel and observed the shafts spinning).
If it was clutch type it would had clutches, shims and cam mechanism visible instead.

In conclusion at least my JDM GRB STI came with Torsen (and it does not look like it was after market installation as all the bolts and seals are pristine).

Reverse engineering Hikvision SADP Tool (now with script!)

$
0
0

This is a continuation from here.

Here is the complete script that can reset any given Hikvision camera with firmware of up to 5.3 (allegedly).
The security through obscurity aspect of it, and inability to reset the camera without contacting the Hikvision support under normal circumstances puts me off the Hikvision hardware entirely.

There is an obvious problem with contacting Hikvision support, no way they will provide support for cameras bought from Aliexpress. Since password reset is not under owner’s control, it means that owner does not technically own the camera.

This script will discover the Hikvision cameras (both via UDP and magical frame 0x8033) on local L2. You can also specify to reset a camera with a specific MAC address (although it is not too difficult to modify it to own all the cameras, but I purposely left that bit out).

The script is a bit crude and inefficient (too many byte to ASCII conversions).
The reset code algorithm was lifted off here: https://www.ipcamtalk.com/hik-pw-reset.php. I had to “pythonise” it from javascript.

TL;DR: do not buy Hikvision cameras as the official password recovery involves Hikvision support, while “hackers” can own your camera once they get L2 access to your network.

mini0806 design flaw

$
0
0

Alternative title: why my mini0806 was crashing and stopped working after a light drop.

One of the differences between mini0805 and mini0806 is this heat sink:
IMG_20160703_110658

It is a bitch to remove, so I gently coerced it with a blade:
IMG_20160703_110803

After some time of gentle pushing and heating it managed to peel off:
IMG_20160703_111536

Revealing Samsung ram chip and Ambarella A7LA50 SoC:
IMG_20160703_111758

Here is why it was not working after slight drop (and crashing before that):
IMG_20160703_113213

Pulled out pads! Note that the blade I used to remove would cause other side of pads missing if I applied too much pressure.

My theory is following: the heat sink that bridges RAM and SoC is causing stress on these chips. Mostly because it is glued and not mechanically pressed against the chips. This is a very silly design flaw, if for example, only SoC would have the heat sink (like found on IP cameras) then there would not be any stresses. I don’t think RAM needs heat sinking on those things.

I am tempted to take dremel to my other mini and split the heat sink in two…

Viofo A119

$
0
0

Box:
A119_box

A119_box_side

Camera:
A119_side_usb

A119_screen

A119_lens

GPS mount:
A119_gps_mount_side

A119_gps_mount

Mounting position:
A119_led_front

A119_descreete_mount_screen_on

A119_descreete_mount_screen_off

A119_descreete_mount_outside

A119_descreete_mount_mirror

A119 vs A118c:
A119_A118c_side

A119_A118c_screen_top

A119_A118c_screen_bottom

A119_A118c_mount_side

A119_A118c_lens_mount_side

A119_A118c_lens

A119 vs A118c vs DR400G-HDII vs Mini0806:
A119_A118c_mini0806_DR400GHDII_side

A119_A118c_mini0806_DR400GHDII_lens

A119_A118c_mini0806_DR400GHDII_back

To be continued…

Extracting GPS data from Viofo A119 and other Novatek powered cameras

$
0
0

The script.

Here it is: nvtk_mp42gpx.py

What does it do?

This script will attempt to extract GPS data from Novatek MP4 file and output it in GPX format.

Usage: ./nvtk_mp42gpx.py -i<inputfile> -o<outfile> [-f]
        -i input file (will quit if does not exist)
        -o output file (will quit if exists unless overriden)
        -f force (optional, will overwrite output file)

In short: it takes Novatek encoded MP4 file (with embedded GPS data) and extract GPS data in GPX format (as separate file). Note; it does not modify the original MP4 file.

In long:

What the? Where is the bloody GPS data?
Unlike competitors (Ambarella and such) Novatek actually embeds the GPS data in MP4, specifically in free atoms/boxes in midst of the stream chunks. This is a bit different than Amberalla’s embedding in the subtitle track (which is trivial to extract with open source tools).

The search for documentation for the Novatek data structure was a scavenger hunt on itself.

Although writing the MP4 rudimentary parser took longest time, figuring out Novatek data structure was more complicated due to lack of information.

MP4 container basics
Disclaimer: I am no expert or even at enthusiast level regarding the video containers, thus information below is not guaranteed to be correct. These are simply my findings and should be “taken with a grain of salt”.

In very simple terms the MP4 container consists of atoms/boxes (the name depends which documentation you read). The boxes can contain other boxes.

Each box starts with 8 byte “header” (including the beginning of the file). The first 4 bytes is the size of the box (big endian unsigned int), the second 4 bytes contains 4 character string name/type of the box. The size includes itself (so valid size is >= 0x0008 unless the special type of large box which I will conveniently omit in this post ;)). Basically MP4 container can be treated as some rudimentary file system.

For example:

00 00 00 1c  66 74 79 70

translates to box size of 28 bytes (0x1c) of type “ftyp”, the first box in the file (0x66=f 0x74=t 0x79=y 0x70=p in ASCII). As note: “ftyp” is basically “file type” description box.

00 01 68 7d  6d 6f 6f 76

translates to box size of 92285 bytes and of type “moov”, the box of special importance.

For purpose of extracting data I am interested in only following box types: “moov”, “gps ” and indirectly “free”.

The “moov” box is a special type, kind of index/metadata box (box of all boxes ;)). It contains video/audio/other data chunk mapping, other boxes and of a special importance, a non-standard “gps ” box.
This non-standard “gps ” box contains mapping of all GPS data boxes (will cover this later).

I assume that “moov” box should always be in top level (not a sub-box).

In my script I basically iterate through all top level boxes until I hit the “moov” box. Then I begin to iterate sub-boxes inside of the “moov” box, until I hit “gps ” box (this where the fun begins).

Note: Here is the reference I used to figure some of it out: http://l.web.umkc.edu/lizhu/teaching/2016sp.video-communication/ref/mp4.pdf and http://www.cmlab.csie.ntu.edu.tw/~cathyp/eBooks/14496_MPEG4/ISO_IEC_14496-14_2003-11-15.pdf

Novatek special “gps ” box
The “gps ” box is found inside of “moov” box.
The “gps ” box stores the file offset (in bytes) and size (in bytes) for each GPS data box.
The first 8 bytes in the “gps ” box contain version and encoded build date. I simply chose to ignore this data.
The subsequent 8 bytes contain 4 byte file offset (absolute) and 4 byte size (offset and size are big-endian unsigned ints).

00 2b e9 50  00 00 10 00

Translates to a GPS data box at position 0x002be950 (at 2877776 bytes) of size of 4096 bytes (0x1000).
Following the offset we find the GPS data box exactly where it supposed to be:

002be950  00 00 10 00 66 72 65 65  47 50 53 20 4c 00 00 00  |....freeGPS L...|

Novatek special “free” box beginning “GPS “
Not to be confused with “gps ” box ;).
This box sits in “free” box in midst of data chunks. The box can be identified with a magic “GPS ” string.
For some reason Novatek decided to store all the data in this box in little-endian format…

Here is the structure:

# Datetime data
hour: unsigned little-endian int (4 bytes)
minute: unsigned little-endian int (4 bytes)
second: unsigned little-endian int (4 bytes)
year: unsigned little-endian int (4 bytes)
month: unsigned little-endian int (4 bytes)
day: unsigned little-endian int (4 bytes)

# Coordinate data
active: string (1 byte) # satelite lock "A"=active, everything else (eg " ") lost reception
latitude hemisphere: string (1 byte) # "N"=North or "S"=South
longitude hemisphere: string (1 byte) # "E"=East or "W"=West
unknown: string (1 byte) # No idea, always "0"? 
latitude: little-endian float (4 bytes) # unusual format of DDDmm.mmmm D=degrees m=minutes
longitude: little-endian float (4 bytes) # unusual format of DDDmm.mmmm D=degrees m=minutes
speed: little-endian float (4 bytes) # Knots (the nautical kind)
bearing: little-endian float (4 bytes) # degrees, not used in GPX.

Disclaimer: this was a good hint in right direction: https://github.com/kbsriram/dcutils

Converting odd DDDmm.mmmm coordinate format to GPX compatible
Here is the algorithm:

def fix_coordinates(hemisphere,coordinate):
    # Novatek stores coordinates in odd DDDmm.mmmm format
    minutes = coordinate % 100.0
    degrees = coordinate - minutes
    coordinate = degrees / 100.0 + (minutes / 60.0)
    if hemisphere == 'S' or hemisphere == 'W':
        return -1*float(coordinate)
    else:
        return float(coordinate)

Converting knots to m/s

speed * float(0.514444)

Putting together GPX format

For GPX format to work one needs header similar to this:

<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.0"
        creator="Sergei's Novatek MP4 GPS parser"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.topografix.com/GPX/1/0"
        xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
        <name>../Videos/ubertec moron/2016_0716_235252_140.MP4</name>
        <url>sergei.nz</url>
</gpx>

Specifically it will not import without:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.topografix.com/GPX/1/0"
xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd"

The track data is put together in following way:

<trk><name>test.gpx</name><trkseg>
                <trkpt lat="-36.863672" lon="174.765625"><time>2016-07-16T23:52:51Z</time><speed>23.484369</speed></trkpt>
                <trkpt lat="-36.863546" lon="174.765397"><time>2016-07-16T23:52:52Z</time><speed>23.479224</speed></trkpt>
</trkseg></trk>

Testing GPX file

I found an utility called xmllint that can be used to test GPX data (apt-get install libxml2-utils):

xmllint --noout --schema http://www.topografix.com/GPX/1/0/gpx.xsd test.gpx

One year with Mini0806

$
0
0

WARNING: DO NOT BUY MINI0806 UNDER ANY CIRCUMSTANCES.

You have been warned.

Here is simple reason why: out of 8 mini0806s that passed through my hands, 5 failed and one dying(failure rate >60%).

Here is the tally:

First ever mini0806 I got was on 01/05/2016.
I purchased it from gearbest.com on 31/03/2016, and got it after a month of being, what I assumed, shipped via a bottle thrown in the sea.
Immediately I noticed that it would crash when chosen any high resolution other than 2560x1080p30. Press stop/start recording 3 times and it would lockup (30s power button reset was the only way to recover it).
I created a ticket with gearbest only to be given run around. They suggested to get it fixed locally, and they will reimburse the bill. How many component level repair specialist that charge $5/hour are in New Zealand? After being offered 10% discount coupon, I decided to contact Megtech directly (the manufacturer of the camera).
After spending $40NZD (~30% of the cost of the camera) on shipping, in about one month I got the replacement. While waiting for the replacement I bought another mini0806 (I never learn ;)) this turned out to be the only reliable mini I personally owned).
The replacement from Megtech had exactly same problem. As if they simply returned my camera back, if it was not for protective film on LCD suggesting it is another new unit.
In between getting my faulty camera returned, I had the second camera running well, thus my friends decided to buy mini0806 for themselves (bad move).

Friend #1: 2x minis, both faulty (crash on power off, crash on running).
Friend #2: 1x faulty (crash on power off, crash on running), 1x OK (replacement) so far
Friend #3: 1x OK but never checked the recordings for missing data.

So total so far: 5/8 failed. My good mini0806 has low battery warning permanently on.

Megtech suggested bad Micro SD cards. Well, I tested the mini0806s with Samsung Pro, Transcend Ultimate 633x, Strontium Nitro, all class 10, most of them are MLC flash. All of these cards Work fine in Blackvue, Viofo, Navman (MiVue), GitUp cameras. All of these cards also work fine in good mini as well.

At this stage I removed my mini in favour of Viofo A119, which runs really well, has reasonable temperature ratings and no battery.

In conclusion do not buy anything that Megtech makes, or anything from gearbest.com.

Head unit wiring clean up after wire-twister

$
0
0

While I was fixing indecisive heater control servo in a Toyota Ist, I discovered a wiring horror left a by a wire-twisting moron:


headunit_wire_twisted_by_moron_1

headunit_wire_twisted_by_moron_2
In my opinion wire twisting from above is lazy, stupid, and dangerous! Unless, of course you want to set your car on fire. They didn’t even bother to properly apply insulation tape.

The Fix.

Untangling the mess:
wire_horror_untangling_0

Cutting off the twists:
wire_horror_untangling_1

Feeding in supporting heat-shrink:
wire_horror_untangling_2

Splicing the wires properly before soldering (a variant of Lineman’s splice, give it a gentle tug after twisting):
wire_proper_twist_0

Soldering the wires (just enough of solder, do not “blob”):
wire_proper_twist_1

Heat-shrink:
wire_heatshrink_0
wire_heatshrink_1
wire_heatshirnk_3
wire_heatshirnk_3
Loop and heat-shrink unused wires:
wire_heatshrink_2

End result:
wire_proper_connection_complete_0
wire_proper_connection_complete_1


Mysterious clicking noise inside dash of a Toyota Ist

$
0
0

Do you have annoying clicking (similar to seeking CD player) sound coming from inside of your Toyota dash, sometimes only happening at set heater temperature setting? It could be “indecisive” heater control servo.

Below is how I fixed the noise in a Toyota Ist (hint: it is was a problem with sliding contacts inside of the servo).

To get to the servo (it sits on top of the heater/AC ducting) you need to remove head unit and heater controls. To get to screws in Ist you need to unclip silver trims (not visible):
heater_control_removal_0

The heater control and head unit surround/centre vents is held by couple of screws. After removal of the screws the surround just unclips:
heater_control_removal_1

The heater control is connected via one plug and a corrugated hose (which vents to a thermistor in the heater control unit):
heater_control_removal_2

The servo is located in depth of the dash board:
heater_servo_location_0

The servo is held by 3 screws (it has 4 holes, just to confuse people) and is connected via single plug
heater_servo_location_1

It was very hard to unlatch the levers so I removed it with them in place. The was 1 screw and a plastic washer holding the levers in place:
heater_servo_removed_0

Levers removed:
heater_servo_removed_1

Servo is held together by plastic clips around the perimeter:
heater_servo_repair_0

The problem is due to wear contact springs lose tension:
heater_servo_repair_1

Here are the contacts in greater detail:
heater_servo_contacts_0

Other side:
heater_servo_contacts_1

The fix is to bend contacts up and clean the contact surface from carbon (while trying not to remove too much grease).

To reinstall the servo make sure that the levers sit correctly. Check that the flaps are actuated properly by moving the lever by hand:
heater_servo_levers_0

After reassembly check maximum temperature (should be 50-60 degrees Celsius):
heater_check_high_temp

Check minimum temperature (should be around 8 degrees Celcius, providing that the A/C is working):
heater_check_low_temp

Check set temperature on lower end (in this case 22 degrees Celsius):
heater_check_22c

Check set temperature on higher end (27 degrees Celsius):
heater_check_27c

Note: temperature settings take a while to stabilize.

Success! No more noises!

Prezzy card scam

$
0
0

A while ago I was gifted a prezzy card. These buggers: https://www.prezzycard.co.nz/.
They are actually Kiwi bank.
This prezzy card is not accepted in many places. In addition it needs to be activated.
I was putting it off, until the bloody thing expired.

So these bastards take legal tender (that does not have expiry) and set expiry on it.
I simply see no point of these things as cash is accepted pretty much everywhere, and it can also be deposited in your account (stating obvious here).

What these gift card/prepay debit cards companies rely on is chumps like me that let their cards expire.
This is a very shady business model.

So if you want to be a good friend and want to gift some cash, just gift the cash. No prezzy card or Dicksmith gift cards or any other stupid vouchers, thank you very much.

As for Kiwibank – shame on you for supporting such scam.

RS New Zealand training Windows users bad security practices

$
0
0

Recently I received promo letter from RS New Zealand which contained a mysterious USB dongle device thingy:

rs_nz_dongle0

hmm… should I plug this thing in…

rs_nz_dongle1

rs_nz_dongle2

Word of warning: never plug anything into USB port if you didn’t ask for it. For “science” I plugged it into a sacrificial Linux box.

Turns out the dongle is a keyboard device that mashes magic Windows specific key sequences (more on that later).

This whole marketing campaign is extremely stupid move from RS NZ. Now a 3rd malicious party can copy their marketing material and send it out with a dongle that has malicious payload (could be the same keyboard sequence that goes to a site and downloads root kit, while “Allowing” all the UAC dialogues).

It is a shame that RS NZ trains already security deficient Windows users with more horrible security practices.

The device presents itself with following ID:
Bus 001 Device 018: ID 05ac:020b Apple, Inc. Pro Keyboard [Mitsumi, A1048/US layout]

Here is the magic key sequence:

Caps_Lock
Caps_Lock
Super_L + r
Home
Shift_L + End
BackSpace
# above is running Win+R 
# clearing the line 
# while Caps Lock on for some reason

Alt_L + KP_End
Alt_L + KP_Insert
Alt_L + KP_Left
# Alt + 104 = h

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Right
# Alt + 116 = t <- guess where this is going?

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Right
# Alt + 116 = t <- is 'p' next?

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Down
# Alt + 112 = p <- yep, it is an obscure way of typing 'http'.

Alt_L + KP_Insert
Alt_L + KP_Begin
Alt_L + KP_Up
# Alt + 058 = : <- http:

Alt_L + KP_Insert
Alt_L + KP_Left
Alt_L + KP_Home
# Alt + 047 = / <- http:/

Alt_L + KP_Insert
Alt_L + KP_Left
Alt_L + KP_Home
# Alt + 047 = // <- http://

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Begin
# Alt + 115 = s <- where is this going?

Alt_L + KP_End
Alt_L + KP_Insert
Alt_L + KP_End
# Alt + 101 = e <- http://se ?

Alt_L + KP_Insert
Alt_L + KP_Prior
Alt_L + KP_Prior
# Alt + 099 = c <- secure? but not https?

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Home
# Alt + 117 = u <- http://secu...

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Left
# Alt + 114 = r <- http://secur...

Alt_L + KP_End
Alt_L + KP_Insert
Alt_L + KP_End
# Alt + 101 = e <- http://secure...

Alt_L + KP_Insert
Alt_L + KP_Left
Alt_L + KP_Begin
# Alt + 045 = - <-http://secure-

Alt_L + KP_Insert
Alt_L + KP_Prior
Alt_L + KP_Prior
# Alt + 099 = c <- http://secure-c

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Right
# Alt + 116 = t <- http://secure-ct

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Prior
# Alt + 119 = w <- http://secure-ctw

Alt_L + KP_Insert
Alt_L + KP_Left
Alt_L + KP_Right
# Alt + 046 = . <- http://secure-ctw.

Alt_L + KP_Insert
Alt_L + KP_Prior
Alt_L + KP_Prior
# Alt + 099 = c <- http://secure-ctw.c

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_End
# Alt + 111 = o <- http://secure-ctw.co

Alt_L + KP_End
Alt_L + KP_Insert
Alt_L + KP_Prior
# Alt + 109 = m <- http://secure-ctw.com

Alt_L + KP_Insert
Alt_L + KP_Left
Alt_L + KP_Right
# Alt + 047 = / <- http://secure-ctw.com/

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Down
# Alt + 112 = p <- http://secure-ctw.com/p

Alt_L + KP_End
Alt_L + KP_End
Alt_L + KP_Home
# Alt + 117 = u <- http://secure-ctw.com/pu

Return
Caps_Lock
# the end

The resultant http://secure-ctw.com/pu redirects to http://nz.rs-online.com/web/generalDisplay.html?id=tct .
For some reason they decided to use 3rd party redirection service, whose domain/URL is not much shorter than http://nz.rs-online.com.
The funny thing is they could have registered rs-tct.nz (or rstct.nz) for something like $30 and set-up redirect there. It smells of their marketing department stumbling in the dark.

The whole thing pretty pointless IMHO. Could have just sent a postcard with a QR Code and URL on it. Actually form environment point of view it is very wasteful.

I guess they are forcing dumbass Windows users to visit their page (who otherwise would not follow the link)…

python OpenCV basic motion detection

$
0
0

Here I will describe how I use OpenCV for capturing RTSP streams, with purpose of motion detection.

For basic OpenCV I use these two libraries:

import cv2
import numpy as np

cv2 is OpenCV library (second version), and numpy is python numeric lybrary (useful for manipulating matrices among other things).

To initiate capture one simply does following:

cap = cv2.VideoCapture('rtsp://192.168.1.69:554/Streaming/Channels/2')

In this example I use second stream (of lower resolution) for motion detection.

From there you can get heigh and width of the frame (this will be useful later):

width = cap.get(3)
height = cap.get(4)

I use BackgroundSubtractorMOG for motion detection (somewhat cheating ;)):

bg = cv2.BackgroundSubtractorMOG(100,3,0.6,30)

The magic is in parameters, I used following:
100 – history
3 – number of Gaussian mixtures
0.6 – background ratio
30 – noise strength
The numbers above are not necessarily “correct” but I came to them with error and trial (and “guestimation”).
Here is document in detail describing this algorithm: http://personal.ee.surrey.ac.uk/Personal/R.Bowden/publications/avbs01/avbs01.pdf

The actual capture loop looks something like this:

while(True):
    ...
    ret, frame = cap.read()
    motion = bg.apply(frame, learningRate=0.005)
    kernel = np.ones((3, 3), np.uint8)
    motion = cv2.morphologyEx(motion, cv2.MORPH_CLOSE, kernel, iterations=1)
    motion = cv2.morphologyEx(motion, cv2.MORPH_OPEN, kernel, iterations=1)
    motion = cv2.dilate(motion,kernel,iterations = 1)
    contours, hierarchy = cv2.findContours(motion, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    ...
ret, frame = cap.read()

captures a single frame

motion = bg.apply(frame, learningRate=0.005)

extracts a black and white image with the background removed (learnignRate value has been chosed by error and trial).

Next four lines simply manipulate extracted image in such that it does following:
MORPH_CLOSE: removes small holes (up to 3×3 pixel, defined by kernel) within the object (“white”) in the extracted motion matrix.
MORPH_OPEN: removes small dots within the “background” (black) in the extracted motion matrix.
dilate: is making sure there all adjacent islands are joined together, so when we extract contours we get small amount of contours as result.

The “3×3 pixel” block comes from here:

kernel = np.ones((3, 3), np.uint8

The last step from processing frame is extracting the contours:

contours, hierarchy = cv2.findContours(motion, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

The extracted contours can then be iterated and hull drawn around them:

for cnt in contours:
    hull = cv2.convexHull(cnt)

The hull points then can be checked against the mask if motion is inside of the area of interest:

Lets define the mask as the whole frame (I am pretty sure there is a better way;)):

mask_points = [
( 0 , 0 ),
( 1 , 0 ),
( 1 , 1 ),
( 0 , 1 ),
]

mask_array=[]
for point in mask_points:
    mask_array.append([[int(point[0] * width ), int(point[1] * height )]])
mask = np.array(mask_array, np.int32)

This looks cumbersome, but what I am achieving here is converting mask_points list of human readable relative coordinate tuples (eg: centre will be at (0.5,0.5)). Mask can be defined as a polygon with relative positioning of each corner to the frame (independent from pixel size).

We check if hull point is inside our mask

for point in hull:
    distance = cv2.pointPolygonTest(mask,tuple(point[0]),1)
    if distance > 0:
        it_is_inside()

and vice-versa (in case if mask is smaller than the frame):


Note: The colour is defined by this tuple: (0,255,0)

Then do display the whole thing insert this inside of the while(True):

cv2.imshow('motion',frame)
k = cv2.waitKey(30) & 0xff
if k == 27:
    break

The above is basic idea behind my motion detection scripts. I have omitted a lot of glue logic and arithmetic due to my script is not ready for public display ;).

ILDVR INC-MH40D06 security nightmare part 2

$
0
0

I have put off the ILDVR camera, as I kind of lost interest.
For previous posts see here, here and here.

I was bored so I decided to poke at again.

I was interested where does the camera store users and in what format. What I found out is an atrocious mocking of security.
The camera stores local users and their passwords (in plain text) in following file:

/mnt/flash/data/OwnUserInfo.txt

Yep: the same directory which is accessible without auth via port 10081. So if you forgot password (and forgot the silly hardcoded HANKVISION), then you can get a reminder what it is by simply going here:

http://${CAMERA_IP}:10081/OwnUserInfo.txt

There is also another “binary” file that contains interesting references to HANKVISION and local users:

/mnt/flash/data/UserInfo

strings that and you get following:

HANKVISION
e82f5af1f39f021b44e78089b5a40a8e0aa8d2768c705e8f139bec04d87d5a54
8f081b5a8e0685ca975a01d4159930f9
0d9a1f80bcc7a1e4a00f04588062ed67
admin
8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
21232f297a57a5a743894a0e4a801fc3
76eb00c6458e9b2755b570ae565ba0a6

Changing the password to HANKVISION reveals that this string is “encoded” “HANKVISION”:

e82f5af1f39f021b44e78089b5a40a8e0aa8d2768c705e8f139bec04d87d5a54
8f081b5a8e0685ca975a01d4159930f9

Not sure if the obfuscation is worth spending time on, especially when we already know HANKVISION is hardcoded in web server binary and OwnUserInfo.txt already contains passwords in clear texts.

strace-ing ‘webs’ process during certain conditions opens the /tmp/umconfig.txt, which contains following:

TABLE=users
ROW=0
name=HANKVISION
password=0d9a1f80bcc7a1e4a00f04588062ed67
group=Administrator
prot=1
disable=0
ROW=1
name=admin
password=76eb00c6458e9b2755b570ae565ba0a6
group=Administrator
prot=1
disable=0
ROW=2
name=adminadmin
password=5ca1e16e4fa3fa58b6656b9ad547fa0f
group=Normal
prot=0
disable=0
TABLE=groups
ROW=0
name=Administrator
priv=4
method=2
prot=0
disable=0
ROW=1
name=Normal
priv=4
method=2
prot=0
disable=0
TABLE=access
ROW=0
name=/browse/
method=2
secure=0
ROW=1
name=/jpgimage/
method=2
secure=0
ROW=2
name=/mjpgstreamreq/
method=2
secure=0
ROW=3
name=/form/
method=2
secure=0
group=Administrator
ROW=4
name=/cgi/
method=2
secure=0

The “hashes” correlate to /mnt/flash/data/UserInfo…

Looking firmware upload function (in browse/javascript/sysInf.js) I found this bit:

function fileUpload(){
...
		var typeAllow = [".ifu", "macaddr.txt", "deviceid.txt", "sn.txt", "audio.dat", ".bin", ".png", ".ifc", ".lib", ".uid", ".pid","logo.gif","whitelist.txt"];
		var fileType = ["ifu", "mac", "deviceid", "sn", "audio", "bin", "png", "ifc", "lib", "uid", "pid","gif","wlst"];
....

I have tested the upload function with logo.gif and that worked: the logo on top got replaced, so it brings a possibility of doing something more (sneaking in a binary?).

Looking at ‘webs’ binary I decided to google for strings in case someone leaked the source or these bastards stole somebody else’s work.
Here what I found:
The string:

webs: websWrite lost data, buffer overflow

Matches suspiciously named file here:
https://github.com/socoola/yhrouter/blob/master/user/goahead/src/webs.c

Same could be said for these strings:

webs: Listening for HTTP requests at address %s
webs: accept request

What is surprising is that they avoided doing execve calls where they could. IP addresses, routes, all set via ioctl, even time is set via settimeofday function. This removed possibility of command injection.

Here is what I believe is going on with this firmware:

The video side and core functionality has been lifted off SDK by Hisilicon. The web server stuff has been implemented by actual Hankvision people, most likely low paid undergraduate Chinese students. The core web server functionality has been lifted off the internet (see above).

What could have been done better without spending much on development:

Remove hard coded passwords!
Throw away all activeX crap (use MJPEG stream for “preview”).
Turn off telnet and leave ssh on with configurable password (perhaps make it a separate user?).
Do not store plain passwrods anywhere
Throw away all the dyndns and cloud nonsense.
Add actual off checkbox for FTP, Mail and SIP stuff (and possbly throw away SIP stuff).
Add VLC plug-in functionality.
Remove web server that listens on port 10081 exposing whole bunch of private data.

I am not sure what they are trying to achieve by not allowing SSH/Telnet access, but this is counter productive. I will not buy a security product to which I do not have control! Besides if I wanted to get access to your firmware, I don’t need SSH or Telnet, when I have RS232 and soldering iron.

For those who purchased this camera, if you really have to use it do the following:

Hexedit webs binary and change the HANKVISION bit to something else

And

Remove gateway setting (set it the same IP as camera) and preferably isolate camera from rest of the network (separate VLAN and port forwarding to recorder).

Or

Just chuck it in the bin and never purchase anything from ILDVR again.

Shame on you ILDVR for not responding to me when I contacted you almost a year ago about hard coded passwords. Shame on you ILDVR for not providing root password or firmware updates.

Viewing all 58 articles
Browse latest View live