## **Malware Overview**
FrameworkPOS is a Point-of-Sale (POS) malware that is designed to steal credit card information. The malware is associated with the cybercrime group FIN6. Based on compilation dates of the malware, this strain is believed to have emerged around late 2015. The malware has remained relevant and saw a resurgence in 2019 from the FIN6 group. FrameworkPOS is a stealthy piece of malware that disguises itself as 'LogMein' software that abuses native binaries on the system for communication and persistence; it has a unique approach on being able to clean itself off the system if it is possibly being detected.
| Hash | Value |
| ------ | ---------------------------------------------------------------- |
| MD5 | 67a53bd24ee8499fed79c8c368e05f7a |
| SHA256 | 81cea9fe7cfe36e9f0f53489411ec10ddd5780dc1813ab19d26d2b7724ff3b38 |
![[Pasted image 20250722182005.png]]
### **File Identification (DiE)**
Initial File enumeration shows this is a 32-bit C++ binary, compiled with Visual Studio using the Microsoft Linker.
![[Pasted image 20250722182052.png]]
Looking for potential program functionality, there is 4 imports that can be seen at compile time that are statically loaded. While many of these are native system binaries that are loaded by default for a executable to run, they do give initial insight into what can be expected.
![[Pasted image 20250722182107.png]]
In particular drilling into WS2_32.dll, a common DLL used for network communication, there is multiple Windows API's that appear to use Ordinals for light obfuscation.
![[Pasted image 20250722182118.png]]
While unable to see what these ordinals correspond to, WS2_32.dll purpose is to aide with the setting up of the network sockets which the malware will use to communicate on the target host. Digging into the binary further, the malware will XOR its data with an encryption key of 0x4d for most of it's evasion. In particular it also utilizes this for some of the WS2_32.dll functions, which when using the XOR key of 0x4d on two
of the strings near the loading of WS2_32.dll, 'recv' & 'send' are decrypted. Both of these API function's are crucial for the sending and receiving of data between sockets.
![[Pasted image 20250722182129.png]]
## **Main Malware Function**
FramewordPOS has 4 main control operations that dictate the flow of the program:
1. Stop
2. Uninstall
3. Install
4. Service
![[Pasted image 20250722182137.png]]
### **Service**
Dropping into the 'service' within the FramewordPOS Main Routine, the mw_CheckAdminPrivs() dictates the flow of the service argument. Within mw_CheckAdminPrivs, AllocateAndInitializeSid is used to create an admin SID and this is checked against current process token for same SID structure. If there is no admin SID match, there is a mutex created called 'DLLLaunchasdf1'. From there the injection process for credit card scanning and networking communication is set-up through mw_Enumerate_and_Injection_Setup(). If there is a match to the admin SID that was created, The 'LogMeIn Hamachi' Service is created and started up; Very similar to if the 'install' parameter argument is supplied. Admin privileges are often required to create a service, in this case when the malware is put into a service mode and admin is not present it appears to attempt to just into the process injection portion.
### **Install (Service Creation)**
In order to create persistence, if admin privileges exist for the user, a service is created named 'LogMeInHamachi'. A couple notable things with the service is the dwDesiredAccess:SERVICE_ALL_ACCESS and dwStartType:SERVICE_AUTO_START. While admin rights are required to create a service, the malware puts minimal restrictions on who can interact with the service and ensures persistence on reboots by enabling SERVICE_AUTO_START. Additionally within the service creation we see a buffer supplied to lpBinaryPathName, the GetModuleFileNameA writes to this variable the full path of the executable running. This allows for dynamic path and naming conventions if the malware should be moved or renamed across systems.
![[Pasted image 20250722182149.png]]
### **Uninstall/Stop**
The malware makes use of getting a handle to the service with OpenSCManagerA and OpenServiceA. If successful, the API's for CloseServiceHandle and DeleteService are used to Delete the malware off the system.
## **Process Scanning**
If the User running the executable is not an administrator, or no argument is supplied, the malware will jump to the function that kicks of the process snapshots and scanning of memory. FrameworkPOS relies on an XOR routine for decrypting it's variables with a key of 0x4d. Using this routine, the Injection Routine decrypts a String 'SeDebugPrivilege'. Passing this argument into mw_Lookup_Token_Privs, a check is made for any Processes with that privilege assigned.
![[Pasted image 20250722182158.png]]
The purpose of this process injection is to loop through process tokens looking where 'SeDebugPrivilege' is and attempting to enable the privilege.
![[Pasted image 20250722182204.png]]
Per our decompiled code, the crux of the process injection relies on the Windows API's AdjustTokenPrivileges() and LookupPrivilegeValueA(). The decoded SeDebugPrivilege string is passed into LookupPrivilegeValueA() to determine if that privilege exists within the process token. If it is present, a call is made to AdjustTokenPrivileges() with the token handle attempting to ENABLE the privileges in the specified token. Should that be successful, a 0 is returned allowing the malware to continue on; if the SeDebugPrivilege is not present or it's unable to adjust privileges, the malware will continue to loop through processes on the system.
If SeDebugPrivilege is present and able to be enabled, the malware attempts to load WS2_32.dll, presumably for any network communication that's going to perform. FrameworkPOS uses a custom routine for it's network communication, preferring to set-up a file IO Stream with a pointer to a buffer of data with a specified length such as below:
![[Pasted image 20250722182211.png]]
CreateToolhelp32Snapshot is used to get a handle to a snapshot of the processes which includes the heaps, modules, and threads for these processes. A PROCESSENTRY32 structure is created from the Snapshot taken, with each Process within the snapshot being looped through checking for injection opportunities. Before the process is scanned, it's compared against a whitelist of executables which contains:
- 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
Looking at the disassembly, the size is loaded into a variable to loop through. The base address of 0x42e098 is the location of the first process name string 'wininet.exe'. As long as the PROCESS32ENTRY process doesn't match wininet.exe, the loop will continue to iterate from base address of 0x42e098 and adding 24 bytes to each iteration until it loops through the list of the 20 processes. If there is a process match, the next process taken from the Snapshot will be loaded in and comparisons ran again. While it remains to be seen why these processes are singled out to not be scanned, this can be due to:
- Too time consuming if the process is allocated large amount of memory
- Low likelihood of credit card data being stored in that process memory
- Security controls in place that would detect memory scanning of specific processes
![[Pasted image 20250722182221.png]]
Within mw_Scan_Processes_For_Injection, memory pages are queried looking for specific memory permissions on pages. If conditions for memory criteria are met, a structure for the process is created with a handle returned to this structure; struct_Process_info in this case being a pointer to the struct.
![[Pasted image 20250722182227.png]]
Components of the Structure (Created within mw_Scan_Processes_For_Injection):
![[Pasted image 20250722182235.png]]
Being unable to 100% see what was being created, I deferred to Sidekick to take a stab at it, indicating the following information below
```
struct injection_info {
int32_t processHandle; // offset 0: *result = arg1
int32_t baseAddress; // offset 4: result[1] = *arg2
int32_t regionSize; // offset 8: result[2] = arg2[3]
int32_t padding; // offset 12: (unused/alignment)
int32_t* bitMap; // offset 16: result[4] = malloc(arg2[3] >> 3)
int32_t totalSize; // offset 20: result[5] = arg2[3]
int32_t flags; // offset 24: result[6] = arg3
int32_t* next; // offset 28: result[7] = 0
};
Key points about this structure:
- Allocated with malloc(0x20)
- Contains process and memory region information
- Includes a bitmap for tracking scanned memory
- Uses a linked list structure (result[7] points to next)
- Stores injection flags and parameters
```
Regardless of being able to confirm this, the pointer to struct_Process_info is passed into the Main Credit Card structure, which is the entire purpose of this malware. This allows us to confirm the pointer being passed contains the processes and their memory regions that will be scanned for credit card information
![[Pasted image 20250722182246.png]]
## **Credit Card Stealing**
The entire point of the FramewordPOS malware is to steal credit card numbers. Nested within the main credit card function is a routine to determine valid credit card numbers. Examining a few of the credit card checks, the first number is validated to determine the CC processor. The malware attempts to validate common credit card processors such as Visa, Mastercard, Amex, and Diners Club.
Checking for Visa and MasterCard Numbers
![[Pasted image 20250722182353.png]]
Checking for Diners Club Numbers
![[Pasted image 20250722182408.png]]
If the start of the number matches the sequence, a call is made to the Luhn Algorithm function. The Luhn Algorithm is a checksum formula that can be used to validate credit card numbers. This ensures to a higher degree data that is being exfiltrated are valid credit card numbers.
The malware also pays attention to the length of the credit card data. Track1 and Track2 credit card data is of different lengths, and the malware attempts to sort them accordingly. Based on the size, 'tt1' or 'tt2' is prepended to the exfiltration string.
![[Pasted image 20250722182515.png]]
Upon finding valid credit card numbers, the FramewordPOS malware attempts to exfiltrate the data through DNS. The credit card numbers are exfiltrated as a subdomain to 'a193-45-3-47-deploy-akamaitechnologies.com'. Analyzing domain registration information for 'a193-45-3-47-deploy-akamaitechnologies.com', we can find registration history and geographically where this domain had been registered. Registration points to December of 2015, which is also a similar time frame when the malware was compiled. Additionally, we can see a REG.RU which can be traced back to Russia.
![[Pasted image 20250722182614.png]]
## **Service Cleanup**
Within the DNS Communication Function of the malware, there is a clean-up routine (mw_Cleanup_Routine()), which appears to be invoked by the ascii characters 'cccc' from the C2 server. This allows us to presume the malware will clean-up if a 'cccc' is received from the server it's communicating with.
![[Pasted image 20250722182720.png]]
The malware cleans up it's Registry Key, "LogMeIn Hamachi Launcher", within "Software\Microsoft\Windows\CurrentVersion\Run". After deleting the registry persistence, a call is made to the C2 data exfiltration routine passing a .dat file. We can presume from this, this is likely data containing Credit Card numbers that is being exfiltrated before the malware is completely cleaned up. Additionally, a deletion of logmein.bid is performed. Lastly, a batch script is created with the contents:
![[Pasted image 20250722182852.png]]
As the batch script is executed, a ping command is performed to cause a delay in the deletion of the malware files. This allows FrameworkPOS to finish it's clean-up routine before completely exiting.