Up until yesterday when Brian Krebs wrote A First Look at the Target Intrusion, Malware, there weren’t many details about the involved code. Now that its out there, I thought it might be interesting to see how the “RAM scraping” feature worked in comparison to the Dexter malware. As it turns out, the two are quite similar, and neither are really exciting. This just goes to show that you don’t need advanced (fine tuned, maybe) tools to be successful at cyber crime.
The BlackPOS malware (see Krebs’ article) A.K.A Trojan.POSRAM uses EnumProcesses to get the list of active PIDs on the system. It then cycles through the list, skipping its own PID (Dexter also skipped its parent PID). For all other processes, it calls GetModuleFileNameEx to get the full path to the executable, then strips off the file name (i.e. explorer.exe) portion, converts it to lowercase, and compares it against “pos.exe” with strcmp. Had Target known that this specific sample only looks in the memory of processes named pos.exe, it could have renamed its Point-of-Sale application and avoided the news (for a few minutes anyway… other samples are known to exist that looked for other process names).
The “pos.exe” string isn’t exactly in plain text, but the malware isn’t packed either. It uses a very simple obfuscation technique where the string is split and the characters are shifted around a bit. You can see it in the read-only section of the PE file:
Once it finds a pos.exe process, it opens a handle with OpenProcess and uses VirtualQueryEx to begin iterating through the process’s available memory blocks. This is exactly what Dexter did — the only difference being that Dexter also checked memory protection constants and skipped ranges that were marked PAGE_NOACCESS or PAGE_GUARD. As a result, the BlackPOS malware could easily lead to an access violation (e.g. STATUS_PAGE_GUARD_VIOLATION) capable of crashing the malware. I can only imagine the look on the attackers’ faces once they realized that they came up with 0 credit cards because they didn’t check page permissions before reading a memory address. Unfortunately for Target, the pos.exe processes must not have had any no-access or guard pages set.
Here’s a snippet of code reverse engineered from the malware that shows how it determines which ranges to scan:
VOID ScanMemory(HANDLE hProcess)
{
int lpAddress = 0;
int lpMaxAddress = 0x6FFFFFFF;
int endAddress = 0;
MEMORY_BASIC_INFORMATION anMBI;
SIZE_T cbReturned;
do {
cbReturned = VirtualQueryEx(hProcess,
(LPCVOID)lpAddress,
&anMBI,
sizeof(anMBI));
if (cbReturned && anMBI.RegionSize)
{
endAddress = (int)((char *)anMBI.BaseAddress + anMBI.RegionSize);
ScanRange(hProcess,
anMBI.BaseAddress,
endAddress);
}
lpAddress = (int)(char *)lpAddress + anMBI.RegionSize;
} while (lpAddress < lpMaxAddress);
}
In conclusion, Dexter and Trojan.POSRAM are really quite similar in terms of how they scan memory for the sensitive data.
-Michael Ligh (@iMHLv2)
