Red Team Notes
  • What is ired.team notes?
  • 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 Takeover
      • 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
      • Active Directory Lab with Hyper-V and PowerShell
      • ADCS + PetitPotam NTLM Relay: Obtaining krbtgt Hash with Domain Controller Machine Certificate
      • From Misconfigured Certificate Template to Domain Admin
      • Shadow Credentials
      • Abusing Trust Account$: Accessing Resources on a Trusted Domain from a Trusting Domain
  • 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
      • regsvr32
      • MSHTA
      • Control Panel Item
      • Executing Code as a Control Panel Item through an Exported Cplapplet Function
      • Code Execution through Control Panel Add-ins
      • CMSTP
      • InstallUtil
      • Using MSBuild to Execute Shellcode in C#
      • 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
      • 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
      • Binary Exploitation
        • 32-bit Stack-based Buffer Overflow
        • 64-bit Stack-based Buffer Overflow
        • Return-to-libc / ret2libc
        • ROP Chaining: Return Oriented Programming
        • SEH Based Buffer Overflow
        • Format String Bug
    • 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
      • Obfuscated Powershell Invocations
      • Masquerading Processes in Userland via _PEB
      • Commandline Obfusaction
      • File Smuggling with HTML and JavaScript
      • Timestomping
      • Alternate Data Streams
      • Hidden Files
      • Encode/Decode Data with Certutil
      • Downloading Files with Certutil
      • 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 Global Address List (GAL) from OWA
      • Application Window Discovery
      • Account Discovery & Enumeration
      • Using COM to Enumerate Hostname, Username, Domain, Network Drives
      • Detecting Sysmon on the Victim Host
    • Privilege Escalation
      • Primary Access Token Manipulation
      • Windows NamedPipes 101 + Privilege Escalation
      • DLL Hijacking
      • WebShells
      • 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++
      • Credentials in Registry
      • 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
      • WinRM for Lateral Movement
      • WinRS for Lateral Movement
      • WMI for Lateral Movement
      • RDP Hijacking for Lateral Movement with tscon
      • Shared Webroot
      • 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
      • Man-in-the-Browser via Chrome Extension
      • ShadowMove: Lateral Movement by Duplicating Existing Sockets
    • Persistence
      • DLL Proxying for Persistence
      • Schtask
      • Service Execution
      • Sticky Keys
      • Create Account
      • AddMonitor()
      • NetSh Helper DLL
      • 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
      • Screensaver Hijack
      • Application Shimming
      • BITS Jobs
      • COM Hijacking
      • SIP & Trust Provider Hijacking
      • Hijacking Time Providers
      • 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
    • 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
      • Windows x64 Calling Convention: Stack Frame
      • Linux 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
      • Writing a Custom Bootloader
    • 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
  • _TOKEN
  • 1. Replacing Tokens for Privilege Escalation
  • Listing Processes
  • Medium Integrity Process
  • Finding Powershell Token
  • Confirming SIDs
  • Finding SYSTEM Token
  • Swapping Tokens
  • 2. Modifying Token Privileges
  • Enabling Existing Privileges
  • Adding More Privileges
  • References
  1. reversing, forensics & misc
  2. Internals

Token Abuse for Privilege Escalation in Kernel

PreviousInterrupt Descriptor Table - IDTNextManipulating ActiveProcessLinks to Hide Processes in Userland

Last updated 5 years ago

The purpose of this lab is to understand at a high level (will not be writing any kernel code, rather playing around with WinDBG) how kernel exploits abuse tokens for privilege escalation.

I will look briefly into two techniques:

  • - low privileged token is replaced with a high privileged token

  • - adding and enabling more privileges to an existing token

Key Structures

Before proceeding, there's a couple of kernel memory structures we need to know about.

_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 as 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 is a snippet of the structure:

dt _eprocess

_TOKEN

_TOKEN is a kernel memory structure that describes process's security context and contains information such as process token privileges, logon id, session id, token type (i.e primary vs. impersonation) and much more.

Below is a snippet of the _TOKEN structure:

dt _token

Let's now see how we can use the above information about processes and tokens to elevate a medium integrity process to a system integrity process the way kernel exploits do it.

1. Replacing Tokens for Privilege Escalation

One way kernel exploits escalate privileges is by replacing a low privileged token with a high privileged token. Below are some key points in explaining the exploitation process:

  • Each process running on the system has its corresponding _EPROCESS kernel structure

  • _EPROCESS structure contains a pointer to a _TOKEN memory structure that describes process's security context

  • Kernel exploit finds address of the _TOKEN structure of a low privileged process - the one it wants to escalate from

  • Kernel exploit finds address of the _TOKEN structure of a privileged process, running as NT\SYSTEM

  • Kernel exploit replaces the low privileged process's token with the high privileged token

In this lab, I'm going to replace the authentication token of a low privileged powershell process with a high privileged token of the system process (always a PID 4) following the above described process, except I will do it manually using WinDBG.

My lab is running Windows 10 x64 1903

Below is an attempt to visually represent the above described process with a high level diagram:

  • Boxes with blue headings represent a MEDIUM integrity process, running as WS02\spotless

    • WS02 is my lab machine name

    • spotless is a low privileged local user.

  • Boxed with red headings indicate a SYSTEM integrity process, effectively running as NT\SYSTEM

    • WS02$ is my lab computer account

    • OFFENSE is the domain the machine is a member of

  • Red dotted line signifies that the low privileged process powershell will assume the high privileged token from the process system once the _TOKEN kernel memory structure is manipulated.

Let's now try to see how we can replace process tokens using WinDBG.

Listing Processes

First off, listing all running processes on the system in WinDBG can be done like so:

!process 0 0

Below is a snippet of some of the processes running on the system and highlighted are addresses pointing to _EPROCESS structures for given processes:

Medium Integrity Process

Next, let's launch powershell (this is the process for which we will replace the low privileged token with a high privileged token) as a medium integrity/non-elevated process (in my case running as a local non-admin user ws02\spotless) and get its process ID:

Let's get a process summary in WinDBG for our powershell process with PID 2648 (0xa58):

!process a58 0

Below confirms we're looking at our powershell.exe process. Note the _EPROCESS location ffffdc8fbe1f1080:

Finding Powershell Token

Once we have powershell's _EPROCESS location in the kernel, we can inspect its contents like so:

kd> dt _eprocess ffffdc8fbe1f1080

Since we're interested in swapping the token, the key member of the _EPROCESS memory structure we are after is Token located at offset 0x358:

Note that offset0x358 suggests it's pointer to _EX_FAST_REF memory structure and we will come back to this shortly.

Let's read memory contents of the pointer the _EPROCESS.Token is pointing to, which is ffffc507`dab7799f in my case:

kd> dq ffffdc8fbe1f1080+0x358 l1
ffffdc8f`be1f13d8  ffffc507`dab7799f

If we try inspecting the memory location ffffc507`dab7799f with !token ffffc507dab7799f command, we are told that this address does not point to a token object, which we may find a bit odd:

However, this is where the _EX_FAST_REF comes into play. It was pointed out earlier that _EPROCESS.Token actually points to a _EX_FAST_REF structure rather than a _TOKEN structure.

Let's overlay the address stored in _EPROCESS.Token which is ffffdc8f`be1f13d8 (_EPROCESS location plus the Token member offset (ffffdc8fbe1f1080+0x358)) with the _EX_FAST_REF structure and see what's inside:

kd> dt _EX_FAST_REF ffffdc8fbe1f1080+0x358
ntdll!_EX_FAST_REF
   +0x000 Object           : 0xffffc507`dab7799f Void
   +0x000 RefCnt           : 0y1111
   +0x000 Value            : 0xffffc507`dab7799f

Notice how all three members have the same offset and Object and Value are pointing to the same address, but the interesting piece is the RefCnt with 4 bits on (equals to 0xF, which looks like it is the last digit of both Object and Value members are pointing to - 0xffffc507`dab7799f).

If we inspect the _EX_FAST_REF without data, based on the symbols, it's defined like so:

ntdll!_EX_FAST_REF
   +0x000 Object           : Ptr64 Void
   +0x000 RefCnt           : Pos 0, 4 Bits
   +0x000 Value            : Uint8B

Which indicates and confirms that the last 4 bits (the last hex digit of the Object or Value) of the value pointed to by members Object and Value (in my case 0xffffc507`dab7799f) is used to denote the reference count to this token, which means it's not part of the token address, which means we should be able to zero it out and get an actual _TOKEN structure address for our powershell process.

Essentially, if Object and Value are 0xffffc507`dab7799f, we should be able to just swap the last f with 0 which would give us 0xffffc507`dab77990 and it should be our _TOKEN address.

In fact, if we inspect our powershell process with a more verbose output like so:

!process ffffdc8fbe1f1080 1 
// or !process 0xa58 1

..we see that indeed the Token is pointing to 0xffffc507`dab77990 - note the last digit is 0 rather than f, which confirms that we can always zero out the last digit pointed to by _EX_FAST_REF to get the effective _TOKEN structure address:

We can mask out the last digit with a bitwise AND operation as shown below:

kd> ? (ffffc507dab7799f & 0xFFFFFFF0); !token (ffffc507dab7799f & 0xFFFFFFF0)

Now, if we try the !token command again with the last digit of _EPROCESS.Token->Value set to 0, we no longer see the error message suggesting there's no token at that address and we start seeing some actual token details like user group it belongs to, etc.:

Confirming SIDs

We can double check we're actually looking at the right token - the SID's seen in the output of whoami /all and the !token (ffffc507dab7799f & 0xFFFFFFF0) match:

Finding SYSTEM Token

Now let's find the address of the high privileged _TOKEN - the token that our low privileged powershell process will assume.

Below shows some information about the SYSTEM process - we're interested in it's _TOKEN location which is at ffffc507d8818040 as shown below:

kd> !process 4 1
Searching for Process with Cid == 4
PROCESS ffffdc8fbdad3040
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001aa002  ObjectTable: ffffc507d88032c0  HandleCount: 3042.
    Image: System
    VadRoot ffffdc8fbdad1170 Vads 8 Clone 0 Private 21. Modified 76433. Locked 0.
    DeviceMap ffffc507d8818eb0
    Token                             ffffc507d8818040

Swapping Tokens

We now have all the required information to successfully swap the powershell process token (located at ffffdc8fbe1f1080+0x358) with that held by the SYSTEM process (ffffc507d8818040) by simply writing the SYSTEM process's token address to the the _EPROCESS.Token of our powershell process:

eq ffffdc8fbe1f1080+0x358 ffffc507d8818040

Below shows the above in action and how prior to the token manipulation, the powershell was running as ws02\spotless and nt authority\system after:

2. Modifying Token Privileges

Another interesting (and abused for privilege escalation) member of the _TOKENstructure is Privileges at offset 0x040, defined as _SEP_TOKEN_PRIVILEGES structure:

dt _token 0xffffc507dab77990

Enabling Existing Privileges

We can overlay our low privileged powershell token address + offset 0x40 to inspect the _sep_token_privileges structure:

dt _sep_token_privileges 0xffffc507dab77990+0x40

In essence, _sep_token_privileges shows which privileges the token has and which of them are enabled/disabled - the info that we can also check from the userland with whoami /priv.

Note how _sep_token_privileges Present and Enabled values do not match and this is what results in Enabled/Disabled privileges that we see in the whoami /priv State column:

We can manipulate the kernel memory and make Present and Enabled values match like so:

eq 0xffffc507dab77990+0x40+8 0x00000006`02880000

After manipulating the memory and matching the Present and Enabled values, we can now see how all the privileges in the State column of the whoami /priv output are Enabled:

Adding More Privileges

Let's see if we can try to add more privileges to that exsiting token rather than just enabling those that already exist.

How do we know what is a valid value in the Present field that would give us more/elevated privileges? We can get a good hint by inspecting the Present value of the SYSTEM process (PID 4) token:

!process  4 1
sep_token_privileges 0x40+ffffde8fe9a06040

From the above, Present value is 0x0000001f`f2ffffbc - this represents all the privileges the SYSTEM process token has.

Let's see if we can assign this value to our powershell process's token to both Present and Enabled fields. If successful, we should have all the SYSTEM privileges enabled for our low privileged powershell process running in the context of the user ws02\spotless:

kd> eq 0x40+ffffde8ff8cde5f0+8 0x0000001f`f2ffffbc
kd> eq 0x40+ffffde8ff8cde5f0 0x0000001f`f2ffffbc

Let's check if the new values got assigned to our _sep_token_privileges structure:

kd> dt _sep_token_privileges 0x40+ffffde8ff8cde5f0
nt!_SEP_TOKEN_PRIVILEGES
   +0x000 Present          : 0x0000001f`f2ffffbc
   +0x008 Enabled          : 0x0000001f`f2ffffbc
   +0x010 EnabledByDefault : 0x40800000

Running whoami /priv now shows that we have all the SYSTEM privileges and all of them are enabled:

References

Token stealing/replacement
Token privilege adjustment
token-priv/abusing_token_eop_1.0.txt at master · hatRiot/token-privGitHub
http://mcdermottcybersecurity.com/articles/x64-kernel-privilege-escalationmcdermottcybersecurity.com
Starting with Windows Kernel Exploitation – part 3 – stealing the Access Tokenhasherezade's 1001 nights
Logo
Logo
Token stealing / swapping process
0xf being zeroed out