This post is also available in: 日本語 (Japanese)

Unit 42 has discovered a new Point of Sale (POS) malware family, which includes multiple variants created as early as November 2014. Over the past few weeks we have been analyzing this malware family, which we have dubbed ‘FindPOS’ due to strings consistently found in each variant.

While this malware doesn’t show strong sophistication, the large number of variants shows prevalence similar to families such as Alina and Backoff. It is clear that FindPOS should be considered a strong threat to Microsoft Windows POS vendors, and measures should be taken to ensure protection.

Workflow

The malware in question has the ability to scrape memory for track data, exfiltrate any discovered data via HTTP POST requests, and in some instances log keystrokes. While the malware family uses many common techniques witnessed in previous malware families targeting POS devices, the prevalence and continued development of this malware demonstrates a threat to those running Windows-based point of sale terminals.

The general workflow of the FindPOS malware family can be seen below.

Evolution

Over the course of our research, a total of nine variants of FindPOS have been discovered. Using compile timestamp information, we can see a timeline of these variants below.

A breakdown of the specific functionality changes between versions is as follows:

Version 2.1

Modified hashing algorithm to use the following information: Volume Serial Number Networking Adapters (IPv4 Only)

Added ‘uinfo’ POST parameter

Version 5.57

Added ability to terminate previously installed FindPOS upon installation

Code cleanup during install

Set main thread to lowest priority

Added memory scraping checks Expiration year between 2014 and 2030 Expiration month between 1 and 12 Service code set to either ‘101’ or ‘201’

Added ability to download/execute files

Removed ‘Cookie: income=1’ HTTP Header

Added User-Agent HTTP Header

Version 5.80

Modified memory scraping checks Expiration year cannot exceed 2030 (no lower bound check) Expiration month cannot exceed 12 (no lower bound check)

Code enhancements to domain/URI configuration

Version 5.90

Added keylogging functionality

Version 6.0

No significant changes identified

Version 6.02

Minor modifications to exfiltration function

Version 6.03

No significant changes identified

Version 6.04

Minor modifications to exfiltration sleep timer

As we can see from the above timeline, FindPOS appears to have been very actively developed early on, while over time the author made minimal changes. These minimal changes were likely made for performance reasons or potentially bug fixes.

Installation

Upon execution, FindPOS will generate a lowercase alphabetic executable name of eight characters (example: abodeign.exe). This name is generated using the following system information:

C:\ Volume Serial Number

SystemBiosdate

VideoBiosdate

CPU Identifier

Microsoft Windows ProductId

Using these values in order to generate results in a consistently generated name when run on the same machine. Please note that the hashing algorithm used was modified in version 2.1. Please refer to the ‘Evolution’ section above for details.

This executable name is then compared against the original executable name of the running malware. Should those names not match, the malware will proceed to continue with its installation routine.

FindPOS proceeds to copy itself to the following directories using the executable name that was previously generated:

%SystemRoot%\System32\[name].exe

%USERPROFILE%\[name].exe

Should these file copy operations prove successful, the malware will write the following registry keys:

HKLM\Software\Microsoft\Windows\CurrentVersion\Run [name] : %SystemRoot%\System32\[name].exe

HKCU\Software\Microsoft\Windows\CurrentVersion\Run [name] : %USERPROFILE%\[name].exe

The malware will proceed to spawn a new instance of %SystemRoot%\System32\[name].exe via a call to CreateProcessA. Should this prove successful, the malware will execute the following command prior to exiting. This command is responsible for deleting the original executable.

cmd.exe /c del [original_executable_path] >> NUL

Should the CreateProcessA call on %SystemRoot%\System32\[name].exe fail, FindPOS will attempt to spawn a new instance of %USERPROFILE%\[name].exe. If this proves successful, FindPOS will attempt to delete the original executable using the same technique previously seen.

After installation of FindPOS is successful, the malware will create a global mutex in order to ensure only one instance of FindPOS is running. This mutex has the following name:

WIN_[hex]

Where [hex] is a series of 16 uppercase hexadecimal characters that are generated using the same technique witnessed when generating the malware’s executable name during the installation routine.

After this mutex is successfully created, FindPOS will continue to scrape memory and optionally log keystrokes.

Memory Scraping

Memory scraping is a technique found in the majority of POS malware families discovered in prior years. The concept is fairly simple: read the memory of running processes on a POS terminal, and look for track data. When a card is swiped on a POS terminal, and the transaction is processed, the card data will often reside in memory unencrypted for a brief period of time. Attackers exploit this weakness in order to find track data.

A common technique for increasing performance of memory scrapers is to denylist a list of commonly seen process names, such as explorer.exe, lsass.exe, csrss.exe, etc. Alternatively, some malware families leverage an allowlist approach, where only specific process names are targeted. FindPOS, however, uses a brand new approach. This particular family determines the owner of every process on the system, via calls to EnumProcesses, OpenProcess, GetTokenInformation and LookupAccountSid. The owner of the process is then compared against the ‘NT AUTHORITY’ string. This filters out any processes not being run as system or as a service. In the example below, all processes except for ‘dwm.exe’ and the multiple instances of ‘conhost.exe’ would be filtered.

Figure 1. Example Running Processes

In the event a process is not filtered, memory is scraped via calls to VirtualQueryEx and ReadProcessMemory. This is a very common approach that is witnessed in almost all memory scrapers.

Once the data is read, FindPOS proceeds to look for track data. Starting with version 5.57, the author began making checks based on various data found within the track data. For example, in version 5.57 the author began ignoring any track data that did not have an expiration date between January 2014 to December 2030. This helped to ensure expired card data was not captured.

Additionally, the author paid close attention to the service codes that appeared within any discovered track data. The service code is a three-digit number that represents the type of card being swiped. In this particular instance, the author chose to only capture cards that held the following options:

First Digit – ‘International interexchange OK’ or ‘International interchange, use IC (chip) where feasible’

Second Digit – ‘Normal’

Third Digit – ‘No restrictions’

By adding these restrictions, the author was able to ignore cards that it did not consider to be appealing. Such cards included gift cards, debit cards, and test cards to name a few.

Any discovered track data is stored in memory until exfiltration occurs. This data is exfiltrated via the ‘data’ POST parameter.

Keylogging

Starting in version 5.90, the author of FindPOS began adding keylogging to this family. Many magnetic card readers often will emulate a keyboard device. Knowing this, many POS malware authors incorporate this functionality into their families. In addition to collecting track data, keylogging also has the ability to potentially collect usernames, passwords, or other sensitive data on the victim machine.

In order to accomplish this, the author spawns a new thread that is responsible for keylogging. A common technique of creating a new empty window, registering itself as a raw input device, and making calls to the GetRawInputData API is used.

Any keystrokes are stored in memory until exfiltration occurs. The keystrokes are exfiltrated via the ‘logs’ POST parameter.

Exfiltration

Exfiltration for FindPOS takes place via HTTP POST requests. A number of hardcoded domains are configured for each sample, often varying between FindPOS variants. HTTP POST requests are made every 120 seconds (2 minutes). In the event any data has been discovered, such as track data or keystroke data, this data is included. An example request from version 5.80 is shown below:

As we can see, a number of POST variables are included in each request:

An example of decoding the ‘uinfo’ parameter can be seen below:

>>> import base64

>>> base64.b64decode(“Sk9TSC1QQyBAIGpvc2gtUENcam9zaA==”)

‘JOSH-PC @ josh-PC\\josh’

Keystroke data and track data is obfuscated using a combination of Base64 encoding and a single-byte XOR encryption. Decoding this data can be seen below:

>>> import base64

>>> raw = “”

>>> for s in base64.b64decode(“HxkaGxgfGhodGhoaGhsTGxcbHxoSGxobGhMbGBkeHxwdEhMaGxU=”):

>>> raw += chr(ord(s) ^ 0x2a)

>>> print raw

5301250070000191=15081010912345678901?

In addition to data exfiltration, FindPOS added the ability to download/execute further malware. Upon sending an exfiltration request, should the server respond with a 0x1 or 0x4 byte, followed by a URL, this file will be downloaded and subsequently executed.

The file is downloaded to a temporary folder, with the file itself prefixed by ‘BN’. This downloaded file is executed via a call to CreateProcessA. In the event the file cannot be properly downloaded or executed, it is deleted from disk.

Domain/IP Address Information

A total of 37 domains were discovered while researching the FindPOS malware family. Of these domains, 13 unique IP addresses were discovered. The geographic location of these IP addresses can be seen below. Please refer to the Appendix for a full list of all domains.

The majority of the domains discovered were configured with the following WHOIS information.

Registrant Name: Julio Quinlan

Registrant Organization: NA

Registrant Street: 4516 Glory Road

Registrant City: Nashville

Registrant State/Province: TN

Registrant Postal Code: 37204

Registrant Country: us

Registrant Phone: +01.9318135965

Registrant Phone Ext:

Registrant Fax: +01.9318135965

Registrant Fax Ext:

Registrant Email: barkmanueta@rambler.ru

Please note that the registrant email was slightly different depending on the domain queried. While the information above appears legitimate, it was discovered to be falsified.

Related Samples – Keylogging/LogMeIn Recon

During the course of our research, a number of similar samples were discovered. One such sample can be seen below.

Version 8.3 – LogMeIn Recon / Keylogger

This particular sample is responsible for collecting LogMeIn account information, logging keystrokes and mouse-clicks, and periodically exfiltrating this data to a remote server. This sample shares a number of characteristics with the FindPOS samples previously discovered. Some of these similarities include the installation process, URI scheme, format of the HTTP POST requests, and the PDB string.

Upon execution, this malware will install itself in the same method as FindPOS. Additionally, a mutex is created using the technique previously mentioned. The malware will attempt determine if LogMeIn Ignition is installed on the victim machine by checking the following registry keys:

HKCU\Software\LogMeIn Ignition\[Variable Hash]\Account : Email

Any discovered emails are exfiltrated using the same HTTP POST requests witnessed in FindPOS. However, instead of using the ‘data’ POST parameter, this particular sample uses the ‘logs’ parameter. This can be seen below:

The malware proceeds to log keystrokes and mouse clicks. This data is exfiltrated every two minutes.

While this sample certainly could have been used to scrape track data from POS terminals that have card readers that emulate keyboard devices, I suspect this sample was more likely used to gain access to more POS machines. It is most likely that this sample was dropped on a machine that was administering multiple POS machines, and the information obtained from this particular box was leveraged to gain access to said POS machines.

It’s also interesting to note that the compile timestamp for this particular sample lines up to just about two weeks after the introduction of keylogging functionality (starting in version 5.90). It would appear that right around this time the malware author added a new trick to his or her repertoire.

Conclusion

Overall, FindPOS isn’t terribly sophisticated. It lacks a number of features that we’ve seen in previous malware families, such as a more sophisticated command and control structure, stronger encryption, and performing luhn checks on any discovered data. Additionally, the evolution of this family provides interesting clues to the notion that this malware was written from scratch. While FindPOS may share minimal similarities with previously witnessed malware families, we are strongly confident that this malware is a brand new family.

While this malware doesn’t show strong sophistication, the large number of variants shows prevalence similar to families such as Alina and Backoff. It is clear that FindPOS should be considered a strong threat to Microsoft Windows POS vendors, and measures should be taken to ensure protection.

Such measures include, but are not limited to, configuring two-factor authentication for any remote access services (LogMeIn, VNC, RDP, etc.), ensuring anti-virus is installed and updated, and ensuring POS devices are not used non-approved functions, such as browsing the web or checking email.

Palo Alto Networks customers are protected by WildFire, which automatically classifies FindPOS samples as malware. Additionally, the indicators we’ve discovered that are related to these attacks have been added to PANDB and Anti-Malware protection systems.

Appendix

Sample Information

Version 2.0

Version 2.1

Version 5.57

Version 5.80

Version 5.90

Version 6.0

Version 6.02

Version 6.03

Version 6.04

YARA Rule