Detect KernelCallbackTable in Microsoft Sentinel
Adversaries abuse the KernelCallbackTable in the Process Environment Block (PEB) to hijack execution flow and execute shellcode within a target process. The KernelCallbackTable is initialized when user32.dll is loaded into a GUI process, containing function pointers for handling Win32 messages. An adversary uses NtQueryInformationProcess() to locate the PEB, reads the KernelCallbackTable pointer, duplicates the table in new process memory via WriteProcessMemory(), replaces a function pointer (e.g., fnCOPYDATA) with shellcode address, then updates the PEB to point to the modified table. Sending a Windows message (e.g., WM_COPYDATA) to the target triggers the shellcode. Used by Lazarus Group (DPRK) and FinFisher/FinSpy. Execution is masked under a legitimate GUI process.
MITRE ATT&CK
- Technique
- T1574 Hijack Execution Flow
- Sub-technique
- T1574.013 KernelCallbackTable
- Canonical reference
- https://attack.mitre.org/techniques/T1574/013/
KQL Detection Query
DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName in~ ("NtQueryInformationProcess", "ntdll.dll")
or ProcessCommandLine has_any ("VirtualAllocEx", "WriteProcessMemory", "NtWriteVirtualMemory")
| join kind=inner (
DeviceProcessEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ ("explorer.exe", "notepad.exe", "calc.exe", "mspaint.exe")
| where not(FolderPath startswith "C:\\Windows\\System32")
| project DeviceName, ParentProcessId=ProcessId, ParentFileName=FileName, ParentPath=FolderPath
) on DeviceName
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
ParentFileName, ParentPath
| sort by Timestamp desc
| union (
DeviceEvents
| where Timestamp > ago(24h)
| where ActionType == "ProcessInjection" or ActionType == "RemoteThreadInjection"
| where TargetProcessFileName in~ ("explorer.exe", "notepad.exe", "iexplore.exe", "chrome.exe", "firefox.exe")
| project Timestamp, DeviceName, AccountName=InitiatingProcessAccountName,
InitiatingProcessFileName, TargetProcessFileName, ActionType
)
| sort by Timestamp desc Detects KernelCallbackTable-style injection by monitoring for remote process memory operations targeting GUI processes. Since KernelCallbackTable hijacking requires WriteProcessMemory into a GUI process's address space, this query looks for: (1) process injection events targeting common GUI applications (explorer.exe, notepad.exe), and (2) cross-process memory write operations from unexpected processes. The technique requires the target process to have user32.dll loaded and to receive a Windows message.
Data Sources
Required Tables
False Positives & Tuning
- Legitimate accessibility software (screen readers, magnifiers) that interact with other process memory for UI automation
- Debug builds of applications that legitimately use WriteProcessMemory for inter-process communication
- Virtualization and container tools that may access process memory for management purposes
- Some game anti-cheat systems that inject DLLs into game processes
Other platforms for T1574.013
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Enumerate PEB and KernelCallbackTable Location
Expected signal: PowerShell process creation with inline C# code using P/Invoke. The NtQueryInformationProcess call may be logged by EDR. Sysmon Event ID 1 captures the PowerShell execution. This is the API call chain that precedes KernelCallbackTable modification.
- Test 2Detect Processes with Write Access to GUI Process
Expected signal: PowerShell process creation with module enumeration. Get-Process calls generate multiple process handle opens. EDR may detect enumeration of module lists across processes. Sysmon may log multiple process access events.
- Test 3Send WM_COPYDATA to Trigger KernelCallbackTable Execution
Expected signal: PowerShell process creation with P/Invoke calls to user32.dll (GetForegroundWindow, GetWindowThreadProcessId). These API calls precede the SendMessage/PostMessage calls used to trigger KernelCallbackTable callbacks in the target process.
References (5)
- https://attack.mitre.org/techniques/T1574/013/
- https://blog.malwarebytes.com/threat-intelligence/2022/01/north-koreas-lazarus-apt-leverages-windows-update-client-github-in-latest-campaign/
- https://modexp.wordpress.com/2019/05/25/windows-injection-finspy/
- https://www.microsoft.com/security/blog/2018/03/01/finfisher-exposed-a-researchers-tale-of-defeating-traps-tricks-and-complex-virtual-machines/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1574.013/T1574.013.md
Unlock Pro Content
Get the full detection package for T1574.013 including response playbook, investigation guide, and atomic red team tests.