The cuckoo's nest

Part 1 - Getting startedTop

I've recently purchased a Wi-Fi/Ethernet surveillance camera from the usual Chinese sources. The camera is based on XiongMai software, notorious for its lack of security.

Web interfaceTop

The camera exposes a web interface, which greets us with a message "Your browser is too new, Some features will not work properly. Please download 51.0 or earlier". Afterwards, it attempts to load an ActiveX control. No way I'm going to run it.

Getting videoTop

ffplay rtsp://admin:@IPADDR/

You can see the camera stream with the above command. The stream is 1920x1080 by default, I don't know how to enable the full 5MP resolution (assuming the sensor is actually 5MP).

What's insideTop

There's a small PCB in the fixed camera base, hosting, among other components, a USB-to-WiFi chip and Ethernet magnetics. A flexible ribbon and some other cables run through the pan/tilt mechanism to the camera PCB.

This is the main PCB hosting the camera sensor, main SoC, SPI flash chip and some other components. The pictures also show my jumper cables soldered to the UART header - that's the obvious unpopulated four-pin header on the board. The SoC markings, not visible on the photo, are: 30WX1 96__201216.

I've routed the UART cables to the microSD socket area, which is accessible through an opening in the case. Note - don't try to use hot-melt glue inside, the heat from the electronics will melt it away in minutes. Ask me how I know :)

U-BootTop

This is the UART output shown when the camera boots up:

U-Boot 2014.04 (Jul 06 2020 - 19:39:51)

CPU: XM530
WDT: 300S
DRAM:  64 MiB
MMC:   arasan: 0
In:    serial
Out:   serial
Err:   serial
Net:   dwmac.10010000
Press Ctrl+C to stop autoboot
SF: 1572864 bytes @ 0x40000 Read: OK
## Booting kernel from Legacy Image at 80007fc0 ...
   Image Name:   Linux-3.10.103+
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1548688 Bytes = 1.5 MiB
   Load Address: 80008000
   Entry Point:  80008000
   XIP Kernel Image ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.

This indicates that the SoC is called XM530, and the board runs Linux (as would be expected). I couldn't find any traces of kernel sources for this SoC, which is a blatant GPL violation, but that's not really a surprise.

Dumping the flashTop

I could have just dumped the SPI flash while I had the camera opened, but I didn't have my SO8 clip on hand, so I decided to dump it from U-Boot instead.

Others have managed to use the tftp command to transfer data from the board over Ethernet, but in my case, the tftp command was not available. What was available was the UART. So I did something like this:

U-Boot> sf read 80008000 0 800000 # read full flash contents
SF: 8388608 bytes @ 0x0 Read: OK
U-Boot> md.l 80008000 200000 # and dump it all through the uart
80008000: ea00000f e59ff014 e59ff014 e59ff014    ................
80008010: e59ff014 e59ff014 e59ff014 e59ff014    ................
80008020: 080000e0 08000140 080001a0 08000200    ....@...........
80008030: 08000260 080002c0 08000320 12345678    `....... ...xV4.
80008040: 0badc0de eb000014 e10f0000 e200101f    ................
80008050: e331001a 13c0001f 13800013 e38000c0    ..1.............
80008060: e129f000 ee110f10 e3c00a02 ee010f10    ..).............
80008070: e59f02f0 ee0c0f10 eb000008 eb000015    ................

And after about an hour, I've had the full hexdump of the flash logged on my PC.

UART access under LinuxTop

The most obvious problem is the lack of kernel boot messages. In a thread on ipcamtalk.com people have said that setting the U-Boot environment variable 'xmuart' to 0 would enable the UART under Linux. Unfortunately, this version of U-Boot silently ignores any attempts to change this variable (also as discussed here).

But maybe we could somehow trick U-Boot? After all, we have full access to the RAM using md and mw. U-Boot is loaded at an address indicated by bdinfo

U-Boot> bdinfo
arch_number = 0x000022B8
boot_params = 0x80000100
DRAM bank   = 0x00000000
-> start    = 0x80000000
-> size     = 0x04000000
eth0name    = dwmac.10010000
ethaddr     = 00:12:41:ce:28:6c
current eth = dwmac.10010000
ip_addr     = 192.168.1.10
baudrate    = 115200 bps
TLB addr    = 0x83FF0000
relocaddr   = **0x83F96000**
reloc off   = 0x7BF96000
irq_sp      = 0x83B85F40
sp start    = 0x83B85F30
U-Boot> md.b 0x83F96000 20000
83f96000: 0f 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5    ................
83f96010: 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5    ................
83f96020: e0 60 f9 83 40 61 f9 83 a0 61 f9 83 00 62 f9 83    .`..@a...a...b..
83f96030: 60 62 f9 83 c0 62 f9 83 20 63 f9 83 78 56 34 12    `b...b.. c..xV4.

...

83fb3950: 6d 65 6e 74 0a 00 0a 53 74 61 72 74 69 6e 67 20    ment...Starting 
83fb3960: 6b 65 72 6e 65 6c 20 2e 2e 2e 25 73 0a 0a 00 62    kernel ...%s...b
83fb3970: 6f 6f 74 61 72 67 73 00 78 6d 75 61 72 74 00 78    ootargs.xmuart.x
83fb3980: 6d 61 75 74 6f 00 4e 55 4c 4c 00 65 74 68 61 64    mauto.NULL.ethad
83fb3990: 64 72 00 48 57 49 44 00 52 65 73 65 74 74 69 6e    dr.HWID.Resettin

... ok, this was the interesting part. Let's change this a bit.

U-Boot> mw.b 83fb3978 41
U-Boot> md.b 83fb3970 10
83fb3970: 6f 6f 74 61 72 67 73 00 41 6d 75 61 72 74 00 78    ootargs.Amuart.x

With this simple change U-Boot will filter writes to "Amuart" instead - so we can now freely alter the xmuart variable.

U-Boot> setenv xmuart 0
U-Boot> printenv xmuart
xmuart=0

Note that the xmuart variable needs to be saved to flash, Linux apparently reads it back from flash instead of having the value passed from U-Boot. Note that U-Boot will look at the same in-memory string when passing the parameter to Linux, so you need to either save the updated environment to flash (saveenv) and reboot (to restore the unmodified U-Boot image), or restore the 'x' before running bootcmd, as shown below.

U-Boot> mw.b 83fb3978 78
U-Boot> run bootcmd
SF: 1572864 bytes @ 0x40000 Read: OK
## Booting kernel from Legacy Image at 80007fc0 ...
   Image Name:   Linux-3.10.103+
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1548688 Bytes = 1.5 MiB
   Load Address: 80008000
   Entry Point:  80008000
   XIP Kernel Image ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 3.10.103+ (wangzhuowei1@xm) (gcc version 4.9.2 (Buildroot 2014.08) ) #2 SMP Mon Jun 22 17:18:36 CST 2020
CPU: ARMv7 Processor [410fc051] revision 1 (ARMv7), cr=10c53c7d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine: xm530

... and lots and lots of output ...

That's better.

I haven't managed to log into the system yet. The root password in the flash dump is "xmhdipc", but the login prompt doesn't accept this. You can get a shell to browse a bit by appending init=/bin/sh to bootargs in U-Boot.

UPDATE This is solved in part 2