I had a lot of success with various Chinese IP cameras as all of them supported standard ONVIF protocol, which allowed to almost entirely avoid their custom software and apps. However, my latest purchase was not that successful. I bought a mini 1080p camera from aliexpress which I intended to use in a van. As soon as I received it, I went to check it with nmap and it turns out that it only has port 80 open. That means no ONVIF, no RTSP streams.

The only way to use this camera is through iMiniCam app on android, custom Internet Explorer ActiveX plugin or a horrible MJPEG stream. Since I wanted to record the stream on a raspberry, I needed some usable stream format. I tried wiresharking IE stream, but I couldn’t figure out what protocol it was. All I knew that it was going through HTTP. And so it is reverse engineering time!

Opening the case revealed a HiSilicon Hi3518E V200 SoC which is quite common across IP cams. The sensor is OV2710, which is a 1080p sensor, but the provided streams are only 720p. Bummer.

There were also two test points which I suspected to be a serial console. A quick check with a scope confirmed that so I soldered some wires to connect it to an USB adapter. Baud rate is 115200. Be aware that voltage level is 3.3V.

This is the output during bootup:

System startup

U-Boot 2010.06 (Sep 08 2018 - 14:16:59)

Check Flash Memory Controller v100 ... Found
SPI Nor(cs 0) ID: 0xc2 0x20 0x17
Block:64KB Chip:8MB Name:"MX25L6406E"
SPI Nor total size: 8MB
EMMC/MMC/SD controller initialization.
Card did not respond to voltage select!
No EMMC/MMC/SD device found !
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Hisilicon ETH net controler
hieth_init :0
MAC:   00-00-23-34-45-66
PHY not link.
Hit any key to stop autoboot:  0
8192 KiB hi_fmc at 0:0 is now current device

## Booting kernel from Legacy Image at 82000000 ...
   Image Name:   Linux-3.4.35
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2442376 Bytes = 2.3 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Loading Kernel Image ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0
Linux version 3.4.35 (zg@ESNTD_ZGLUX) (gcc version 4.8.3 20131202 (prerelease) (Hisilicon_v300) ) #179 Tue Oct 9 09:55:26 CST 2018
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: hi3518ev200
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 8128
Kernel command line: mem=32M console=ttyAMA0,115200 root=/dev/mtdblock4 rootfstype=squashfs mtdparts=hi_sfc:256k(boot),128k(env),128k(conf),2752k(os),3904k(rootfs),1024k(userfs)
PID hash table entries: 128 (order: -3, 512 bytes)
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 32MB = 32MB total
Memory: 27476k/27476k available, 5292k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    vmalloc : 0xc2800000 - 0xff000000   ( 968 MB)
    lowmem  : 0xc0000000 - 0xc2000000   (  32 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .text : 0xc0008000 - 0xc044a000   (4360 kB)
      .init : 0xc044a000 - 0xc046a344   ( 129 kB)
      .data : 0xc046c000 - 0xc049a8e0   ( 187 kB)
       .bss : 0xc049a904 - 0xc04d8bb8   ( 249 kB)
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
VIC @fe0d0000: id 0x00641190, vendor 0x41
sched_clock: 32 bits at 49MHz, resolution 20ns, wraps every 86767ms
Console: colour dummy device 80x30
Calibrating delay loop... 266.24 BogoMIPS (lpj=133120)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
Initializing cgroup subsys freezer
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0x80345470 - 0x803454c8
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 = 30) is a PL011 rev2
uart:2: ttyAMA2 at MMIO 0x200a0000 (irq = 25) is a PL011 rev2
bio: create slab <bio-0> at 0
SCSI subsystem initialized
hi-spi-master hi-spi-master.0: with 1 chip select slaves attached
hi-spi-master hi-spi-master.1: with 2 chip select slaves attached
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Switching to clocksource timer0
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
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
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
squashfs: version 4.0 (2009/01/31) Phillip Lougher
NFS: Registering the id_resolver key type
jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
fuse init (API version 7.18)
msgmni has been set to 53
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
io scheduler noop registered
io scheduler deadline registered (default)
io scheduler cfq registered
brd: module loaded
Check Flash Memory Controller v100 ...  Found.
SPI Nor(cs 0) ID: 0xc2 0x20 0x17
Block:64KB Chip:8MB Name:"MX25L6436F"
SPI Nor total size: 8MB
6 cmdlinepart partitions found on MTD device hi_sfc
6 cmdlinepart partitions found on MTD device hi_sfc
Creating 6 MTD partitions on "hi_sfc":
0x000000000000-0x000000040000 : "boot"
0x000000040000-0x000000060000 : "env"
0x000000060000-0x000000080000 : "conf"
0x000000080000-0x000000330000 : "os"
0x000000330000-0x000000700000 : "rootfs"
0x000000700000-0x000000800000 : "userfs"
SPI Nand ID Table Version 1.9
No NAND device found
ESNTD Kernel NVRAM initialized
ESNDT GPIO HZ[1000] Ver 1.0 ... PTZ Speed 8 (5 [1--10  @@ 1000])
PTZ Cfg 0 PTZ Startpost 0, Speed 8, SavePos:-1--1
esndt gpio init max moto step 20000
 Init Power Key->>OK
PTZ Cfg Step 1050 - 16500
esntd_hiadc_init --> OK
himii: probed
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
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
mousedev: PS/2 mouse device common for all mice
i2c /dev entries driver
hisi_i2c hisi_i2c.0: Hisilicon [i2c-0] probed!
hisi_i2c hisi_i2c.1: Hisilicon [i2c-1] probed!
hisi_i2c hisi_i2c.2: Hisilicon [i2c-2] probed!
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
TCP: cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 17
NET: Registered protocol family 15
lib80211: common routines for IEEE802.11 drivers
Registering the dns_resolver key type
VFS: Mounted root (squashfs filesystem) readonly on device 31:4.
Freeing init memory: 128K

 ||||\  |||||  |||   ||  ||||||  ||||||
 |\    \||     \|||  |\    ||    ||   ||
 ||||\  |||\   \| |\ |\    ||    ||   ||
 ||       usb 1-1: new high-speed USB device number 2 using hiusb-ehci
\||  \|  |||\    ||    ||   ||
 ||     \  ||  \|  \||\    ||    ||  ||\
 ||||| \||||\  ||   ||\    ||    |||||\


[RCS]: /etc_ro/init.d/S00devs
[RCS]: /etc_ro/init.d/S01udev
usbdev11 -> /dev/usbdev1.2
Not recognise ACTION:change
Not recognise ACTION:change
Not recognise ACTION:change
[RCS]: /etc_ro/init.d/S80network
Start User Init ...!
mmz_start: 0x82000000, mmz_size: 32M
Hisilicon Media Memory Zone Manager
Module himedia: init ok
hi3518e_base: module license 'Proprietary' taints kernel.
Disabling lock debugging due to kernel taint
load sys.ko for Hi3518EV200...OK!
PHY: himii:01 - Link is Up - 10/Half
load tde.ko ...OK!
load region.ko ....OK!
load vgs.ko for Hi3518EV200...OK!
ISP Mod init!
load viu.ko for Hi3518EV200...OK!
load vpss.ko ....OK!
load rc.ko for Hi3518EV200...OK!
load venc.ko for Hi3518EV200...OK!
load chnl.ko for Hi3518EV200...OK!
load h264e.ko for Hi3518EV200...OK!
load jpege.ko for Hi3518EV200...OK!
load ive.ko for Hi3518EV200...OK!
==== Your input Sensor type is ov2710 ====
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0040: 0x00000000 --> 0x00000002
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0044: 0x00000000 --> 0x00000002
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0000: 0x00000001 --> 0x00000001
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0004: 0x00000000 --> 0x00000000
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f007c: 0x00000000 --> 0x00000001
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0080: 0x00000000 --> 0x00000001
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0084: 0x00000000 --> 0x00000001
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0088: 0x00000000 --> 0x00000001
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f008c: 0x00000000 --> 0x00000002
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0090: 0x00000000 --> 0x00000002
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0094: 0x00000000 --> 0x00000001
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x2003002c: 0x000C4003 --> 0x000C4001
acodec inited!
insert audio
init phy power successful!
load hi_mipi driver successful!
==== Your input Sensor type is ov2710 ====
Hisilicon Watchdog Timer: 0.01 initialized. default_margin=60 sec (nowayout= 0, nodeamon= 0)
Load wifi ...!
ESNDO_Startup ...
rtusb init rtusbSTA --->

=== pAd = c2d58000, size = 860832 ===

<-- RTMPAllocTxRxRingMemory, Status=0
<-- RTMPAllocAdapterBlock, Status=0
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 c2dd8bec!
RTMP_TimerListAdd: add timer obj c2dd8c04!
RTMP_TimerListAdd: add timer obj c2dd8c1c!
RTMP_TimerListAdd: add timer obj c2dd8bd4!
RTMP_TimerListAdd: add timer obj c2dd8b8c!
RTMP_TimerListAdd: add timer obj c2dd8ba4!
RTMP_TimerListAdd: add timer obj c2d6da24!
RTMP_TimerListAdd: add timer obj c2d5a1e0!
RTMP_TimerListAdd: add timer obj c2d5a1fc!
RTMP_TimerListAdd: add timer obj c2d6da7c!
RTMP_TimerListAdd: add timer obj c2d5ccf0!
RTMP_TimerListAdd: add timer obj c2d5c3a0!
RTMP_TimerListAdd: add timer obj c2d5ccd4!
RTMP_TimerListAdd: add timer obj c2d5cf14!
RTMP_TimerListAdd: add timer obj c2d5cd0c!
RTMP_TimerListAdd: add timer obj c2d5cd28!
RTMP_TimerListAdd: add timer obj c2d5cd44!
RTMP_TimerListAdd: add timer obj c2d6d9f4!
RTMP_TimerListAdd: add timer obj c2d6da64!
RTMP_TimerListAdd: add timer obj c2d5cf44!
RTMP_TimerListAdd: add timer obj c2d5cf5c!
RTMP_TimerListAdd: add timer obj c2d5cf74!
RTMP_TimerListAdd: add timer obj c2d5cf8c!
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 = 86(0x56)
<--- 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!
Auto login as root ...
Jan  1 00:00:09 login[1124]: root login on 'ttyS000'
Welcome to HiLinux.
# killall: goahead: no process killed
Start System Server ...
app_startup.sh   esndo            teldbg.sh        web
default_cfg.bin  goahead          usr_init
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200300c4: 0x00000A02 --> 0x00000A00
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0008: 0x00000001 --> 0x00000000
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200300ec: 0x00000082 --> 0x00000000
===>rt_ioctl_giwscan. 3(3) BSS returned, data->length = 502
PTZ Speed 8 (5 [1--10  @@ 1000])
mount: mounting /dev/mmcblk0p1 on /sd/ failed: No such file or directory
*** Board tools : ver0.0.1_20121120 ***
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x2003002c: 0x000C4001 --> 0x000B4001
=============SAMPLE_COMM_VI_SetMipiAttr enWDRMode: 0
***link down status changed***.
PHY: himii:01 - Link is Down
linear mode
=== soih62 720P30fps(Parallel port) init success!=====
Failed to connect to wpa_supplicant - wpa_ctrl_open: No such file or directory
KS:0001 -> 10
KS:0002 -> 00
KS:0000 -> 00
KS:0022 -> ee
KS:0023 -> 02
KS:0001 -> 17
KS:0001 -> 22
KS:0001 -> 32
KS:0001 -> 49
KS:0001 -> 6b
KS:0001 -> 9e
KS:0001 -> e2
KS:0001 -> 44
KS:0002 -> 01
KS:0001 -> cc
KS:0001 -> 8d
KS:0002 -> 02
KS:0001 -> ec
KS:0000 -> 03
KS:0000 -> 0a
KS:0000 -> 11
KS:0000 -> 15
KS:0000 -> 19
KS:0000 -> 1d
KS:0000 -> 1f
KS:0000 -> 20
KS:0000 -> 1f
KS:0000 -> 1d
KS:0000 -> 1c
KS:0000 -> 1a
KS:0000 -> 19
KS:0000 -> 18
KS:0000 -> 17
KS:0000 -> 16
KS:0000 -> 15
Failed to connect to wpa_supplicant - wpa_ctrl_open: No such file or directory
Failed to connect to wpa_supplicant - wpa_ctrl_open: No such file or directory
===>rt_ioctl_giwscan. 14(14) BSS returned, data->length = 2392
Failed to connect to wpa_supplicant - wpa_ctrl_open: No such file or directory
killall: wpa_supplicant: no process killed
rfkill: Cannot open RFKILL control device
P2P Font:CST_008
Use Web Port 80
NetIF : ra0
NetIF : ra0
ifconfig: SIOCSIFHWADDR: Operation not supported
ifconfig: SIOCSIFHWADDR: Operation not supported
route: SIOCADDRT: File exists
adding dns
adding dns
adding dns
adding dns
udhcpc: option -h NAME is deprecated, use -x hostname:NAME
udhcpc (v1.20.2) started
Sending discover...
[SAMPLE_RGN_ShowOrHide]-2896: HI_MPI_RGN_GetDisplayAttr (2)) failed with 0xa0038005!
[esntd_enc_do_osd_show]-2926: region(2) show failed with 0xffffffff!
[SAMPLE_RGN_ShowOrHide]-2896: HI_MPI_RGN_GetDisplayAttr (3)) failed with 0xa0038005!
[esntd_enc_do_osd_show]-2926: region(3) show failed with 0xffffffff!
To OPEN Audio Module LibName:(libhive_HPF.so)
To OPEN Audio Module LibName:(libhive_ANR.so)
To OPEN Audio Module LibName:(libhive_AGC.so)
To OPEN Audio Module LibName:(libhive_HPF.so)
To OPEN Audio Module LibName:(libhive_ANR.so)
To OPEN Audio Module LibName:(libhive_AGC.so)
===>rt_ioctl_giwscan. 15(15) BSS returned, data->length = 2623
PeerBeaconAtJoinAction(): HT-CtrlChannel=1, CentralChannel=>1
PeerBeaconAtJoinAction(): Set CentralChannel=1
Rcv Wcid(1) AddBAReq
Start Seq = 00000001
RTMP_TimerListAdd: add timer obj c2e26434!
===>rt_ioctl_giwscan. 15(15) BSS returned, data->length = 2623
Sending discover...
RTMP_TimerListAdd: add timer obj c2e25020!
===>rt_ioctl_giwscan. 15(15) BSS returned, data->length = 2584
Sending discover...
Rcv Wcid(1) AddBAReq
Start Seq = 00000005
Sending select for
Lease of obtained, lease time 6749
deleting routers
route: SIOCDELRT: No such process
default gw
adding dns
KS:0001 -> a3
KS:0000 -> 18
KS:0001 -> 65
KS:0002 -> 04
KS:0000 -> 0d
KS:0022 -> ca
KS:0023 -> 08
KS:0000 -> 0b
KS:0000 -> 0a
KS:0000 -> 09
KS:0001 -> 27
KS:0002 -> 06
KS:0000 -> 01
KS:0000 -> 00
KS:0001 -> 46
KS:0002 -> 05
KS:0000 -> 02
KS:0000 -> 01
KS:0000 -> 00
KS:0001 -> 65
KS:0002 -> 04
KS:0000 -> 02
KS:0000 -> 01

Unfortunately uboot is configured with 0 delay and I was unable to interrupt it to get into uboot shell. I tried spamming various combinations but none did the trick. Why would anyone want to protect this piece of garbage software.

On the other hand, I had full terminal access and could explore the file system. This is how the root looks like (remember what I told about garbage?):

total 85
-rwxr--r--    1     12800 Sep 17  2015 alm.wav
-rwxr--r--    1     21434 Aug 23  2016 ap_start.wav
drwxrwxr-x    2       957 Jun 13  2018 bin
drwxr-xr-x    2         3 Apr 19  2006 boot
-rwxr--r--    1      4624 Jun 28  2018 clock.wav
drwxrwxrwt    6      3520 Jul 24 07:53 dev
drwxr-xr-x    3       144 Sep  8  2018 esntd
drwxrwxrwt    6       340 Jul 24 07:56 etc
drwxr-xr-x    6       185 Jun 13  2018 etc_ro
drwxr-xr-x    3       641 Jun  8  2018 hiko
drwxr-xr-x    2         3 Apr 19  2006 home
drwxr-xr-x    2       704 Jun  8  2018 lib
lrwxrwxrwx    1        11 Jun 13  2018 linuxrc -> bin/busybox
drwxr-xr-x    2         3 Apr 19  2006 lost+found
-rwxr-xr-x    1      1341 Apr 21  2011 mkimg.rootfs
-rwxr-xr-x    1       431 Apr 21  2011 mknod_console
drwxr-xr-x    2         3 Apr 19  2006 mnt
drwxr-xr-x    2       316 Sep  8  2018 mylib
drwxr-xr-x    2         3 May 21  2008 nfsroot
drwxr-xr-x    2         3 Apr 19  2006 opt
dr-xr-xr-x   61         0 Jan  1  1970 proc
drwxr-xr-x    2         3 Mar 24  2016 root
drwxrwxr-x    2       712 Jul  2  2018 sbin
drwxr-xr-x    2         3 Mar 14  2016 sd
drwxr-xr-x    2         3 Apr 19  2006 share
dr-xr-xr-x   12         0 Jan  1  1970 sys
-rwxr--r--    1     22894 Aug 23  2016 sys_reset.wav
drwxrwxrwt    2        40 Jul 24 07:53 tmp
drwxrwxr-x    6        62 Jun  8  2018 usr
drwxrwxrwt    4       120 Jul 24 07:56 var
-rwxr--r--    1     21740 Aug 23  2016 wifi_ok.wav

After a bit of exploring, it seems that all relevant stuff is happening inside /esntd directory. It contains static web pages under /esntd/web and a 1.5MB /esntd/goahead binary which does pretty much everything.

At this point I got so frustrated that I was going to desolder the SPI chip and dump all the flash to fix the stupid bootloader delay. I have also seen multiple firmware variants for the Hi3518E SoC, which I thought would work and turn it into a proper ONVIF camera. However, after further digging I realised that chances of getting a different firmware to work would be slim (different camera sensors, wifi chips, etc).

Instead, I moved onto analysing that large binary. I got it out of the flash with ftpput utility, which was present in the busybox. I loaded it up in IDA and went skimming through the strings until I found something interesting:

It seems that the only proper stream format is microsoft ASF, which is not that bad. With little digging I could find the url and open the stream on VLC. The URL is http://camera/videostream.asf. It has some parameters such as resolution, rate and channel. The resolution parameter valid values are 8 – 320×240, 16 – 1280×720, 32 – 640×480, 64 – 1280×720. No 1080p resolution :<  The rate parameter doesn’t seem to have any effect and the channel parameter seems to be the same as resolution. You can also provide user and pwd parameters so it does not ask for http authentication like so: http://camera/videostream.asf?user=admin&pwd=&resolution=64

There are also some other CGI endpoints:

http://camera/snapshot.cgi – generates image snapshot

http://camera/get_ircfg.cgi – returns IR filter configuration:

var ir_low=100;
var ir_high=120;
var ir_curr=4;
var ir_status=1;
var ir_disabled=0;
var ir_timer=0;

You can set these values like so: http://camera/set_ircfg.cgi?ir_disabled=1. I assume that ir_low and ir_high parameters are for automatic ir filter switching, but I could not get that to work. I could only control it manually via ir_disabled.

Other endpoints can be easily sniffed via chrome network tools or by analysing the binary.

Bottom line: you are better off buying an IP camera module like this which has a proper ONVIF and RTSP support.

4 thoughts on “Hacking Chinese Mini IP Camera”
  1. Hi,

    I have a chinese IP camera as well. I have access to it using telnet and I have basic controls. However, a lot of the commands seem to have been stripped out, a lot of it seems to be read only, I can’t find what is sending the video and I don’t have a serial connection. Looking at your blog above, looks like you are quite the expert!

    So, I was wondering if you could point me in the right direction for some of my issues. eg how did you determine where the serial connection was and how can I tell where the video is being sent from? I’ve been through the directories a number of times but haven’t found anything conclusive.


    1. Hi,

      Serial port is usually exposed as a connector or test points like in this case. Finding it is easiest by poking various points with oscilloscope and looking for serial-like signal. If you don’t have one, you can just try poking with serial adapter RX line, if you see some garbage data – try different baud rates.

      I couldn’t figure out what was used for encoding and serving video (didn’t try much). I found these endpoints by a combination of other blog posts/forums and looking ant firmware binary strings.

      You could also try ONVIF manager as some cameras support this protocol. It gives you a list of supported streams with URLs. https://sourceforge.net/projects/onvifdm/

      1. thanks for the info. I found the serial ports but, because they were so small and close together, I managed to blow the board with my soldering.


        1. Hi,

          I bought another camera, same as the one I bricked. I have successfully connected to the serial port and it has a uboot countdown that I can interrupt. So, I think I have access to what you called the uboot shell. However, having done that, I’m now a bit clueless as to what the next step is.

          What I want to do is ‘replace’ the crap app that came with the camera and stream and record the video to a better app or a browser, with controls. Would you be able to help me understand the code and change it as required?


Leave a Reply

Your email address will not be published. Required fields are marked *