Level 45
Content Creator
Aug 17, 2014
The LockPoS Point-of-Sale (PoS) malware has been leveraging a new code injection technique to compromise systems, Cyberbit researchers say.
First detailed in July this year, LockPoS steals credit card data from the memory of computers attached to PoS credit card scanners. The malware was designed to read the memory of running processes and collect credit card data that is then sent to its command and control (C&C) server.

Previous analysis revealed that the threat used a dropper that injects it directly into the explorer.exe process. After execution, the dropper extracts a resource file from itself and injects various components that load the final LockPoS payload.

The malware is now employing an injection method that appears to be a new variant of a technique previously employed by the Flokibot PoS malware. With LockPoS distributed from the Flokibot botnet, and with the two threats sharing similarities, this doesn’t come as a surprise.

One of the injection techniques employed by LockPoS involves creating a section object in the kernel, calling a function to map a view of that section into another process, then copying code into the section and creating a remote thread to execute the mapped code, Cyberbit says.

LockPoS was observed using 3 main routines to inject code into a remote process, namely NtCreateSection, NtMapViewOfSection, and NtCreateThreadEx, all three exported from ntdll.dll, a core Dynamic-link library (DLL) file in the Windows operating system.

Instead of calling said routines, the malware maps ntdll.dll from the disk to its own virtual address space, which allows it to maintain a “clean” copy of the DLL file. LockPoS also allocates a buffer for saving the system calls number, copies malicious code to the shared mapped section, then creates a remote thread in explorer.exe to execute its malicious code.

By using this “silent” malware injection method, the malware can avoid any hooks that anti-malware software might have installed on ntdll.dll, thus increasing the chances of a successful attack.

“This new malware injection technique suggests a new trend could be developing of using old sequences in a new way that makes detection difficult,” Hod Gavriel, malware analyst at Cyberbit, explains.

While most endpoint detection and response (EDR) and next-gen antivirus products already monitor the Windows functions in user mode, kernel functions can’t be monitored in Windows 10, where the kernel space is still guarded. To ensure successful detection, improved memory analysis should be employed, the researcher says.

Deleted member 65228

Firstly, the injection technique relies on remote thread creation. Normally, you use CreateRemoteThread (KERNEL32) however this lands at RtlCreateUserThread (NTDLL) and this leads to the calling of NtCreateThreadEx (NTDLL). Remote thread creation injection is by far the most popular injection method on Windows in history which exists, and has been abused by thousands of malware samples. That's an understatement. Millions of malware samples.

Secondly, on 32-bit systems an Anti-Virus can intercept remote thread creation from kernel-mode by patching the NtCreateThreadEx routine within NTOSKRNL directly. Since kernel-mode patching is not going to work on 64-bit right off the bat due to PatchGuard, virtualisation can be applied with the hyper-visor to isolate a program in a duplicate environment, with or without sharing resources such as the Global Descriptor Table (GDT). Moving on, after this is applied, emulation of KiSystemCall32 or KiSystemCall64 can be utilised to intercept all system calls system-wide. The only way to bypass this emulation interception is to re-implement the routines using kernel-only routines or manually replicate KiSystemCallXx yourself, which would work by extracting the address of the System Service Routine from the KeServiceDescriptorTable (or Shadow for win32k) manually, and then update the PreviousMode under the KTHREAD structure for the current thread to KernelMode (the offsets change depending on the OS version/updates and the KTHREAD structure is opaque therefore this will cause a BSOD depending on the scenario), calling the routine using the extracted address, and then updating the PreviousMode back to the original it was previously because if the previous mode is not reverted back, there's a big security risk considering this is enforced as a privilege escalation protection mechanism in the Windows Kernel to restrict user-mode software from performing Native API calls using kernel-mode addresses.

Thirdly, you don't need to patch NtCreateThreadEx in kernel-mode (which is unstable and will decrease system performance most likely), nor hook it in user-mode. Microsoft offer a stable, documented and officially supported kernel-mode callback called PsSetCreateThreadNotifyRoutine. There's also an Extended version (with an Ex prefix) which is updated for modern versions of Windows. This is all accessible (at least for the non-Ex variant) since Windows Vista and/or Windows XP for (x64 kernel only for XP). Within the callback routine, you'll be executing within the context of the process which spawned the new thread but before the remote thread is successfully created, and you can identify the target for the remote thread creation effortlessly because all of this data is provided to you with the callback automatically.

On top of this, for a 32-bit process executing on a 64-bit environment, you can intercept WOW64 (Windows On Windows 64). The 32-bit compiled NTDLL is used for 32-bit compiled processes regardless of the OS environment architecture, and if WOW64 is active, it'll redirect execution flow to the 64-bit NTDLL after moving into 64-bit world, which is achieved by switching the segment selector to 0x33 (0x23 is used for 32-bit world). Therefore, a 32-bit process running on a 64-bit environment will still trigger interception of WOW64 unless the technique known as Heavens Gate is being applied, which evolves around manually replicating WOW64 to access 64-bit addresses (e.g. perform an x64 system call within a 32-bit process on a x64 environment). This sample doesn't use Heavens Gate so if it is 32-bit compiled then you can exploit that vulnerability to block it from bypassing your hooks just by intercepting WOW64 which is very simple to do because all the 32-bit NTDLL stubs for Nt*/Zw* (Zw* addresses are the same as Nt* with NTDLL) will reference an address which gets put into EDX and then you can just trace all these addresses and hook one of them, and then compare what is within the EAX register to identify which system call is being targeted.

On the note, you can prevent the "hook" bypass mechanism of this malicious software very easily. We know it is copying code across which is being extracted from NTDLL... Therefore, you can intercept the read request and give it back the modified data. This will give it the bytes for the stub which is still hooked, regardless of not being taken from the image already loaded in the process. You can also detect the SYSENTER/SYSCALL instructions being copied to memory, and then determine the system call routine target via the system call ID being put into the EAX register -> re-hook the memory on the go if its a routine you've already hooked to intercept. This would leave the malware doing all these operations and achieving no results, because the buffer containing the system call bytes would still be hooked.

The actual method for getting the code executed is old, the different part is having the malicious code copied across to the address space of the process. Creating a remote thread is the stupidest thing because it triggers the kernel-mode callback, and the routine NtCreateThreadEx can still be hooked in user-mode alone and not evaded with the technique it used to try and bypass the hooks, as I've already noted.

All any vendor has to do to block the payload of the injector is use PsSetCreateThreadNotifyRoutineEx for their anti-code injection feature for the remote thread creation monitoring, or use the hyper-visor and emulate KiSystemCallXx (which Kaspersky do for that matter although I am not sure how much they apply it - I just know they do emulate KiSystemCall64).

Alternatively, a vendor can strip the PROCESS_CREATE_THREAD access rights being granted to a new handle to explorer.exe (both for handle creation and duplication) using the famous ObRegisterCallbacks kernel-mode callback. Another documented, stable, reliable and officially documented callback. No patching of NtOpenProcess/ObOpenObjectByPointer/ObpCreateHandle/PspOpenProcess blah blah required. 99% of modern vendors already use this callback as one of their self-defence mechanisms, you can bet McAfee definitely do. LOL.

The section stuff is interesting but the actual method for remote thread creation is not new, and the malware is at a disadvantage. Not to mention explorer.exe is STANDARD RIGHTS by default, so it's still going to not have privileged access unless it targets a PRIVILEGED process which will require the malware launcher to be PRIVILEGED (either via UAC allowance or a bypass for UAC - which it doesn't seem it has).

Nothing to worry about. If you have a good AV product which is good with preventing code injection, it isn't going to miss this attack. And if it does, then it clearly isn't monitoring for remote thread creation properly because it must be pretty blind to miss it.
Last edited by a moderator:

Deleted member 65228

In fact, maybe it is a good idea for AVs to start flagging access to NTDLL on disk for reading into memory under certain circumstances. This could be a good idea, since genuine software isn't going to do this. Excluding the Windows Loader for when programs are started up of course.

They can track the call stack and use this to distinguish between the Windows Loader, and the authors own code trying to access NTDLL on disk. There's also built-in support to do this using a Win32 API library but I can't remember what it is called... Related to debugging functionality if I recall correctly.

Alternatively, they can do it by waiting for a file-system event hit for \\??\\SystemDriveLetter:\\WINDOWS\\System32\\ntdll.dll is hit, they can check if it's for mapping/reading into memory. Then, they can check if NTDLL is already loaded in the process, as well as the creation time of the process (available within the Process Environment Block AFAIK), and then add some verification to prevent false positives - maybe set a wait trap for the buffer to be accessed for copying contents across to executable pages in memory. And restrict it for untrusted/unknown or non-digitally signed binaries only.