{"id":62,"date":"2016-05-01T12:38:27","date_gmt":"2016-05-01T16:38:27","guid":{"rendered":"http:\/\/www.hackspot.net\/CircleBlog\/?p=62"},"modified":"2016-05-03T08:13:52","modified_gmt":"2016-05-03T12:13:52","slug":"firmware-updates","status":"publish","type":"post","link":"http:\/\/www.hackspot.net\/CircleBlog\/2016\/05\/01\/firmware-updates\/","title":{"rendered":"Firmware updates"},"content":{"rendered":"<p>The Circle will automatically check for firmware updates, and install them if it&#8217;s between 1am and 4:59am local time.<\/p>\n<p>It is also possible to &#8220;push&#8221; a firmware update image to the device (at any time), with the limitation being that the &#8216;source IP address&#8217; of the computer pushing the update must be on the &#8220;10.123.234.xx&#8221; subnet (that is the subnet used by the default Circle Wifi AP before it is associated with your router). \u00a0I&#8217;ve only done the firmware update &#8220;push&#8221; before the Circle was associated with my router. \u00a0I suppose if I reconfigured my router to use the &#8220;10.123.234.xx&#8221; subnet (and hand-out DHCP addresses there), it would be possible to push firmware updates after it&#8217;s been associated.<\/p>\n<p>Firmware updates are AES-encrypted gzipped .tar files. \u00a0Below is the part of the &#8220;\/mnt\/shares\/usr\/bin\/firmware_updater.sh&#8221; that does the decrypt and install:<\/p>\n<pre>#update firmware \r\nif [ \"$firmware_ver\" != \"0.0\" -a \"$my_firmware_ver\" != \"$firmware_ver\" ] ; then\r\n cd \/mnt;\r\n rm -f update_firmware.sh;\r\n rm -f \/mnt\/firmware.bin;\r\n echo fastblink &gt; \/tmp\/blueled;\r\n \/tmp\/wget -q -O \/mnt\/firmware.bin \"http:\/\/download.meetcircle.co\/dev\/firmware\/get_firmware.php?DEVID=$MAC$EXTRA&amp;ENCRYPT=1\"\r\n if [ -f \/mnt\/firmware.bin ] ; then\r\n aescrypt -d -o - \/mnt\/firmware.bin | gunzip -c | tar xf -\r\n if [ -f \/mnt\/update_firmware.sh ] ; then\r\n mkdir -p \/mnt0\r\n mount -t ext4 -o rw,noatime,nodiratime \/dev\/sda2 \/mnt0 &amp;&amp; rm -f \/mnt0\/firmware.bin &amp;&amp; cp \/mnt\/firmware.bin \/mnt0 &amp;&amp; umount \/mnt0\r\n rm -f \/mnt\/firmware.bin;\r\n sh \/mnt\/update_firmware.sh\r\n exit 0\r\n fi\r\n rm -f \/mnt\/firmware.bin;\r\n fi\r\n echo \"error downloading and installing firmware\" \r\n exit 1\r\nelse\r\n echo \"not updating firmware: firmware_ver=$firmware_ver my_updater_ver=$my_firmware_ver\";\r\nfi<\/pre>\n<p>As you can see, the new &#8220;\/mnt\/firmware.bin&#8221; file is decrypted and passed through gunzip\/tar, directly on top of the &#8220;\/mnt&#8221; filesystem (&#8220;\/dev\/sda3&#8221; ext4 filesystem on eMMC).<\/p>\n<p>The &#8220;aescrypt&#8221; command is a customized version of the open-source utility available here:\u00a0<a href=\"https:\/\/www.aescrypt.com\">https:\/\/www.aescrypt.com<\/a>. Circle&#8217;s primary customization is to use a hard-coded password (normally, you have to use either the &#8220;-p&#8221; option to specify a password, or &#8220;-k&#8221; to specify a key file &#8211; they use neither in their command above).<\/p>\n<p>After the untar is finished, it mounts &#8220;\/dev\/sda2&#8221; and copies the encrypted &#8220;\/mnt\/firmware.bin&#8221; to that partition. \u00a0I believe this partition is used for a failsafe\/recovery in case of corruption (or maybe just for any factory reset).<\/p>\n<p>After that, the script &#8220;\/mnt\/update_firmware.sh&#8221; (which was at the top-level inside the &#8220;\/mnt\/firmware.bin&#8221; tar file) is run. \u00a0Normally, this script just does a &#8220;reboot&#8221; of the device.<\/p>\n<p>It&#8217;s possible to create a modified firmware image with a customized &#8220;\/mnt\/update_firmware.sh&#8221; (where you can do whatever you want, such as installing new &#8220;passwd&#8221; and &#8220;shadow&#8221; files). \u00a0As a matter of fact, you can create a firmware update image which <em>only<\/em> contains an &#8220;update_firmware.sh&#8221; script at the top-level (no other &#8216;firmware&#8217; inside), but keep in mind that this image will be copied to the &#8216;failsafe\/recovery&#8217; partition, and if it doesn&#8217;t include a full firmware image, you could be left with a &#8216;bricked&#8217; device.<\/p>\n<h5>Downloading your own firmware from Circle:<\/h5>\n<p>If you want to download your own firmware image (for reverse-engineering\/poking around), you can. \u00a0Below is the command that the Circle device uses to pull-down a new (encrypted) firmware image:<\/p>\n<pre> \/tmp\/wget -q -O \/mnt\/firmware.bin \"http:\/\/download.meetcircle.co\/dev\/firmware\/get_firmware.php?DEVID=00:00:00:00:00:00&amp;HWVER=1&amp;ENCRYPT=1\"<\/pre>\n<p>&#8220;DEVID&#8221; is the MAC address of your Circle device &#8211; I&#8217;ve found that it&#8217;s OK to specify all zeros. \u00a0As a matter of fact, you don&#8217;t need to specify it at all:<\/p>\n<pre>wget -O firmware.bin \"http:\/\/download.meetcircle.co\/dev\/firmware\/get_firmware.php?HWVER=1&amp;ENCRYPT=1\"<\/pre>\n<p>As I said, the firmware is encrypted using a hard-coded key. \u00a0I&#8217;ve uploaded a key file <a href=\"http:\/\/hackspot.net\/Circle\/KEYFILE.dat\">here<\/a>. \u00a0Use the &#8220;-k&#8221; option to &#8220;<a href=\"https:\/\/www.aescrypt.com\">aescrypt<\/a>&#8221; to specify the key when decrypting:<\/p>\n<pre>aescrypt -d -k KEYFILE.dat -o firmware_decrypted.bin firmware.bin<\/pre>\n<p>After executing the above command, you will have a &#8220;firmware_decrypted.bin&#8221; (which is really a gzip-compressed .tar)<\/p>\n<p>As I said, you can modify the firmware (for example, modify &#8220;update_firmware.sh&#8221; to add your own customization), then encrypt it with the &#8220;-e&#8221; option.<\/p>\n<h5>Pushing your own firmware update to the Circle:<\/h5>\n<p>Here&#8217;s a &#8220;curl&#8221; command to push an encrypted firmware image (&#8220;firmware.bin&#8221;) to your Circle device:<\/p>\n<pre>curl -k -F \"file=@firmware.bin;filename=nameinpost\" https:\/\/10.123.234.1:4567\/api\/UPLOAD_FIRMWARE<\/pre>\n<p>As I said, the UPLOAD_FIRMWARE API command only works when sent from a computer on the 10.123.234.xxx subnet (the subnet used by the Circle before it is associated with your router).<\/p>\n<p>More details later&#8230;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Circle will automatically check for firmware updates, and install them if it&#8217;s between 1am and 4:59am local time. It is also possible to &#8220;push&#8221; a firmware update image to the device (at any time), with the limitation being that the &#8216;source IP address&#8217; of the computer pushing the update must be on the &#8220;10.123.234.xx&#8221; &hellip; <a href=\"http:\/\/www.hackspot.net\/CircleBlog\/2016\/05\/01\/firmware-updates\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Firmware updates&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/posts\/62"}],"collection":[{"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/comments?post=62"}],"version-history":[{"count":9,"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/posts\/62\/revisions"}],"predecessor-version":[{"id":76,"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/posts\/62\/revisions\/76"}],"wp:attachment":[{"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/media?parent=62"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/categories?post=62"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.hackspot.net\/CircleBlog\/wp-json\/wp\/v2\/tags?post=62"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}