-
Laugh-out-loud shipping ingenuity
01/18/2017 at 21:09 • 2 commentsThe ProMark website listed replacement parts such as an extra battery and spare blades but no way to order them. An email to their support line went unanswered. After finding that the ProMark drone seemed to share at least a mechanical similarity to a Syma drone I went to a website carrying Syma products and ordered an extra battery and some spare blades. They arrived last night.
The battery came packaged in a fully functional toy police car with instructions to take apart the car to get the battery. Literally just stuffed in the empty space inside the car (which motors around, making noises and blinking its LED headlights just fine on a pair of AA batteries). No doubt this is to get around shipping restrictions for LiPo batteries. I thought it was really funny and kinda clever. -
Wireshark to the rescue / figuring out a UDP data stream
01/16/2017 at 07:11 • 0 commentsI guessed that the phone app opened some sort of socket communication channel with the "aircraft-ctl" program running on the camera board. I figured the thing to do was to try to capture the packet stream between the camera and app and then find out the packets associated with the controls. I started with Wireshark running on my Mac with the Mac connected to the camera's WiFi network. Even though I had selected promiscuous mode, I got nothing of interest initially. I figured the Mac's WiFi interface couldn't see packets that weren't related to it's traffic. So I went looking for apps to run on the phone itself and found tPacketCapture. It looked promising and I did some experiments with it. It acts as a proxy to capture all network traffic in and out of the phone and generates a pcap file that can be viewed by Wireshark. Unfortunately it slowed down network traffic (not entirely sure why - perhaps my phone is too slow) and I ended up losing a lot of packets and couldn't really make heads or tails of the data except to suspect that the app was sending UDP packets with the control information to port 8080 on the camera (my earlier prediction of a TCP telnet-like service was wrong). But UDP made sense since the app might just stream the packets like many simple remote controls and the loss of a few packets here or there wouldn't matter (just like a traditional RF remote control). Back to the drawing board (google...) and I was able to ascertain that the WiFi interface on my Mac did, in-fact, support a monitor mode which could be enabled in Wireshark to see all WiFi traffic. I enabled it and success! I saw all communication with the camera board. Sorting on UDP packets yielded a constant stream of 11-byte packets to port 8080 whenever the app on-screen controls were enabled. Control packets seem to be sent on approximately 25 mSec intervals and simply represent the state of the controls when they are set (e.g. bits might remain set as long as an on-screen button is pressed).
I displayed the serial data from the camera board in a CoolTerm window and then set about methodically capturing the packets as I manipulated only one control at a time. This way I could more easily associate changing data in the UDP packet with the serial data sent from the camera to the drone's controller. I ended up generating 16 different captures (my notes with some raw data analysis at the end of this log entry) and was able to figure out the basic format of the UDP packet.11 byte UDP packets: (about every 25 mSec) Bytes 0:1 = 0xff04 which seem constant Byte 2 = Throttle (8-bit values 0x00 - 0xFF). Directly output in serial stream. Byte 3 = Rotate Left/Right (7-bit value 0x00 - 0x7F, center 0x3F). Remapped around 0x80 on serial. Byte 4 = Forward/Backward pitch (7-bit value 0x80 - 0xFF, center 0xC0). Remapped around 0x80 on serial. Byte 5 = Left/Right pitch (7-bit value 0x00 - 0x7F, center 0x3F). Remapped around 0x80 on serial. Byte 6 = Rotate Trim (5- or 6-bit value 0x00 - 0x1F or 0x20, center 0x10). Added or subtracted from Rotate value. Bit 7 indicates takeoff/landing controls displayed. Byte 7 = Forward/Backward trim (6-bit value 0x20 - 0x00, center 0x10). Added or subtracted from Forward/Backward pitch. Byte 8 = Left/Right trim (6-bit value 0x00 - 0x20, center 0x10). Added or subtracted from Left/Right pitch. Byte 9 = Flags Bit 7: Set initially when either takeoff or landing pressed Bit 6: Set after bit 7 for takeoff Bit 5: Emergency stop (bit 7 is also set) Bit 4: Bit 3: Bit 2: Normal/Headless Bit 1:0: Speed Model 00 : 30% 01 : 60% 10 : 100% 11 : Unused Byte 10: Checksum (added to bytes 1-9 = 0xFF)
Questions remain about the header byte values. Is that a fixed value or could different header bytes (especially byte 1 : 0x04 - since it is included in the Checksum) have additional packet information? What, if anything, do the unused bits in the trim bytes and flag byte mean?
Most UDP data was directly mapped (potentially shifted) to the serial data stream. However the Speed Model seems to affect the mapping of control data to serial data, perhaps exponentially. The faster the Speed Model, the faster the serial data changes (less fine control).
Probably a follow-on activity is to write a program on the computer to open a UDP socket connection with the camera board and make sure that I can send bytes to control the output. This might make it easier to figure out what the unknown bits do. Interestingly, at this point, the camera board could be used as a controller for some other project, like a remote-controlled car with video feed, or simply a webcam with servo pan/tilt. Both would require some external controller to take the serial data stream and control the motors or servos but this is something an arduino or other 8-bit micro could easily handle.
Data Format Analysis: Line 1: Wireshark UDP -> port 8080: ff04003fc03f101010008d Line 2: Serial Output —data without header or checksum bytes— - Wireshark packet is 8 bytes long - Serial packet is 5 bytes long controls displayed -> takeoff/landing displayed -> takeoff -> takeoff/landing undisplayed -> controls undisplayed 00 3F C0 3F 10 10 10 00 80 80 00 80 00 7E 3F C0 3F 90 10 10 00 80 80 7E 80 40 7E 3F C0 3F 90 10 10 80 80 80 7E 80 42 7E 3F C0 3F 90 10 10 40 80 80 7E 80 41 00 3F C0 3F 10 10 10 00 80 80 00 80 00 controls displayed —> throttle up then down —> controls undisplayed 00 3F C0 3F 10 10 10 00 80 80 00 80 00 00 42 C0 3F 10 10 10 00 00 43 C0 3F 10 10 10 00 00 43 C0 3F 10 10 10 00 00 43 C0 3F 10 10 10 00 00 43 C0 3F 10 10 10 00 04 44 C0 3F 10 10 10 00 0A 43 C0 3F 10 10 10 00 14 43 C0 3F 10 10 10 00 1A 42 C0 3F 10 10 10 00 26 41 C0 3F 10 10 10 00 2C 41 C0 3F 10 10 10 00 38 41 C0 3F 10 10 10 00 3E 41 C0 3F 10 10 10 00 4C 41 C0 3f 10 10 10 00 54 42 C0 3F 10 10 10 00 … up to F2 45 C0 3F 10 10 10 00 … down to 00 3F C0 3F 10 10 10 00 ^ +— Throttle Serial Output: 80 80 TT 80 00 where TT is throttle with sequence: 26 2C 38 3E 4C 54 … F2 … 00 controls displayed —> takeoff/land displayed —> rotate left then right then center —> controls undisplayed 00 3F C0 3F 10 10 10 00 80 80 00 80 00 7E 3F C0 3F 90 10 10 00 80 80 7E 80 40 TT RR C0 3F 90 10 10 00 80 80 TT RR 40 TT = Throttle RR = Rotate (many more UPD packets than serial packets) RR went essentially between 00 - 7F (7E) 7E 3F C0 3F 90 10 10 00 80 80 7E 80 40 controls displayed —> Left trim left (trim associated with rotate) -> controls undisplayed 00 3F C0 3F 10 10 10 00 80 80 00 80 00 00 3F C0 3F 0F 10 10 00 00 3F C0 3F 0E 10 10 00 … 00 3F C0 3F 00 10 10 00 ==> 80 80 00 80 00 … 80 80 00 70 00 up to 00 3F C0 3F 1F 10 10 00 for 80 80 00 8F 00 controls displayed —> right/left pitch —> controls undisplayed 00 3F C0 PP 10 10 10 00 PP went essentially between 00 - 7F (7E) PP 80 00 80 00 PP went between 41 and BE controls displayed —> right/left trim —> controls undisplayed 00 3F C0 3F 10 10 TT 00 TT went between 00 and 20 TT 80 00 80 00 TT went from 70 to 90 controls displayed —> forward/backward pitch —> controls undisplayed 00 3F PP 3F 10 10 10 00 PP went essentially between 80 (81) - FF 80 PP 00 80 00 PP went from BE - 41 controls displayed —> forward/backward trim —> controls undisplayed 00 3F C0 3F 10 TT 10 00 TT went between 20 - 00 80 TT 00 80 00 TT went from 90 - 70 controls displayed —> normal/headless toggled —> controls undisplayed 00 3F C0 3F 10 10 10 00 80 80 00 80 00 00 3F C0 3F 10 10 10 04 80 80 00 80 20 00 3F C0 3F 10 10 10 00 80 80 00 80 00 controls displayed —> emergency stop —> controls undisplayed (emergency stop “sticks” set on app) 00 3F C0 3F 10 10 10 00 80 80 00 80 00 00 3F C0 3F 10 10 10 A0 80 80 00 80 80 controls displayed —> takeoff/land displayed —> land —> controls undisplayed 00 3F C0 3F 10 10 10 00 80 80 00 80 00 7E 3F C0 3F 90 10 10 00 (takeoff/land displayed) 80 80 7E 80 40 7E 3F C0 3F 90 10 10 80 80 80 7E 80 42 controls displayed -> gravity sense Mode toggled -> controls undisplayed No change controls displayed -> speed model toggled through settings —> controls undisplayed 00 3F C0 3F 10 10 10 00 (default 30% speed model) 00 3F C0 3F 10 10 10 01 (60% speed model) 00 3F C0 3F 10 10 10 02 (100% speed model) No change on serial out controls displayed -> snapshot —> start video —> stop video —> controls undisplayed No change additional testing with speed model: controls displayed —> throttle up ~ 50% —> speed model toggled through settings -> controls undisplayed 6E 3F C0 3F 10 10 10 00 (throttle to ~50%, default 30% speed model) 80 80 6E 80 00 6E 3F C0 3F 10 10 10 01 (60% speed model) 80 80 6E 80 00 6E 3F C0 3F 10 10 10 02 (100% speed model) 80 80 6E 80 00 additional testing with speed model = 100% -> throttle up/down -> rotate left/right —> tilt left/right —> tilt forward/backward -> controls undisplayed Th Ro FB LR th fb lf fl Throttle: FA - 0A (serial: goes 00 - 68 in one step then up to FA down to 24 then to 00 in one step) Rotate: 01 - 7E (serial: goes 80 - 3a in one step then to 02 up to FC with big steps) Left/Right: 01 - 7D (serial: goes 80 - 5C in one step then to 02 up to FA with big steps) Forward/Backward: 82 - FF (serial: goes 80 - A2 in one step then to FA down to 01 in big steps) Larger speed model seems to make a guard band around center-point but quickly decrease/increase values to limits) - maybe just makes control more sensitive (e.g. exponential multiplier)
-
Comm protocol between camera and drone controller
01/12/2017 at 03:31 • 1 commentInitially I thought the data stream from the camera board to the quadcopter controller was PPM. This signal is only active when the app is running and the on-screen controls are brought up. The quadcopter has to be power-cycled in order to be controlled by the RF remote again. However a closer look at the signal as the on-screen controls were manipulated hinted that it was a serial stream instead. This makes some sense. The HI3518 has two serial ports and it would certainly be easier to ship a set of bytes of a serial port than generate a PPM data stream. A complete frame, shown below, takes about 4.06 mSec.
The period between frames is about 25 mSec although it seemed to vary a bit.
The smallest "bit" period in the frame is about 52 uSec which implies a bit rate of 19,200 baud and an 8-byte packet. Sure enough connecting the signal to the USB serial converter and a 19.2 kBaud 8N1 terminal connection yielded what looked like good data. Even better data seemed to be byte aligned and I saw direct changes when I manipulated the on-screen controls. What follows are the notes I took while associating data with control action. At the end is my guess as to what each byte means. The trim controls simply seem to add a small + or - offset to the actual control value. The start-byte and end-byte sum to 0xFF and the remaining bytes are protected by a XOR checksum.Some bytes were repeated while the control was being touched. I am wondering now if the application just opens a simple telnet-like port connection with the camera board (perhaps on port 8080) and sends these bytes straight through (ala a remote serial connection). Next up will be to try to suss out the network traffic between the application and camera board.
Upon boot: ??? FF 69 6E 69 74 20 6F 6B 0A CC 80 80 00 80 00 80 33 66… Upon app connection: ??? 66 80 80 00 80 00 80 99 Upon app controls: CC 80 80 00 80 00 80 33 66 80 80 00 80 00 80 99 (repeated) Launch: CC 80 80 7E 80 40 BE 33 66 80 80 7E 80 40 BE 99 (repeated when takeoff/land displayed) CC 80 80 7E 80 42 BC 33 66 80 80 7E 80 42 BC 99 (repeated 6 times when takeoff pressed) CC 80 80 7E 80 41 BF 33 66 80 80 7E 80 41 BF 99 (repeated 59 times - maybe while press) CC 80 80 7E 80 40 BE 33 66 80 80 7E 80 40 BE 99 Land: CC 80 80 7E 80 40 BE 33 66 80 80 7E 80 40 BE 99 CC 80 80 7E 80 42 BC 33 66 80 80 7E 80 42 BC 99 (repeated 62 times - maybe while press) CC 80 80 00 80 00 80 33 66 80 80 00 80 00 80 99 (repeated after controls removed) Throttle up: CC 80 80 00 80 00 80 33 66 80 80 00 80 00 80 99 CC 80 80 26 80 00 A6 33 66 80 80 2E 80 00 AE 99 CC 80 80 44 80 00 C4 33 66 80 80 4E 80 00 CE 99 CC 80 80 64 80 00 E4 33 66 80 80 7E 80 00 FE 99 CC 80 80 86 80 00 06 33 66 80 80 96 80 00 16 99 CC 80 80 A0 80 00 20 33 66 80 80 B2 80 00 32 99 CC 80 80 B8 80 00 38 33 66 80 80 C8 80 00 48 99 CC 80 80 D0 80 00 50 33 66 80 80 D4 80 00 54 99 CC 80 80 DC 80 00 5C 33 66 80 80 E0 80 00 60 99 CC 80 80 EA 80 00 6A 33 66 80 80 EE 80 00 6E 99 CC 80 80 F6 80 00 76 33 66 80 80 F8 80 00 78 99 CC 80 80 FC 80 00 7C 33 66 80 80 FC 80 00 7C 99 Throttle left/right: CC 80 80 78 80 00 F8 33 66 80 80 78 C0 00 B8 99 CC 80 80 78 C0 00 B8 33 66 80 80 78 C2 00 BA 99 … CC 80 80 86 E6 00 60 33 66 80 80 88 E4 00 6C 99 (max right although real max seems FC) … CC 80 80 74 01 00 75 33 66 80 80 74 01 00 75 99 (min left) Right Stick up/down: CC 8B BD 88 80 00 3E 33 66 8B BB 88 80 00 38 99 (up) CC 80 41 88 80 00 C9 33 66 80 41 88 80 00 C9 99 (down) Right Stick left/right: CC AE 74 00 80 00 5A 33 66 B5 74 00 80 00 41 99 (right) CC 53 80 00 80 00 53 33 66 53 80 00 80 00 53 99 (left) Normal/Headless button: CC 80 80 00 80 20 A0 33 66 80 80 00 80 20 A0 99 Right Trim Throttle twice (from center): CC 80 80 00 82 00 82 33 66 80 80 00 82 00 82 99 Left Trim Throttle once (from center): CC 80 80 00 7F 00 7F 33 66 80 80 00 7F 00 7F 99 CC 80 80 00 75 00 75 33 66 80 80 00 75 00 75 99 (left a bunch) Right Trim Right Stick: CC 83 80 00 80 00 83 33 66 83 80 00 80 00 83 99 (several clicks) Left Trim Right Stick all the way: CC 70 80 00 80 00 70 33 66 70 80 00 80 00 70 99 Up Trim Right Stick: CC 80 81 00 80 00 81 33 66 80 81 00 80 00 81 99 (one click) CC 80 90 00 80 00 90 33 66 80 90 00 80 00 90 99 (all the way) Down Trim Right Stick: CC 80 7F 00 80 00 7F 33 66 80 7F 00 80 00 7F 99 (one click) CC 80 70 00 80 00 70 33 66 80 70 00 80 00 70 99 (all the way) Emergency Stop: CC 80 80 00 80 80 00 33 66 80 80 00 80 80 00 99 Gravity Sense Mode: no change? Speed Mode: no change? Photo/Recording: no changes Byte Order Guess: Byte 0: Start of packet: CC (0x11001100) or 66 (0x01010101) Byte 1: Right/Left pitch Byte 2: Forward/Backward pitch Byte 3: Throttle Byte 4: Right/Left rotate Byte 5: Flags bit 7: Emergency Stop bit 6: Takeoff/Landing Mode (controls displayed) bit 5: Normal/Headless bit 4: bit 3: bit 2: bit 1: Set initially when either takeoff or landing pressed bit 0: Set after bit 1 for takeoff Byte 6: XOR Checksum of Bytes 1-5 Byte 7: End of packet: 33 (0x00110011) or 99 (0x10011001)
-
Connecting to Linux
01/10/2017 at 06:42 • 0 commentsThe Android app "Fing" provided a list of the services available on the Linux camera ports (one could have used nmap on a computer):
- 23 telnet
- 80 http
- 554 rtsp
- 8080 http-proxy
Telnetting to the device from my Mac gave me a login prompt but as I described in the previous post, there was no login possible because no users are enabled.
The HTTP server helpfully serves up a simple page designed to load new firmware (which there appears, currently, to be none - in fact the ProMark website is strange. It exists but things like the pages to order replacement parts like propellers and batteries have no prices or links to actually buy anything - which makes one wonder if the company really still exists...or only existed for one Christmas season).
I could get nothing at the 8080 port but was more interested to see if I could find a way to stream video from the board. Many, many hours later I was able to figure out the following way to watch real-time video using VLC. The intermediate time was spent with Wireshark watching packets on my Mac between the board and my android phone and *a lot* of googling. A hint from the wireshark log agreed with Fing that there was a RTSP video stream.rtsp://192.168.0.1:554/0 RTSP/1.0\r\n URL rtsp://192.168.0.1/0/track1
So finally I was able to watch the camera's output in VLC with the following URL for VLC (it seems so simple written here, but there were hours of my befuddled thinking before....):
rtsp://192.168.0.1/0
-
UBoot experiments
01/10/2017 at 05:52 • 0 commentsProMark helpfully left a second's worth of delay in UBoot before staring the boot process available on the serial port. This meant I could get a UBoot prompt and output the machine's environment variables which show some interesting information (the output of "printenv" shown at the end of this post). It also meant I could try to boot into a single-user prompt which I was ultimately able too after a bunch of experimenting and a friend's helpful suggestion to watch some master's manipulation of UBoot on youtube. The trick for this device is to set "flashargs" as shown below to boot into /bin/sh.
setenv flashargs ‘run commonargs; set bootargs ${bootargs} root=${flashroot} rootfstype=${flashrootfstype} noinitrd init=/bin/sh’ boot
I also changed the boot delay to 3 seconds to make it easier to interrupt the boot process (which is simply sending some character via the console serial port). "saveenv" writes the changes permanently to the flash memory (as opposed to the change I made above to flashargs which does not persevere over a power-cycle).setenv bootdelay 3 saveenv
The system uses busybox to provide most functions including "cat". I took a look at /etc/passwd from the single-user prompt and was disappointed. The system allows no logins, whatsoever, even though it allows a telnet connection and provides a login on the serial port. Score one for the security conscious developers at ProMark. Here's the contents of the /etc/passwd file from the single-user prompt (all the way from setting the UBoot environment variable "flashargs" through the boot and cat of /etc/passwd):
ipcam # setenv flashargs 'run commonargs; set bootargs ${bootargs} root=${flashroot} rootfstype=${flashrootfstype} noinitrd init=/bin/sh' ipcam # printenv flashargs flashargs=run commonargs; set bootargs ${bootargs} root=${flashroot} rootfstype=${flashrootfstype} noinitrd init=/bin/sh ipcam # boot Booting from SPI Flash... 8192 KiB hi_sfc at 0:0 is now current device ## Booting kernel from Legacy Image at 81000000 ... Image Name: Linux-3.0.8 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1723048 Bytes = 1.6 MiB Load Address: 80008000 Entry Point: 80008000 Loading Kernel Image ... OK OK Starting kernel ... Uncompressing Linux... done, booting the kernel. Linux version 3.0.8 (root@hiber) (gcc version 5.2.0 (Buildroot 2015.11.1) ) #4 Thu Aug 25 05:42:37 EDT 2016 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. Built 1 zonelists in Zone order, mobility grouping on. Total pages: 10160 Kernel command line: mem=40M mmz=24M console=ttyAMA0,115200n8 mtdparts=hi_sfc:512k(uboot)ro,256k(uboot-env),256k(mfd),3m(kernel),4m(rootfs) hieth.mdioifu=1 hieth.mdioifd=1 hieth.phyaddru=0 hieth.phyaddrd=1 root=/dev/mtdblock4 rootfstype=squashfs,jffs2 noinitrd init=/bin/sh 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: 40MB = 40MB total Memory: 35852k/35852k available, 5108k reserved, 0K highmem Virtual kernel memory layout: vector : 0xffff0000 - 0xffff1000 ( 4 kB) fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB) DMA : 0xffc00000 - 0xffe00000 ( 2 MB) vmalloc : 0xc3000000 - 0xfe000000 ( 944 MB) lowmem : 0xc0000000 - 0xc2800000 ( 40 MB) modules : 0xbf000000 - 0xc0000000 ( 16 MB) .init : 0xc0008000 - 0xc0027000 ( 124 kB) .text : 0xc0027000 - 0xc044b000 (4240 kB) .data : 0xc044c000 - 0xc047d740 ( 198 kB) .bss : 0xc047d764 - 0xc0496d70 ( 102 kB) SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 NR_IRQS:128 nr_irqs:128 128 sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 42949ms Calibrating delay loop... 218.72 BogoMIPS (lpj=1093632) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 512 CPU: Testing write buffer coherency: ok devtmpfs: initialized 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 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. 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 70 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 Spi id table Version 1.22 Spi(cs1) ID: 0xEF 0x40 0x17 0x00 0x00 0x00 SPI FLASH start_up_mode is 3 Bytes Spi(cs1): Block:64KB Chip:8MB Name:"W25Q64FV" spi size: 8MB chip num: 1 5 cmdlinepart partitions found on MTD device hi_sfc Creating 5 MTD partitions on "hi_sfc": 0x000000000000-0x000000080000 : "uboot" 0x000000080000-0x0000000c0000 : "uboot-env" 0x0000000c0000-0x000000100000 : "mfd" 0x000000100000-0x000000400000 : "kernel" 0x000000400000-0x000000800000 : "rootfs" Fixed MDIO Bus: probed himii: probed RTL871X: module init start RTL871X: rtl8188eu v4.3.24_16705.20160509 RTL871X: build time: Aug 25 2016 05:41:55 usbcore: registered new interface driver rtl8188eu RTL871X: module init ret=0 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 sp805-wdt dev:wdog: registration successful TCP cubic registered NET: Registered protocol family 10 IPv6 over IPv4 tunneling driver NET: Registered protocol family 17 registered taskstats version 1 .VFS: Mounted root (squashfs filesystem) readonly on device 31:4. devtmpfs: mounted Freeing init memory: 124K usb 1-1: new high speed USB device number 2 using hiusb-ehci /bin/sh: can't access tty; job control turned off / # bFWReady == _FALSE call reset 8051... RTL871X: hal_com_config_channel_plan chplan:0x08 RTL871X: rtw_ndev_init(wlan0) if1 mac_addr=00:0a:e2:1f:49:59 / # / # cat /etc/passwd root:x:0:0:root:/root:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/false bin:x:2:2:bin:/bin:/bin/false sys:x:3:3:sys:/dev:/bin/false sync:x:4:100:sync:/bin:/bin/sync mail:x:8:8:mail:/var/spool/mail:/bin/false www-data:x:33:33:www-data:/var/www:/bin/false operator:x:37:37:Operator:/var:/bin/false nobody:x:99:99:nobody:/home:/bin/false dbus:x:1000:1000:DBus messagebus user:/var/run/dbus:/bin/false / #
The system filesystem is booted into a Read-only state so modifying files during runtime is not possible. This means that we have to either modify them on the SPI flash chip (the HI3518 boots from an 8-pin SPI flash chip) or upload a modified firmware update (which, sadly, ProMark seems to have none of...). Since I don't have access to Wifi (yet?) from single-user prompt then right now the only possibility seems to be to offload the SPI chip and then modify the data before reprogramming it (a chore...). Perhaps later or sooner if some expert gives me some advice...
Output of UBoot "printenv":ipcam # printenv bootargs=mem=40M console=ttyAMA0,115200 bootcmd=run autoboot bootdelay=1 baudrate=115200 ethaddr=00:00:23:34:45:66 ipaddr=192.168.1.10 serverip=192.168.1.2 preboot=mw 200f000c 0; mw 20150400 10; mw 20150040 10 rootpath=/tftpboot/hi3518/rootfs gatewayip=192.168.1.1 netmask=255.255.255.0 bootfile=hi3518/uImage loadaddr=0x81000000 mdio_intf=rmii phyaddru=0 phyaddrd=1 meminfo=mem=40M mmzinfo=mmz=24M console=ttyAMA0,115200n8 netdev=eth0 nfsopts=hard,tcp,vers=3 hieth=hieth.mdioifu=1 hieth.mdioifd=1 hieth.phyaddru=0 hieth.phyaddrd=1 flashroot=/dev/mtdblock4 flashrootfstype=squashfs,jffs2 mtdparts=hi_sfc:512k(uboot)ro,256k(uboot-env),256k(mfd),3m(kernel),4m(rootfs) commonargs=setenv bootargs ${meminfo} ${mmzinfo} console=${console} mtdparts=${mtdparts} ${hieth} flashargs=run commonargs; set bootargs ${bootargs} root=${flashroot} rootfstype=${flashrootfstype} flashboot=echo Booting from SPI Flash...; run flashargs; sf probe 0 && sf read ${loadaddr} 0x100000 0x300000 && bootm nfsargs=run commonargs; setenv bootargs ${bootargs} root=/dev/nfs nfsroot=${serverip}:${rootpath},${nfsopts} addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off nfsboot=run nfsargs; run addip; tftp ${loadaddr} ${bootfile} && bootm ${loadaddr} serialboot=echo Booting from serial (Y-MODEM)...; run commonargs; loady && bootm autoboot=if run flashboot; then; else run serialboot; fi sensor_type=gc1014 hwmode=g mLwFlg=0 wifi_channel=2 ssid=P70-VR Mirror=1 stdin=serial stdout=serial stderr=serial verify=n ver=U-Boot 2010.06 (Jul 26 2016 - 01:40:47) Environment size: 1587/65531 bytes ipcam #
-
Linux in a toy
01/10/2017 at 04:52 • 0 commentsThe first part of the drone I took apart was the camera. It is a complete linux machine based on the HiSilicon HI3518 ARM SOC that usually finds a home in Web Cams along with a USB-connected WiFi module and a 4-wire connection to the Drone itself. It was fairly easy to figure out that two wires were power (GND and 3.3 volts), one wire was a GPIO trigger from the drone (via it's dedicated remote control to take a picture or start a video) and one wire was control data from the app to control the drone itself. I initially assumed that data was traditional PPM but later analysis showed it was a serial stream. I found two test points which I correctly surmised where a serial port was was rewarded with 115,200 baud 8N1 goodness when they were connected to a 3.3V FTDI 230X USB-serial interface.
It seems that this board is essentially a web-cam with an additional process added to allow it to control a quad-copter. It seems that this chip is used in a lot of "cheap" web-cams that have lots of potential exploits including hardwired login credentials. I found lists of username/password combinations online that various security researchers had found on a lot of products. I tried them all without any success. It turns out that the ProMark people are a little more security conscious but I didn't know that at this point in the reverse engineering process.
Interesting aside: The board runs at between 300-400 mA at 3.3V when no-one is connected. It takes around 500 mA when someone is connected and above 600 mA when streaming video.U-Boot 2010.06 (Jul 26 2016 - 01:40:47) Check spi flash controller v350... Found Spi(cs1) ID: 0xEF 0x40 0x17 0x00 0x00 0x00 Spi(cs1): Block:64KB Chip:8MB Name:"W25Q64FV" In: serial Out: serial Err: serial uboot version:2.0.2 Hit any key to stop autoboot: 1 ... 0 Booting from SPI Flash... 8192 KiB hi_sfc at 0:0 is now current device ## Booting kernel from Legacy Image at 81000000 ... Image Name: Linux-3.0.8 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1723048 Bytes = 1.6 MiB Load Address: 80008000 Entry Point: 80008000 Loading Kernel Image ... OK OK Starting kernel ... Uncompressing Linux... done, booting the kernel. Linux version 3.0.8 (root@hiber) (gcc version 5.2.0 (Buildroot 2015.11.1) ) #4 Thu Aug 25 05:42:37 EDT 2016 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. Built 1 zonelists in Zone order, mobility grouping on. Total pages: 10160 Kernel command line: mem=40M mmz=24M console=ttyAMA0,115200n8 mtdparts=hi_sfc:512k(uboot)ro,256k(uboot-env),256k(mfd),3m(kernel),4m(rootfs) hieth.mdioifu=1 hieth.mdioifd=1 hieth.phyaddru=0 hieth.phyaddrd=1 root=/dev/mtdblock4 rootfstype=squashfs,jffs2 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: 40MB = 40MB total Memory: 35852k/35852k available, 5108k reserved, 0K highmem Virtual kernel memory layout: vector : 0xffff0000 - 0xffff1000 ( 4 kB) fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB) DMA : 0xffc00000 - 0xffe00000 ( 2 MB) vmalloc : 0xc3000000 - 0xfe000000 ( 944 MB) lowmem : 0xc0000000 - 0xc2800000 ( 40 MB) modules : 0xbf000000 - 0xc0000000 ( 16 MB) .init : 0xc0008000 - 0xc0027000 ( 124 kB) .text : 0xc0027000 - 0xc044b000 (4240 kB) .data : 0xc044c000 - 0xc047d740 ( 198 kB) .bss : 0xc047d764 - 0xc0496d70 ( 102 kB) SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 NR_IRQS:128 nr_irqs:128 128 sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 42949ms Calibrating delay loop... 218.72 BogoMIPS (lpj=1093632) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 512 CPU: Testing write buffer coherency: ok devtmpfs: initialized 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 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. 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 70 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 Spi id table Version 1.22 Spi(cs1) ID: 0xEF 0x40 0x17 0x00 0x00 0x00 SPI FLASH start_up_mode is 3 Bytes Spi(cs1): Block:64KB Chip:8MB Name:"W25Q64FV" spi size: 8MB chip num: 1 5 cmdlinepart partitions found on MTD device hi_sfc Creating 5 MTD partitions on "hi_sfc": 0x000000000000-0x000000080000 : "uboot" 0x000000080000-0x0000000c0000 : "uboot-env" 0x0000000c0000-0x000000100000 : "mfd" 0x000000100000-0x000000400000 : "kernel" 0x000000400000-0x000000800000 : "rootfs" Fixed MDIO Bus: probed himii: probed RTL871X: module init start RTL871X: rtl8188eu v4.3.24_16705.20160509 RTL871X: build time: Aug 25 2016 05:41:55 usbcore: registered new interface driver rtl8188eu RTL871X: module init ret=0 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 sp805-wdt dev:wdog: registration successful TCP cubic registered NET: Registered protocol family 10 IPv6 over IPv4 tunneling driver NET: Registered protocol family 17 registered taskstats version 1 .VFS: Mounted root (squashfs filesystem) readonly on device 31:4. devtmpfs: mounted Freeing init memory: 124K usb 1-1: new high speed USB device number 2 using hiusb-ehci bFWReady == _FALSE call reset 8051... mount: mounting devtmpfs on /dev failed: Device or resource busy Starting logging: RTL871X: hal_com_config_channel_plan chplan:0x08 RTL871X: rtw_ndev_init(wlan0) if1 mac_addr=00:0a:e2:1f:49:59 OK Starting mdev... Starting watchdog... read-only file system detected...done Starting himpp: Hisilicon Media Memory Zone Manager hi3518_base: module license 'Proprietary' taints kernel. Disabling lock debugging due to kernel taint Hisilicon UMAP device driver interface: v3.00 pa:82800000, va:c3240000 load sys.ko ...OK! load viu.ko ...OK! ISP Mod init! load vpss.ko ....OK! load venc.ko ...OK! load group.ko ...OK! load chnl.ko ...OK! load h264e.ko ...OK! load jpege.ko ...OK! load rc.ko ...OK! load region.ko ....OK! load vda.ko ....OK! hi_i2c init is ok! acodec inited! insert audio ==== Your input Sensor type is gc1014 ==== OK Starting system message bus: done Starting hostapd: crc0_ok=1 crc1_ok=1 crc0_ok=1 crc1_ok=1 crc0_ok=1 crc1_ok=1 OK Starting network... ==> rtl8188e_iol_efuse_patch ADDRCONF(NETDEV_UP): wlan0: link is not ready RTL871X: assoc success ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready Starting httpd: OK Starting udhcpd: OK Starting led-status: OK Starting live-streamer: OK Starting aircraft-ctl: OK Welcome to IPCAM ipcam login: