The Next Level: Memory Address Analysis
In my previous article, we explored how DLL sequence analysis can detect process injection attempts. But what if we could go deeper? What if we could analyze not just which DLLs are loaded, but where in memory they’re being accessed?
This is where terminal ntdll.dll memory offset analysis comes in. When a process accesses another process’s memory, the call stack doesn’t just tell us which DLLs are involved — it tells us the exact memory addresses where those DLLs are being accessed. And that’s where the real gold is hidden.
Why Memory Offsets Matter
The Memory Address Story
Every DLL in a call stack comes with a memory offset — the exact address where that DLL function is being executed. For example:
ntdll.dll+1cef4 (Normal Windows offset)
ntdll.dll+7FFFFFFF (Suspicious high memory)
ntdll.dll+00000000 (Suspicious zero offset)
The Attack Pattern
Attackers don’t just inject code — they inject it at specific memory addresses. When malware performs process injection, it often:
- Allocates memory at unusual addresses
- Writes code to those addresses
- Creates call stacks that reference those addresses
This creates memory offset patterns that deviate from normal Windows behavior.
The Detection Approach: Statistical Memory Analysis
Typical Log Event of Sysmon Event ID 10
{“EventTime”:”2025–07–03 18:27:27″,”Hostname”:”DESKTOP-RMOK8DB”,”Keywords”:-9223372036854775808,”EventType”:”INFO”,”SeverityValue”:2,”Severity”:”INFO”,”EventID”:10,”SourceName”:”Microsoft-Windows-Sysmon”,”ProviderGuid”:”{5770385F-C22A-43E0-BF4C-06F5698FFBD9}”,”Version”:3,”Task”:10,”OpcodeValue”:0,”RecordNumber”:4207,”ProcessID”:3128,”ThreadID”:3884,”Channel”:”Microsoft-Windows-Sysmon/Operational”,”Domain”:”NT AUTHORITY”,”AccountName”:”SYSTEM”,”UserID”:”S-1–5–18″,”AccountType”:”User”,”Message”:”Process accessed:\r\nRuleName: technique_id=T1003,technique_name=Credential Dumping\r\nUtcTime: 2025–07–04 01:27:27.640\r\nSourceProcessGUID: {ded167f5–2df5–6867–4b00–000000000500}\r\nSourceProcessId: 3168\r\nSourceThreadId: 7088\r\nSourceImage: C:\\ProgramData\\Microsoft\\Windows Defender\\platform\\4.18.25050.5–0\\MsMpEng.exe\r\nTargetProcessGUID: {ded167f5–2df3–6867–0c00–000000000500}\r\nTargetProcessId: 688\r\nTargetImage: C:\\Windows\\system32\\lsass.exe\r\nGrantedAccess: 0x1010\r\nCallTrace: C:\\Windows\\SYSTEM32\\ntdll.dll+9d524|C:\\Windows\\SYSTEM32\\KERNELBASE.dll+308ee|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+efcc0|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+efad7|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1beb44|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1be627|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+5003a9|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+3b4a2|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+12ff66|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+3af77|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+3eeab|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+3dd33|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+9f461|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+9f082|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+a3160|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+dbe17|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+d9601|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1ac482|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+438418|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+438360|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+42b86b|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+42b79d|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1ab4c9|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1ab12f\r\nSourceUser: NT AUTHORITY\\SYSTEM\r\nTargetUser: NT AUTHORITY\\SYSTEM”,”Category”:”Process accessed (rule: ProcessAccess)”,”Opcode”:”Info”,”RuleName”:”technique_id=T1003,technique_name=Credential Dumping”,”UtcTime”:”2025–07–04 01:27:27.640″,”SourceProcessGUID”:”{ded167f5–2df5–6867–4b00–000000000500}”,”SourceProcessId”:”3168″,”SourceThreadId”:”7088″,”SourceImage”:”C:\\ProgramData\\Microsoft\\Windows Defender\\platform\\4.18.25050.5–0\\MsMpEng.exe”,”TargetProcessGUID”:”{ded167f5–2df3–6867–0c00–000000000500}”,”TargetProcessId”:”688″,”TargetImage”:”C:\\Windows\\system32\\lsass.exe”,”GrantedAccess”:”0x1010″,”CallTrace”:”C:\\Windows\\SYSTEM32\\ntdll.dll+9d524|C:\\Windows\\SYSTEM32\\KERNELBASE.dll+308ee|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+efcc0|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+efad7|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1beb44|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1be627|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+5003a9|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+3b4a2|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+12ff66|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+3af77|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+3eeab|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+3dd33|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+9f461|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+9f082|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+a3160|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+dbe17|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+d9601|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1ac482|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+438418|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+438360|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+42b86b|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+42b79d|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1ab4c9|C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\{D8DDFE81–56C6–4F46–93A5–3020B6B89AE4}\\mpengine.dll+1ab12f”,”SourceUser”:”NT AUTHORITY\\SYSTEM”,”TargetUser”:”NT AUTHORITY\\SYSTEM”,”EventReceivedTime”:”2025–07–03 18:31:15″,”SourceModuleName”:”in”,”SourceModuleType”:”im_msvistalog”}
The Core Concept
Instead of looking for known bad patterns, we analyze the statistical distribution of memory offsets for terminal ntdll.dll calls. Every process pair has a “normal” memory offset range. When malware injects code, it creates offsets that fall outside these normal ranges.
Note: The complete detection query with offset anomaly detection is available in the StealPack beta release of the Bloo platform.
Memory Region Analysis: What the Numbers Tell Us
Normal Windows Memory Patterns
Low Memory Region (0x1xxxxx): Normal user space
High Memory Region (0x7xxxxx): Normal user space
Kernel Space (0x8xxxxx): System calls
Suspicious Memory Patterns
Zero Offset (0x00000000): Potential null pointer dereference
High Memory (0x7FFFFFFF): Potential stack overflow
Kernel Space (0x8xxxxx): Unauthorized kernel access
Real-World Detection Scenarios
Scenario 1: Process Injection via Memory Allocation
Normal: explorer.exe → chrome.exe
Terminal DLL: ntdll.dll+1cef4 (Normal offset)
Z-Score: 0.3
Malicious: malware.exe → chrome.exe
Terminal DLL: ntdll.dll+7FFFFFFF (Suspicious high memory)
Z-Score: 4.2
Scenario 2: Code Injection via Memory Writing
Normal: wininit.exe → lsass.exe
Terminal DLL: ntdll.dll+4cc91 (Normal offset)
Z-Score: 0.1
Malicious: mimikatz.exe → lsass.exe
Terminal DLL: ntdll.dll+00000000 (Suspicious zero offset)
Z-Score: 5.1
Operational Trade-offs: Precision vs. Coverage
The Challenge
Memory offset analysis is incredibly precise but requires careful tuning:
Pros:
- Catches sophisticated process injection techniques
- Identifies memory manipulation attempts
- Provides exact memory address context
- Adapts to environment-specific baselines
Cons:
- Requires sufficient historical data for meaningful baselines
- May generate false positives during legitimate software updates
- Needs tuning per environment and process pairs
- Memory addresses can vary between Windows versions
The Reality Check
In production, we’ve found that:
- Z-scores > 3.0 typically indicate real threats
- Z-scores 2.0–3.0 require investigation
- Z-scores < 2.0 are usually noise
MITRE ATT&CK Mapping: Why T1055 Still Fits
T1055 — Process Injection applies because:
- Technique Context: Attackers inject code into legitimate processes at specific memory addresses
- Memory Evidence: Injected code creates unusual memory offset patterns
- Detection Relevance: Our z-score analysis catches these memory deviations
This isn’t just about DLL loading — it’s about where in memory those DLLs are being accessed.
Platform-Level Implications
For Detection Engineers:
- Implement baseline learning periods (30+ days recommended)
- Tune z-score thresholds based on your environment
- Create separate alerts for different memory regions
- Monitor for memory address pattern changes
For Security Architects:
- Consider memory analysis as part of your EDR strategy
- Balance detection depth with performance impact
- Plan for the operational overhead of memory-based alerts
For MDR Teams:
- This detection requires context and investigation
- Not every unusual memory offset is malicious
- Build playbooks for memory address analysis
Advanced Memory Analysis Techniques
1. Memory Region Correlation
Analyze memory regions for suspicious patterns
CASE
WHEN CAST(CONCAT(‘0x’, terminal_offset) AS BIGINT) BETWEEN 0x00000000 AND 0x0000FFFF
THEN ‘Suspicious Low Memory Region’
WHEN CAST(CONCAT(‘0x’, terminal_offset) AS BIGINT) BETWEEN 0x7FFFFFFF AND 0xFFFFFFFF
THEN ‘Suspicious High Memory Region’
ELSE ‘Normal Memory Region’
END AS memory_region_analysis
2. Memory Jump Detection
Detect large memory jumps between calls
CASE
WHEN ABS(
CAST(CONCAT(‘0x’, regexp_extract(element_at(split(CallTrace, ‘\\|’), 1), ‘\\+([0–9a-fA-F]+)’, 1)) AS BIGINT) –
CAST(CONCAT(‘0x’, regexp_extract(element_at(split(CallTrace, ‘\\|’), 2), ‘\\+([0–9a-fA-F]+)’, 1)) AS BIGINT)
) > 1000000
THEN ‘Large Memory Jump Detected’
ELSE ‘Normal Memory Progression’
END AS jump_analysis
What’s Next: Beyond Memory Offsets
This detection is just the beginning. Consider extending it to:
- Cross-Process Memory Analysis: Linking memory patterns across multiple processes
- Memory Allocation Tracking: Monitoring where processes allocate memory
- Memory Permission Analysis: Checking memory protection attributes
- Memory Corruption Detection: Identifying memory manipulation patterns
The Bottom Line
Memory offset analysis isn’t about finding needles in haystacks — it’s about finding haystacks that shouldn’t be there. By applying statistical anomaly detection to ntdll.dll memory offsets, we can catch sophisticated process injection techniques that traditional detection misses.
The key is operational discipline: tune your thresholds, investigate your alerts, and build your baselines. Because in the end, the best detection is the one that catches real threats without drowning you in false positives.
This approach has been tested in production environments and has successfully identified process injection attempts, memory manipulation, and other sophisticated attack techniques. The statistical approach provides a foundation for catching unknown threats while maintaining operational efficiency.