{"id":228,"date":"2016-06-03T22:01:25","date_gmt":"2016-06-03T20:01:25","guid":{"rendered":"https:\/\/www.schlafhacking.de\/blog\/?p=228"},"modified":"2016-06-03T22:01:25","modified_gmt":"2016-06-03T20:01:25","slug":"schaf-im-wolfspelz-sleep-shepherd-blue-reversed","status":"publish","type":"post","link":"https:\/\/www.schlafhacking.de\/blog\/?p=228","title":{"rendered":"Schaf im Wolfspelz: sleep shepherd blue reversed"},"content":{"rendered":"<p>Nun, wie es aussieht, bekomme ich keine Unterst\u00fctzung vom Hersteller. Man habe andere Priorit\u00e4ten als ein SDK zu \u00f6ffnen. Verstehe ich. Warten m\u00f6chte ich aber auch nicht. Also r\u00fccken wir dem Ding mit \u00fcblichen Reversing tools zuleibe: bluez\/gattool und einem decompiler.<\/p>\n<p>Schlie\u00dflich muss die offizielle App ja irgendwie mit dem Ding reden. Dazu hole ich mir als erstes mal das APK von <a href=\"https:\/\/apkpure.com\/sleep-shepherd-blue\/com.mindrocket.sleep\">hier<\/a>. Apks sind erst mal ja nur zips, die man umbenennen und dann einfach auspacken kann. Darin sind tolle Dinge wie Ressoucen (Bilder, sounds, &#8230;) und das Programm selbst. Im konkreten Fall als .dex Datei. Au\u00dferdem erkennt man sofort, dass diese App mit Phonegap\/Cordova entwickelt ist, weil es den Ordner assets\\www gibt und darin die ganzen typischen Sachen rumliegen. Sch\u00f6n, das kenne ich, damit kenne ich mich aus. Weiterhin angenehm ist, dass die ganze Applikationslogik als javascript-files quasi im Quellcode rumliegt und ich mir erst mal den tieferen Blick in die .dex Datei (z.B, mit <a href=\"https:\/\/sourceforge.net\/projects\/dex2jar\/\">dex2jar<\/a> und <a href=\"https:\/\/github.com\/java-decompiler\/jd-gui\/\">java-decompiler<\/a>) f\u00fcr sp\u00e4ter aufheben kann \ud83d\ude42<\/p>\n<p>Es w\u00e4re eigentlich denkbar und der einfachste Weg, diese tolle app einfach auszupacken und erweitert um ein paar LD Funktionen mit Phonegap neu zu builden. Aber das Ergebnis k\u00f6nnte man nicht verteilen, weil es vermutlich Stress mit &#8220;geistigem Eigentum&#8221; gibt. Also lieber schnell was von Null mit den wichtigsten Infos zusammenbasteln. Wobei&#8230; *hust* im 1.1.10 apk ist in der index.js der Vermerk (einfach dringelassen vom phonegap sch\u00e4tze ich), dass das File unter Apache license steht :p<\/p>\n<p>So, man will also laut dem .js code ein Ger\u00e4t mit folgenden Eigenschaften finden:<\/p>\n<blockquote><p>serviceUuid = &#8220;ffe0&#8221;,<br \/>\ncharUuid = &#8220;ffe1&#8221;,<br \/>\ndesiredName = &#8220;SSV1_00000&#8221;<\/p>\n<p>bluetoothle.subscribe(subSuccess, subFail, {&#8220;address&#8221;:address,&#8221;serviceUuid&#8221;:serviceUuid,&#8221;characteristicUuid&#8221;:charUuid, &#8220;isNotification&#8221;:true });<\/p><\/blockquote>\n<p>schauen wir mal&#8230;<\/p>\n<blockquote><p>root@zeopi8-1:\/# hcitool lescan<br \/>\nLE Scan &#8230;<br \/>\n20:91:48:AA:B8:FA (unknown)<br \/>\n20:91:48:AA:B8:FA SSV1_00000<\/p>\n<p>root@zeopi8-1:\/# gatttool -b 20:91:48:AA:B8:FA -I<br \/>\n[20:91:48:AA:B8:FA][LE]&gt; connect<br \/>\nAttempting to connect to 20:91:48:AA:B8:FA<br \/>\nConnection successful<br \/>\n[20:91:48:AA:B8:FA][LE]&gt; primary<br \/>\nattr handle: 0x0001, end grp handle: 0x000b uuid: 00001800-0000-1000-8000-00805f9b34fb<br \/>\nattr handle: 0x000c, end grp handle: 0x000f uuid: 00001801-0000-1000-8000-00805f9b34fb<br \/>\nattr handle: 0x0010, end grp handle: 0xffff uuid: 0000ffe0-0000-1000-8000-00805f9b34fb<\/p><\/blockquote>\n<p>yep. Hab ich. Nice.<\/p>\n<p>Jetzt die ganzen Funktionen. Ziemlich w\u00fcster Wust, das geh\u00f6rt eigentlich gekapselt und zentralisiert, aber ich bin dankbar \u00fcber die vielen Kommentare und dass auch einige unbenutzte Sachen noch im Code auskommtentiert drin gelassen wurde. Einige Highlights:<br \/>\nfunction getVersionNumber(){<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;99&#8243;,&#8221;20&#8243;,&#8221;00&#8243;,&#8221;&#8221;];<br \/>\nfunction sendCheckDataCommand()\u00a0\u00a0\u00a0 var hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;94&#8243;,&#8221;20&#8243;,&#8221;00&#8243;,&#8221;&#8221;];<br \/>\nfunction sendGetHeaderCommand()<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;93&#8243;,&#8221;20&#8243;,&#8221;00&#8243;,&#8221;&#8221;];<br \/>\nfunction sendEraseDataCommand()<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;96&#8243;,&#8221;20&#8243;,&#8221;00&#8243;,&#8221;&#8221;];<br \/>\nfunction getAccel()<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;58&#8243;,&#8221;20&#8243;,&#8221;00&#8243;,&#8221;&#8221;];<br \/>\nfunction sendConfirmationCommand()<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;9A&#8221;,&#8221;10&#8243;,&#8221;01&#8243;,&#8221;&#8221;];<br \/>\nfunction sendDataRecordingCmd()<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;95&#8243;,&#8221;20&#8243;,&#8221;00&#8243;,&#8221;&#8221;];<br \/>\nfunction sendTurnOffRecordCmd()<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;95&#8243;,&#8221;10&#8243;,&#8221;00&#8243;,&#8221;&#8221;];<br \/>\nfunction setVolCmd(value)<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;84&#8243;,&#8221;10&#8243;,hexValue,&#8221;&#8221;];<br \/>\nfunction setWakeTime(value){<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;06&#8243;,&#8221;34&#8243;,&#8221;10&#8243;];<br \/>\nfunction changeState(newState)<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;03&#8243;,&#8221;24&#8243;,&#8221;10&#8243;,newState.toString(),&#8221;&#8221;];<br \/>\nfunction sendStartCommand()<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;0C&#8221;,&#8221;82&#8243;,&#8221;10&#8243;];<br \/>\nhexArray = hexArray.concat(intToBytes(time,6), intToBytes(sampleRate*1000,4), [&#8220;&#8221;]);<br \/>\nfunction sendEndCommand()<br \/>\nvar hexArray = [&#8220;AA&#8221;,&#8221;AA&#8221;,&#8221;08&#8243;,&#8221;83&#8243;,&#8221;10&#8243;];<br \/>\nhexArray = hexArray.concat(intToBytes(time,6), [&#8220;&#8221;]);<\/p>\n<p>Weiter unten findet sich in der Bologneseso\u00dfe um den Javascript-Spaghettihaufen ab Zeile 2557 (index.js) Information dar\u00fcber, wie das Protokoll aufgebaut ist, z.B.<\/p>\n<p>\/\/ &#8212; Received accel data &#8212; \/\/<br \/>\nif (returnedBytes[0] == 170 &amp;&amp; returnedBytes[1] == 170 &amp;&amp; returnedBytes[3] == 88 &amp;&amp; returnedBytes[4] == 48){<br \/>\n\/\/alert(&#8220;received signal strength of: &#8220;+returnedBytes[4]);<br \/>\nvar xArray = [returnedBytes[5], returnedBytes[6]];<br \/>\nvar yArray = [returnedBytes[7], returnedBytes[8]];<br \/>\nvar zArray = [returnedBytes[9], returnedBytes[10]];<\/p>\n<p>\/\/ &#8212; Received Sleep Data Header Packet &#8212; \/\/<br \/>\nif (returnedBytes[0] == 170 &amp;&amp; returnedBytes[1] == 170 &amp;&amp; returnedBytes[3] == 129 &amp;&amp; returnedBytes[4] == 48){<\/p>\n<p>\/\/ &#8212; Received Sleep Data Stream Packet &#8212; \/\/<br \/>\nif (returnedBytes[0] == 170 &amp;&amp; returnedBytes[1] == 170 &amp;&amp; returnedBytes[2] == 11 \/* 16 *\/){<\/p>\n<p>\/\/ &#8212; Received Sleep Data Footer Packet &#8212; \/\/<br \/>\nif (returnedBytes[0] == 170 &amp;&amp; returnedBytes[1] == 170 &amp;&amp; returnedBytes[3] == 131 &amp;&amp; returnedBytes[4] == 48){<\/p>\n<p>Leider findet sich im Code der App kein Hinweis auf eine M\u00f6glichkeit, der M\u00fctze Audio zum Abspielen zu schicken. Das hei\u00dft, auch die Firmware der M\u00fctze selbst m\u00fcsste mal gehackt werden. Dass man so einfach an den Code kommt wie an den der App, glaube ich weniger, als n\u00e4chstes m\u00fcsste man mal die Plastikbox vorsichtig \u00f6ffnen, und den Inhalt begutachten, ein ROM-Dump versuchen usw.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nun, wie es aussieht, bekomme ich keine Unterst\u00fctzung vom Hersteller. Man habe andere Priorit\u00e4ten als ein SDK zu \u00f6ffnen. Verstehe ich. Warten m\u00f6chte ich aber auch nicht. Also r\u00fccken wir dem Ding mit \u00fcblichen Reversing tools zuleibe: bluez\/gattool und einem &hellip; <a href=\"https:\/\/www.schlafhacking.de\/blog\/?p=228\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[6,3,30],"tags":[33,32,31],"_links":{"self":[{"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/228"}],"collection":[{"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=228"}],"version-history":[{"count":1,"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/228\/revisions"}],"predecessor-version":[{"id":230,"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/228\/revisions\/230"}],"wp:attachment":[{"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=228"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=228"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.schlafhacking.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=228"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}