✍️
Red Teaming Experiments
  • What is this iRed.team?
  • Pinned
    • Pentesting Cheatsheets
      • SQL Injection & XSS Playground
    • Active Directory & Kerberos Abuse
      • From Domain Admin to Enterprise Admin
      • Kerberoasting
      • Kerberos: Golden Tickets
      • Kerberos: Silver Tickets
      • AS-REP Roasting
      • Kerberoasting: Requesting RC4 Encrypted TGS when AES is Enabled
      • Kerberos Unconstrained Delegation
      • Kerberos Constrained Delegation
      • Kerberos Resource-based Constrained Delegation: Computer Object Take Over
      • Domain Compromise via DC Print Server and Kerberos Delegation
      • DCShadow - Becoming a Rogue Domain Controller
      • DCSync: Dump Password Hashes from Domain Controller
      • PowerView: Active Directory Enumeration
      • Abusing Active Directory ACLs/ACEs
      • Privileged Accounts and Token Privileges
      • From DnsAdmins to SYSTEM to Domain Compromise
      • Pass the Hash with Machine$ Accounts
      • BloodHound with Kali Linux: 101
      • Backdooring AdminSDHolder for Persistence
      • Active Directory Enumeration with AD Module without RSAT or Admin Privileges
      • Enumerating AD Object Permissions with dsacls
      • Active Directory Password Spraying
  • offensive security
    • Red Team Infrastructure
      • HTTP Forwarders / Relays
      • SMTP Forwarders / Relays
      • Phishing with Modlishka Reverse HTTP Proxy
      • Automating Red Team Infrastructure with Terraform
      • Cobalt Strike 101
      • Powershell Empire 101
      • Spiderfoot 101 with Kali using Docker
    • Initial Access
      • Password Spraying Outlook Web Access: Remote Shell
      • Phishing with MS Office
        • Phishing: XLM / Macro 4.0
        • T1173: Phishing - DDE
        • T1137: Phishing - Office Macros
        • Phishing: OLE + LNK
        • Phishing: Embedded Internet Explorer
        • Phishing: .SLK Excel
        • Phishing: Replacing Embedded Video with Bogus Payload
        • Inject Macros from a Remote Dotm Template
        • Bypassing Parent Child / Ancestry Detections
        • Phishing: Embedded HTML Forms
      • Phishing with GoPhish and DigitalOcean
      • Forced Authentication
      • NetNTLMv2 hash stealing using Outlook
    • Code Execution
      • T1117: regsvr32
      • T1170: MSHTA
      • T1196: Control Panel Item
      • Executing Code as a Control Panel Item through an Exported Cplapplet Function
      • Code Execution through Control Panel Add-ins
      • T1191: CMSTP
      • T1118: InstallUtil
      • Using MSBuild to Execute Shellcode in C#
      • T1202: Forfiles Indirect Command Execution
      • Application Whitelisting Bypass with WMIC and XSL
      • Powershell Without Powershell.exe
      • Powershell Constrained Language Mode ByPass
      • Forcing Iexplore.exe to Load a Malicious DLL via COM Abuse
      • T1216: pubprn.vbs Signed Script Code Execution
    • Code & Process Injection
      • CreateRemoteThread Shellcode Injection
      • DLL Injection
      • Reflective DLL Injection
      • Shellcode Reflective DLL Injection
      • Process Doppelganging
      • Loading and Executing Shellcode From PE Resources
      • Process Hollowing and Portable Executable Relocations
      • APC Queue Code Injection
      • Early Bird APC Queue Code Injection
      • Shellcode Execution in a Local Process with QueueUserAPC and NtTestAlert
      • Shellcode Execution through Fibers
      • Shellcode Execution via CreateThreadpoolWait
      • Local Shellcode Execution without Windows APIs
      • Injecting to Remote Process via Thread Hijacking
      • SetWindowHookEx Code Injection
      • Finding Kernel32 Base and Function Addresses in Shellcode
      • Executing Shellcode with Inline Assembly in C/C++
      • Writing Custom Shellcode Encoders and Decoders
      • Backdooring PE Files with Shellcode
      • NtCreateSection + NtMapViewOfSection Code Injection
      • AddressOfEntryPoint Code Injection without VirtualAllocEx RWX
      • Module Stomping for Shellcode Injection
      • PE Injection: Executing PEs inside Remote Processes
      • API Monitoring and Hooking for Offensive Tooling
      • Windows API Hooking
      • Import Adress Table (IAT) Hooking
      • DLL Injection via a Custom .NET Garbage Collector
      • Writing and Compiling Shellcode in C
      • Injecting .NET Assembly to an Unmanaged Process
    • Defense Evasion
      • AV Bypass with Metasploit Templates and Custom Binaries
      • Evading Windows Defender with 1 Byte Change
      • Bypassing Windows Defender: One TCP Socket Away From Meterpreter and Beacon Sessions
      • Bypassing Cylance and other AVs/EDRs by Unhooking Windows APIs
      • Windows API Hashing in Malware
      • Detecting Hooked Syscalls
      • Calling Syscalls Directly from Visual Studio to Bypass AVs/EDRs
      • Retrieving ntdll Syscall Stubs from Disk at Run-time
      • Full DLL Unhooking with C++
      • Enumerating RWX Protected Memory Regions for Code Injection
      • Disabling Windows Event Logs by Suspending EventLog Service Threads
      • T1027: Obfuscated Powershell Invocations
      • Masquerading Processes in Userland via _PEB
      • Commandline Obfusaction
      • File Smuggling with HTML and JavaScript
      • T1099: Timestomping
      • T1096: Alternate Data Streams
      • T1158: Hidden Files
      • T1140: Encode/Decode Data with Certutil
      • Downloading Files with Certutil
      • T1045: Packed Binaries
      • Unloading Sysmon Driver
      • Bypassing IDS Signatures with Simple Reverse Shells
      • Preventing 3rd Party DLLs from Injecting into your Malware
      • ProcessDynamicCodePolicy: Arbitrary Code Guard (ACG)
      • Parent Process ID (PPID) Spoofing
      • Executing C# Assemblies from Jscript and wscript with DotNetToJscript
    • Enumeration and Discovery
      • Windows Event IDs and Others for Situational Awareness
      • Enumerating COM Objects and their Methods
      • Enumerating Users without net, Services without sc and Scheduled Tasks without schtasks
      • Enumerating Windows Domains with rpcclient through SocksProxy == Bypassing Command Line Logging
      • Dump GAL from OWA
      • T1010: Application Window Discovery
      • T1087: Account Discovery & Enumeration
      • Using COM to Enumerate Hostname, Username, Domain, Network Drives
      • Detecting Sysmon on the Victim Host
    • Privilege Escalation
      • T1134: Primary Access Token Manipulation
      • Windows NamedPipes 101 + Privilege Escalation
      • T1038: DLL Hijacking
      • T1108: WebShells
      • T1183: Image File Execution Options Injection
      • Unquoted Service Paths
      • Pass The Hash: Privilege Escalation with Invoke-WMIExec
      • Environment Variable $Path Interception
      • Weak Service Permissions
    • Credential Access & Dumping
      • Dumping Credentials from Lsass Process Memory with Mimikatz
      • Dumping Lsass Without Mimikatz
      • Dumping Lsass without Mimikatz with MiniDumpWriteDump
      • Dumping Hashes from SAM via Registry
      • Dumping SAM via esentutl.exe
      • Dumping LSA Secrets
      • Dumping and Cracking mscash - Cached Domain Credentials
      • Dumping Domain Controller Hashes Locally and Remotely
      • Dumping Domain Controller Hashes via wmic and Vssadmin Shadow Copy
      • Network vs Interactive Logons
      • Reading DPAPI Encrypted Secrets with Mimikatz and C++
      • T1214: Credentials in Registry
      • T1174: Password Filter
      • Forcing WDigest to Store Credentials in Plaintext
      • Dumping Delegated Default Kerberos and NTLM Credentials w/o Touching Lsass
      • Intercepting Logon Credentials via Custom Security Support Provider and Authentication Packages
      • Pulling Web Application Passwords by Hooking HTML Input Fields
      • Intercepting Logon Credentials by Hooking msv1_0!SpAcceptCredentials
      • Credentials Collection via CredUIPromptForCredentials
    • Lateral Movement
      • T1028: WinRM for Lateral Movement
      • WinRS for Lateral Movement
      • T1047: WMI for Lateral Movement
      • T1076: RDP Hijacking for Lateral Movement with tscon
      • T1051: Shared Webroot
      • T1175: Lateral Movement via DCOM
      • WMI + MSI Lateral Movement
      • Lateral Movement via Service Configuration Manager
      • Lateral Movement via SMB Relaying
      • WMI + NewScheduledTaskAction Lateral Movement
      • WMI + PowerShell Desired State Configuration Lateral Movement
      • Simple TCP Relaying with NetCat
      • Empire Shells with NetNLTMv2 Relaying
      • Lateral Movement with Psexec
      • From Beacon to Interactive RDP Session
      • SSH Tunnelling / Port Forwarding
      • Lateral Movement via WMI Event Subscription
      • Lateral Movement via DLL Hijacking
      • Lateral Movement over headless RDP with SharpRDP
      • ShadowMove: Lateral Movement by Duplicating Existing Sockets
    • Persistence
      • DLL Proxying for Persistence
      • T1053: Schtask
      • T1035: Service Execution
      • T1015: Sticky Keys
      • T1136: Create Account
      • T1013: AddMonitor()
      • T1128: NetSh Helper DLL
      • T1084: Abusing Windows Managent Instrumentation
        • WMI as a Data Storage
      • Windows Logon Helper
      • Hijacking Default File Extension
      • Persisting in svchost.exe with a Service DLL
      • Modifying .lnk Shortcuts
      • T1180: Screensaver Hijack
      • T1138: Application Shimming
      • T1197: BITS Jobs
      • T1122: COM Hijacking
      • T1198: SIP & Trust Provider Hijacking
      • T1209: Hijacking Time Providers
      • T1130: Installing Root Certificate
      • Powershell Profile Persistence
      • RID Hijacking
      • Word Library Add-Ins
      • Office Templates
    • Exfiltration
      • Powershell Payload Delivery via DNS using Invoke-PowerCloud
  • reversing, forensics & misc
    • Windows Internals
      • Configuring Kernel Debugging Environment with kdnet and WinDBG Preview
      • Compiling a Simple Kernel Driver, DbgPrint, DbgView
      • Loading Windows Kernel Driver for Debugging
      • Subscribing to Process Creation, Thread Creation and Image Load Notifications from a Kernel Driver
      • Listing Open Handles and Finding Kernel Object Addresses
      • Sending Commands From Your Userland Program to Your Kernel Driver using IOCTL
      • Windows Kernel Drivers 101
      • x64 Calling Convention: Stack Frame
      • System Service Descriptor Table - SSDT
      • Interrupt Descriptor Table - IDT
      • Token Abuse for Privilege Escalation in Kernel
      • Manipulating ActiveProcessLinks to Hide Processes in Userland
      • ETW: Event Tracing for Windows 101
      • Exploring Injected Threads
      • Parsing PE File Headers with C++
      • Instrumenting Windows APIs with Frida
      • Exploring Process Environment Block
    • Cloud
      • AWS Accounts, Users, Groups, Roles, Policies
    • Neo4j
    • Dump Virtual Box Memory
    • AES Encryption Using Crypto++ .lib in Visual Studio C++
    • Reversing Password Checking Routine
Powered by GitBook
On this page
  • Key Structures
  • _EPROCESS
  • _LIST_ENTRY
  • LIST_ENTRY Importance
  • Goal of the Lab
  • Walkthrough
  • Launching Target Process
  • Notepad's Flink and Blink
  • Svchost 9cc Flink and Blink
  • Svchost 1464 Flink and Blink
  • Unlinking the Notepad
  • Moment of Truth
  • Detection
  • References

Was this helpful?

  1. reversing, forensics & misc
  2. Windows Internals

Manipulating ActiveProcessLinks to Hide Processes in Userland

PreviousToken Abuse for Privilege Escalation in KernelNextETW: Event Tracing for Windows 101

Last updated 4 years ago

Was this helpful?

The purpose of this lab is to look into how Windows kernel rootkits hide / unlink (or used to) processes in the userland for utilities trying to list all running processes on the system such as Windows Task Manager, tasklist or Get-Process cmdlet in Powershell.

This is going to be a high level overview and no kernel code will be written, instead, kernel memory structures will be manipulated manually with WinDBG.

Lab is performed on Windows 10 Professional x64, 1903.

Update 1 Some replies to my tweet to this post suggested that PatchGuard would normally kick-in and BSOD the OS, which I am sure is the case, although in my lab I experienced no BSODs even though the kernel stayed patched with an unlinked process for 12+ hours.

Update 2 I realized that my Windows VM is running in test mode with no integrity checks, possibly explaining the lack os BSODs - unconfirmed.

Update 3 Thanks **[@**FuzzySec]() for clarifying the BSOD/PatchGuard matter!

Key Structures

We need to be familiar with two kernel memory structures before we proceed.

_EPROCESS

_EPROCESS is a kernel memory structure that describes system processes (or in other words - each process running on a system has its corresponding _EPROCESS object somewhere in the kernel) as we know them. It contains details such as process image name, which desktop session it is running in, how many open handles to other kernel objects it has, what access token it has and much more.

Below shows a snippet of the structure and a highlighted a member that is key to this lab - ActiveProcessLinks . It is a pointer to a structure called LIST_ENTRY:

dt _eprocess

_LIST_ENTRY

In programming, there is a data structure known as doubly-linked list . It contains records (also called nodes) that are linked to each other, meaning each node in the list contains two fields (hence doubly), that reference previous and the next record of that linked list.

Simplified (head and tail omitted) graphical representation of the doubly-linked list is shown below:

LIST_ENTRY is the doubly-linked list equivalent data structure in Windows kernel and is defined as:

kd> dt _list_entry
ntdll!_LIST_ENTRY
   +0x000 Flink            : Ptr64 _LIST_ENTRY
   +0x008 Blink            : Ptr64 _LIST_ENTRY

...where FLINK (forward link) and BLINK (backward link) are the equivalents of Next and Previous references to the next and previous element in the list in our graphical representation of the doubly-linked list discussed above.

LIST_ENTRY Importance

All Windows processes have their corresponding kernel objects in the form of an EPROCESS kernel structure. All those EPROCESS objects are stored in a doubly-linked list.

Effectively, this means that when a cmd /c tasklist or get-process is invoked to get a list of all running processes on the system, Windows walks through the doubly-linked list of EPROCESS nodes, utilizing the LIST_ENTRY structures and retrieves information about all currently active processes.

Below is a simplified visualization of the above:

Goal of the Lab

With all of the above information, we can now define what we're trying to do in the lab - we want to hide a process of our choice from being shown in a process list when a get-process cmdlet or similar is issued in the userland.

Below is a simplified diagram illustrating how this will be achieved by manually manipulating kernel structures in WinDBG in order to hide the EPROCESS 2 (white):

  • ActiveProcessLinks.Flink in EPROCESS 1 will be pointed to EPROCESS 3 ActiveProcessLinks.Flink

  • ActiveProcessLinks.Blink in EPROCESS 3 will be pointed to EPROCESS 1 ActiveProcessLinks.Flink

Kernel memory manipulations will unlink the EPROCESS 2 from the previous node (EPROCESS 1) and the next node (EPROCESS 3) in the doubly-linked list and, effectively, render it invisible to all userland APIs that retrieve running system processes - exactly like Windows kernel rootkits do it.

Walkthrough

Launching Target Process

Let's launch a process that we will try to hide - a notepad.exe in my case:

In kernel, we can get more information about our notepad process like so:

kd> !process e14 0

Below shows that our notepad's corresponding EPROCESS structure is located at ffffb208f8b304c0:

Checking the EPROCESS structure of our notepad:

kd> dt _eprocess ffffb208f8b304c0

...we can see the ActiveProcessLinks, the doubly-linked list, populated with two pointers (Flink and Blink):

We can also read those values with dt _list_entry ffffb208f8b304c0+2f0 or by dumping two 64-bit long values from ffffb208f8b304c0+2f0:

kd> dq ffffb208f8b304c0+2f0 L2
ffffb208`f8b307b0  ffffb208`f8d1e7b0 ffffb208`f8b89370

Notepad's Flink and Blink

Let's now figure out the previous and next EPROCESS nodes our notepad.exe is pointing to.

Below shows in two different ways (1. observing ActiveProcessLinks from the EPROCESS structure; 2. reading two 64-bit values from the EPROCESS+0x2f0) that our notepad's:

  • FLINK (green) is pointing to ffffb208`f8d1e7b0

  • BLINK (blue) is pointing to ffffb208`f8b89370

For curiosity, we can check the process's image name referenced by the notepad's FLINK at ffffb208`f8d1e7b0 - the next EPROCESS node to our notepad's EPROCESS:

We need to:

  • find the EPROCESS location by subtracting 0x2f0 from the FLINK ffffb208`f8d1e7b0. This is because FLINK points to EPROCESS.ActiveProcessLinks and ActiveProcessLinks is located at offset 0x2f0 from the beginning of the EPROCESS location

  • add 0x450 since this is the offset of the ImageFileName in the EPROCESS structure

kd> da ffffb208`f8d1e7b0-2f0+450

Let's do the same for the process referenced by the notepad's BLINK to get the previous EPROCESS node to our notepad's EPROCESS:

kd> da ffffb208`f8b89370-2f0+450

Looks like our notepad EPROCESS is surrounded by two svchost EPROCESS nodes.

Continuing, we can get PIDs of those two svchost.exe processes referenced by FLINK and BLINK and they are 0x000009cc and 0x00001464 respectively as shown below:

kd> dd ffffb208`f8d1e7b0-2f0+2e8 L1
ffffb208`f8d1e7a8  000009cc

kd> dd ffffb208`f8b89370-2f0+2e8 L1
ffffb208`f8b89368  00001464

kd> !process 000009cc 0
Searching for Process with Cid == 9cc
PROCESS ffffb208f8d1e4c0
    SessionId: 0  Cid: 09cc    Peb: 44b2cd5000  ParentCid: 025c
    DirBase: 1e5730002  ObjectTable: 00000000  HandleCount:   0.
    Image: svchost.exe

kd> !process 00001464 0
Searching for Process with Cid == 1464
PROCESS ffffb208f8b89080
    SessionId: 0  Cid: 1464    Peb: a260bb6000  ParentCid: 025c
    DirBase: 19071002  ObjectTable: ffffc208ea7e4a80  HandleCount: 141.
    Image: svchost.exe

Below shows essentially the same as the above output with some colour-coding:

...where highlighted in green is the svchost (0x09cc) referenced by notepad's FLINK and in blue is the svchost (0x1464) referenced by notepad's BLINK.

Svchost 9cc Flink and Blink

Let's get the FLINK and BLINK for the svchost.exe (PID 0x9cc) and note that ffffb208`f8d1e7b0 is the location of EPROCESS.ActiveProcessLinks which will be important later:

kd> dq ffffb208f8d1e4c0+2f0 L2
ffffb208`f8d1e7b0  ffffb208`f94ee7b0 ffffb208`f8b307b0

dt _eprocess ffffb208f8d1e4c0

Green is FLINK and blue is BLINK:

Svchost 1464 Flink and Blink

Let's get FLINK and BLINK for the svchost.exe (PID 0x1464) and note that ffffb208`f8b89370 is the location of EPROCESS.ActiveProcessLinks which will be important later:

kd> dq ffffb208f8b89080+2f0 L2
ffffb208`f8b89370  ffffb208`f8b307b0 ffffb208`f96c97b0

kd> dt _eprocess ffffb208f8b89080

Green is FLINK and blue is BLINK:

Unlinking the Notepad

We can now summarize the FLINK and BLINK pointers we have for all the processes we are interested in:

Image

PID

EPROCESS

ActiveProcessLinks

Flink

Blink

svchost

0x1464

ffffb208f8b89080

ffffb208`f8b89370

ffffb208`f8b307b0

ffffb208`f96c97b0

notepad

0xe14

ffffb208f8b304c0

ffffb208`f8b307b0

ffffb208`f8d1e7b0

ffffb208`f8b89370

svchost

0x9cc

ffffb208f8d1e4c0

ffffb208`f8d1e7b0

ffffb208`f94ee7b0

ffffb208`f8b307b0

Below are the two kernel modifications we need to perform in order to hide notepad.exe from process listing APIs in the userland:

  1. Point svchost's (0x1464) FLINK at ffffb208`f8b89370 to svchost's (0x9cc) FLINK at ffffb208`f8d1e7b0

  2. Point svchost's (0x9cc) BLINK at ffffb208`f8d1e7b0+8 (+8 because LIST_ENTRY is two fields FLINK/BLINK and are 8 bytes each on x64) to svchost's (0x1464) FLINK at ffffb208`f8b89370

Below visualizes the above outlined steps:

Let's perform the above mentioned kernel modifications:

kd> eq ffffb208`f8b89370 ffffb208`f8d1e7b0
kd> eq ffffb208`f8d1e7b0+8 ffffb208`f8b89370

Moment of Truth

Once the kernel memory is modified, we can run a get-process or ps notepad in powershell and observe that notepad.exe has been successfully hidden:

...although it can still be looked up by its PID in the kernel:

!process e14 0

Below is another quick demo showing how notepad.exe disappears from the Windows Task Manager once the kernel memory is tampered and the debugger is resumed. Additionally, ps notepad returns nothing, although notepad is visible in the taskbar and underneath the Windows Task Manager:

In the above demo, memory offsets of structures are different due to a system reboot since the initial write up.

Detection

References

In order to detect unlinked processes exhibited by malware on systems without PatchGuard, explore and from Volatility.

psscan
psxview
https://twitter.com/FuzzySec
LIST ENTRY - aldeid
Logo
Doubly Linked List (Data Structure) In C++HackerEarth
notepad not seen when "ps notepad" is executed, although notepad is still running in the foreground
Logo