{"id":7518,"date":"2025-07-26T23:07:21","date_gmt":"2025-07-26T23:07:21","guid":{"rendered":"https:\/\/41j.com\/blog\/?p=7518"},"modified":"2025-07-29T08:18:35","modified_gmt":"2025-07-29T08:18:35","slug":"m7-wifi-camera-notes","status":"publish","type":"post","link":"https:\/\/41j.com\/blog\/2025\/07\/m7-wifi-camera-notes\/","title":{"rendered":"M7 Wifi Camera Notes"},"content":{"rendered":"\n<p>I picked up a cheap Wifi security camera on Amazon, it uses a mobile app called &#8220;seeing&#8221;. Which appears to be that referenced at seeing.store.<\/p>\n\n\n\n<p>No ports were open when scanned with nmap. Monitoring traffic on the router indicated it was talking to a remote server (appears to be on Alibaba&#8217;s cloud service):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>traffic when streaming video: \n18:19:21.995059 IP 192.168.8.191.36198 &gt; 47.79.82.123.443: Flags &#91;F.], seq 228080, ack 6579, win 6169, length 0\n18:19:21.998765 IP 47.79.82.123.443 &gt; 192.168.8.191.36198: Flags &#91;F.], seq 6579, ack 228080, win 831, length 0\n18:19:22.671581 IP 192.168.8.191.36200 &gt; 47.79.82.123.443: Flags &#91;S], seq 4002814628, win 29200, options &#91;mss 1460,sackOK,TS val 4294938745 ecr 0,nop,wscale 3], length 0\n<\/code><\/pre>\n\n\n\n<p>With some more fiddling it appears that the cloud service coordinates with the phone\/camera but if they are on the same network the camera will stream directly to the phone:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>8:52:29.753976 IP navas-iPhone.lan.49936 &gt; 192.168.8.191.10666: UDP, length 48\n...\n18:52:29.841608 IP 192.168.8.191.10666 &gt; navas-iPhone.lan.49936: UDP, length 1332\n18:52:29.841943 IP 192.168.8.191.10666 &gt; navas-iPhone.lan.49936: UDP, length 1332<\/code><\/pre>\n\n\n\n<p>Whatever communication the phone coordinates via the cloud appears to open up a UDP port on the camera. It first sends a packet with a payload of &#8220;dummy&#8221;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"77\" src=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1024x77.png\" alt=\"\" class=\"wp-image-7519\" srcset=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1024x77.png 1024w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-300x23.png 300w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-150x11.png 150w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-768x58.png 768w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1536x116.png 1536w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-2048x155.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Which the camera seems to echo back:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"74\" src=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1-1024x74.png\" alt=\"\" class=\"wp-image-7520\" srcset=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1-1024x74.png 1024w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1-300x22.png 300w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1-150x11.png 150w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1-768x55.png 768w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1-1536x110.png 1536w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-1-2048x147.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The phone then sends a more complex binary payload:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"146\" src=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-2-1024x146.png\" alt=\"\" class=\"wp-image-7521\" srcset=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-2-1024x146.png 1024w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-2-300x43.png 300w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-2-150x21.png 150w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-2-768x110.png 768w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-2-1536x219.png 1536w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-2-2048x292.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The camera then replies with some clear text:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"145\" src=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-3-1024x145.png\" alt=\"\" class=\"wp-image-7522\" srcset=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-3-1024x145.png 1024w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-3-300x42.png 300w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-3-150x21.png 150w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-3-768x109.png 768w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-3-1536x217.png 1536w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/image-3-2048x290.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The phone sends some more binary data to setup the stream&#8230; I was able to replay the initial packet from a PC and receive the clear text reply. But this only works if the port has been opened via the phone first.<\/p>\n\n\n\n<p>With no clear routes into the camera via the network I pulled it apart. The camera uses a AllWinner IP Camera SoC. I tried probing all the pads labelled RX\/TX for a serial interface but didn&#8217;t have any luck here. <\/p>\n\n\n\n<p>So, dumped the flash next. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"1024\" src=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/flash-768x1024.jpg\" alt=\"\" class=\"wp-image-7526\" style=\"width:336px;height:auto\" srcset=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/flash-768x1024.jpg 768w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/flash-225x300.jpg 225w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/flash-113x150.jpg 113w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/flash-1152x1536.jpg 1152w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/flash-1536x2048.jpg 1536w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/flash-scaled.jpg 1920w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/figure><\/div>\n\n\n<p>Via a raspberry pi using: sudo flashrom -p linux_spi:dev=\/dev\/spidev0.0,spispeed=500K -r m7_firmware.bin<\/p>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-a17ee66f-6961-4560-b0aa-c4708171e9e3\" href=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/m7cam.fw\">m7cam<\/a><a href=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/m7cam.fw\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-a17ee66f-6961-4560-b0aa-c4708171e9e3\">Download<\/a><\/div>\n\n\n\n<p>The camera appears to use an OpenWRT fork called Tina Linux. <code>eGON<\/code>&nbsp;header found at beginning of flash, indicating use of Allwinner&#8217;s built-in BROM and SPL bootloader. Bootargs suggest a serial console should be present.. so some more hunting may reveal it.<\/p>\n\n\n\n<p>That&#8217;s all for now!<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"1024\" src=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/telegram-cloud-photo-size-4-5775873888427822044-y-768x1024.jpg\" alt=\"\" class=\"wp-image-7530\" style=\"width:356px;height:auto\" srcset=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/telegram-cloud-photo-size-4-5775873888427822044-y-768x1024.jpg 768w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/telegram-cloud-photo-size-4-5775873888427822044-y-225x300.jpg 225w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/telegram-cloud-photo-size-4-5775873888427822044-y-113x150.jpg 113w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2025\/07\/telegram-cloud-photo-size-4-5775873888427822044-y.jpg 960w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/figure><\/div>\n\n\n<p>More notes.<\/p>\n\n\n\n<p>The pins on the top right of the board above labeled W-RX0 etc. show an interface which responds only during boot, here is some sample output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;74648]&#91;D]PACKET_CMD_USER_DATA 5a 51 0 0 64 d2 66 24\n&#91;74649]&#91;D]PACKET_CMD_USER_DATA 5a 51 0 0 64 d2 66 24\n&#91;74724]&#91;D]ecd.poweron_qrcode 0, ecd.ring_power_off_valid_count 0\n&#91;75051]&#91;I]GET_WIFI_DATA(3) len: 9 1\n&#91;75052]&#91;I]GET_NET_INFO(25) len: 8 0\n$>Welcome to Wlan Bluetooth Console Tools ......\n$>&#91;75202]&#91;D]PACKET_CMD_USER_DATA 5a 51 0 0 64 d2 66 24\n&#91;75202]&#91;I]GET_SOME_DATA(7) len: 8 0\n&#91;75724]&#91;D]ecd.poweron_qrcode 0, ecd.ring_power_off_valid_count 0\n&#91;75724]&#91;I]&#91;W0] wifi: 0 81 0 | 335 137, 0(0\/0\/0), 0(0\/0\/0) | 403 0 135 112002 1042001100 | 127320 67068 60252\n&#91;UMAC WARN] sta_add():360, scan entry >= 10, discard rssi lowest one\n&#91;UMAC WARN] sta_add():360, scan entry >= 10, discard rssi lowest one\n&#91;UMAC WARN] sta_add():360, scan entry >= 10, discard rssi lowest one\n&#91;76715]&#91;D]PACKET_CMD_USER_DATA 5a 51 0 0 64 d2 66 24\n&#91;76715]&#91;I]GET_WIFI_DATA(3) len: 9 1\n&#91;76724]&#91;D]ecd.poweron_qrcode 0, ecd.ring_power_off_valid_count 0\n&#91;76724]&#91;I]&#91;W0] wifi: 0 81 0 | 169 33, 0(0\/0\/0), 0(0\/0\/0) | 403 0 135 112002 1042001100 | 127320 67716 59604\n&#91;76733]&#91;D]PACKET_CMD_USER_DATA 5a 51 0 0 64 d2 66 24\n&#91;76738]&#91;I]GET_SOME_DATA(7) len: 8 0\n&#91;net INF] msg &lt;wlan scan success>\n&#91;76888]&#91;D]NET_CTRL_MSG_WLAN_SCAN_SUCCESS\nen1: Trying to associate with 94:83:c4:6c:98:2c (SSID='youanji1' freq=2412 MHz)\nen1: Associated with 94:83:c4:6c:98:2c\nen1: Clear keys to send no encrypt 4 of 4-way handshake\nen1: WPA: Key negotiation completed with 94:83:c4:6c:98:2c &#91;PTK=CCMP GTK=CCMP]\nen1: CTRL-EVENT-CONNECTED - Connection to 94:83:c4:6c:98:2c completed &#91;id=0 id_str=]\n&#91;net INF] msg &lt;wlan connected>\n&#91;net INF] netif is link up\n&#91;net INF] start DHCP...\n&#91;77267]&#91;D]============= dhcp =============\n&#91;77269]&#91;D]ip:0.0.0.0\n&#91;77271]&#91;D]netmask: 0.0.0.0\n&#91;77274]&#91;D]gateway: 0.0.0.0\n&#91;77276]&#91;D]dns&#91;0]: 0.0.0.0\n&#91;77279]&#91;D]dns&#91;1]: 0.0.0.0\n&#91;77281]&#91;D]dns&#91;2]: 0.0.0.0\n&#91;77283]&#91;D]dns&#91;3]: 0.0.0.0\n&#91;77286]&#91;D]invalid ip\n&#91;77288]&#91;D]NET_CTRL_MSG_WLAN_CONNECTED\n&#91;77724]&#91;D]ecd.poweron_qrcode 0, ecd.ring_power_off_valid_count 0\n&#91;77724]&#91;I]&#91;W0] wifi: 0 81 0 | 182 48, 0(0\/0\/0), 98(1\/0\/0) | 403 0 135 112002 1042001100 | 127320 71412 55908\n&#91;77746]&#91;D]PACKET_CMD_USER_DATA 5a 51 0 0 64 d2 66 24\n&#91;77746]&#91;I]GET_WIFI_DATA(3) len: 9 1\n&#91;77761]&#91;D]PACKET_CMD_USER_DATA 5a 51 0 0 64 d2 66 24\n&#91;77761]&#91;I]GET_SOME_DATA(7) len: 8 0\n&#91;net INF] netif (IPv4) is up\n&#91;net INF] address: 192.168.8.207\n&#91;net INF] gateway: 192.168.8.1\n&#91;net INF] netmask: 255.255.255.0\n&#91;net INF] msg &lt;network up>\n&#91;78221]&#91;D]============= dhcp =============\n&#91;78224]&#91;D]ip:192.168.8.207\n&#91;78227]&#91;D]netmask: 255.255.255.0<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I picked up a cheap Wifi security camera on Amazon, it uses a mobile app called &#8220;seeing&#8221;. Which appears to be that referenced at seeing.store. No ports were open when scanned with nmap. Monitoring traffic on the router indicated it was talking to a remote server (appears to be on Alibaba&#8217;s cloud service): With some [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-7518","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1RRoU-1Xg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/7518","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/comments?post=7518"}],"version-history":[{"count":3,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/7518\/revisions"}],"predecessor-version":[{"id":7533,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/7518\/revisions\/7533"}],"wp:attachment":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/media?parent=7518"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/categories?post=7518"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/tags?post=7518"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}