Welcome to the deep dive. You give it some really interesting material here, focusing on Windows security internals and PowerShell.
Yeah, it's a great combination to look at.
So that's our focus today. Our mission really is to pull out the core ideas, give you a shortcut to understanding how Windows handles security management and how PowerShell fits in as well, like an investigative.
Tool, right without getting totally lost in the weeds. There's a lot of detail in these sources exactly.
We're aiming for those aha moments, you know, finding the surprising bits about Windows security that PowerShell helps uncover.
And what's really cool is how the sources link these like abstract security concepts directly to practical PowerShell commands.
So it's not just theory, not at all.
We'll actually see how PowerShell can light up the internals.
Okay, let's dive in. The material starts by emphasizing setting up a PowerShell testing environment. Why is that the first crucial step.
Well, it's super important because you need a safe place, a sandbox, right to try out these commands without messing up your actual system.
Makes sense, you don't want to break anything accidentally exactly.
And the source talks about set execution policy. Think of that as your first safety net stops accidental script running.
Which can be a security risk in itself.
Oh definitely. And the key thing is that set scope current user option for.
Keeping tests just within your user account.
Right, isolated testing. If you want system wide changes, well that's different. You'd need admin privileges for that, and you wouldn't use the scope parameter.
Then gotcha. And the source notes that some setups, like maybe open source PowerShell or newer server versions might already have remote signed as the default.
Yeah, so it's always smart to just check first, know where you stand.
Okay, Next up PowerShell language basics. For someone diving into this material, what are the foundational bits that really give you leverage here?
The sources bring up a few key things special variables like null p TOBE for your current directory pobid that's.
The PowerShell process idea itself.
Yeah, exactly, and ORNA four for environment variables like EnEv windeer knowing innovator D is surprisingly useful for security scripting context matters.
And the difference between single and double quotes crucial.
Double quotes allow string interpolation.
So variables get automatically substituted in right.
Makes building dynamic commands way easier, no messy string joining single quotes. They treat everything literally good when you need that exact string.
That interpolation is a huge time saver. The source also mentions creating objects a new object using a GID as an example.
Yeah, basic object creation and the naming convention for commands verb noun like a get item.
Seems designed to make things easier to find.
It really does help. You can often guess command names and then parameters like megapath with get item, let you focus.
The command so you can target specific.
Things exactly, and we'll get to get member later. But think of that as your magnifying glass for figuring out what an object is and what you can do with it.
Okay, so you have these basic tools, how do you learn to use them effectively? The source talks a lot about get help.
Oh, get help is your best friend in PowerShell, seriously indispensable.
What does it give you?
The synopsis, the full syntax, detailed descriptions, and what's really handy is using wild cards for parameter.
Names like the ubjet example to find parameters starting with.
Objeck exactly and the example's parameter that's often the best part real world usage examples invaluable can't.
Be practical examples. Okay, now, what about making your own PowerShell tools. The material covers functions. What's key there, Well.
The basics are the function keyword, then your function name. It's good practice to stick to that verb noun convention even for your own stuff. Keeps things consistent, makes sense, and parameters defined in the tarum block. You can specify types like string name, but you don't have to. PowerShell's pretty flexible.
What if you don't use param.
Then any arguments you pass just end up in the arg's array. You access them by number, like ARGs dollars or r T one.
So named parameters are just numbered arguments. Good flexibility. Okay. The deep dive then shifts to output. How PowerShell shows you stuff and how you can control it.
Right, So, when a command runs and you don't assign the output to a variable, PowerShell steps in and tries to display it nicely, usually a table or a list.
It guesses the best format.
Kind of yeah, based on the object's properties, but you have control. Select object is key for picking just the properties you care about. Cuts down the noise.
Nice and format list forces.
It into a list view one property per line. Basically great when you want to see all the details for a single object rather than a wide table.
And if you don't even know what properties are available, that's where get member comes in again, right with DJ type property.
Exactly if pipe your command output to get member iban type property and boom, you get the full list of data points you can access on those objects. It's like asking, what can you tell me about yourself?
The decoder ring analogy works. Yeah, and sort object to organize it, yep, sort.
My name, my side by memory usage, whatever property you need. Brings order to the chaos.
Okay, so you can view the data how you want in the console, but what about saving it?
Exporting data out file is the straightforward way. Saves the text output just as you see it to a file, then get content reads.
It back end and the symbol.
That's just a shortcut for outfile, quick and easy. But for like structured data you might want and excel h that's where export csv comes in. Creates a proper comma separated value file, much better for spreadsheets or databases.
And that not no type information parameter.
Oh yeah, good catch that just stops PowerShell from Putting that extra halftag type information line at the top of the CSV makes it cleaner for other programs to read.
Okay, good tip. We've covered a lot of PowerShell basics. Now the material shifts gears, heading down into the Windows kernel and its security role. This feels like the real deep dive part.
This is where it gets really fascinating. Yeah. The kernel, that's the absolute core of the OS, where a fundamental security decisions.
Happen, and the connection point is system calls exactly.
System calls are the bridge the way user mode applications, the stuff we normally run talk to the privileged kernel mode where the OS does its heavy lifting and enforcement.
The link between our apps and the OS's security core. Okay, the material is several key kernel subsystems. Can you give us the quick security relevance run down?
Sure you've got The object manager manages all kernel objects, the basic building blocks. The io manager handles data moving in and out. Process and thread manager creates and manages running code. Memory manager controls memory use. Configuration manager that's the registry code integrity. Make sure only trusted code runs.
A lot of managers.
Yeah, and crucially for security, the Security reference monitor, the SRM.
SRM sounds important, the ultimate gatekeeper.
Maybe that's a good way to put it. The SRM is the kernel component that actually enforces security policy. It decides who gets access to what.
How does it do that?
It uses two key things mentioned right in your source, access tokens and security descriptors. Every process has an access token saying who it is. Every resource, like a file or registry key, has a security descriptor saying who's allowed to access.
So the SRN compares the token.
To the descriptor exactly when a process tries to access something, the SRM looks at its token, looks at the resources security descriptor, and makes the call allow or deny access.
Tokens and security descriptors yes, central players, yeah, okay. The material then dives into security descriptors and sids. What's the relationship there.
Sid's security identifiers are the unique names for users, groups, computers, anything the system needs to identify for security.
Think of them like unique ideas, and they're inside security descriptors right.
Security descriptors use sids to specify who is being allowed or denied access. The source shows using get into SID to translate the raw SID string like S one five, three, two, five.
Four five into built users.
Exactly, translating the system's internal ID into something we recognize.
So sids are the language of security identity. Next the object manager and its name space. This sounds like how the kernel keeps all its objects organized. It is.
Think of the object manager name space the OMNS as like a hidden file system just for kernel.
Objects, a file system for kernel stuff.
Yeah, it's hierarchical like folders and files. Get ant type shows you the kinds of objects in there. Directory, symbolic link, token, process thread, lots more directory objects build the hierarchy and the.
Source mentions the anti object PowerShell drive.
Right that lets you browse this hidden name space using familiar commands like LS or CD. It's a fantastic way to explore.
Very cool. And one specific directory gets called out Base named objects. Why is that one special?
Ah? Base Named objects or B and O. That's the standard place where different processes potentially running as different users can create named kernel objects that they can then share.
So for interprocess community sharing resources.
Exactly, if you want two different programs to easily find and use the same kernel object like a mutex or an event, putting it in B and O is the common way to do it. It's the public square for named kernel objects.
Okay, shared resources go there makes sense. Now back to system calls. The deep dive mentiones NT and ZW prefixes. Is there a big difference for us calling.
From user mode? Not really the sources they're mostly interchangeable from our perspective, and crete mutant ZW crete mutant. They generally do the same thing when called from an application.
Okay, so just note they signal a system call, right.
And they usually follow that verb noun pattern too, like create followed by the object type mutant.
Got it. The source also mentions unicodestring structures for parameters, especially names. What's important about those?
So many system calls take names using this Unicodes string structure. It's not just a pointer to the characters. It also includes the strings current length, invites, and the buffer's maximum.
Size self describing strings.
Yeah, and crucial, the length is just the characters used, not including a null terminator. In fact, you can have null characters inside object names at this level.
Really, that seems like it could cause problems.
It can mishandling these counted strings versus null terminated strings has definitely been a source of security bugs over the years. It uses UCS two encoding.
By the way, good detail. Okay, so a system call runs, it needs to report back success, failure, what happened. That's where anti status codes come in.
Exactly, and status codes are the standard return values. They tell you the outcome, and.
They're more than just error or okay, oh yeah.
The source breaks down the structure. There's a severity level success info, warning, error, a facility code telling you which part of the system generated the status like default debugger win thirty two, and the specific status code number.
So lots of context.
Tons and get end status in the PowerShell module lets you look up these codes, get the symbolic name and the message text. Super useful for debugs.
And PowerShell itself often turns these into exceptions.
We see right when a PowerShell command wraps a system call and gets an error and sisteris it often surfaces that as a dot net exception. The example of get ent directory on a non existent.
Path gives that object name not found exception.
Yep, and you can take the error code from that exception, feed it to get end status and get the underlying into status info. It shows how PowerShell bridges that low level kernel world with the managed dot net.
World neat connection. Okay, next topic, object handles. User applications don't touch kernel objects directly. They use these handles as like tickets.
Precisely, when you successfully create or open a kernel object via a system call, the kernel gives your process back a handle. Think of it as an index number into your process's private handle table.
And what's in that handle table entry Three key things.
The handle number itself, the access rights that were granted to your process for that object like read, write, synchronize, and critically a pointer to the action object down in kernel memory.
So when my app uses that handle later, say, to read from a file.
Object, it passes the handle number in another system call. The kernel uses that number to look up the entry in your process as handle table. Then it does vital checks like what First, it checks if the access you're requesting now, say read access is allowed by the access rights granted when the handle was created stored in the table. Second, it checks if the handle actually points to the right type of object trying to read from a mutex handle that's going to fail.
Makes sense, access check and type check. Secure way to manage things, which brings us to access masks those granted rights right.
The permissions granted are stored as a thirty two bit number called an access mask. It's a bitfield. Different bits mean different permissions.
And it's specific to the object type largely.
Yes, the top sixteen bits are generally type specific. So a file object's access mask will have bits for things like read data, write data, a pen data, while a thread object will have bits for terminate, suspend, resume, set information, and so.
On, granular permissions tailored to the object. The source then shows duplicating handles with copynt object. Why would you do that?
Copy anti object lets you duplicate an existing handle. You can just make an identical copy or and this is useful. You can request different access rights for the new handle.
Ah, so you could create a less privileged version of a handle exactly.
Maybe you have a handle with full access, but you want to pass a handle to another part of your code or another process that only has a query access. Duplicating the handle with a restricted desired access mask is how you do that.
Smart and compare and object checks if two handles point to the same actual kernel object.
Yep, even if they have different access rights. Compare end to object tells you if they're ultimately referencing the same thing done in the kernel.
Cool. What about that protect from close attribute sounds obvious?
It is what it sounds like. If you set that astribute on a handle, the system won't let it be closed. Palls to close handle will fail with status handle not closeable.
Why to keep a critical handle alive?
Could be maybe you need to guarantee a resource stays accessible and don't want some stray code closing the handle prematurely.
Okay. The deep dive then talks about enquery information object and end set information object, sort of generic get and set for object data.
That's the idea. Instead of having dozens of specific system calls for every little piece of info about every object type, the kernel provides these general purpose calls.
How do they work?
You give them the handle, an information class number that specifies what data you want, and a buffer to put the data in for query or get from for set.
And how do you know the right information class number? Ah?
Well, get nt object information class can list the known ones for an object type, but as the source notes, not all classes are officially documented. Sometimes it involves a bit of digging or experimentation, like.
Figuring out database fields. The example with querying process info and getting buffer too small that highlights needing the right buffer size exactly.
You often have to figure out how much space the information needs. Sometimes you call it once to get their required size, allocate a buffer, then call it again, or just guess with the like parameter until it works.
Got it okay? Quickly. Touching on device objects and symbolic links in the OMNS. How do they fit in?
Device objects represent hardware or virtual devices. You can see them under nty object. Device Symbolic links like system root are just pointers or aliases to other paths in the OMNS.
So when I open see windowsnoepad dot.
Ex, the system uses symbolic links C likely points to a device hard disc volume X path. Windows might involve system route to resolve the path down to the actual file object, passing through the device object representing the disk volume, all involving the object manager.
Path resolution involves the OMMS. Okay, next, process and thread manager key security points.
Processes and threads are the things that run code, and they are securable objects themselves. They have security descriptors, so you.
Need permission to say terminate another process.
Absolutely and importantly you generally can't open a process or thread just by knowing its name. You need its unique process ID PID or thread id TID helps prevent arbitrary interference just based on names.
Right, need the specific ID. Okay. Memory management in sections sounds like fertile ground for security issues.
Definitely. Sections are blocks of memory that can be shared between processes. New antisection creates one add in section, maps it into a process's address space.
And you control permissions on that memory.
Yes crucial. You specify protection like read only read write, execute read write. The kernel enforces these. Trying to map a section with incompatible permissions fails, as the example.
Showed and shared ritable sections. The source mentions CVE twenty nineteen Uro nine, four to three. That sounds bad.
It was a privileged process shared a section. A lower privileged process could map it as writable modified data the privileged process trusted and potentially get code execution. Big problem.
Yikes. How would you even find such shared sections?
The source shows using get and handle to look at all handles and processes, filtering for section objects, and using test n access mask to see if any have right access section map right or potentially dangerous combinations like section exten size. You'd compare handles between a high privilege and low privileged process, so.
You can hunt for potentially risky sharing configurations and even fuzz them.
Yeah, if you find a writable shared section, you could use right anti virtual memory to poke at it, write unexpected data. See if you can crash or exploit the other process sharing it. Show in t section even gives you a x editor GUI for it.
Wow. The big takeaway seems to be writable and executable memory is inherently dangerous.
Extremely that combo is classic malware territory for code injection. He's very careful justification if you used at all?
Okay, shifting up a level. Now user mode applications and Win thirty two APIs. This is where most developers live. Right, how does this relate to the kernel stuff?
Right? Most apps don't call nt create file directly. They call the Win thirty two API function create file. These Win thirty two APIs are the documented stable interface for applications, the layer of abstraction exactly. They provide functions for everything files, Windows network registry under the hood. Many of these WIN thirty two functions eventually translate into one or more and or ZW system calls to the kernel to do the actual work. Understanding that translation is key, So.
Win thirty two is the friendly face. System calls are the engine room. Okay. DLL imports and API sets what are these?
Ds? Dynamic link libraries are shared code libraries. Apps import functions from them. Get Win thirty two module import. Let's you see which functions and app uses from which DLLs.
Useful for understanding dependencies and API.
Sets Introduced in Windows seven. They're like virtual DLLs, and app might link against apm's wind core process threads LANs onesaushal on zero dot dll instead of directly against kernel thirty two dot dll or at VAP thirty two dot dll. It decouples the app from the exact DLLLL Providing the function makes it easier for Microsoft to refactor things behind the scenes without breaking apps. Get n TAPA set. Let's you see which real DLL actually backs a specific API set on your system as flexibility.
Okay, next, searching for DLLs and DL hijacking. This is a classic attack, right Oh yeah?
Very common. When an app asks to load a DLL just by name like graphics dot DLL without a full path, Windows has to.
Search for it where does it look.
The search order has changed over time for security reasons. Older Windows versions often check the app's current directory first, which was dangerous.
Because an attacker could drop a malicious graphics dot DLL.
There precisely if a privileged app loaded it from an unsecured directory boom dll hijack code execution. Vista and later have a safer default order prioritizing system directories, but vulnerabilities can still exist if apps aren't careful about where they load DLLs from, or if their current directory is attacker can.
Always specify the full path if you can't. Basically, Windows stations and desktops UI stuff, but security implications.
Yes, Window stations are secure containers for UI elements, primarily desktops. WINDSTA is the main interactive one we use why separate stations Isolation services might run in a different Window station from the interactive user. It prevents processes in one station from easily interfering with the UI of another. Desktops live inside window stations, providing another layer. Get INNT window station name and get in desktop name.
Let you list them boundaries even for the UI. Uh huh okay. Windows messages. How Windows talk to.
Each other fundamentally, yeah, A message is just a number identifying the message type, plus a couple of parameters. Apps can send messages, wait for processing, or post them, put in a queue and continue.
And windows belong to threads.
Right. Each window has thread affinity. Only the thread that created it should really process its messages. That thread runs a message loop using APIs like get message and dispatch message.
The source has a conceptual example of sending a message to notepad. Yeah.
It shows finding the notepad window, get an itt window, maybe finding its edit child control, and conceptually how you'd send it a message, perhaps to pace text or close it. It shows the potential for programmatic UI interaction, which could be used for.
Good or bad. Okay. Console sessions, we have the physical console, but also remote desktop, fast user switching exactly.
Each of those creates a separate session get and T process info only group objects. Session edge shows you which session each processes in.
Why separate sessions isolation?
Again? Each session gets its own memory areas for certain things, its own instance of base named objects, its own window stations. Session zero is special reserve for system services usually no GUI there.
Session zero for services that leads into shatter attacks and UIPI. What were shatter attacked?
Back before Vista user apps and many services ran together in session zero, a low privileged app could send malicious window messages to a high privileged service window in the same session, tricking it into doing things or even running code. That was a shatter attack.
Asked how is it fixed?
Two main things Invista session zero isolation moved interactive users out of session zero and user interface privilege isolation UIPI was introduced.
What does UIPI do.
It prevents lower privileged low integrity level processes from sending most window messages to higher privileged process windows, even if they're on the same desktop in the same session. It blocks that message based attack vector.
A crucial privilege boundary for the UI and the source mentioned procession based named objects in Windows directories again right.
Under sessions ID base Named objects and sessions ID Windows. This keeps named objects and window stations isolated between different user sessions. NT object session drive lets you see the BNO for your current.
Session isolation everywhere, okay. Comparing Win thirty two APIs versus system calls again using create mutexx Win thirty two and anti create mutant ciscle key differences.
Look at the return values. Create mutech x returns the handled directly on success or NLL on failure. Anti create mutant returns an anti status code indicating success or failure, and the handle comes back through an output parameter a pointer.
So Win thirty two often hides the anti status and pointer stuff.
Yeah. It translates the anti status error into an NUL return or sets an error code retrievable via get laster. It's a more abstract, arguably simpler interface for the application developer.
Got it registry interaction. The module has WIN thirty two.
Path Yes, so you can use familiar paths like HKLM Software Microsoft with commands like get an it key instead of the native OMNS path Registry Machine.
Software handy, and you can convert between them yep.
The key objects return have properties like Win thirty two path and full path the OMNS path for easy conversion.
PowerShell has built in registry drives HKLM HKCU. Why use the module's provider.
Ah The NUL character issue malware sometimes hides keys or values by putting an NUL character inside the name the bill, and PowerShell provider can't handle those because it relies on annual terminated strings, but.
The anti object module can yes.
Because it uses the native APIs which work with counted strings, so it can see and interact with those hidden by annual entries, crucial for finding certain types of malware persistence.
Meki okay path limits max path still a thing.
Still a thing in many Win thirty two APIs that two hundred and sixty character limit two hundred and fifty nine usable for paths. Get anti file path demonstrates it. Try to convert a longer path and you'll get status name a too long.
A classic Windows limitation process. Creation Yeah, anti create user process versus create process. We use create process usually.
Always use create process or wrappers like start process or a new Win thirty two process. Anti create user process is the raw kernel call, but create process does a ton of essential setup work and user mode talking to CSRSS, setting up environment variables, et cetera.
Skipping create process would lead to a broken process pretty much.
It wouldn't be properly initialized for the user environment. New and thirty fo process is a wrapped around Create.
Process and the source mentions command line parsing issues with new wind thirty two process.
Right it tries to be helpful splitting on spaces adding lot exx. But if you just give it, say C program files my app and there's also a C program dot exx which one.
Runs, ambiguity and potential hijacking.
Exactly if a privileged process runs something based on a path that could be manipulated, like relying on the path, environment, variable or relative paths, it could be tricked into running the wrong executable or loading malicious DLLs. Best practice use applicate application name with the full explicit path to the executable you intend to run.
Be specific, avoid ambiguity. Okay, Shell APIs and file associations. How does double clicking my doc dot txt work?
Explorer doesn't try to run my doc dot txt. It looks up the file association for dot txt in the registry, finds that notepad or whatever is the handler. Then it uses shell APIs probably shall execute, telling it to open my dooc dot txt using notepad.
So new wind thirty two pm dot txt.
Would fail yep, because not txt isn't an executable. You need that shell layer to handle document types. The source shows querying the registry to find the handler and mentions shell execute verbs like open print et cetera.
Smart indirection Okay, quick recap, LSAs and SCM.
Still vital, absolutely fundamental. LSS Local Security Authorities subsystem handles authentication, log on sessions, security policy, SCM Service Control Manager manages background services, core security infrastructure.
Got it now? Finding those hidden registry keys with NUL characters again, how.
Exactly the source shows creating one with new end key embedding a zero back take zero in the name string. Then you use else recurs in the NT object registry derive and pipe it to where object name matches zero to find keys containing that NUL.
And for hidden values.
Similar idea, Create a value with an NUL in its name, then use a custom function like the select hidden value shown, which likely iterates through value names character by character looking for the nul. It bypasses the standard tools limitation.
Very clever, okay, Final section intro. Tokens. We mentioned them, but let's define them clearly right.
Tokens are the objects that represent the security context of a process or thread. Who is it? What can it do? Two main types primary tokens Every process has one, defines its main identity, usually the user who launched it. And impersonation tokens allow a thread to temporarily act with a different identity, maybe a client's identity for a specific task.
Primary is the baseline. Impersonation is temporary borrowing. Sets us up nicely for the next part.
YEP, Now we dive into what's in those tokens and how they're used.
All right, let's unpack primary tokens in more detail. These are the main ID badges for processes.
Right, that's exactly it. Every running process gets one. It holds the security identity, primarily the SID of the user account that started.
It, and this is what the SRM looks at for access checks.
Correct. When that process tries to touch a file or registry key, whatever, the SRM grabs this primary token and compares it against the resources security descriptor.
And the source mention. Figure four two showing the token details.
What are the critical parts, Yeah, that figures helpful. Key things are the user SID obviously, the token type primary versus impersonation, maybe an impersonation level if it's that type. And then those four sixty four bit IDs.
Right, token ID, authentication.
ID, authentication ID, origin login ID, and modified ID. The token ID is just a unique identifier for this specific token instance.
But the authentication ID seems important, linking back to a log on session very important.
When you log on, Elsas creates a log on session and the SRM assigns it a unique authentication ID. Every token created during that session gets the same authentication ID, So if I.
Log off and log back on, I get a new authentication.
IDY, even if you're the same user. It distinguishes different login instances. Helps with auditing and resource management.
Makes sense, and we can see this with get in token right.
Get in token grabs the token object. You can then look properties like token dot user or use format in token for a nicely formatted summary.
What does format and token show?
User groups with their sids and attributes, privileges and key stuff all shows even more and show in token gives you that GUI view similar to the figure commandline.
And GUI good options. Okay, impersonation tokens? Why does services use these? So?
A service often running as a powerful account like system might need to access a resource on behalf of a specific user who connected to it, like reading that user's files.
But the system account might not have permission for that user's files.
Directly exactly, so the service thread temporarily impersonates the user who made the request. It borrows their identity using an impersonation token. Now when it accesses the file, the SRM check uses the user's identity from the impersonation token, not the service's identity, a way.
To act as the user for a specific task. The source showed trying different impersonation levels with invoke in token and getting an.
Error right this status bat impersonation level error. It tried impersonating at the identification level, which is very weak lets the server see who the client is, but not act as them, especially not remotely.
So trying to open an object failed.
Yes, because that operation required a higher level, probably impersonation level, which does allow acting locally as the client. It wasn't an access denied on the object itself, but a failure because the type of impersonation wasn't sufficient for the action.
Subtle but important difference and duplicating a token handle isn't the same as duplicating the token object correct.
Duplicating the handle just gives you another reference pointer to the same token To create a new independent token object based on another, like making an impersonation token from a primary one, you need the duplicate access right on the original token.
Handle and you use anti duplicate token.
Which is wrapped by copy and token and PowerShell. That creates a whole new token object you can then modify or use for impersonation. The source shows creating a delegation level token. This way, that's the highest level, allowing remote impersonation to delegation.
Sounds powerful and potentially risky. Well, okay. The use for deny only attribute on sids in a token. How does that work?
It changes how the SRM evaluates acees. If a SID in your token has used for denyingly set that SID only counts when checking deny acees in a security descriptor. It's completely ignored for allow aces.
So it can only be used to deny access, not grant it.
Pretty much, the example was good. You're in the employee group allow access and remote access group deny access marked use for nine only. The deny still wins because of that attribute. It lets you build rules where specific memberships explicitly block access even if other memberships would normally allow it.
Explicit denials take precedence. Got it now. Token privileges These aren't access rights on objects, but system wide powers exactly.
Privileges grant the ability to perform specific system operations regardless of object permissions. Get and token privilege lists them for a token. Examples see shut down privilege, reboot the machine. See change notified privilege bypassed drivers. Checking lets you access see users other user desktop even if you can't list other users. See load driver privileged load kernel drivers very
powerful type to code signing. See take ownership privilege, become owner of file subjects, serie label privilege, change integrity labels.
Big powers, need careful assignment, okay, sandbox tokens restricted right, restricted, low box. What's the goal here?
Containment? Limit the damage If a process gets compromised, especially one handling untrusted input like a web browser or PDF reader, Run it with a weaker token, so even if hacked, it can't do much harm.
Makes sense? How to restrict a tokens work? They're the oldest type.
Yeah, you create a new token based on an existing one, but you add limitations. You specify restricting sids. These only count for allow acees, limiting what it can access. You can mark existing groups as use for deny only, and you can explicitly disable privilege, so.
You surgically weaken the original token. Right.
The example shows making one adding nt authority restricted, making everyone deny only disabling privileges. Browsers like Chrome Firefox use this concept heavily.
Okay, what about right restricted tokens?
Simpler, much simpler concept. A process with this token is blocked from writing to most things, but can usually still read and execute introduced in XPSP two for hardening services.
Easier but maybe less secure.
Potentially the source nodes a compromise. Process could still read sensitive files even if it can't write them.
It's a trade off read okay, right blocked, got it and low box tokens.
The source doesn't detail them much here, but they're a newer type often used with app containers. For UWP apps even more restrictive focus on deep isolation following least privilege principles.
So different levels of sandboxing available via tokens. Shifting topics, administrator privileges if not just one root SID in Windows.
Definitely not being an administray is more nuanced. It's a combination of things, usually membership in the builty in administrators group sid s one five thirty two five four four that group having powerful permissions granted on resources, and the
token possessing certain key privileges. Which privileges are typically admin level things like c create token privilege, make new tokens, CTB privilege act as part of the OS extremely powerful cetic ownership privilege, ce load driver privilege see a HEP privilege, SARAH store privilege see the bug privilege, access any processes memory see impersonate privilege. Having these indicates administrative capability and.
The source mentioned elevated sids based.
On the RA yeah kind of kernel shortcut for certain checks. Instead of looking for specific well known sids, the kernel just checks the last number the RID. If it's say five hundred and forty four administrators RID or five forty five users RID, it treats it as having that role in certain contexts.
Interesting pattern matching, okay. User count control UAC and elevation the pop up boxes.
We are right. UAC aims to have even administrators run with standard user rights by default. When you need to do something requiring admin rights, UAC prompts for consent. If you give it, the task runs elevated with your full administrator token.
And apps can request elevation automatically.
True their manifest file Yeah, an XML file embedded in the dot ex get executable manifest shows it. It specifies an execution level as invoker, run as caller, highest available, run elevated if possible or required.
Administrator must elevate and how do you manually elevate something?
Start processed after verb runas in PowerShell or using the shell execute API with the runa's verb both trigger the UAC prompt if needed.
Okay, link tokens and elevation type. What's that?
When an admin logs in UAC actually creates two tokens, a standard limited one and the full admin one, they're linked. Elevation is the process of switching from the limited token to the full one for a specific task.
After UAC consent, split tokens one limited one full makes sense? Security attributes more data in tokens.
Yeah, Extra bits of info beyond sids and privileges can be strings, numbers, sids, binary data. They add more context for potentially finer grained access decisions, especially with conditional acees can have flags like non inheritable, case sensitive new end token can add them, but needs see create token privilege.
More context for decisions. Okay. Token assignment and impersonation criteria. What rules apply when assigning or impersonating tokens.
Assigning a primary token if not inherited, needs assigned primary access on the token. Kernel checks integrity levels, log on session relationships. Impersonation is more complex see token can impersonate function check's integrity levels, can't impersonate higher privileges See impersonate Privilege often needed UPI flags, log on sessions, user sids.
And the system account gets special treatment big.
Time because user log on sessions ultimately derive from the initial system session. System can basically impersonate any user token of equal or lower integrity, even without seeing person at privilege. It's implicitly trusted in that way.
Wow. System is powerful and Windows ten added a check for the elevated flag.
Right before wind ten. You could potentially impersonate and admin's elevated token if you first lowered its integrity level. Win ten added a check you can't impersonate the elevated token of the same user if your current token isn't also elevated, closed a potential loophole.
Good hardening step and test antoken impersonation checks if impersonation.
Is allowed YEP, and set antoken integrity level lets you change integrity levels. Useful for testing these rules.
Okay? Finding UI access processes? What are they and why look for them?
Processes with the UI Access's flag set in their token can bypass some UIPI restrictions. They can send messages to higher privileged windows, needed for things like screen readers, accessibility.
Tools, but potentially risky if nowhere gets.
It exactly, so finding them is useful. The source shows get and process with excess query limited information and a filterscript checkingtoken dot UI access to list them identifies processes with that special UI interaction capability.
Good to note okay. Final major topic security descriptors the actual rules. What are the components?
Four main parts Owner SID, who controls the permissions Group SID mostly for POSTX compatibility less used in Windows, access checks, DACL Discretionary Access Control List, and SACL System Access Control List.
DCL is where the allowed NY rules live exactly.
It's a list of AC's access control entries. Each AC says six gets allowed to I access Y. The acess mask Y details the specific permissions and the SECL primarily for auditing ACS. There say a log an event if SidD X tries axs Y and succeeds fails. Since Vista, it also holds mandatory integrity lobles, non auditing, ACEES.
Owner group, DACL, SACL, got it well known sad's predefined identifiers YEP, consistent across systems, NL, SID, everyone, WD, local creator owner, built in.
Users BU system sy administrators B authenticated users AU medium mandatory level lots of them. They have a structure revision authority like NT authority five. Then relative identifiers built in users is S one five thirty two five forty five authority five RIDE thirty two for builton domain ride five forty five for users group.
Hierarchical structure access control lists ACLS. The DACL and SACL are types of these.
Structure simple header revision size followed by the list of ACS. Revision tells you the ACL version two, three four commonly, and.
The access control entries acees themselves.
ACE header type, flag size, and type specific data. For standard loagenie acees, the data is the SID and the access mask. Many types allow deny audit callback object ACS for property specific permissions.
And AC flags modified behavior.
Right inherently inherited from parent. Critical successful access, failed access for auditing, fine grained control okay.
Constructing and viewing security descriptors with PowerShell.
New n Security Descriptor lets you build one setting owner group, adding ACS format and security discret Victor is key for viewing shows owner group, DAC l ACS sec LACS clearly use show all and map generic for more detail and friendly permission names also shows control flex for the sd itself.
Powerful Inspection Tools Security Descriptor Definition Language SDDL.
The text format yeah much easier to read, write and store than binary blobs. Get NTCID. SDDL converts a SID to its SDDL string. Has aliases like wd BA, s y, A U, i U for well known sids, human.
Readable security descriptors and conditional expressions in SDDL for dynamic rules.
Exactly ACS that only apply if conditions based on security attributes in the token or on the resource are met at access time. Use attributes like token, integrity level, TI, user, SID, TU, device properties, et cetera. Uses operators like containers and errata adds huge flexibility.
Context where access control cool Finally brute forcing known sids with get account sids.
How why the function takes a base SID like S one five for NT authority and a range of IDs it tries. Each ried constructs the full SID and attempts to look up the account name. If it finds a name from the local system LSS, it means that SID exists.
So you can discover accounts by iterating rids YEP.
Useful for mapping out all the built in accounts and groups under S one five or S one five thirty two built in as the example shows a discovery technique.
A systematic way to find existing principles. Wow, that brings us to the end of this really really deep dive.
It certainly covered a lot of ground, from setting up PowerShell, the language basics all the way down into kernel objects, handles, tokens, security descriptors. It's intricate stuff, it really is.
But it's amazing how PowerShell, especially with modules like the one discussed in the source, lets you interact with and really understand these core window security mechanisms.
Absolutely it pulls back the curtain and having gone through this gives you a fantastic foundation. You know, you can now dig deeper into specific areas process security, privileged management, ecls, on specific objects, whatever interests you or is relevant to your work.
Definitely, powershow really is the key to unlocking a lot of this.
It provides the tools to explore as far as you want to go.
So the final thought to leave you with knowing just how granularly Windows controls access down to individual permissions and attributes. What are some maybe unexpected ways this might impact application behavior or security configurations you see every day. Certainly gives you a new perspective. Thanks for joining us on this deep dive
