Point of sale (POS) malware has become something of a hot topic over the past 12 months, the most notable being the Target breach that disclosed up to 110 Million records. And it doesn't stop there. On August 22nd, 2014, DHS reported that over 1,000 businesses were compromised by a previously unknown malware known as "Backoff".

What is Backoff

Backoff is POS malware developed for Windows, as this tends to be the most common operating system (OS) for these systems. The samples from these compromises were packed with varying novel methods and at first glance, the samples do not look related. Some of them are written in Visual Basic, while others are written in C. Each one of the samples have different sizes. It's only after unpacking that we–the human analysts–see the relation between the samples, however, the Cylance engine recognizes them as threats WITHOUT the need for detonation.

Detecting the "Undetectable"

Even the packed versions of this malware are a walk in the park for our mathematical detection engine, with each sample being detected as malcious–without having seen them before. One of the most powerful aspects of our engine is its ability to attach a "confidence rating" for each object detected–allowing for greater granularity and improved ability to convict malicious files.

If we take one of these samples (d9ba782016e834bab365d72071a66c54aa3b6821d957908b2da316cc5b66a8bd) and look at its detection history, we can see it was first uploaded to malware forums in July of 2014.

The sample Cylance detected was compiled on April 29th, 2014. Our latest mathematical model–which powers the Cylance engine–was compiled on April 30th, 2014 and detected this sample as a threat without the need for a "sacrificial lamb". This means that our customers were protected from this threat one day after the sample was first created. When I dig into our model archives, I actually find that we detected this sample with a model that was generated on February 5th, 2014 with a score of -0.97 (bad with 97% confidence), nearly three months before the compilation date of the sample. Zero-days? What zero-days?

We were detecting this sample as a threat before it was developed, conflicting with the claim made in this NYTimes article claiming the malware was undetectable up until July 31st.

Unpacking a Sample

For an unpacking example, I will use the most recent variant (11591204155db5eb5e9c5a3adbb23e99a75c3b25207d07d7e52a6407c7ad0165). The packer for this version is not in Visual Basic, but also does not contain many artifacts that show what was used to develop it. This packer works by storing the real PE as an obfuscated string along with code to finish unpacking. The packer code removes the obfuscation, then jumps into the appended code, which then unmaps the original file from memory, then replaces it with the original unpacked binary.

Instead of going into technical details about how it works, I will show how to unpack it with open source tools. Load it up in OllyDbg (in a virtual machine of course), and start stepping through the instructions. The unpacking is done a few functions deep, so we need to step into a few CALL instructions. The first one is right by the entry point.

The next one is after a loop, and has a fairly long string as a parameter.

In the resulting function, we can see a VirtualAlloc call which we can step over.

Then, we reach the unpacking function. Before the function runs, if we look at the memory segment at 0x20000, we can see it is readable, writable and executable. We can see currently it only contains 0's.

Set a break point right after the next call, in this case, it is at 0x004010BA.

Then we let the application run until it reaches that break point. Once it reaches that break point, we can jump back to the memory view of 0x20000. There we can see that section now has code in it, as well as a PE.

We can now dump this memory segment to disk. All we need to do is right click on the window with the memory segment open, and select Backup -> Save data to file.

Once we have this dumped to a file, we can use any means we wish to remove the bytes leading up to the beginning of the PE. I transferred the file to my Linux host. By using tail, hexdump, and head, we can search around for where the PE starts. We could also use grep.

Since we found the offset, we can use tail and redirection to write the PE to disk. This PE is no longer packed.

If we search for hosts in this file with eh, we can see the command and control servers used by the attackers.

If we search for the string "php", we can find the path on the command and control server to which the bot reports back.

Static Analysis

Once the sample is unpacked, it is quite simple to analyze. We can quickly develop a Yara rule that can detect these samples.

rule backoff { meta: author = "Brian Wallace @botnet_hunter" author_email = "bwallace@cylance.com" date = "2014-08-21" description = "Identify Backoff" strings: $s1 = "&op=%d&id=%s&ui=%s&wv=%d&gr=%s&bv=%s" $s2 = "%s @ %s" $s3 = "Upload KeyLogs" condition: all of them }

Signatures like these are useful for identification, but are far less effective than the protection provided by CylancePROTECT™.

Operation

These samples all copy themselves to new locations, then delete the files at the original locations. This is one of the first things these samples do. Different variations of the malware relocate to the following locations.

%APPDATA%\AdobeFlashPlayer\mswinsvc.exe %APPDATA%\AdobeFlashPlayer\mswinhost.exe %APPDATA%\OracleJava\javaw.exe

The samples also utilize mutexes to avoid running more than one instance at a time. The following are observed mutexes by different samples.

uhYtntr56uisGst uyhnJmkuTgD Undsa8301nskal nuyhnJmkuTgD nUndsa8301nskal

The main operation of the bot occurs in three different threads. These threads do not directly communicate with each other, and from a software engineering stand point, could indicate that Backoff was created by multiple developers without much cooperative development experience. The three threads do the following: Credit Card Scraping, Keystroke Logging, and Command and Control Communications.

Command and Control

The command and control thread regularly checks with the command and control server for commands as well as uploading credit card data. The command and control server is a PHP script (at least one) which is communicated to via HTTP and would require a code change to use HTTPS. Each request made is a POST request with identifier information.

For this example, the bot is reporting home from a virtual machine named "LAB", where the user is "dexter". The "wv" parameter dictates the version of Windows. The "gr" parameter dictates which variant is reporting to the command and control server. The "bv" parameter is the malware version. The "id" parameter is used later.

Also in that example, I have my fake command and control returning a command of "Upload KeyLogs". The command and control server has various commands.

Update - Downloads binary to replace itself Terminate - exits Uninstall - uninstalls itself and exits Download and Run - Downloads and executes binary Upload KeyLogs - Uploads data gathered from key logging Thanks! - Empty command

Credit card information is uploaded while the malware is operating regardless of the set command.

Data Uploads

When information is uploaded, it is encrypted and encoded in the "data" parameter. The encoding is Base64 and the encryption is RC4. The key being used for the RC4 encryption changes between samples and installs of the malware. The "id" parameter and the "ui" parameter are both used along with a static string that varies between samples. The following are the known static strings so far.

jhgtsd7fjmytkr ihasd3jasdhkas9 ihasd3jasdhkas zXqW9JdWLM4urgjRkX

Before MD5 hashing, the parts are in the order of: id, static string, ui. The following Python script can decrypt the encoded and encrypted data.

#!/usr/bin/env python2 import hashlib import base64 import string # Update these variables with data to decrypt to_decrypt = "eOtiYEntho7IvwjfJ7beQnot4xfoscImZeoWG76nK38kYsSzRws5rjZZ38zinkQF9AG77aGhfG5zvZ5eTbmqng==" id = "NYGOsSB" ui = "dexter @ LAB" class rc4: def swap(self): t = self.state[self.i] self.state[self.i] = self.state[self.j] self.state[self.j] = t def __init__(self, key): self.state = [i for i in xrange(256)] self.j = 0 for i in xrange(256): self.i = i self.j = (self.j + self.state[self.i] + ord(key[self.i % len(key)])) % 256 self.swap() self.i = 0 self.j = 0 def next(self): self.i = (self.i + 1) % 256 self.j = (self.j + self.state[self.i]) % 256 self.swap() return self.state[(self.state[self.i] + self.state[self.j]) % 256] def decrypt_data(data, id, ui): data = data.replace(" ", "+") m = hashlib.md5() m.update(id) m.update(ui) rc4_key = m.hexdigest().upper() r = rc4(rc4_key) return "".join([chr(r.next() ^ ord(c)) for c in base64.b64decode(data)]) static_strings = ["zXqW9JdWLM4urgjRkX", "ihasd3jasdhkas", "ihasd3jasdhkas9", "jhgtsd7fjmytkr"] for s in static_strings: result = decrypt_data(to_decrypt, id + s, ui) v = True for c in result: if c not in string.printable: v = False break if v: print result break

This Python script already contains the values for the following example POST request with the encrypted data in the "data" parameter.

The script decrypts the data value as the following.

[Untitled - Notepad] - [23/08/2014 00:52:04] hello world!!!

This data is from the key logging, as I typed "hello world!!!" into an instance of notepad.exe.

Credit Card Scraping

The credit card scraping is done in its own thread. The functionality of the scraping is not different from the methods seen in other point of sale malware. It will enumerate running processes, then attempt to open each one. Once the process handle is open, it will attempt to enumerate memory segments that it can read. For each of these, it will read the memory segment, and parse through it for credit card track information. It will then upload parts of the track data just as it did with the key logging information.

When we decrypt this information, we get the following.

4111111111111111^^210510100000000000000011400000 4111111111111111=210510100000114000?

This is fake credit card information I stored in an instance of notepad.exe. The code parsing for credit card information ignores any credit card that does not use normal rules for authorization processing (prepaid credit cards, temporary bank cards, etc). Specifically, it ignores any credit card track data in which the second digit of the Service Code is not 0. You can get more information on the specifics of credit card track information here.

Conclusion

The Backoff POS malware was previously unknown until it was discovered at over 1,000 businesses. Despite being similar to other POS malware, it managed to stay hidden mostly due to the novel packing methods that were able to defeat some of the biggest cybersecurity vendor's ability to detect it. CylancePROTECT and other Cylance products would have stopped this attack, as our mathematical models from February detected some of these samples before they were even compiled. Want to get plugged in to the power of PROTECT? Contact a Cylance expert today!

Samples Used in this Post