There’s been a lot of media discussion about rawpos in the past few weeks, most notably the recently disclosed breach of Goodwill. But there has been surprisingly little from the reversing community—aside from this write-up by Symantec. So I wanted to discuss some technical points of rawpos and hopefully shed some light into its capabilities and functionality.
What is rawpos?
rawpos is a simple memory scraper that is responsible for aggregating card data on the victim system. This particular family of memory scrapers is about as simple as they come. It uses a particularly ugly regular expression to find card data and dumps any results in clear-text to one or more dump files.
rawpos is typically seen bundled with two other pieces of malware:
- A Perl2Exe-compiled sample that is responsible for encrypting any discovered card data. (Perl2Exe is a program that bundles a piece of code that was scripted using the Perl language into a Microsoft Windows executable. This ensures a piece of Perl code can run across most, if not all, Microsoft Windows operating systems.)
- A component that is installed as a service, and is responsible for running rawpos and the Perl2Exe sample. In short, this malware’s only purpose in life is to ensure rawpos and the Perl2Exe run if the system is restarted.
While the additional malware samples are not required in order for rawpos to function, they provide additional capabilities that enhance it greatly. I’ve outlined the flow of how these samples interact with each other below.
The rawpos malware execution flow
- The attacker drops the three files on the victim machine.
- A malicious service is installed to ensure rawpos and Perl2Exe run at reboot.
- rawpos targets specific processes and dumps any identified card data to dump files in clear text.
- Perl2Exe monitors the dump directory and encrypts any dump files using a simple XOR key.
As I’ve said, rawpos itself does not have an installation routine. Instead, it relies on the malicious service for all persistence requirements. The malicious service executable has the ability to accept a number of different arguments when executed, prefaced by either the ‘-‘ or ‘/’ character:
- install – Install the malware as a service
- remove – Remove the service
- debug – Run the malware without the service dependency.
Malicious service command line arguments
After being installed as a service, this malware sets a description for the malicious service. We’ve seen a number of malware samples use this technique to deter administrators and forensic investigators from easily discovering the malicious service.
The malicious service with a description
As you can see in the screenshot above, giving the malicious service a description makes it difficult to detect by simply looking at the installed service list. The lack of misspellings and improper grammar is also interesting. Other malware families we have observed often contain such mistakes, probably because the malware is written by individuals who do not speak English natively.
When executed, the malicious service will simply make an external system() call to run the Perl2Exe and rawpos samples. I’ve provided an example of what this looks like (link to sample).
The malicious service running rawpos and Perl2Exe
While this particular tactic lacks elegance from a coding point of view, it remains effective. The malicious service enters an infinite loop after the system() call is made.
Memory scraping is the primary function of the rawpos malware. But before I dig into the logistics of how it does this, I’d like to quickly discuss the main() function of the rawpos malware. The malware author took a slightly odd approach here.
Instead of simply running the malware in an infinite loop, the author decided to attempt to scrape memory from the targeted executable(s) once. It then executes a new instance of itself before exiting. In doing so, the author essentially replicates an infinite loop without actually using an infinite loop.
It’s unclear why the author chose this technique. If I had to speculate, I’d argue it was either a lack of sophistication by the author, or perhaps he/she discovered that this technique was less likely to be caught by antivirus heuristics.
The main() function of rawpos
Fortunately for us, this main() function is consistent across a number of variants I’ve analyzed. This allows us to use this function as a point of detection in a YARA rule, which I’ve provided here.
As for the memory scraping functionality, the malware uses the common EnumProcesses Windows API call to iterate the running processes on the victim machine. It will then target a specific list of executable names. This list of names varies based on the specific variant of rawpos you’re looking at. Should the malware encounter one of these executable names, it will attempt to identify card data using the following regular expression:
It then writes any discovered cardholder data to a ‘memdump’ directory that it previously created. This folder resides in the current working directory (CWD) of rawpos. The dump files themselves are formatted with the following naming convention:
rawpos does not obfuscate or encrypt the card data within these files. Instead, this job falls to the Perl2Exe malware I previously mentioned.
The great thing about Perl2Exe, from a reversing point of view, is the fact that we can recover the complete raw code, complete with comments made by the author. While this task is outside the scope of this blog post, I’d direct any curious individuals to these two blog posts, which outline steps that can be taken to extract this raw Perl code.
When we extract the raw Perl code of one of the rawpos Perl2Exe samples, we see that the file monitors the ‘memdump’ directory previously created by rawpos. When it discovers a *.dmp file, it encrypts this data using the following code:
The routine is quite trivial; it’s simply XORing any data found in *.dmp files with the multi-byte XOR key of ‘memdump’ (previously defined in the Perl code). It writes this encrypted data to a ‘spoolsv.chm’ file (again, previously defined). It takes a few other actions taken, such as time stomping this ‘spoolsv.chm’ file, but that’s all the Perl2Exe file does.
I’ve yet to encounter a Perl2Exe file that has built-in exfiltration of any discovered data. However, I wouldn’t be surprised to discover that some variants might have this functionality. As exfiltration is not typically encountered in the three malware samples I’ve discussed, you can infer that the attackers manually acquired the discovered track data.
Comparing rawpos to other point-of-sale malware families, it’s much more rudimentary. But organizations should still treat it as a threat. The malware family is quite prevalent, and that fact alone shows that this malware works and is effective.
In hopes of defending against this family, I’ve included YARA signatures for the rawpos malware, its associated malicious service, and Perl2Exe compiled samples. I’ve also included MD5 hashes for publicly encountered samples.