Hacking the Woshida T7866WIP HD IP Camera

I’m at it again with taking inexpensive cameras and pushing them to the limits; this time it’s with a Woshida T7866WIP IP camera and uncovering undocumented functionality through curiosity, exploration, hacking, and reverse engineering. This camera resembles that of my Foscam clone which is nice when it comes to setting up a nicer remote interface or integrating with another security system. From the overall quality of the 720P video to the healthy click of the relay activating the IR LEDs, my overall experience with this camera leaves me wanting more of them! There are a few features, some of which are undocumented:

  • 720P video RTSP video stream
  • M-JPEG stream at 640×360 (VGA) or 320×180 (QVGA)
  • Micro-SD slot for recording video (continuous, scheduled, or alarm) and still photos (alarm)
  • ONVIF SOAP API
  • SDK for a proprietary ActiveX plugin and CGI functions
  • Telnet shell
  • Really bad Chinese to English translations

Knocking on some doors

Of course I didn’t install the accompanying CD, who does that? Read the instructions? I’m a guy, instructions are for wimps. After hardwiring the camera to the network, I tried to access the camera’s web interface on port 80 with no avail so I had to kick it up a notch and see what port it was configured for. I was a little surprised by what I saw:

Starting Nmap 6.49BETA6 ( https://nmap.org ) at 2015-11-22 19:58 Central Standard Time
NSE: Loaded 131 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 19:58
Completed NSE at 19:58, 0.00s elapsed
Initiating NSE at 19:58
Completed NSE at 19:58, 0.00s elapsed
Initiating ARP Ping Scan at 19:58
Scanning 192.168.0.14 [1 port]
Completed ARP Ping Scan at 19:58, 0.58s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 19:58
Completed Parallel DNS resolution of 1 host. at 19:58, 0.02s elapsed
Initiating SYN Stealth Scan at 19:58
Scanning 192.168.0.14 [65535 ports]
Discovered open port 23/tcp on 192.168.0.14
Discovered open port 10080/tcp on 192.168.0.14
Discovered open port 9600/tcp on 192.168.0.14
Discovered open port 81/tcp on 192.168.0.14
Discovered open port 10554/tcp on 192.168.0.14
Completed SYN Stealth Scan at 20:02, 201.34s elapsed (65535 total ports)
Initiating Service scan at 20:02
Scanning 5 services on 192.168.0.14
Completed Service scan at 20:02, 38.52s elapsed (5 services on 1 host)
Initiating OS detection (try #1) against 192.168.0.14
NSE: Script scanning 192.168.0.14.
Initiating NSE at 20:03
Completed NSE at 20:03, 31.05s elapsed
Initiating NSE at 20:03
Completed NSE at 20:03, 0.00s elapsed
Nmap scan report for 192.168.0.14
Host is up (0.049s latency).
Not shown: 65530 closed ports
PORT STATE SERVICE VERSION
23/tcp open telnet security DVR telnetd (many brands)
81/tcp open http GoAhead WebServer
| http-auth:
| HTTP/1.1 401 Unauthorized
|_ Digest qop=auth stale=FALSE nonce=cebfc77df182124b2cc0d4d43ff4c8b7 opaque=5ccc069c403ebaf9f0171e9517f40e41 algorithm=MD5 realm=GoAhead domain=:81
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: GoAhead-Webs
|_http-title: Document Error: Unauthorized
9600/tcp open tcpwrapped
10080/tcp open tcpwrapped
10554/tcp open rtsp
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port10554-TCP:V=6.49BETA6%I=7%D=11/22%Time=565273B7%P=i686-pc-windows-w
SF:indows%r(GenericLines,2E,"RTSP/1\.0\x20551\x20Option\x20not\x20supporte
SF:d\r\nCseq:\x200\r\n\r\n")%r(GetRequest,2E,"RTSP/1\.0\x20551\x20Option\x
SF:20not\x20supported\r\nCseq:\x200\r\n\r\n")%r(FourOhFourRequest,2E,"RTSP
SF:/1\.0\x20551\x20Option\x20not\x20supported\r\nCseq:\x200\r\n\r\n");
MAC Address: 48:02:2A:02:C0:CF (B-Link Electronic Limited)
Device type: general purpose
Running: Linux 2.6.X|3.X
OS CPE: cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3
OS details: Linux 2.6.32 - 3.5
Uptime guess: 0.044 days (since Sun Nov 22 18:59:57 2015)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=257 (Good luck!)
IP ID Sequence Generation: All zeros

TRACEROUTE
HOP RTT ADDRESS
1 48.67 ms 192.168.0.14

NSE: Script Post-scanning.
Initiating NSE at 20:03
Completed NSE at 20:03, 0.00s elapsed
Initiating NSE at 20:03
Completed NSE at 20:03, 0.00s elapsed
Read data files from: C:\Program Files (x86)\Nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 278.67 seconds
Raw packets sent: 65556 (2.885MB) | Rcvd: 74499 (4.658MB)

Interesting things I found were:

  • Telnet is enabled which could be fun.
  • HTTP is configured on port 81.
  • RTSP on port 10554?!?

After logging in to the web interface, with the default username of “admin” and default password of “888888”, I was greeted with a menu of available interfaces for various browsers and platforms. I went for the Firefox interface which used a M-JPEG push and only supported VGA and QVGA resolutions which made me very sad. After firing up Internet Explorer and installing the ActiveX plugin, I was able to view full 720P video and manage my video recordings.

What the hell, I don’t want to rely on a stupid ActiveX plugin and that simply hinders my usage of the thing. I want the full 720P video stream, especially for adding the camera to ZoneMinder. So, two things I needed to do: I needed to get the files off of the camera for some reverse engineering and snoop on the listening sockets from within the camera. How? We’re going to remote in like it’s 1990 (telnet).

Telnetting in…

Upon trying to telnet in, I was prompted for a username and password. From my past experience with IP based security camera solutions, I tried the first username/password combination that has worked in the past: username of “root” and password of “123456”. Voila!

Trying 192.168.0.14...
Connected to 192.168.0.14.
Escape character is '^]'.

(none) login: root
Password:
Welcome to HiLinux.
# uname -a
Linux (none) 3.0.8 #30 Tue May 27 21:58:10 CST 2014 armv5tejl GNU/Linux
#

Before getting into the good stuff, let’s learn a little more about the hardware:

# dmesg
Linux version 3.0.8 (root@ubuntu) (gcc version 4.4.1 (Hisilicon_v100(gcc4.4-290+uclibc_0.9.32.1+eabi+linuxpthread)) ) #30 Tue May 27 21:58:10 CST 2014
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: hi3518
Memory policy: ECC disabled, Data cache writeback
AXI bus clock 200000000.
On node 0 totalpages: 9216
free_area_init_node: node 0, pgdat c03dcf60, node_mem_map c03ec000
Normal zone: 72 pages used for memmap
Normal zone: 0 pages reserved
Normal zone: 9144 pages, LIFO batch:1
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 9144
Kernel command line: mem=36M console=ttyAMA0,115200 root=/dev/mtdblock2 rootfstype=squashfs rw init=/sbin/init mtdparts=hi_sfc:1024k(boot),3072k(kernel),7168k(rootfs),5120k(system)
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 36MB = 36MB total
Memory: 32472k/32472k available, 4392k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
DMA : 0xffc00000 - 0xffe00000 ( 2 MB)
vmalloc : 0xc2800000 - 0xfe000000 ( 952 MB)
lowmem : 0xc0000000 - 0xc2400000 ( 36 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.init : 0xc0008000 - 0xc0021000 ( 100 kB)
.text : 0xc0021000 - 0xc03c3000 (3720 kB)
.data : 0xc03c4000 - 0xc03dd5e0 ( 102 kB)
.bss : 0xc03dd604 - 0xc03ebba0 ( 58 kB)
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS:32 nr_irqs:32 32
sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 42949ms
Console: colour dummy device 80x30
Calibrating delay loop... 217.08 BogoMIPS (lpj=108544)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
Serial: AMBA PL011 UART driver
uart:0: ttyAMA0 at MMIO 0x20080000 (irq = 5) is a PL011 rev2
console [ttyAMA0] enabled
uart:1: ttyAMA1 at MMIO 0x20090000 (irq = 5) is a PL011 rev2
bio: create slab at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
cfg80211: Calling CRDA to update world regulatory domain
Switching to clocksource timer1
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
NetWinder Floating Point Emulator V0.97 (double precision)
squashfs: version 4.0 (2009/01/31) Phillip Lougher
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
fuse init (API version 7.16)
msgmni has been set to 63
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
io scheduler noop registered
io scheduler deadline registered (default)
io scheduler cfq registered
brd: module loaded
Spi id table Version 1.22
Hisilicon Spi Flash Controller V350 Device Driver, Version 1.10
Spi(cs1) ID: 0xC2 0x20 0x18 0xC2 0x20 0x18
SPI FLASH start_up_mode is 3 Bytes
Spi(cs1):
Block:64KB
Chip:16MB
Name:"MX25L128XX"
spi size: 16MB
chip num: 1
4 cmdlinepart partitions found on MTD device hi_sfc
Creating 4 MTD partitions on "hi_sfc":
0x000000000000-0x000000100000 : "boot"
0x000000100000-0x000000400000 : "kernel"
0x000000400000-0x000000b00000 : "rootfs"
0x000000b00000-0x000001000000 : "system"
Fixed MDIO Bus: probed
himii: probed
usbcore: registered new interface driver rt2500usb
usbcore: registered new interface driver rt73usb
usbmon: debugfs is not available
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
hiusb-ehci hiusb-ehci.0: HIUSB EHCI
hiusb-ehci hiusb-ehci.0: new USB bus registered, assigned bus number 1
hiusb-ehci hiusb-ehci.0: irq 15, io mem 0x100b0000
hiusb-ehci hiusb-ehci.0: USB 0.0 started, EHCI 1.00
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
hiusb-ohci hiusb-ohci.0: HIUSB OHCI
hiusb-ohci hiusb-ohci.0: new USB bus registered, assigned bus number 2
hiusb-ohci hiusb-ohci.0: irq 16, io mem 0x100a0000
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 1 port detected
usbcore: registered new interface driver cdc_acm
cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
usbcore: registered new interface driver cdc_wdm
TCP cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 17
NET: Registered protocol family 15
lib80211: common routines for IEEE802.11 drivers
lib80211_crypt: registered algorithm 'NULL'
registered taskstats version 1
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
VFS: Mounted root (squashfs filesystem) readonly on device 31:2.
Freeing init memory: 100K
usb 1-1: new high speed USB device number 2 using hiusb-ehci
mmc0: new SDHC card at address e624
mmcblk0: mmc0:e624 SU08G 7.40 GiB
mmcblk0: p1
udevd (414): /proc/414/oom_adj is deprecated, please use /proc/414/oom_score_adj instead.
Hisilicon Watchdog Timer: 0.01 initialized. default_margin=60 sec (nowayout= 0, nodeamon= 0)
mt7601Usta: module license 'unspecified' taints kernel.
Disabling lock debugging due to kernel taint
rtusb init rtusbSTA --->

=== pAd = c2ae9000, size = 860440 ===

RTMPAllocTxRxRingMemory, Status=0
RTMPAllocAdapterBlock, Status=0
RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x8
RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x4
RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x5
RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x6
RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x7
RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x9
NVM is EFUSE
Endpoint(8) is for In-band Command
Endpoint(4) is for WMM0 AC0
Endpoint(5) is for WMM0 AC1
Endpoint(6) is for WMM0 AC2
Endpoint(7) is for WMM0 AC3
Endpoint(9) is for WMM1 AC0
Endpoint(84) is for Data-In
Endpoint(85) is for Command Rsp
usbcore: registered new interface driver rtusbSTA
1. LDO_CTR0(6c) = a64799, PMU_OCLEVEL c
2. LDO_CTR0(6c) = a6478d, PMU_OCLEVEL 6
FW Version:0.1.00 Build:7640
Build Time:201308222153____
ILM Length = 47000(bytes)
DLM Length = 0(bytes)
Loading FW....
#
RTMP_TimerListAdd: add timer obj c2b6992c!
RTMP_TimerListAdd: add timer obj c2b69944!
RTMP_TimerListAdd: add timer obj c2b6995c!
RTMP_TimerListAdd: add timer obj c2b69914!
RTMP_TimerListAdd: add timer obj c2b698cc!
RTMP_TimerListAdd: add timer obj c2b698e4!
RTMP_TimerListAdd: add timer obj c2afe764!
RTMP_TimerListAdd: add timer obj c2aeb1e0!
RTMP_TimerListAdd: add timer obj c2aeb1fc!
RTMP_TimerListAdd: add timer obj c2afe7bc!
RTMP_TimerListAdd: add timer obj c2aedcf0!
RTMP_TimerListAdd: add timer obj c2aed3a0!
RTMP_TimerListAdd: add timer obj c2aedcd4!
RTMP_TimerListAdd: add timer obj c2aedf14!
RTMP_TimerListAdd: add timer obj c2aedd0c!
RTMP_TimerListAdd: add timer obj c2aedd28!
RTMP_TimerListAdd: add timer obj c2aedd44!
RTMP_TimerListAdd: add timer obj c2afe734!
RTMP_TimerListAdd: add timer obj c2afe7a4!
RTMP_TimerListAdd: add timer obj c2aedf44!
RTMP_TimerListAdd: add timer obj c2aedf5c!
RTMP_TimerListAdd: add timer obj c2aedf74!
RTMP_TimerListAdd: add timer obj c2aedf8c!
cfg_mode=9
wmode_band_equal(): Band Equal!
Key1Str is Invalid key length(0) or Type(0)
Key2Str is Invalid key length(0) or Type(0)
Key3Str is Invalid key length(0) or Type(0)
Key4Str is Invalid key length(0) or Type(0)
1. Phy Mode = 14
2. Phy Mode = 14
NVM is Efuse and its size =1d[1e0-1fc]
3. Phy Mode = 14
AntCfgInit: primary/secondary ant 0/1
---> InitFrequencyCalibration
InitFrequencyCalibrationMode:Unknow mode = 3
InitFrequencyCalibration: frequency offset in the EEPROM = 105(0x69)
- InitFrequencyCalibration
RTMPSetPhyMode: channel is out of range, use first channel=1
MCS Set = ff 00 00 00 01
== rt28xx_init, Status=0
0x1300 = 00064300
RTMPDrvOpen(1):Check if PDMA is idle!
RTMPDrvOpen(2):Check if PDMA is idle!
PeerBeaconAtJoinAction(): HT-CtrlChannel=6, CentralChannel=>6
PeerBeaconAtJoinAction(): Set CentralChannel=6
RTMP_TimerListAdd: add timer obj c2bb5d60!
Rcv Wcid(1) AddBAReq
Start Seq = 00000002
RTMP_TimerListAdd: add timer obj c2bb7174!
ERROR!!! CntlEnqueueForRecv: BlockAck Request frame length size = 44 incorrect
Hisilicon Media Memory Zone Manager
Hisilicon UMAP device driver interface: v3.00
pa:82400000, va:c2c40000
load sys.ko for Hi3518...OK!
load viu.ko for Hi3518...OK!
ISP Mod init!
load vpss.ko ....OK!
load vou.ko ....OK!
load venc.ko for Hi3518...OK!
load group.ko for Hi3518...OK!
load chnl.ko for Hi3518...OK!
load h264e.ko for Hi3518...OK!
load jpege.ko for Hi3518...OK!
load rc.ko for Hi3518...OK!
load region.ko ....OK!
load vda.ko ....OK!
*************************init down!
hi_i2c init is ok!
gpio_init...................
base108 0 base10c 0 value a0
Kernel: ssp initial ok!
acodec inited!
base108 0 base10c 0 value a0
0x20050000 value is 0x150124
ERROR!!! RTMPSetTimer failed, Halt in Progress!
ERROR!!! MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS
Check RxQ page count max
unlink cmd rsp urb
1. LDO_CTR0(6c) = a6478d, PMU_OCLEVEL 6
2. LDO_CTR0(6c) = a6478d, PMU_OCLEVEL 6
RTMP_TimerListAdd: add timer obj c2b6992c!
RTMP_TimerListAdd: add timer obj c2b69944!
RTMP_TimerListAdd: add timer obj c2b6995c!
RTMP_TimerListAdd: add timer obj c2b69914!
RTMP_TimerListAdd: add timer obj c2b698cc!
RTMP_TimerListAdd: add timer obj c2b698e4!
RTMP_TimerListAdd: add timer obj c2afe764!
RTMP_TimerListAdd: add timer obj c2aeb1e0!
RTMP_TimerListAdd: add timer obj c2aeb1fc!
RTMP_TimerListAdd: add timer obj c2afe7bc!
RTMP_TimerListAdd: add timer obj c2aedcf0!
RTMP_TimerListAdd: add timer obj c2aed3a0!
RTMP_TimerListAdd: add timer obj c2aedcd4!
RTMP_TimerListAdd: add timer obj c2aedf14!
RTMP_TimerListAdd: add timer obj c2aedd0c!
RTMP_TimerListAdd: add timer obj c2aedd28!
RTMP_TimerListAdd: add timer obj c2aedd44!
RTMP_TimerListAdd: add timer obj c2afe734!
RTMP_TimerListAdd: add timer obj c2afe7a4!
RTMP_TimerListAdd: add timer obj c2aedf44!
RTMP_TimerListAdd: add timer obj c2aedf5c!
RTMP_TimerListAdd: add timer obj c2aedf74!
RTMP_TimerListAdd: add timer obj c2aedf8c!
cfg_mode=9
wmode_band_equal(): Band Equal!
Key1Str is Invalid key length(0) or Type(0)
Key2Str is Invalid key length(0) or Type(0)
Key3Str is Invalid key length(0) or Type(0)
Key4Str is Invalid key length(0) or Type(0)
1. Phy Mode = 14
2. Phy Mode = 14
NVM is Efuse and its size =1d[1e0-1fc]
3. Phy Mode = 14
AntCfgInit: primary/secondary ant 0/1
---> InitFrequencyCalibration
InitFrequencyCalibrationMode:Unknow mode = 3
InitFrequencyCalibration: frequency offset in the EEPROM = 105(0x69)
- InitFrequencyCalibration
RTMPSetPhyMode: channel is out of range, use first channel=1
MCS Set = ff 00 00 00 01
== rt28xx_init, Status=0
0x1300 = 00064300
RTMPDrvOpen(1):Check if PDMA is idle!
RTMPDrvOpen(2):Check if PDMA is idle!
motocmd:1 motospeed:0 onestep:0 runtimes:0
motocmd:5 motospeed:0 onestep:0 runtimes:0
levelmidflag 1 midtimes 2575
vertmidflag 1 midtimes 900
leveltimers 5150
verttimes 2000
motocmd:25 motospeed:10 onestep:0 runtimes:0
PeerBeaconAtJoinAction(): HT-CtrlChannel=6, CentralChannel=>6
PeerBeaconAtJoinAction(): Set CentralChannel=6
/home/aplink/work-hisi/work-file/DPA_MT7601U_LinuxSTA_3.0.0.4_20130916/MODULE/os/linux/../../sta/rtmp_data.c:757 assert pRxWI->RxWIWirelessCliID == BSSID_WCIDfailed
RTMP_TimerListAdd: add timer obj c2bb5d60!
Rcv Wcid(1) AddBAReq
Start Seq = 00000002
RTMP_TimerListAdd: add timer obj c2bb7174!
ERROR!!! CntlEnqueueForRecv: BlockAck Request frame length size = 44 incorrect
hirtc_set_time->396:
check state error!

RTMP_TimerListAdd: add timer obj c2bb5d88!
RTMP_TimerListAdd: add timer obj c2bb5db0!
DownRateIdx=10

# cat /proc/cpuinfo
Processor : ARM926EJ-S rev 5 (v5l)
BogoMIPS : 217.08
Features : swp half thumb fastmult edsp java
CPU implementer : 0x41
CPU architecture: 5TEJ
CPU variant : 0x0
CPU part : 0x926
CPU revision : 5

Hardware : hi3518
Revision : 0000
Serial : 0000000000000000

# mount
rootfs on / type rootfs (rw)
/dev/root on / type squashfs (ro,relatime)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
tmpfs on /dev type tmpfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)
/dev/mtdblock3 on /system type jffs2 (rw,relatime)
none on /tmp type tmpfs (rw,relatime,size=3072k)
/dev/mmcblk0p1 on /mnt/sda0 type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=cp437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)

NOTE: /dev/mmcblk0p1 is the 8GB Micro-SD card that I inserted in the camera.

And now for the good stuff:

# netstat -ntulp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:10080 0.0.0.0:* LISTEN 541/encoder
tcp 0 0 0.0.0.0:9600 0.0.0.0:* LISTEN 426/wifidaemon
tcp 0 0 0.0.0.0:81 0.0.0.0:* LISTEN 541/encoder
tcp 0 0 0.0.0.0:23 0.0.0.0:* LISTEN 422/telnetd
tcp 0 0 0.0.0.0:10554 0.0.0.0:* LISTEN 541/encoder
netstat: /proc/net/tcp6: No such file or directory
udp 0 0 127.0.0.1:6666 0.0.0.0:* 426/wifidaemon
udp 0 0 127.0.0.1:6667 0.0.0.0:* 541/encoder
udp 592 0 0.0.0.0:47908 0.0.0.0:* 541/encoder
udp 1576 0 0.0.0.0:47909 0.0.0.0:* 541/encoder
udp 592 0 0.0.0.0:60726 0.0.0.0:* 541/encoder
udp 1576 0 0.0.0.0:60727 0.0.0.0:* 541/encoder
udp 0 0 0.0.0.0:10056 0.0.0.0:* 541/encoder
udp 0 0 0.0.0.0:32108 0.0.0.0:* 541/encoder
udp 0 0 0.0.0.0:3702 0.0.0.0:* 541/encoder
udp 0 0 0.0.0.0:2697 0.0.0.0:* 541/encoder
udp 0 0 0.0.0.0:8600 0.0.0.0:* 426/wifidaemon
netstat: /proc/net/udp6: No such file or directory

It looks like the /system/system/bin/encoder process is the swiss army knife of this camera as it handles the HTTP, RTSP, and ONVIF services. I wanted to get a closer look at that binary so, through exploring, I noticed that there is an FTP daemon so I fired that up and copied everything except for /dev and /proc:

# tcpsvd -vE 0.0.0.0 21 ftpd /
tcpsvd: listening on 0.0.0.0:21, starting

If you’ve already noticed some of the crappiness of the web interface then keep in mind that via FTP, you can upload your very own web interface. Keep in mind that a firmware update will probably ruin your hard work BUT there are separate firmware updates for the base operating system and for the front-end; the odds are in your favor my friends.

Disassembly and Reverse Engineering

What I’m after is the endpoints needed for the various services. The web UI to the camera failed to provide me with information I needed and the ActiveX plugin is just disgusting, so time to break out the big guns. Now for the good stuff!

.text:0007BA94 MOV R3, R0
.text:0007BA98 ADD R3, R3, #1
.text:0007BA9C STR R3, [R11,#s1]
.text:0007BAA0 LDR R1, =aRtsp09aZaZ_AvH ; "rtsp://%*[0-9A-Za-z.:]/%[^/]/av%hhd"
.text:0007BAA4 LDR R3, [R11,#var_64]
.text:0007BAA8 ADD R3, R3, #0x1000
.text:0007BAAC ADD R3, R3, #0x39
.text:0007BAB0 SUB R2, R11, #-var_34
.text:0007BAB4 LDR R0, [R11,#s1] ; s
.text:0007BAB8 BL sscanf
.text:0007BABC MOV R3, R0
.text:0007BAC0 STR R3, [R11,#var_14]
.text:0007BAC4 LDR R3, [R11,#var_14]
.text:0007BAC8 CMP R3, #2
.text:0007BACC BNE loc_7BBC0
.text:0007BAD0 LDR R1, =aRtsp09aZaZ_A_0 ; "rtsp://%*[0-9A-Za-z.:]/%[^/]/av%hhd_%hh"...
.text:0007BAD4 LDR R3, [R11,#var_64]
.text:0007BAD8 ADD R3, R3, #0x1000
.text:0007BADC ADD R3, R3, #0x39
.text:0007BAE0 SUB R2, R11, #-var_58
.text:0007BAE4 SUB R12, R11, #-var_35
.text:0007BAE8 STR R3, [SP,#0x6C+var_6C]
.text:0007BAEC LDR R0, [R11,#s1] ; s
.text:0007BAF0 MOV R3, R12
.text:0007BAF4 BL sscanf

The short version is that you have two RTSP endpoints that correlate with audio and video channels:

  • rtsp://%*[0-9A-Za-z.:]/%[^/]/av%hhd_%hhd
  • rtsp://%*[0-9A-Za-z.:]/%[^/]/av%hhd

To break down the URL, there is “%*[0-9A-Za-z.:]” which represents the address of the camera, “%[^/]” is representing protocol (more on that later), and “av%hhd_%hhd” represents the audio and video stream (example: “av0_0”) or “av%hhd” representing the video-only stream (example: “av0”).

Now, more on that protocol stuff. Like I said at the top of this page, this supports TCP and UDP unicasting. How do I know?

.text:0007BAF8 SUB R3, R11, #-var_34
.text:0007BAFC MOV R0, R3 ; s1
.text:0007BB00 LDR R1, =aTcp ; "tcp"
.text:0007BB04 MOV R2, #3 ; n
.text:0007BB08 BL strncasecmp
.text:0007BB0C MOV R3, R0
.text:0007BB10 CMP R3, #0
.text:0007BB14 BNE loc_7BB2C
.text:0007BB18 LDR R2, [R11,#var_64]
.text:0007BB1C LDR R3, =0x1038
.text:0007BB20 MOV R1, #1
.text:0007BB24 STRB R1, [R2,R3]
.text:0007BB28 B loc_7BB88

.text:0007BB2C SUB R3, R11, #-var_34
.text:0007BB30 MOV R0, R3 ; s1
.text:0007BB34 LDR R1, =aUdp ; "udp"
.text:0007BB38 MOV R2, #3 ; n
.text:0007BB3C BL strncasecmp
.text:0007BB40 MOV R3, R0
.text:0007BB44 CMP R3, #0
.text:0007BB48 BNE loc_7BB60
.text:0007BB4C LDR R2, [R11,#var_64]
.text:0007BB50 LDR R3, =0x1038
.text:0007BB54 MOV R1, #2
.text:0007BB58 STRB R1, [R2,R3]
.text:0007BB5C B loc_7BB88

As you can see there, both TCP and UDP are supported. This leaves a pair of possible RTSP stream URLs for each protocol but this stream will require authentication. Good news! It’s the same username/password as setup by the camera and in this case, it was the username of “admin” and a password of “888888”.

  • rtsp://:@
    :10554/udp/av0
  • rtsp://:@
    :10554/udp/av0_0
  • rtsp://:@
    :10554/tcp/av0
  • rtsp://:@
    :10554/tcp/av0_0

Now keep in mind that for RTSP, UDP is the preferred method due to the lower overhead. TCP may be better for routing through a firewall though but will increase the traffic overhead considerably. On that note, the RTSP stream says it’s unicast but I have had trouble routing the RTSP stream outside of a residential Netgear cable modem/router combo device. However, feel free to open up VLC on your computer or Live Media Player on your iPhone (sorry Android users, you’re not cool enough) and open up one of these RTSP

More about the RTSP stream

After using VLC on my laptop, here is a sniplet of the RTSP stream setup:

OPTIONS rtsp://192.168.0.14:10554/udp/av0_0 RTSP/1.0
CSeq: 2
User-Agent: LibVLC/2.2.1 (LIVE555 Streaming Media v2014.07.25)

RTSP/1.0 200 OK
Cseq: 2
Date: Wed, Nov 25 2015 04:41:12 GMT
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER

DESCRIBE rtsp://192.168.0.14:10554/udp/av0_0 RTSP/1.0
CSeq: 3
User-Agent: LibVLC/2.2.1 (LIVE555 Streaming Media v2014.07.25)
Accept: application/sdp

RTSP/1.0 401 Unauthorized
Cseq: 3
WWW-Authenticate: Digest realm="RTSPD",nonce="l4m9sai59rv319fk190z256698u9skyt"

DESCRIBE rtsp://192.168.0.14:10554/udp/av0_0 RTSP/1.0
CSeq: 4
Authorization: Digest username="admin", realm="RTSPD", nonce="l4m9sai59rv319fk190z256698u9skyt", uri="rtsp://192.168.0.14:10554/udp/av0_0", response="443a8ab92f63472fcd7f662ebc51f0d9"
User-Agent: LibVLC/2.2.1 (LIVE555 Streaming Media v2014.07.25)
Accept: application/sdp

RTSP/1.0 200 OK
Cseq: 4
Date: Wed, Nov 25 2015 04:41:12 GMT
Content-Type: application/sdp
Content-Length: 333

v=0
o=- 1448426472 1448426473 IN IP4
s=streamed by the APKLINK RTSP server
t=0 0
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=control:track0
m=audio 0 RTP/AVP 8
a=rtpmap:8 PCMA/8000/1
a=control:track1
a=range:npt=0-
a=fmtp:96 packetization-mode=1;profile-level-id=42001F;sprop-parameter-sets=Z0IAH5WoFAFuQA==,aM48gA==

SETUP rtsp://192.168.0.14:10554/udp/av0_0/track0 RTSP/1.0
CSeq: 5
Authorization: Digest username="admin", realm="RTSPD", nonce="l4m9sai59rv319fk190z256698u9skyt", uri="rtsp://192.168.0.14:10554/udp/av0_0", response="ea049603404593719652104ade79a990"
User-Agent: LibVLC/2.2.1 (LIVE555 Streaming Media v2014.07.25)
Transport: RTP/AVP;unicast;client_port=55696-55697

RTSP/1.0 200 OK
Cseq: 5
Date: Wed, Nov 25 2015 04:41:12 GMT
Session: 9069744780674813943
Transport: RTP/AVP;unicast;client_port=55696-55697;server_port=58908-58909

SETUP rtsp://192.168.0.14:10554/udp/av0_0/track1 RTSP/1.0
CSeq: 6
Authorization: Digest username="admin", realm="RTSPD", nonce="l4m9sai59rv319fk190z256698u9skyt", uri="rtsp://192.168.0.14:10554/udp/av0_0", response="ea049603404593719652104ade79a990"
User-Agent: LibVLC/2.2.1 (LIVE555 Streaming Media v2014.07.25)
Transport: RTP/AVP;unicast;client_port=55698-55699
Session: 9069744780674813943

RTSP/1.0 200 OK
Cseq: 6
Date: Wed, Nov 25 2015 04:41:12 GMT
Session: 9069744780674813943
Transport: RTP/AVP;unicast;client_port=55698-55699;server_port=38872-38873

PLAY rtsp://192.168.0.14:10554/udp/av0_0 RTSP/1.0
CSeq: 7
Authorization: Digest username="admin", realm="RTSPD", nonce="l4m9sai59rv319fk190z256698u9skyt", uri="rtsp://192.168.0.14:10554/udp/av0_0", response="f59269d6c291e4e120d82be94be8f3e9"
User-Agent: LibVLC/2.2.1 (LIVE555 Streaming Media v2014.07.25)
Session: 9069744780674813943
Range: npt=0.000-

RTSP/1.0 200 OK
Cseq: 7
Date: Wed, Nov 25 2015 04:41:12 GMT
Session: 9069744780674813943

GET_PARAMETER rtsp://192.168.0.14:10554/udp/av0_0 RTSP/1.0
CSeq: 8
Authorization: Digest username="admin", realm="RTSPD", nonce="l4m9sai59rv319fk190z256698u9skyt", uri="rtsp://192.168.0.14:10554/udp/av0_0", response="39206bb401702286cfebbefd3bacffb5"
User-Agent: LibVLC/2.2.1 (LIVE555 Streaming Media v2014.07.25)
Session: 9069744780674813943

RTSP/1.0 200 OK
Cseq: 8
Date: Wed, Nov 25 2015 04:41:12 GMT
Session: 9069744780674813943

This is more informative than anything but those of you who know about RTSP streams may appreciate this information. If you want to know more about RTSP streams, please consult Google.

.h264 Video Files

When you download recorded video files, or copy them from the camera’s SD card, they come with a .h264 extension and will need some conversion to be more usable. Looking closer at one of the files from the camera:

$ ffprobe -i 20151127031213_010.h264
ffprobe version N-72086-g51f6455 Copyright (c) 2007-2015 the FFmpeg developers
built with gcc 4.9.2 (GCC)
configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libdcadec --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-lzma --enable-decklink --enable-zlib
libavutil 54. 23.101 / 54. 23.101
libavcodec 56. 38.100 / 56. 38.100
libavformat 56. 33.101 / 56. 33.101
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 1.100 / 1. 1.100
libpostproc 53. 3.100 / 53. 3.100
Input #0, h264, from '20151127031213_010.h264':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: h264 (Main), yuv420p, 1280x720, 25 fps, 25 tbr, 1200k tbn, 50 tbc

What I did was simply change the container of the file and it worked out splendidly just by doing:

$ ffmpeg -i 20151127031213_010.h264 20151127031213_010.mp4

And boom goes the dynamite.

The resulting MP4 looks like:

$ ffprobe -i 20151127031213_010.mp4
ffprobe version N-72086-g51f6455 Copyright (c) 2007-2015 the FFmpeg developers
built with gcc 4.9.2 (GCC)
configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libdcadec --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-lzma --enable-decklink --enable-zlib
libavutil 54. 23.101 / 54. 23.101
libavcodec 56. 38.100 / 56. 38.100
libavformat 56. 33.101 / 56. 33.101
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 1.100 / 1. 1.100
libpostproc 53. 3.100 / 53. 3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '../../../../Downloads/20151127031213_010.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf56.33.101
Duration: 00:00:42.80, start: 0.000000, bitrate: 458 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720, 457 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
Metadata:
handler_name : VideoHandler

For more information

More information will soon be coming to this page. In the interim, please reach out to me: jamie.ivanov gmail com with any questions or if you want data files associated with this project.

One comment to Hacking the Woshida T7866WIP HD IP Camera

  • Pablo Balogh  says:

    Hi, genius! Goodnight! Congratulations for the great work! I have a VSTARCAM c7833 ip camera and I updated the “firmware” through the web interface of the camera, but I did not select the correct firmware and now the camera does not work. The WLAN and LAN connection work fine, but there is no open port, only the 9600 tcp. Can I fix the problem? Can I somehow reinstall the original firmware through the LAN or WLAN and Kali Linux? Thank you very much for your time and apologies for not understanding this issue.

Leave a reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>