Thursday, January 16, 2014

Comparing the Dexter and BlackPOS (Target) RAM Scraping Techniques

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);
}

Notice the malware stops at 0x6FFFFFFF, to avoid scanning inside system DLLs which normally exist in high regions of process memory space. The ScanRange function (not shown) breaks the ranges identified by VirtualQueryEx into (roughly) 10 MB chunks and uses ReadProcessMemory to read the data into a buffer, which it then checks for patterns and substrings related to the credit card information that it wants to steal. Dexter did something similar, but read data in roughly 400 KB chunks instead.

In conclusion, Dexter and Trojan.POSRAM are really quite similar in terms of how they scan memory for the sensitive data.

-Michael Ligh (@iMHLv2)

No comments:

Post a Comment