Speaker 1: Welcome to the deep dive. Today. We're really getting into
Speaker 1: the weeds with Windows System Programming.
Speaker 2: Yeah, this is part two, building on those fundamentals exactly.
Speaker 1: We're thinking about our listener, the learner who's maybe bumped
Speaker 1: into terms like DLLs, memory management, security, maybe even performance analysis.
Speaker 2: Right and wants to get a clearer picture without drowning
Speaker 2: in super technical details.
Speaker 1: Our goal is to give you the learner, that clearer,
Speaker 1: more insightful understanding.
Speaker 2: Think of it like getting the essential toolkit for these
Speaker 2: complex topics. Wow, we want those aha moments, not just
Speaker 2: the list of functions for sure.
Speaker 1: And we're drawing heavily from Windows ten System Programming Part two.
Speaker 1: It's a great resource for digging into the advanced Windows
Speaker 1: API stuff.
Speaker 2: It really tries to bridge that gap for programmers working
Speaker 2: with modern Windows, covering well everything from memory tricks to
Speaker 2: security layers.
Speaker 1: So our mission today extract the really crucial, the fascinating.
Speaker 2: Bits exactly, give you those key insights that solid foundation
Speaker 2: will hit advanced memory management, the whole world of DLLs.
Speaker 1: The complexities of Window security, and.
Speaker 2: The tools you need for debugging and diagnostics when things
Speaker 2: go sideways.
Speaker 1: Okay, let's kick things off with memory management. We're going
Speaker 1: way beyond the basics here.
Speaker 2: Definitely think raw control. First up is virtual memory allocation
Speaker 2: virtual alec and uh virtual alex.
Speaker 1: What's the core difference there, y x.
Speaker 2: Well, virtual ALIC is for your own processes memory. Virtual
Speaker 2: alec though, that lets you allocate memory inside another process,
Speaker 2: assuming you have the permissions of course.
Speaker 1: Ah. Okay, so that's key for things like debuggers, right
Speaker 1: reaching into another program.
Speaker 2: Space Precisely, it's fundamental for those kinds of tools. But
Speaker 2: it also hints at more complex system interactions.
Speaker 1: But that sounds potentially risky. How is that controlled?
Speaker 2: Security is paramount? You need specific privileges to target another
Speaker 2: process with virtual alex. We'll touch more in security later,
Speaker 2: but it's tightly controlled. It makes it a powerful tool,
Speaker 2: but not easily misused.
Speaker 1: Okay, makes sense now the book mentioned something specific about
Speaker 1: security with these functions. Committed pages get zamboed out.
Speaker 2: Yes, that's crucial. When Windows commits memory using virtual alec
Speaker 2: or x, it wipes it clean, fills it with zeros.
Speaker 1: Why do that extra step?
Speaker 2: It prevents information leakage. You don't want one process accidentally
Speaker 2: seeing leftover data from whatever process. Use that physical.
Speaker 1: Memory before think of it, like wiping a whiteboard.
Speaker 2: Got it, unlike say, malik, which might just give you whatever.
Speaker 1: Was there exactly a clean slate every time.
Speaker 2: Now Reserving versus committing memory why the two stages.
Speaker 1: It's like planning versus building. Reserving is like staking out
Speaker 1: a claim in the virtual address space. You say this
Speaker 1: range is mine, nobody else.
Speaker 2: Touch it, okay, prevents conflicts, right.
Speaker 1: Committing is when you actually tell the system, okay, I
Speaker 1: need physical memory RAM or page filespace backing this part
Speaker 1: of my reserve space. You make it usable so you.
Speaker 2: Can reserve a big chunk, but only commit what you
Speaker 2: actually need right now.
Speaker 1: Precisely reserve the whole plot, build houses one by one,
Speaker 1: very efficient.
Speaker 2: What about these memory set and members Satendo flags. They
Speaker 2: sound a bit niche, they are, Yeah. Member set basically
Speaker 2: tells Windows, hey, I don't care about the contents of
Speaker 2: this committed memory anymore. Feel free to take the physical
Speaker 2: pages back if needed, but leave it allocated.
Speaker 1: Sort of like marking it as discardible.
Speaker 2: Kind of, and memorys Tottendo's signals you might need it again,
Speaker 2: but there's no guarantee the old data is still there.
Speaker 2: If the physical pages got reused, it's for specific optimation scenarios.
Speaker 1: Okay, Now that micro excel to example in the book
Speaker 1: using page based allocation and exception handling. That's the takeaway there.
Speaker 2: It's clever. Virtual allock works on pages right, usually four
Speaker 2: kb chunks, so microcell reserves a huge virtual address space
Speaker 2: for its grid.
Speaker 1: It doesn't actually commit most of it initially exactly.
Speaker 2: Then if you try to access to sell in an
Speaker 2: uncommitted part, it triggers an access violation and exception.
Speaker 1: Ah.
Speaker 2: The application catches that specific exception, commits the record fired
Speaker 2: page using virtualolock inside the exception handler, and then tells
Speaker 2: the CPU Okay, try that instruction again. Wow.
Speaker 1: So it looks like a massive spreadsheet but only uses
Speaker 1: RAM for the bits you're actually using Memory on demand.
Speaker 2: BINGO super efficient for potentially huge data sets.
Speaker 1: Brilliant. Okay. Let's shift gears slightly within memory management working sets.
Speaker 1: What are those? Exactly?
Speaker 2: A process is working set is basically the set of
Speaker 2: its memory pages currently residing in physical RAM, stuff it
Speaker 2: can access without a page fault.
Speaker 1: So the stuff it needs readily available for good performance exactly.
Speaker 2: The memory manager tries to keep the actively used pages
Speaker 2: in the working set and juggles this across all running
Speaker 2: processes to keep the system.
Speaker 1: Responsive, and if a page isn't used for a while,
Speaker 1: it might get kicked out of the working set. The
Speaker 1: book mentions soft page faults though.
Speaker 2: Right, If a page is removed from the working set
Speaker 2: but it's still somewhere else in RAM, accessing it causes
Speaker 2: a soft page fault. The system can quickly map it
Speaker 2: back in minimal delay.
Speaker 1: As opposed to a hard page fault.
Speaker 2: Yeah, a hard fault happens when the page isn't in
Speaker 2: RAM at all, it's been paged out to disc. That
Speaker 2: requires reading it back from the disc, which is much
Speaker 2: much slower.
Speaker 1: Gotcha. Now, can you actually control the working set size?
Speaker 1: The book mentions set process working set size and empty
Speaker 1: working set.
Speaker 2: You can influence it. Yeah, Set process working set size
Speaker 2: lets you suggest minimum and maximum sizes useful if you
Speaker 2: really need certain things to stay in RAM.
Speaker 1: And empty working set.
Speaker 2: That's more aggressive, especially with size at one. It tells
Speaker 2: the system trim this process is working set way down.
Speaker 2: Maybe if it's going idle for a long time. You
Speaker 2: free UPRAM for others.
Speaker 1: And tools like the working sets app let you see
Speaker 1: the stuff they do.
Speaker 2: Yeah, though you usually need admin rights to peek into
Speaker 2: other processes working sets in detail.
Speaker 1: Right makes sense? Okay, Next memory topic peeps beyond the
Speaker 1: standard library malick free. What Windows specifics are there?
Speaker 2: Well? Windows provides heap walk to look inside the default
Speaker 2: heap of the current process, but just the current one.
Speaker 1: What if you need to look at another processes heap,
Speaker 1: like for debugging, Then.
Speaker 2: You turn to the tool help library use functions like
Speaker 2: create tool help thirty two snapshot with the right flags.
Speaker 2: Then heap thirty two list first next to get the
Speaker 2: heap list for the target process, and heap thirty two
Speaker 2: first next to examine the blocks within each heap.
Speaker 1: Okay, a bit more involved for external processes. The book
Speaker 1: also talks about heap coalescing and heap compact.
Speaker 2: Right coalescing is when the heat manager automatically merges adjacent
Speaker 2: free blocks back together into bigger free blocks.
Speaker 1: Helps fight fragmentation like tidying up the free space.
Speaker 2: Exactly normally as automatic, but you can disable it with
Speaker 2: a global flag maybe for some micro optimization. Heap compact
Speaker 2: lets you force a coalescing operation if it's disabled, or
Speaker 2: just generally try to compact the heap.
Speaker 1: Interesting trade off there now a UMA non uniform memory
Speaker 1: access sounds like it's mainly for big muzzy processor machines.
Speaker 2: Absolutely on systems with multiple CPU sockets and dedicated memory banks.
Speaker 2: For each access time can vary depending on whether a
Speaker 2: CPU is accessing its local memory or memory attached to
Speaker 2: another CPU. That's the non uniform part.
Speaker 1: So how does Windows help with that?
Speaker 2: There are functions like get new mode Processor mask X
Speaker 2: to figure out the system's new MAY topology, which processors
Speaker 2: belong to which node, and then critically, functions like virtual
Speaker 2: alkix NUMA or the newer virtual loc too let you
Speaker 2: specifically allocate memory on a preferred UMA node.
Speaker 1: So you can try and keep memory close to the
Speaker 1: CPU that's going to use.
Speaker 2: It most precisely. For high performance computing or large database servers,
Speaker 2: NUMA aware allocation can give a noticeable performance boost. It's
Speaker 2: about minimizing that cross node latency.
Speaker 1: Makes sense, okay. Last item in our memory deep dive
Speaker 1: memory mapped files or MMFs. These sound quite powerful.
Speaker 2: They really are. Mapewol file is the core function. You
Speaker 2: take a file mapping object which might represent an actual
Speaker 2: file on disc or not, and map it directly into
Speaker 2: your process's virtual address.
Speaker 1: Space, So accessing the file becomes like accessing RAM essentially.
Speaker 2: Yes, The OS handles the magic of loading data from
Speaker 2: the file into memory when needed and writing changes back.
Speaker 2: It's very efficient for file io.
Speaker 1: And great for inner process communication.
Speaker 2: Right IPC Absolutely, It's a classic high performance IPC technique.
Speaker 2: On a single machine, multiple processes map the same file
Speaker 2: mapping object, and boom, they're sharing the same physical memory.
Speaker 2: No need to copy data back and forth through pipes
Speaker 2: or sockets.
Speaker 1: Super efficient. The book mentions mapuof f alex NUMA. I
Speaker 1: guessing that's the NUMA version you got.
Speaker 2: It allows specifying a preferred UMMA node for the mapping,
Speaker 2: just like with virtual alex NUMA.
Speaker 1: Now this is cool. Anonymous MMFs you can share memory
Speaker 1: without even having a file on disc. How does that work?
Speaker 2: Right? Instead of being backed by a file, anonymous MMFs
Speaker 2: are backed by the system's page file. The key is
Speaker 2: you still get a handle to the mapping object. You
Speaker 2: can pass this handle or often just the starting memory
Speaker 2: address after mapping to another process.
Speaker 1: How do you pass it?
Speaker 2: Any standard IPC mechanism, window messages, named pipes, even just
Speaker 2: a shared variable in a DLL. The both processes load
Speaker 2: the second process then uses that handle or address to
Speaker 2: map the same anonymous shared memory region into its own space.
Speaker 1: That sounds incredibly simple for sharing data, just pass a pointer.
Speaker 2: Essentially, it's a very elegant approach for certain kinds of IPC, and.
Speaker 1: One less thing on mmf's MEMO large pages. What's the
Speaker 1: benefit there?
Speaker 2: Standard memory pages are small, typically for KB. Large pages
Speaker 2: are much bigger, maybe two memb or even one GB
Speaker 2: on some systems. Using large pages for memory mapping can
Speaker 2: reduce TLB pressure. That's the translation look aside buffer cash
Speaker 2: and potentially improve performance for applications accessing large amounts of
Speaker 2: map data.
Speaker 1: But there are requirements.
Speaker 2: Yes, you need the Sellock memory privilege which is granted
Speaker 2: by default, and the file mapping object itself must have
Speaker 2: been created with the c clarch pages flag. So it's
Speaker 2: an optimization for specific scenarios.
Speaker 1: Whow okay, that covers a lot of ground on memory.
Speaker 1: Let's switch gears now to dynamic link libraries DLLs. Everyone
Speaker 1: knows they're about res usable code, but how does Windows
Speaker 1: actually handle them?
Speaker 2: Right? Dls are fundamental in Windows. The book gets into
Speaker 2: how they're linked implicitly versus explicitly how they get loaded
Speaker 2: is key.
Speaker 1: Okay, implicit linking first, that's the common way where the
Speaker 1: OS just loads the DLLs your program needs when it starts.
Speaker 2: Pretty much when your ex loads, the Windows loader looks
Speaker 2: at its import table to see which DLLs and functions
Speaker 2: it needs. Then it has to find those ds.
Speaker 1: Is there a specific search order? Where does it look
Speaker 1: there is?
Speaker 2: It's a defined path. First, it checks if the DLL
Speaker 2: is in the known DS list. These are core system
Speaker 2: ds always loaded from the system directory for security on
Speaker 2: performance helps prevent DLL hijacking.
Speaker 1: Okay, known ds first, Then.
Speaker 2: Then the directory the ex itself is in. After that
Speaker 2: the process is current working directory, then the system directory
Speaker 2: System thirty two, the Windows directory, and finally all the
Speaker 2: directory is listed in the path environment variable.
Speaker 1: That order seems important for deployment. What if it can't
Speaker 1: find a needed DLL, usually.
Speaker 2: Get that dreaded error message box saying that DLL is
Speaker 2: missing and the application just won't start. Process terminates. Figure
Speaker 2: fifteen to seven in the book shows a typical example.
Speaker 1: Not very helpful. Sometimes you mentioned known DLLs helping prevent hijacking.
Speaker 2: Yeah, By forcing the load from the system directory to
Speaker 2: find in the registry HKLM no ds, it stops malware
Speaker 2: potentially placing a malicious version of a core DLL in
Speaker 2: say the application directory to get loaded instead.
Speaker 1: Smart Okay, so that's implicit. What about explicit linking.
Speaker 2: Explicit linking is where you, the programmer, take control. You
Speaker 2: use load library to load a DLL specifically when you
Speaker 2: need it, and free library to unload it later.
Speaker 1: When would you do that.
Speaker 2: Perfect For things like plugins, you load the plug in
Speaker 2: DLL only when the user activates that feature. Or maybe
Speaker 2: if a feature depends on a DLL that might not
Speaker 2: be installed, you can try to load library and if
Speaker 2: it fails, you can handle it gracefully. Maybe disable the
Speaker 2: feature instead of crashing.
Speaker 1: Gives you more control and resilience. The book also mentions
Speaker 1: set default deal directories and adult directory customizing the search
Speaker 1: path exactly.
Speaker 2: These let you modify how the loader searches for DLLs,
Speaker 2: especially for explicit loads via load library. Set the fault
Speaker 2: deal directories can restrict the search, for instance, only to
Speaker 2: the system directory or directories added with adult directory.
Speaker 1: And adult directory adds a specific path to the search
Speaker 1: list right.
Speaker 2: There are various flags you can use, like application diet,
Speaker 2: user at I ers System thirty two, Table fifteen to
Speaker 2: one lays them all out. It gives you finer control
Speaker 2: over dependencies, which can be important for security and avoiding conflicts.
Speaker 1: Useful for complex setups. Now, deal main. That's an entry
Speaker 1: point for a DLL.
Speaker 2: Correct, It's a function the loader calls inside the DLL
Speaker 2: for various events when the dealers first loaded into a process,
Speaker 2: DL processed, attack, when it's unloaded, delll process attached, and
Speaker 2: also potentially when threads are created, DL thread attached or
Speaker 2: exit deal thread attached within that process.
Speaker 1: Why the thread notifications.
Speaker 2: Some DLLs might need to do per thread initialization or cleanup,
Speaker 2: but often they don't, so you can call disabled thread
Speaker 2: library calls as an optimization to tell the loader, hey,
Speaker 2: don't bother calling my dealmain for thread events saves a
Speaker 2: bit of overhead.
Speaker 1: Okay, but the book has a big warning about delmain
Speaker 1: and something called the loader lock sounds serious.
Speaker 2: It is very serious. The loader lock is an internal
Speaker 2: lock the system uses while loading or unloading DLLs, including
Speaker 2: when it calls delmain. The danger is deadlock if your
Speaker 2: delmain code tries to do something that also requires the
Speaker 2: loader lock, like calling load library itself or get module handle,
Speaker 2: or maybe waiting on another synchronization object that some other
Speaker 2: thread holds while it's waiting for the loader lock.
Speaker 1: Everything grinds to a halt.
Speaker 2: Exactly deadlock your process hangs. The strong advice is keep
Speaker 2: dealmain simple, do minimal initialization, don't call functions that might
Speaker 2: load other DLLs or wait on complex synchronization. It's a
Speaker 2: notorious trap.
Speaker 1: Definitely something to watch out for. Okay, let's talk about
Speaker 1: DL injection and hooking. This sounds like it could be
Speaker 1: used for interesting purposes.
Speaker 2: Interesting is one word for it. Yes, it can be
Speaker 2: used for legitimate tools like debuggers, monitoring utilities, accessibility aids,
Speaker 2: but also for malware. DLL injection is basically forcing another
Speaker 2: process to load a DLL it wasn't intending to load.
Speaker 1: How is that typically done?
Speaker 2: One common method uses create a remote thread. You need
Speaker 2: privileges first like process vm right and process create thread.
Speaker 2: Then you use virtual allox to allocate some memory in
Speaker 2: the target.
Speaker 1: Process, write the pass to your DLL into that memory.
Speaker 2: Right using right process memory. Then you call create a
Speaker 2: remote thread, telling it to start a new thread in
Speaker 2: the target process, executing the load library function and passing
Speaker 2: it the address of the DLL path you just wrote.
Speaker 1: So you trick the other process into loading your code essentially.
Speaker 2: Yes.
Speaker 1: The book also mentions set Windows hook x. How does
Speaker 1: that fit in can it cause injection?
Speaker 2: It can? Yes. Set Windows sookx lets you install hooks
Speaker 2: to intercept system events, keyboard input, mouse messages, window messages,
Speaker 2: et cetera. If you install a global hook or one
Speaker 2: the target's threads in another process.
Speaker 1: The hook procedure itself needs to run in that other
Speaker 1: process's context.
Speaker 2: Exactly, and for that to happen, the hook procedure must
Speaker 2: be located inside a DLL. When you install such a hook,
Speaker 2: Windows automatically injects that DLL into all the relevant target processes,
Speaker 2: so your hook code can run there.
Speaker 1: Ah, So the hooking mechanism itself performs the injection correct.
Speaker 2: The example in the book uses a whgt methage hook
Speaker 2: to snoop on keyboard input in notepad, and the hook
Speaker 2: code has to be in an injected dlll.
Speaker 1: Okay, then there's itIt hooking Import address table hooking sounds
Speaker 1: very low level.
Speaker 2: It is super low level. Every module EXE DL has
Speaker 2: an import address table that lists the functions that imports
Speaker 2: from other ds, along with the memory addresses where those
Speaker 2: functions actually live. IAT hooking involves finding the entry for
Speaker 2: a specific function in.
Speaker 1: That table and overwriting the address.
Speaker 2: Yes, you overwrite the address with the address of your
Speaker 2: own function, the hook function, so whenever the original code
Speaker 2: tries to call the imported function, it gets redirected to
Speaker 2: your code.
Speaker 1: Instead, like intercepting the call. The book uses getsi's color
Speaker 1: as an example.
Speaker 2: Right replacing calls to the real getsy's color with calls
Speaker 2: to a custom getsi's color hooked. You have to parse
Speaker 2: the module's pe header structure to find the import descriptors,
Speaker 2: locate a target DLL like user thirty two dot dll,
Speaker 2: find the function pointer, and then patch it.
Speaker 1: But the book flags this as tricky.
Speaker 2: Very tricky. First, the exact way you patch the address
Speaker 2: depends heavily on the CPU architecture. By eighty six by
Speaker 2: sixty four arm are all different. Second, you must do
Speaker 2: the patch atomically. If another thread tries to call the
Speaker 2: function while you're halfway through changing the address, crash yaikes. Yeah.
Speaker 2: It requires careful synchronization and knowledge of assembly or low
Speaker 2: level intrinsics. It's powerful, but complex and often fragile. Higher
Speaker 2: level hooking mechanisms are usually preferred if they can do
Speaker 2: the job.
Speaker 1: Good to know, okay, that wraps up DLLs. Let's move
Speaker 1: into our third major area, Windows security.
Speaker 2: This is huge, absolutely massive, and crucial. The book breaks
Speaker 2: it down into key components, show nicely in figure sixteen
Speaker 2: to one SIDS, tokens, access masks, privileges, security descriptors, UAC
Speaker 2: integrity levels.
Speaker 1: Let's start with sids security identifiers. These are the unique
Speaker 1: ideas for users and.
Speaker 2: Groups and computers services. Basically any security principle, every user account,
Speaker 2: every group gets a unique SID. The book shows using
Speaker 2: creat well known SID to get the sids for standard
Speaker 2: built in accounts and groups like local system or.
Speaker 1: Everyone, and you can convert them to strings.
Speaker 2: YEP converts cit as strings in gives you that familiar
Speaker 2: S one five format and look up accounts. It goes
Speaker 2: the other way, finds the account name like administrators for
Speaker 2: a given SID. It also tells you the SID type, user, group,
Speaker 2: et cetera.
Speaker 1: Okay, next, it up tokens. What's their role?
Speaker 2: An access token is like a security passport for a
Speaker 2: process or thread. When you log in, the system creates
Speaker 2: a token holding your user SID, all the group sids
Speaker 2: you belong to, analyst of your privileges.
Speaker 1: Privileges like being able to debug other processes.
Speaker 2: Exactly, or shut down the system or change the system time.
Speaker 2: These are distinct from general user rights. Most privileges are
Speaker 2: actually disabled by default in your token, even if you're
Speaker 2: an admin. You have to explicitly enable them if you
Speaker 2: need them. See Change Notified Privileges. One exception usually enabled.
Speaker 2: Process Explorer shows this clearly.
Speaker 1: How do you check or change privileges in a token?
Speaker 2: Programmatically you use get token information to query the token's contents,
Speaker 2: including privileges, and adjust token privileges to enable, disable, or
Speaker 2: remove them. But you need the token adjust privileges right
Speaker 2: on the token handle first.
Speaker 1: And privileges have those weird names like c DE bug
Speaker 1: privilege they do.
Speaker 2: You use look of privilege value to get the internal
Speaker 2: identifier the LOUE for a privileged name before you can
Speaker 2: use adjust token privileges.
Speaker 1: The book also talks about primary versus impersonation tokens.
Speaker 2: Right, your main process token is the primary token, but
Speaker 2: a thread, particularly in a server process, might temporarily impersonate
Speaker 2: a client. Using an impersonation token means the thread acts
Speaker 2: with the client security context. They're sids their privileges.
Speaker 1: Why would it do that?
Speaker 2: So the server can access resources on behalf of the
Speaker 2: client using the client's permissions. If the client isn't allowed
Speaker 2: to access a file, the server thread impersonating them won't
Speaker 2: be either requires the same person at privilege. You use
Speaker 2: functions like in person log on user and then revert
Speaker 2: to self to stop impersonating. Figure sixteen ten illustrates this
Speaker 2: client server.
Speaker 1: Scenario, very important for secure server design. Okay, access masks,
Speaker 1: these are the permissions themselves.
Speaker 2: Yes, an access mask is just a bit mask, a
Speaker 2: thirty two bit value, where each bit represents a specific
Speaker 2: permission like read, write, to lead, execute, etc. Relevant to
Speaker 2: a particular type of object.
Speaker 1: Are they always specific? I've seen generic reed.
Speaker 2: Good point. There are generic rights like generic creed, generic right,
Speaker 2: generic xCT, generical. The system maps these generic rights to
Speaker 2: a set of specific rights depending on the object type.
Speaker 2: Generic creed on a file means something different than generic
Speaker 2: creed on a registry key. Figure sixteen sixteen shows an
Speaker 2: example mapping.
Speaker 1: And these rights are controlled by security descriptors.
Speaker 2: Correct Every securable object, file, registry, key, process, thread, mutex,
Speaker 2: et cetera has a security descriptor attached. This structure holds
Speaker 2: all the security info the owner SID, the primary group SID,
Speaker 2: less use now the SACL system Access Control List for auditing,
Speaker 2: and crucially the DACL Discretionary Access Control List.
Speaker 1: The DACL is the important one for permissions.
Speaker 2: It is the DACL contains a list of accs access
Speaker 2: control entries. Each ACE specifies a SID, a user or group,
Speaker 2: and an access mask stating whether that SID is allowed
Speaker 2: or denied those specific rights.
Speaker 1: Order matters in the DACL.
Speaker 2: Critically, the system evaluates aces in order. Typically, deny aces
Speaker 2: come first. The first ACE that matches the user group
Speaker 2: in the requested permission determines the outcome, so an explicit
Speaker 2: deny will override a later a LIE allowed for the
Speaker 2: same group.
Speaker 1: How do you work with these security descriptors encode?
Speaker 2: For named objects like files or register keys, you use
Speaker 2: get named security info and set name security info. The
Speaker 2: book show is getting the owner of a file. Remember
Speaker 2: not to free the return buffer yourself. For kernel objects
Speaker 2: like Mutex's, it's get kernel object security and set kernel
Speaker 2: object security.
Speaker 1: What are the default permissions?
Speaker 2: Usually unnamed kernel objects often get a NL DACL, meaning
Speaker 2: everyone has full access. Named objects usually inherit a default
Speaker 2: DACL based on the creator's token, and if you want
Speaker 2: the standard window security UI there's the edit security API,
Speaker 2: but it requires implementing a calm interface I Security information,
Speaker 2: which is more involved.
Speaker 1: Right. Okay, switching to UAC User account control still relevant today,
Speaker 1: very much so.
Speaker 2: Its goal was to get people out of the habit
Speaker 2: of running as admin all the time, even if you
Speaker 2: are an administrator. UAC means most of the things run
Speaker 2: with a standard user token.
Speaker 1: By default, which has fewer privileges than the full administrator token.
Speaker 2: You also get exactly to use the full admin token.
Speaker 2: A process needs to be.
Speaker 1: Elevated, and the standard way to trigger elevation is.
Speaker 2: Using shell execute or shell execute x with the runous
Speaker 2: verb that tells the system this needs admin rights. Thep
Speaker 2: info service then usually prompts the user with that consent dialogue,
Speaker 2: consent dot ex. If approved, the process starts with the
Speaker 2: full admin token. Figure sixteen twenty shows this flow.
Speaker 1: What about UAC virtualization That sounds like a compatibility.
Speaker 2: Thing it is. It's mainly for older thirty two bit
Speaker 2: apps that weren't written with UAC in mind and try
Speaker 2: to write two protected locations like program files or h
Speaker 2: KLM in the registry.
Speaker 1: What does virtualization do?
Speaker 2: It transparently redirects those rights to per user locations under
Speaker 2: users username, app beta local virtual store. The app thinks
Speaker 2: it wrote to the protected location, but it actually wrote
Speaker 2: to the user's private virtualized copy. Keeps the app working
Speaker 2: without needing admin rights.
Speaker 1: Usually, can you see if it's active?
Speaker 2: Yeah, Task Manager and process explore can show the UAC
Speaker 2: virtualization status for a process enabled, disabled, or not allowed.
Speaker 2: Figures sixteen to eight and sixteen to nine illustrate.
Speaker 1: This clever workaround. Okay, then integrity levels another layer on
Speaker 1: top of standard permissions.
Speaker 2: Kind of it's mandatory integrity control. Processes and objects have
Speaker 2: an integrity level, typically low, medium, high, or system. Most
Speaker 2: standard apps run at medium, Elevated apps run at high system,
Speaker 2: services run at system sandbox. Things might run it low.
Speaker 1: Viewable in Process Explorer too, yep.
Speaker 2: Figure sixteen twenty two shows it. The key rule is
Speaker 2: the no write up policy. By default, a lower integrity
Speaker 2: process generally cannot modify a higher integrity object.
Speaker 1: So a medium integrity web browser can't easily write to
Speaker 1: files owned by a high integrity process.
Speaker 2: Correct or even modify the high integrity process itself. In
Speaker 2: memory access is restricted. By default. Objects get medium integrity
Speaker 2: unless they have a specific mandatory label ace setting it. Otherwise,
Speaker 2: you can lower a processes integrity, but raising it needs
Speaker 2: a special privilege seria label privilege that users don't normally have.
Speaker 1: Interesting. The book also mentioned specialized things like control flow
Speaker 1: guard CFG.
Speaker 2: Yeah. CFG is a compiler linker OS feature to mitigate
Speaker 2: exploits that try to hijack the program's control flow. It
Speaker 2: validates targets of indirect calls against a bitmap of known
Speaker 2: valid function entry points. If the target isn't valid, the
Speaker 2: process terminates dumb, and CFG can show if a binary.
Speaker 1: Uses it and process mitigation policies.
Speaker 2: These are extra security arding options you can enable system
Speaker 2: wide or per process using tools like g flags X
Speaker 2: or specific APIs, things like blocking nonsystem fonts, preventing child
Speaker 2: process creation, or restricting system calls. Figure sixteen twenty nine
Speaker 2: shows using g flags sx to disable win thirty two
Speaker 2: K calls for Notepad, causing it to fail.
Speaker 1: Wow. Lots of layers, Okay, Final technical section, Debugging and diagnostics.
Speaker 1: How do we figure out what's really going on?
Speaker 2: Crucial tools here? One simple one is output debugstring. Your
Speaker 2: application sends text messages and a debugger can pick them up.
Speaker 1: What if no debugger is attached.
Speaker 2: Tools like c's internals debug you or the booksdwin viewer
Speaker 2: can monitor these messages system wide. The use a shared
Speaker 2: memory buffer and an event. The OS signals when new
Speaker 2: messages arrive.
Speaker 1: Okay, then performance counters getting metrics on CPU, memory, etc.
Speaker 2: Right. The PDH Performance Data Helper API is the way
Speaker 2: to go. Use pd open query than PDH ad counter
Speaker 2: to specify which counters you want, like percent process or
Speaker 2: time for a specific process.
Speaker 1: Then collect the data yep.
Speaker 2: PDH collect query data, samples the values, and PDHKT formatted
Speaker 2: counter value gives you the result as a nice string
Speaker 2: or number. The book shows getting CPU usage for all
Speaker 2: processes using pdhkt formatted counter array. Sometimes you might want
Speaker 2: pdhh crow counter value for raw data before calculations.
Speaker 1: Useful for performance tuning. What about process snapshotting PSS?
Speaker 2: PSS is cool. It lets you capture a consistent point
Speaker 2: in time snapshot of a process is state, memory, threads, handles,
Speaker 2: et cetera into a file or memory buffer.
Speaker 1: Why would you do that?
Speaker 2: Great for offline analysis of crashes or hangs. You grab
Speaker 2: a snapshot when the problem occurs, then analyze it later
Speaker 2: without holding up the live system. Scapture snapshot takes the
Speaker 2: snapshot ps free snapshot cleans up. Table twenty to one
Speaker 2: lists the flags for what data to.
Speaker 1: Include okay now. ETW Event Tracing for Windows sounds very powerful.
Speaker 2: Is the high performance tracing framework in Windows, the OS
Speaker 2: and many applications. EMIT detailed events via ETW providers identified
Speaker 2: by GEDs logman quaria providers shows you who's registered.
Speaker 1: How do you capture these events?
Speaker 2: You set up an ETW session using star trace. Then
Speaker 2: you tell the session which providers to listen to using
Speaker 2: enable trace x, often filtering by severity, level or keywords.
Speaker 2: The events usually go to an ETL file.
Speaker 1: And then you analyze the ETL file.
Speaker 2: Right using tools like event Viewer for simple logs or
Speaker 2: Windows Performance Analyzer WPA for really deep analysis. WPA is
Speaker 2: incredibly powerful for correlating events across the system. Figures twenty
Speaker 2: thirteen and twenty fourteen show these tools.
Speaker 1: Can you process events in real time?
Speaker 2: Yes? You use open trace with process racing meulial time
Speaker 2: and invide a callback function. Your callback gets invoked for
Speaker 2: each event as it happens.
Speaker 1: How do you make sense of the event data?
Speaker 2: The callback receives an event record. You use the Trace
Speaker 2: Data Helper tdhapis like PDH get event information and TDH
Speaker 2: format property to parse the event's metadata and format its
Speaker 2: specific data fields based on the provider's manifest. The book
Speaker 2: shows parsing and displaying event details.
Speaker 1: It even mentions the kernel provider.
Speaker 2: Yeah, the Windows kernel trace provider emits tons of low
Speaker 2: level OS events about processes, threads, disco, networking, et cetera.
Speaker 2: Requires admin rights. Obviously, you can even create your own
Speaker 2: custom ETW providers for your applications.
Speaker 1: Extremely versatile. Lastly, actual debuggers, the tools that let you
Speaker 1: step through code right.
Speaker 2: Windows provides APIs for one process to debug another. You
Speaker 2: can attach to a running process using debug active process.
Speaker 2: You just need its pig.
Speaker 1: Or start a process under the debugger YEP.
Speaker 2: Use create process with the debug process or debugul this
Speaker 2: process flag. The debugger then gets notified of events in
Speaker 2: the debuggy via the debug zet structure. What kind of
Speaker 2: events exception, thread creation, exit process, exit DLL loads some
Speaker 2: loads output from up with debug string Table twenty to
Speaker 2: five lists them. The debugger calls wait for debug event
Speaker 2: to get the next event, processes it, and then calls
Speaker 2: continued debug event to let the debuggy run again.
Speaker 1: The book has a simple debug example.
Speaker 2: Yeah, shows the basic loop wait for event, check the
Speaker 2: event type like output string er, DLL, load, print info continue.
Speaker 2: It's the fundamental structure of a debugger.
Speaker 1: Okay, we have covered an incredible amount of technical ground there.
Speaker 2: We really have, from the depths of memory management and DLLs,
Speaker 2: through the layers of security right up to debugging and
Speaker 2: tracing with ETW. The full book also dies into CALM
Speaker 2: and win RT, which are foundational.
Speaker 1: To and hopefully for you the learner. This deep dive
Speaker 1: has connected some dots, provided those aha moments, and maybe
Speaker 1: demystified some of these complex Windows internals.
Speaker 2: Yeah, hopefully gives you that solid footing. So maybe next
Speaker 2: time you're using your computer and something interesting happens or
Speaker 2: an application behaves in a certain.
Speaker 1: Way, you can think about these mechanisms underneath. How is
Speaker 1: memory being used, how are these components talking, what security checks.
Speaker 2: Are happening exactly? What new questions does this raise for
Speaker 2: you about the software you interact with every day. Something
Speaker 2: to chew on.
Speaker 1: A great thought to end on. Thanks for joining us
Speaker 1: on the deep dive.