Network Analysis, Logitech Mouse Server

The offensive security team here at Digital Bond spends a lot of our time attacking various control system components, from field device to SCADA server to HMI and everything in between. A big part of these attacks is network analysis. We examine the protocols being used to control the targeted systems, and in the case of unknown of proprietary protocols reverse engineer them, to try to find flaws in the way that the data is data, what functionality we can control without authenticating (far too often it’s far too much), whether its vulnerable to man-in-the-middle attacks, replay attacks, etc. Seldom are we able to talk about the process or the results of that work, so a few nights ago I was testing out some software to control a media server and I found some interesting things. Since its outside of our usual realm of work, I thought it’d be a good topic to write up the analysis, and give you all a glimpse into the process and the results.

My target was Logitech Mouse Server. It’s a fun little piece of software that lets you use an iphone/itouch as a remote keyboard/mouse for whatever system the server is installed on. On initial use no surprise, it works as advertised, but I started getting a little curious when I was controlling the server without any pairing or validation. Sleep was still a couple hours away, so I decided to take a deeper look into it and see what’s happening.

Down to the network layer we go. First things first, let’s see what ports the server is using for the connections. Using netstat, or its nicer looking cousin, TCPView, we see that 4026/tcp and 4026/udp look like our targets.

Using that information we put together a wireshark filter, “udp.port eq 4026 || tcp.port eq 4026” (eq can be read as “==” for those of you that don’t speak wireshark filter) and apply it to the session we’ve been sniffing, and we should see all the important traffic.

It looks like a tcp connection is established, but the data is passed over udp packets, which seem to contain very little data in each packet. Interesting choice in protocol design since you’ve already got the overhead of the tcp connection and I’d guess that you would normally want keystrokes to arrive in the order that you press them, that’s the choice they went with so we’ll ignore that issue and move along. Going down a little deeper and examining the individual udp packets.

Thankfully this protocol is probably the easiest protocol I’ll ever reverse since the client doesn’t send anything without you asking it to, and after going through a few packets you quickly seem the patterns emerge. Here is the data section of the packets sending “test” to the server:

0000 00 00 00 0d 00 00 00 74 00 00 00 00 00 00 00 02 .......t........

0000 00 00 00 0d 00 00 00 65 00 00 00 00 00 00 00 02 .......e........

0000 00 00 00 0d 00 00 00 73 00 00 00 00 00 00 00 02 .......s........

0000 00 00 00 0d 00 00 00 74 00 00 00 00 00 00 00 02 .......t........

And here’s dumps of the <WIN> key being pressed/release and then the <ALT> key being pressed/released:

0000 00 00 00 02 00 00 00 37 00 00 00 00 00 00 00 02 .......7........

0000 00 00 00 01 00 00 00 37 00 00 00 00 00 00 00 02 .......7........

0000 00 00 00 02 00 00 00 3a 00 00 00 00 00 00 00 02 .......:........

0000 00 00 00 01 00 00 00 3a 00 00 00 00 00 00 00 02 .......:........

Notice a pattern? The first four bytes are always fixed when sending simple keyboard, like the ‘A’, ‘S’, or ‘D’ key, and its different fixed value for all meta keys like <CTRL>, <ALT>,<WINDOWS>, etc, and different yet again for mouse left/right and mouse up/down. The 2nd set of 4 bytes changes with each keypress

Putting this together, we see every packet 16 bytes in length, consisting of 3 fields, a 4 byte big endian field to specify the type of command being sent, an 4 byte big endian field to specify the value being sent, and then a 8 byte field that seems to be some sort of increasing and seemingly random data, but in testing appears to be ignored anyways so we won’t worry too much about it. Now onto the fun part, after testing our assumptions a few times with some quick scripting we’ve validated our analysis enough to move onto the next step, and that’s going to be creating a scapy layer so that we can make this a bit more abstract and modular.

Which is as simple as creating a file with this class, dropping it into the layers directory, and adding it to the layers to load on startup in the conf.py file:

Most of the class should speak to itself, its just a collection of fields that are thrown together when the packet is built and sent out on the network, but I tried to make it somewhat user friendly using the enumfields to abstract it out a bit. The conditionalfields are a nice feature that you can use within the scapy framework/libraries, making the defined field only exist in the generated packet if the condition is true. The lambdas, well they’re just an anonymous function to do a simple comparison.

So we’ve broken down the protocol into its important bits, we’ve created a basic abstract class within a framework that we can easily send data. Just a bit of fun and an easy exercise on your way to becoming a network ninja, right? Well, probably, but there is a small legitimate security concern there, since by default the server runs on startup, and it has to accept external connections since that’s the reason it exists. Of course this type of attack is just slightly more stealthy than hitting someone with a wrench and typing commands into their system until they wake up, but nevertheless it could be used to run arbitrary commands. Say when the victim is particular engrossed in their morning coffee at Starbucks, they and any network that they log onto later could easily be

The larger issue, is to be wary of the applications that are not necessary for the tasks of a given system. Software that allows this kind of behavior is just fine on a media server a basement, but has no place on a system that’s ever going to be on an untrusted network.

Comments

Great walk-through of how to do simple, effective protocol analysis and testing. For those who can connect the dots and apply the same methodology for testing their ICS components, what kind of time-frame were you looking at from start to finish?

Granted, this appears to be an extremely basic protocol, but the methodology you’ve outlined seems to produce results within a fairly short period of time. Given the relative ease of this kind of protocol testing and the prevalence of similarly “advanced” protocols in the space, what is your feel for if ICS manufacturers are conducting these kind of tests and if those results are beginning to drive adoption of protocols which have even basic non-repudiation controls?

@Chris Jager,
From start to finish on understanding the protocol was probably around an hour and a half, maybe 2. There were some details that I didnt cover in the post, like that the mouse movement packets have to come in vert/horz pairs or they’re ignored, and looking into the binary a bit to find some of the other keycodes allowed, etc, but what you see in the post was probably there in an hour.

Writing the scapy class was another story, I was trying to do some cool stuff with actionfields for a while before going another direction, and used it to explore the 2.1 lib release a bit in the mean time. Rabbit trails and research go hand in hand :).

As far as this kind of work being done by ICS manufacturers, I think that the understanding that communication between systems needs some sort of validation, but where its being done using the same easily breakable/evadable techniques that we’ve seen used/abandoned other places. Putting trust in things like IP addresses, MAC addresses, a “magic field” in the protocol, instead of things that ensure real validity.

I am trying to reverse engineer this to emulate the server itself. I have achieved a few things, but the one thing I am struggling to figure out is the “keep alive” packets the server sends via the TCP connection which are also 16 bytes (8 bytes 0 and 8 bytes some kind of counter).. Do you happen to know anything about that ?

One thing I have figured out is in the UDP Packets.. its actually 4 bytes of increasing millisecond count and 4 bytes (potentially random).. not sure about the TCP packets though.. but the client seems to accept anything.. so my guess is that it is random..

Our Tweets

About Us

Digital Bond was founded in 1998 and performed our first control system security assessment in the year 2000. Over the last sixteen years we have helped many asset owners and vendors improve the security and reliability of their ICS, and our S4 events are an opportunity for technical experts and thought leaders to connect and move the ICS community forward.