Hacking a Neato Robotics BotVac Connected
-
-
-
What I have come up with so far is that the Neato it self is running a websocket server on port 8081 - and uses some kind of standard Auth-behavior in the headers,
Hypertext Transfer Protocol
GET /drive HTTP/1.1\r\n
Host: xxx.xxx.xxx.xxx:8081\r\n
Sec-WebSocket-Key: XXXXXXX==\r\n
Sec-WebSocket-Version: 13\r\n
Upgrade: websocket\r\n
Origin: ws://xxx.xxx.xxx.xxx:8081/drive\r\n
Date: Tue, 29 Dec 2015 09:17:57 GMT\r\n
Authorization: NEATOAPP XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\n
Connection: Upgrade\r\n
\r\n
[Full request URI: http://xxx.xxx.xxx.xxx:8081/drive]
[HTTP request 1/1]There also a port 8080 open but I can not figure out what's running on that one.
The communication between the Neato and the central server is handled via a server on Amazon - this traffis is HTTPS though. Next step is to set up a SSLSplit and hope that they don't have a pinned cert.
-
If we can figure out what's going on between Cloud <-> Neato we can do a version which is in depended on the Cloud-service being online or not - which also means that we can disallow it internet access
-
If we can figure out what's going on between Cloud <-> Neato we can do a version which is in depended on the Cloud-service being online or not - which also means that we can disallow it internet access
-
I recently ventured into writing some custom scripts both for my cloud connected home security system as well as my music streamer at home. It was quite easy to retrieve the commands needed from my android phone using an app I found called "Packet Capture" by the author Grey Shirts. Even https communication could be found. Perhaps this could be a way forward? Following this thread since I am considering getting a Botvac connected but failing to see the point if I would be dependent on a specific app on specific hardware..
-
I have installed the Packet Capture app. But this isn't working I think.
When starting the capture, the app makes a VPN connection. This VPN is blocking some traffic for the Neato App because my bot doesn't come only in the app. When I shut the VPN connection the bot comes online after 3 seconds.
Going back to the capture I think we miss some vital information because of this block.
This is what I got so far form the app:
<--- (TEXT)
GET /sessions/check HTTP/1.1
Authorization: Token token=xxxxxxxxxxxxxxx
Accept: application/vnd.neato.beehive.v1+json
Content-type: application/json
X-Agent: android-22|SM-G928F|samsung|1.0.0|134
User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; SM-G928F Build/LMY47X)
Host: beehive.neatocloud.com
Connection: Keep-Alive
Accept-Encoding: gzip---> (TEXT)
HTTP/1.1 200 OK
Server: Cowboy
Date: Wed, 30 Dec 2015 00:32:03 GMT
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Type: application/json; charset=utf-8
Etag: W/"a3cdd45ce712890397436cafca38e79a"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: xxxxxxxxxxxxxxxxxxxxxx
X-Runtime: 0.022752
Strict-Transport-Security: max-age=31536000
Content-Length: 39
Via: 1.1 vegur---> (JSON)
{"current_time":"2015-12-30T00:32:04Z"}<--- (TEXT)
GET /dashboard HTTP/1.1
Authorization: Token token=xxxxxxxxxxxxxxxxxxxxxxxx
Accept: application/vnd.neato.beehive.v1+json
Content-type: application/json
X-Agent: android-22|SM-G928F|samsung|1.0.0|134
User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; SM-G928F Build/LMY47X)
Host: beehive.neatocloud.com
Connection: Keep-Alive
Accept-Encoding: gzip---> (TEXT)
HTTP/1.1 200 OK
Server: Cowboy
Date: Wed, 30 Dec 2015 00:32:03 GMT
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Type: application/json; charset=utf-8
Etag: W/"c390b2a69fb7b4a405c8637e86ff321a"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: xxxxxxxxxxxxxxxxxxxxxxxxxx
X-Runtime: 0.014884
Strict-Transport-Security: max-age=31536000
Content-Length: 1337
Via: 1.1 vegur---> (JSON)
{
"email":"xxxxx@xxxxx.nl",
"first_name":"xxxx",
"last_name":"xxxxxx",
"locale":"nl",
"newsletter":false,
"created_at":"2014-06-23T16:39:45Z",
"verified_at":"2015-05-25T13:19:08Z",
"robots": [
{
"serial":"xxxxxxxxxx",
"prefix":"SN",
"name":"xxxxxx",
"model":"BotVacConnected",
"secret_key":"xxxxxxxxxxxxxxxxxxxxx",
"purchased_at":"2015-12-22T00:00:00Z",
"proof_of_purchase_url":"https://neatorobotics.s3.amazonaws.com/proof_of_purchases/xxxxxxxxxx/ProofOfPurchase.jpg",
"proof_of_purchase_generated_at":"2015-12-23T18:31:21Z",
"mac_address":"xxxxxxxxx",
"firmware":"2.0.0",
"created_at":"2015-11-11T20:10:38Z",
"linked_at":"2015-12-23T17:23:55Z"
}
],
"recent_firmwares":{}}
xxxxxxxxx = personal data
-
I have gotten stuck now on my venture -
Trying to figure out how the Authorization is calculated when it comes to the communication with the Neato. Found a place in the Java-code which mentions the Authorization part but can not figure out where it comes from
com/neatorobotics/android/activities/robot/C0645j.java:~142
private void m5619R() { if (!NeatoApplication.f2866a) { m5646a(); try { URI uri = new URI("ws://" + this.f3263d + ":" + this.f3264e + "/drive"); String b = C0764a.m5847b(); String str = this.f3262c.toLowerCase() + "\n" + b + "\n"; Mac instance = Mac.getInstance("HmacSha256"); instance.init(new SecretKeySpec(this.f3265f.getBytes(), "HmacSha256")); str = C0770g.m5880a(instance.doFinal(str.getBytes("UTF-8"))).toLowerCase(); Map hashMap = new HashMap(); hashMap.put("Date", b); hashMap.put("Authorization", "NEATOAPP " + str); this.al = new C0655t(this, uri, new C0017f(), hashMap, 5000); this.al.m41a(); new Thread(new C0661z(this)).start(); } catch (Exception e) { C0767d.m5867a("ManualCleaningFragment", "Exception", e); } }I have also found what String b is
com/neatorobotics/android/utils/C0764a.java:89: public static String m5847b() {public static String m5847b() { Calendar instance = Calendar.getInstance(); instance.add(12, (int) (((C0742a.m5809b(NeatoApplication.m5360a(), "SERVER_DEVICE_TIME_DELTA_MILLIS", 0) * -1) / 1000) / 60)); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); return simpleDateFormat.format(instance.getTime()); }So what we need to figure out is the following variables:
this.f3262c.toLowerCase()
this.f3265f.getBytes() < I am pretty sure this is secret_keywhen we crack these - we get closer to communicating with the central server
-
Maybe I can help because I figured something out. I can get my computer in between the App and the Neato Botvac.
I have a Asus motherboard with a Wifi adapter. With the software "Wifi Engine" from Asus I can make a Access point in my computer.
So what I have done is disabled my home Wifi Netwerk and configured the Wifi of my computer the same as the home network. Both my phone and the Neato Bot connect to the Wifi point with my computer in between now.
I have installed Wireshark so I could capture some date between the app and the Neato.
Unfortunately I can't make anything out of the data. It's not like the "Packet Capture" app I installed on my phone you can see in my earlier post.Someone any idea what I could do to help us out?
-
Already sniffed the Web Socket traffic - was the first thing I did. No sensible easy output - needs more analysing and so. Need to start on the end with reversing the control-part of the app to see what it does.