Tools: Stage 0.2 — Operating System Fundamentals

Tools: Stage 0.2 — Operating System Fundamentals

From Zero to Cybersecurity Professional | Complete Roadmap Series

Table of Contents

1. Why Operating Systems Matter in Cybersecurity

2. What Is an Operating System and How Does It Work

2.1 The Core Definition

2.2 Major Operating System Families

2.3 The OS Architecture — Big Picture

2.4 Monolithic vs Microkernel vs Hybrid

3. The Kernel — The Heart of Everything

3.1 What the Kernel Is

3.2 The Kernel as the Ultimate Security Authority

3.3 Kernel Modules and Drivers — The Expansion Surface

4. User Mode vs Kernel Mode

4.1 The Fundamental Division

4.2 Why This Boundary Exists

4.3 How the Transition Works

4.4 Security Attacks on This Boundary

4.5 Windows-Specific: Sessions, Integrity Levels, and Protected Processes

5. Processes and Threads

5.1 What Is a Process

5.2 What Is a Thread

5.3 Process Creation — What Happens Under the Hood

5.4 Process Scheduling

5.5 Viewing Processes in Practice

6. File System Structures — NTFS, ext4, FAT32

6.1 What Is a File System

6.2 NTFS — Windows File System

NTFS Structure

NTFS Security — Access Control Lists (ACLs)

NTFS Alternate Data Streams (ADS)

NTFS Timestamps — A Forensic Gold Mine (and Minefield)

6.3 ext4 — Linux File System

ext4 Structure

Linux File Permissions — The Security Model

/proc — The Virtual File System That Exposes Everything

6.4 FAT32 — The Legacy Standard

7. Memory Management

7.1 Virtual Memory — The Foundation of Process Isolation

7.2 Pages, Page Faults, and Swapping

7.3 Memory Permissions and the NX/XD Bit

7.4 ASLR — Address Space Layout Randomisation

7.5 Heap Memory and Heap Vulnerabilities

8. System Calls

8.1 What Is a System Call

8.2 How System Calls Work at the Machine Level

8.3 System Calls and Security Monitoring

8.4 Syscall-Based Evasion — Direct Syscalls

9. Key Takeaways and Security Mindset

9.1 The OS Is Both Fortress and Battlefield

9.2 The Hierarchy of Trust

9.3 For OT/ICS Environments

9.4 Core Concepts to Commit to Memory

10. Hands-On Exercises

Exercise 1: Process Archaeology (45 minutes)

Exercise 2: System Call Tracing (30 minutes)

Exercise 3: File System Permissions Audit (30 minutes)

Exercise 4: NTFS Alternate Data Streams (20 minutes)

Exercise 5: Memory Layout Exploration (30 minutes)

Essential Papers

Tools to Install Now

Practice Platforms

Module Summary Series: Cybersecurity × OT/ICS Security — Full Roadmap

Stage: 0 — Computer Science FoundationsModule: 0.2 — Operating System FundamentalsLevel: Beginner → IntermediatePrerequisites: Stage 0.1 — Hardware FundamentalsNext Module: 0.3 — Windows Fundamentals Every single attack you will ever study, execute in a lab, or defend against happens inside an operating system. Malware runs as a process. Privilege escalation exploits the boundary between user mode and kernel mode. Ransomware encrypts files by abusing the file system. Rootkits hook into the kernel. Memory injection attacks manipulate process memory. Shell access means OS access. If you do not understand how an operating system works from the inside, you are essentially trying to pick a lock without knowing how a lock works. You might get lucky occasionally, but you will never be consistent, and you will never be truly dangerous as a professional. For your OT/ICS path specifically: SCADA systems, PLCs, RTUs, and HMIs all run operating systems — sometimes Windows, sometimes Linux, sometimes proprietary real-time operating systems (RTOS). When you assess the security of a power substation's control system or a hospital's building management system, you are assessing an OS. Understanding the foundations here carries directly into every specialised area you will encounter later. The security mindset for this module: The OS is both the defender and the battlefield. Attackers abuse OS mechanisms. Defenders understand the same mechanisms to detect abuse. There is no shortcut around this. An operating system is software that acts as an intermediary between hardware and applications. It does three fundamental things: Abstracts hardware — Applications do not talk to hardware directly. They talk to the OS, which talks to hardware. This is why the same Python script runs on Intel, AMD, and ARM without modification. Manages resources — CPU time, RAM, storage, and I/O devices are shared among many processes. The OS decides who gets what and when. Enforces isolation and security — The OS ensures one process cannot read another process's memory, one user cannot access another user's files, and unprivileged code cannot control hardware directly. OT/ICS Note: The RTOS family is critical for your path. VxWorks runs on Boeing 737 systems, Mars rovers, and countless industrial controllers. QNX powers car infotainment, medical devices, and industrial automation. These systems have their own vulnerability profiles and attack surfaces that differ significantly from Windows or Linux. Understanding general OS concepts here gives you the foundation to approach any OS — including the proprietary ones you will encounter in industrial environments. This layered architecture is the foundation of every security concept you will study. The line between user applications and the kernel is the most important security boundary in modern computing. Understanding kernel architecture types gives you insight into why different OSes have different attack surfaces: Monolithic Kernel (Linux):All OS services — file systems, device drivers, network stack — run in kernel space (Ring 0). Fast because there is no context switching between kernel components. But a bug in any driver can crash or compromise the entire system. Microkernel (QNX, Minix):Only the bare minimum runs in kernel space. Everything else — drivers, file systems — runs in user space. A bug in a driver does not crash the kernel. Slower due to inter-process communication overhead but much more fault-tolerant. Hybrid Kernel (Windows NT, macOS XNU):A pragmatic blend. Core services in kernel, some services in user space. Windows has a separate subsystem process (csrss.exe) for some Win32 services, but most runs in kernel space for performance. Security Insight: QNX's microkernel design is why it is used in safety-critical systems — a fault in one component does not take down the entire system. This is directly relevant to OT/ICS: when evaluating industrial systems, the kernel architecture tells you a lot about fault isolation and what happens when one component is compromised. The kernel is the core of the operating system. It is the first software that loads after the bootloader and the last software that runs. It is the only software with direct, unrestricted access to hardware. Everything else — every application, every service, every process — runs in a sandboxed environment and must ask the kernel for resources through a controlled interface called system calls. The kernel has four primary responsibilities: 1. Process ManagementCreating, scheduling, pausing, and killing processes. Deciding which process runs on which CPU core at what time. 2. Memory ManagementAllocating and freeing RAM. Creating virtual address spaces for each process. Enforcing memory isolation between processes. 3. Device ManagementCommunicating with hardware via device drivers. Abstracting hardware differences so applications do not need hardware-specific code. 4. File System ManagementOrganising storage into a consistent interface. Enforcing access permissions on files and directories. The kernel enforces every software-level security control: The consequence: If an attacker controls the kernel, they control all of these security mechanisms. They can disable file permission checks. They can read any process's memory. They can hide their processes from the process list. They can intercept all network traffic. A kernel-level compromise is total compromise. This is why kernel exploits are so valuable and so dangerous. It is also why rootkits target the kernel — because that is where the security controls live, and controlling the controller means controlling everything. The kernel can be extended at runtime through loadable modules (Linux) or drivers (Windows). These modules run in kernel space with full Ring 0 privilege. Linux Kernel Modules: Security Implication: Loading a malicious kernel module gives an attacker complete, persistent control over the system. This is exactly how kernel rootkits work — they load a malicious module that: Real-world example: The Azazel rootkit, Reptile rootkit, and numerous APT implants use kernel module techniques on Linux. On Windows, rootkits like TDL4 (Alureon) modified the boot process to load malicious kernel drivers before Windows security initialised. Kernel Module Signing: Modern kernels require modules to be cryptographically signed by a trusted key. On Linux with Secure Boot enabled, unsigned modules are rejected. Attackers bypass this by exploiting vulnerabilities in legitimate signed drivers — this is called BYOVD (Bring Your Own Vulnerable Driver), a technique used by threat groups like Lazarus and BlackByte ransomware operators. Key Security Concept: BYOVD is currently one of the most important kernel-level attack techniques in the wild. The attacker does not need to write a malicious driver from scratch. They bring a legitimate, signed driver that has a known vulnerability, exploit it to gain kernel-level code execution, and then use that access to disable security software or install a rootkit. Understanding kernel modules is the prerequisite for understanding this class of attack. This concept is so important it deserves its own section. Modern CPUs implement a hardware-enforced privilege separation between two execution contexts: Without this separation, any program could: The boundary prevents all of this. A bug in a user-mode application can crash that application. A bug in a kernel-mode component can crash the entire system (Blue Screen of Death on Windows, Kernel Panic on Linux). When a user-mode program needs something that requires kernel-mode access — reading a file, creating a network socket, allocating memory — it makes a system call. This is a controlled, intentional crossing of the boundary: The system call interface is the only legitimate way to cross from user mode to kernel mode. Every file read, every network connection, every process creation goes through this path. The user mode / kernel mode boundary is one of the most attacked boundaries in computing: Local Privilege Escalation (LPE):A vulnerability in a kernel system call handler that allows user-mode code to execute with kernel privileges or gain root/SYSTEM access. These are among the most valuable vulnerabilities in offensive security. Kernel Address Space Layout Randomisation (KASLR):The kernel randomises its own memory layout to make exploitation harder. Many modern exploits first leak a kernel address to defeat KASLR before attempting privilege escalation. SMEP and SMAP (from Stage 0.1):CPU features that prevent the kernel from executing or accessing user-mode memory. These hardware features are specifically designed to stop kernel exploits that try to jump into user-mode shellcode. Mindset shift: When you see a vulnerability description that says "allows local privilege escalation" or "EoP (Elevation of Privilege)," you now know exactly what is happening at the architectural level. The vulnerability crosses the user-mode / kernel-mode boundary in an unauthorised way. This understanding is what separates someone who reads exploit descriptions from someone who understands them. Windows adds additional layers on top of the basic user/kernel split: Session 0 Isolation:Services run in Session 0, user applications run in Session 1+. This separation prevents user applications from interacting with service windows (a vector for privilege escalation called "Shatter Attacks" in older Windows). Integrity Levels (Mandatory Integrity Control):Windows adds a trust level to every process and object: A Medium integrity process cannot write to a High integrity process's memory. This is why UAC bypasses are important — they allow a Medium integrity process to elevate to High without triggering the UAC prompt. Protected Processes Light (PPL):Security-critical processes (antivirus engines, LSASS) can run as PPL. Even a process running as SYSTEM cannot open a PPL process with write access. This is why Mimikatz requires a kernel driver to dump credentials from LSASS on modern Windows — it cannot access LSASS from user mode even as SYSTEM. A process is an instance of a running program. When you double-click notepad.exe, Windows creates a process. That process has: Processes are isolated from each other. Process A cannot read Process B's memory directly. The kernel enforces this through the MMU's page table mechanism. A thread is the actual unit of execution within a process. A process can have one thread or thousands. Threads within the same process share: But each thread has its own: Understanding process creation is critical for malware analysis and process injection attacks. The combination of fork() + exec() is how every new process is created on Unix-like systems. The shell forks itself, then the child calls exec() to become the new program. Windows uses a single API call, but internally it creates a new process object, maps the executable, creates the initial thread, and loads required DLLs. Security Relevance — Process Injection: Because threads within a process share memory, attackers inject malicious code into legitimate processes to: Common injection techniques you will study later: All of these techniques manipulate the process and thread model described here. The OS scheduler decides which thread runs on which CPU core at what time. Modern schedulers are preemptive — the OS can interrupt a running thread at any moment and give CPU time to another thread. This is why your computer can run many programs "simultaneously" on a small number of cores. Security Relevance — Race Conditions: Scheduling creates time-of-check to time-of-use (TOCTOU) vulnerabilities. The OS checks if you have permission to access a file, then accesses it. Between the check and the use, another thread can swap the file for a different one. The check was valid, but the use is on the wrong file. CVE-2022-21999 (Windows Print Spooler) and the famous Dirty COW (CVE-2016-5195) Linux kernel vulnerability are TOCTOU race conditions. Dirty COW allowed any local user to write to read-only memory mappings by winning a race in the kernel's copy-on-write implementation — gaining root in seconds on virtually every Linux system in existence at the time. Analyst Note: During malware analysis and incident response, understanding process parent-child relationships is crucial. Legitimate process trees have predictable structures. Malware reveals itself through anomalies — cmd.exe spawned by excel.exe, powershell.exe spawned by winword.exe, or any process with a PPID that does not make logical sense. This is a core detection technique used in every SOC and EDR product. A file system is the method an OS uses to organise, store, and retrieve data on a storage device. Without a file system, a disk is just raw sectors of binary data. The file system imposes structure — files, directories, permissions, metadata — that makes the data usable. Understanding file systems is essential for: NTFS (New Technology File System) has been the primary Windows file system since Windows NT 3.1 (1993). It is a journaling file system with rich security features. The most important structure in NTFS is the MFT (Master File Table). The MFT is a database where every file and directory on the volume has at least one record. Think of it as the file system's index. NTFS implements discretionary access control through ACLs. Every file and directory has a Security Descriptor that contains: Security Relevance: Misconfigured NTFS permissions are a primary vector for Windows privilege escalation. If a service binary is writable by a non-administrative user, that user can replace it with a malicious executable. When the service starts (often as SYSTEM), the malicious code runs with SYSTEM privileges. Tools like PowerUp and WinPEAS automate the search for these misconfigurations during post-exploitation. This is one of the most important NTFS features from a security perspective. NTFS supports multiple data streams per file. Every file has a default, unnamed data stream (:$DATA) that contains the file's contents. But a file can have additional named streams that are completely invisible in normal directory listings. Malware and ADS:Attackers use ADS to hide malicious executables and scripts inside legitimate files. The host file appears innocent, but the malicious code lives in a hidden stream. Zone.Identifier — The Beneficial ADS:Windows uses an ADS called Zone.Identifier to mark files downloaded from the internet. When you download a file from a browser, Windows adds this stream: This is what causes the "This file was downloaded from the internet. Are you sure you want to run it?" warning. Malware often deletes this stream (using Unblock-File in PowerShell or attrib) to suppress the warning. Forensically, the absence of Zone.Identifier on a file that should have been downloaded is itself a suspicious indicator. NTFS maintains four timestamps per file in the Standard Information attribute: And four more in the File Name attribute: Timestomping:Attackers routinely modify timestamps to blend malicious files with legitimate ones or to destroy the forensic timeline. PowerShell makes this trivial: The forensic catch:Timestomping only modifies the $Standard_Information timestamps — the ones visible to normal tools. The $File_Name timestamps are updated by the kernel itself and are much harder to modify from user mode. Forensic tools like Autopsy and MFTECmd compare both sets of timestamps. A discrepancy between $SI and $FN timestamps is a strong indicator of timestomping. ext4 (Fourth Extended File System) is the default file system for most Linux distributions. It is a journaling file system descended from ext2 and ext3. The Inode:The inode is ext4's equivalent of NTFS's MFT record. Every file and directory has an inode that stores: Critical point: The inode does NOT store the filename. Filenames are stored in directory entries that point to inodes. This separation is fundamental to Linux forensics. Linux uses a simple but powerful permission model based on three categories and three permission bits: Octal representation: SUID, SGID, and Sticky Bit — The Dangerous Permissions: These are special permission bits that are frequently misconfigured and exploited for privilege escalation. SUID (Set User ID — bit 4000):When set on an executable, it runs with the privileges of the file's owner, not the user executing it. If root owns a SUID binary, it runs as root for anyone who executes it. Exploiting SUID for privilege escalation:If a SUID binary has a vulnerability or is misconfigured (e.g., a SUID shell), it can be exploited to gain root: GTFOBins (gtfobins.github.io) is an invaluable reference listing SUID binary exploitation techniques for dozens of standard utilities. SGID (Set Group ID — bit 2000):Similar to SUID but sets the effective group ID. On directories, new files inherit the directory's group — useful for shared directories, exploitable if misconfigured. Sticky Bit (bit 1000):On directories, prevents users from deleting files they do not own. /tmp uses this so all users can write to it but cannot delete each other's files. /proc is a pseudo-filesystem in Linux that provides a window into the kernel's view of the system. Nothing in /proc is actually on disk — it is generated dynamically by the kernel. Security Insight: /proc/<PID>/environ can contain environment variables including API keys, passwords, and tokens passed to processes at startup. This is a common source of credential exposure in poorly configured applications. During privilege escalation, examining the environment of high-privilege processes you can read can yield credentials. FAT32 (File Allocation Table 32) is a simple, old file system designed in the MS-DOS era. It lacks security features but is universally compatible: When you encounter FAT32 in security contexts: USB drives and embedded systems — Most USB drives and SD cards are FAT32 for compatibility. Many embedded devices, PLCs, and industrial HMIs use FAT32 for removable media. FAT32 has no access control — anyone with physical access to the media can read everything. UEFI EFI System Partition — The partition that UEFI reads bootloaders from is FAT32. This is why UEFI firmware can read bootloaders before any OS is loaded — UEFI has a built-in FAT32 driver. Forensic recovery — FAT32's simple structure makes file recovery relatively straightforward with tools like Foremost and PhotoRec. OT Devices — Many legacy industrial devices store configuration files and firmware on FAT32 formatted flash cards. These can be removed, copied, modified, and reinserted — a significant physical security concern in OT environments. We introduced virtual memory in Stage 0.1. Here we go deeper into the mechanisms and their security implications. Every process operates in its own virtual address space. The process believes it has a large, contiguous block of memory entirely to itself. In reality, this virtual space is backed by: The MMU (Memory Management Unit) in the CPU performs the translation from virtual to physical addresses using page tables maintained by the kernel. Memory is managed in fixed-size units called pages (typically 4 KB, sometimes 2 MB or 1 GB for huge pages). When a process accesses a virtual address: Security Relevance — The Page File:The Windows page file (pagefile.sys) and Linux swap partition contain pages that were evicted from RAM. This can include: In forensic investigations, the page file is a valuable source of evidence that many investigators overlook. Volatile memory forensics tools like Volatility can process page file content alongside RAM dumps. Each page in virtual memory has associated permission bits that control what operations are allowed: The NX (No-Execute) bit on AMD processors and XD (Execute Disable) bit on Intel processors allow the OS to mark pages as non-executable. Pages containing data should never be executable. This is the basis of DEP (Data Execution Prevention) on Windows and NX protection on Linux. The attacker's response — Return-Oriented Programming (ROP):Since code injection is blocked, attackers stopped injecting new code. Instead, they chain together small snippets of existing executable code called gadgets — sequences of 2-5 instructions ending in a ret instruction. By overwriting the stack with addresses of these gadgets, attackers can build Turing-complete computation entirely from existing, legitimate executable code. This is one of the most important concepts in modern exploitation. You will study it in depth during Stage 4 and beyond, but understanding page permissions and NX is the foundation. ASLR randomises the base addresses of the stack, heap, and shared libraries in virtual memory on each execution. Without ASLR, the attacker knows exactly where the stack is and where system libraries like libc are loaded. ROP chains and other attacks require knowing the addresses of gadgets, which means they need to know where libraries are loaded. KASLR (Kernel ASLR):Applies the same randomisation to the kernel's own memory layout. Many modern kernel exploits begin with an information leak to defeat KASLR before attempting privilege escalation. The heap is the region of memory used for dynamic allocation — when your program calls malloc() in C or new in C++. The heap is managed by the allocator (part of the C runtime library). The allocator maintains internal metadata (headers and footers on each allocation) that tracks the size and status of each chunk. Heap vulnerabilities are some of the most complex and impactful in security: Use-After-Free (UAF):A pointer to freed memory is used after the memory has been returned to the allocator. If the attacker can control what gets allocated in that freed region, they can control what the dangling pointer accesses. UAF vulnerabilities have been responsible for some of the most critical browser exploits. The Chrome V8 engine, Firefox's SpiderMonkey, and Internet Explorer have all had critical UAF vulnerabilities used in real-world attacks. Heap Overflow:Writing beyond the allocated buffer into adjacent heap chunks, overwriting allocator metadata or other allocations. A system call (syscall) is the mechanism by which user-mode programs request services from the kernel. It is the only legitimate crossing point between user mode and kernel mode. Every meaningful action your program takes is ultimately a system call: Linux system call table: This is one of the most important topics for detection engineering and malware analysis. Every malicious action that malware performs must ultimately go through system calls. Malware cannot: Security tools exploit this inescapability: Windows — API Monitor / ETW (Event Tracing for Windows):Windows EDR products use ETW to monitor Windows API calls. When cmd.exe spawns from winword.exe, or powershell.exe makes a network connection, or lsass.exe is accessed with PROCESS_VM_READ rights — all of these generate ETW events that security tools consume. Seccomp (Linux Sandboxing):Modern browsers and containerised applications use seccomp (Secure Computing Mode) to restrict which system calls a process is allowed to make. A browser renderer process probably does not need to call fork() or mount(). Restricting it to only the syscalls it needs dramatically reduces the attack surface. Docker containers use seccomp profiles to restrict container system calls. Understanding seccomp is important for container security (Stage 8). Modern EDR products hook Windows API functions (in ntdll.dll) to monitor behaviour. When malware calls VirtualAllocEx(), the EDR's hook intercepts it, logs it, and decides whether to allow it. Attacker response — Direct Syscalls:Instead of calling the API function that EDR is monitoring, the malware issues the syscall instruction directly, bypassing the hook entirely: Tools like SysWhispers and Hells Gate implement direct syscall techniques and are widely used in offensive tooling including commercial C2 frameworks. The arms race: EDR vendors responded to direct syscalls by moving their hooks into the kernel itself (kernel callbacks). Attackers responded with BYOVD (bringing vulnerable kernel drivers). This escalation is ongoing and understanding syscalls is the foundation for following it. The operating system is simultaneously: Understanding the OS deeply means you understand both how defences work and how they fail. You cannot be effective on either side without this foundation. Every security control at a higher level can be subverted by a compromise at a lower level. OS security controls are meaningless if the kernel is compromised. This hierarchical thinking applies to every system you will assess in your career. The principles in this module apply to every OS — including the ones running on PLCs, HMIs, and SCADA servers. Key specific points: Objective: Understand what a "normal" process tree looks like so you can spot anomalies. Goal: Build the mental model of "normal" — every detection in your career depends on knowing what normal looks like. Goal: See system calls in action. This directly prepares you for malware analysis — you will trace malware's API calls to understand its behaviour. Goal: Perform your first real privilege escalation reconnaissance. These are the exact checks that tools like LinPEAS and WinPEAS automate. Goal: Understand ADS practically. You will encounter this in CTFs, malware analysis, and real-world forensic cases. Goal: Make ASLR tangible. When you later study buffer overflows and ROP chains, you will understand exactly why ASLR exists and why bypassing it is a prerequisite for reliable exploitation. Next Module: Stage 0.3 — Windows FundamentalsPrevious Module: Stage 0.1 — Hardware Fundamentals

Series Index: Full Roadmap Index This document is part of the Cybersecurity × OT/ICS Security Full Roadmap series. All techniques described are presented strictly for educational purposes, authorised security research, and defensive security practice. Always obtain proper authorisation before testing any system. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Code Block

Copy

┌─────────────────────────────────────────────────┐ │ USER APPLICATIONS │ │ (Browser, Word, Malware, Security Tools) │ ├─────────────────────────────────────────────────┤ │ SYSTEM LIBRARIES │ │ (glibc, Win32 API, POSIX) │ ├─────────────────────────────────────────────────┤ │ SYSTEM CALL INTERFACE │ │ (The bridge between worlds) │ ├═════════════════════════════════════════════════╡ ← Security Boundary │ KERNEL │ │ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │ │ │ Process │ │ Memory │ │ File System │ │ │ │ Manager │ │ Manager │ │ Driver │ │ │ ├──────────┤ ├──────────┤ ├────────────────┤ │ │ │ Network │ │ Device │ │ Security │ │ │ │ Stack │ │ Drivers │ │ Module │ │ │ └──────────┘ └──────────┘ └────────────────┘ │ ├─────────────────────────────────────────────────┤ │ HARDWARE │ │ (CPU, RAM, Disk, Network Interface) │ └─────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────┐ │ USER APPLICATIONS │ │ (Browser, Word, Malware, Security Tools) │ ├─────────────────────────────────────────────────┤ │ SYSTEM LIBRARIES │ │ (glibc, Win32 API, POSIX) │ ├─────────────────────────────────────────────────┤ │ SYSTEM CALL INTERFACE │ │ (The bridge between worlds) │ ├═════════════════════════════════════════════════╡ ← Security Boundary │ KERNEL │ │ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │ │ │ Process │ │ Memory │ │ File System │ │ │ │ Manager │ │ Manager │ │ Driver │ │ │ ├──────────┤ ├──────────┤ ├────────────────┤ │ │ │ Network │ │ Device │ │ Security │ │ │ │ Stack │ │ Drivers │ │ Module │ │ │ └──────────┘ └──────────┘ └────────────────┘ │ ├─────────────────────────────────────────────────┤ │ HARDWARE │ │ (CPU, RAM, Disk, Network Interface) │ └─────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────┐ │ USER APPLICATIONS │ │ (Browser, Word, Malware, Security Tools) │ ├─────────────────────────────────────────────────┤ │ SYSTEM LIBRARIES │ │ (glibc, Win32 API, POSIX) │ ├─────────────────────────────────────────────────┤ │ SYSTEM CALL INTERFACE │ │ (The bridge between worlds) │ ├═════════════════════════════════════════════════╡ ← Security Boundary │ KERNEL │ │ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │ │ │ Process │ │ Memory │ │ File System │ │ │ │ Manager │ │ Manager │ │ Driver │ │ │ ├──────────┤ ├──────────┤ ├────────────────┤ │ │ │ Network │ │ Device │ │ Security │ │ │ │ Stack │ │ Drivers │ │ Module │ │ │ └──────────┘ └──────────┘ └────────────────┘ │ ├─────────────────────────────────────────────────┤ │ HARDWARE │ │ (CPU, RAM, Disk, Network Interface) │ └─────────────────────────────────────────────────┘ Linux Kernel Space: [Scheduler] [Memory Manager] [File Systems] [Network Stack] [Drivers] — all at Ring 0 Linux Kernel Space: [Scheduler] [Memory Manager] [File Systems] [Network Stack] [Drivers] — all at Ring 0 Linux Kernel Space: [Scheduler] [Memory Manager] [File Systems] [Network Stack] [Drivers] — all at Ring 0 QNX Kernel Space: [IPC] [Scheduler] [Basic Memory] — minimal User Space: [Drivers] [File Systems] [Network Stack] — isolated QNX Kernel Space: [IPC] [Scheduler] [Basic Memory] — minimal User Space: [Drivers] [File Systems] [Network Stack] — isolated QNX Kernel Space: [IPC] [Scheduler] [Basic Memory] — minimal User Space: [Drivers] [File Systems] [Network Stack] — isolated # List loaded kernel modules lsmod # Load a module sudo modprobe <module_name> # Remove a module sudo rmmod <module_name> # List loaded kernel modules lsmod # Load a module sudo modprobe <module_name> # Remove a module sudo rmmod <module_name> # List loaded kernel modules lsmod # Load a module sudo modprobe <module_name> # Remove a module sudo rmmod <module_name> ┌─────────────────────────────────────────────────┐ │ KERNEL MODE (Ring 0) │ │ │ │ • Direct hardware access │ │ • All CPU instructions available │ │ • Full memory access │ │ • No restrictions │ │ │ │ OS Kernel, Device Drivers, Kernel Modules │ │ │ ├─────────────────────────────────────────────────┤ ← Hardware-enforced boundary │ USER MODE (Ring 3) │ │ │ │ • No direct hardware access │ │ • Privileged instructions cause exception │ │ • Only own process memory accessible │ │ • Must use system calls to request resources │ │ │ │ Applications, Services, Malware, Your Code │ │ │ └─────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────┐ │ KERNEL MODE (Ring 0) │ │ │ │ • Direct hardware access │ │ • All CPU instructions available │ │ • Full memory access │ │ • No restrictions │ │ │ │ OS Kernel, Device Drivers, Kernel Modules │ │ │ ├─────────────────────────────────────────────────┤ ← Hardware-enforced boundary │ USER MODE (Ring 3) │ │ │ │ • No direct hardware access │ │ • Privileged instructions cause exception │ │ • Only own process memory accessible │ │ • Must use system calls to request resources │ │ │ │ Applications, Services, Malware, Your Code │ │ │ └─────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────┐ │ KERNEL MODE (Ring 0) │ │ │ │ • Direct hardware access │ │ • All CPU instructions available │ │ • Full memory access │ │ • No restrictions │ │ │ │ OS Kernel, Device Drivers, Kernel Modules │ │ │ ├─────────────────────────────────────────────────┤ ← Hardware-enforced boundary │ USER MODE (Ring 3) │ │ │ │ • No direct hardware access │ │ • Privileged instructions cause exception │ │ • Only own process memory accessible │ │ • Must use system calls to request resources │ │ │ │ Applications, Services, Malware, Your Code │ │ │ └─────────────────────────────────────────────────┘ User Mode Application │ │ Calls: read(fd, buffer, count) [C library wrapper] │ ▼ System Library (glibc / ntdll.dll) │ │ Issues: SYSCALL instruction (x86-64 Linux) │ or SYSENTER / INT 0x80 (older) │ or SYSCALL via ntdll (Windows) │ ▼ CPU switches to Ring 0, kernel takes over │ │ Kernel: validates parameters, checks permissions, │ performs the actual operation │ ▼ CPU switches back to Ring 3 │ ▼ User Mode Application receives result User Mode Application │ │ Calls: read(fd, buffer, count) [C library wrapper] │ ▼ System Library (glibc / ntdll.dll) │ │ Issues: SYSCALL instruction (x86-64 Linux) │ or SYSENTER / INT 0x80 (older) │ or SYSCALL via ntdll (Windows) │ ▼ CPU switches to Ring 0, kernel takes over │ │ Kernel: validates parameters, checks permissions, │ performs the actual operation │ ▼ CPU switches back to Ring 3 │ ▼ User Mode Application receives result User Mode Application │ │ Calls: read(fd, buffer, count) [C library wrapper] │ ▼ System Library (glibc / ntdll.dll) │ │ Issues: SYSCALL instruction (x86-64 Linux) │ or SYSENTER / INT 0x80 (older) │ or SYSCALL via ntdll (Windows) │ ▼ CPU switches to Ring 0, kernel takes over │ │ Kernel: validates parameters, checks permissions, │ performs the actual operation │ ▼ CPU switches back to Ring 3 │ ▼ User Mode Application receives result Process (notepad.exe) ├── Virtual Address Space (shared) ├── Heap (shared) ├── Open Handles (shared) │ ├── Thread 1 (Main UI thread) │ ├── Stack │ └── Registers (RIP, RSP, ...) │ ├── Thread 2 (Background save thread) │ ├── Stack │ └── Registers │ └── Thread 3 (Spell check thread) ├── Stack └── Registers Process (notepad.exe) ├── Virtual Address Space (shared) ├── Heap (shared) ├── Open Handles (shared) │ ├── Thread 1 (Main UI thread) │ ├── Stack │ └── Registers (RIP, RSP, ...) │ ├── Thread 2 (Background save thread) │ ├── Stack │ └── Registers │ └── Thread 3 (Spell check thread) ├── Stack └── Registers Process (notepad.exe) ├── Virtual Address Space (shared) ├── Heap (shared) ├── Open Handles (shared) │ ├── Thread 1 (Main UI thread) │ ├── Stack │ └── Registers (RIP, RSP, ...) │ ├── Thread 2 (Background save thread) │ ├── Stack │ └── Registers │ └── Thread 3 (Spell check thread) ├── Stack └── Registers fork() → Creates a copy of the current process (parent → child) exec() → Replaces the current process image with a new program fork() → Creates a copy of the current process (parent → child) exec() → Replaces the current process image with a new program fork() → Creates a copy of the current process (parent → child) exec() → Replaces the current process image with a new program CreateProcess() → All-in-one API to create a new process CreateProcess() → All-in-one API to create a new process CreateProcess() → All-in-one API to create a new process # List all processes with details Get-Process | Select-Object Name, Id, CPU, WorkingSet, Path # Find process by name Get-Process -Name "notepad" # Show process tree (parent-child relationships) Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, ExecutablePath # Sysinternals Process Explorer — industry standard for process investigation # Download: https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer # List all processes with details Get-Process | Select-Object Name, Id, CPU, WorkingSet, Path # Find process by name Get-Process -Name "notepad" # Show process tree (parent-child relationships) Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, ExecutablePath # Sysinternals Process Explorer — industry standard for process investigation # Download: https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer # List all processes with details Get-Process | Select-Object Name, Id, CPU, WorkingSet, Path # Find process by name Get-Process -Name "notepad" # Show process tree (parent-child relationships) Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, ExecutablePath # Sysinternals Process Explorer — industry standard for process investigation # Download: https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer # Full process list with details ps aux # Process tree — shows parent-child relationships pstree -p # Real-time process monitor top htop # Better version, install with: sudo apt install htop # Detailed info for specific process ls -la /proc/<PID>/ cat /proc/<PID>/status cat /proc/<PID>/maps # Memory map cat /proc/<PID>/cmdline # Command that started this process ls -la /proc/<PID>/fd/ # Open file descriptors # Full process list with details ps aux # Process tree — shows parent-child relationships pstree -p # Real-time process monitor top htop # Better version, install with: sudo apt install htop # Detailed info for specific process ls -la /proc/<PID>/ cat /proc/<PID>/status cat /proc/<PID>/maps # Memory map cat /proc/<PID>/cmdline # Command that started this process ls -la /proc/<PID>/fd/ # Open file descriptors # Full process list with details ps aux # Process tree — shows parent-child relationships pstree -p # Real-time process monitor top htop # Better version, install with: sudo apt install htop # Detailed info for specific process ls -la /proc/<PID>/ cat /proc/<PID>/status cat /proc/<PID>/maps # Memory map cat /proc/<PID>/cmdline # Command that started this process ls -la /proc/<PID>/fd/ # Open file descriptors MFT Record (1024 bytes per record): ├── Standard Information → Timestamps (Created, Modified, Accessed, MFT Changed) ├── File Name → The file's name (can have multiple for short name compatibility) ├── Security Descriptor → Access Control List (who can read/write/execute) ├── Data Attribute → The actual file content (or pointer to it if large) └── Object ID → Unique identifier for the file MFT Record (1024 bytes per record): ├── Standard Information → Timestamps (Created, Modified, Accessed, MFT Changed) ├── File Name → The file's name (can have multiple for short name compatibility) ├── Security Descriptor → Access Control List (who can read/write/execute) ├── Data Attribute → The actual file content (or pointer to it if large) └── Object ID → Unique identifier for the file MFT Record (1024 bytes per record): ├── Standard Information → Timestamps (Created, Modified, Accessed, MFT Changed) ├── File Name → The file's name (can have multiple for short name compatibility) ├── Security Descriptor → Access Control List (who can read/write/execute) ├── Data Attribute → The actual file content (or pointer to it if large) └── Object ID → Unique identifier for the file # View file permissions Get-Acl C:\Windows\System32\cmd.exe | Format-List # View in icacls format icacls C:\Windows\System32\cmd.exe # View file permissions Get-Acl C:\Windows\System32\cmd.exe | Format-List # View in icacls format icacls C:\Windows\System32\cmd.exe # View file permissions Get-Acl C:\Windows\System32\cmd.exe | Format-List # View in icacls format icacls C:\Windows\System32\cmd.exe # Create an alternate data stream echo "hidden malicious content" > legitimate_file.txt:hidden_stream # The file appears normal in directory listing dir legitimate_file.txt # Output: legitimate_file.txt (shows only the main stream's size) # The hidden content is there more < legitimate_file.txt:hidden_stream # Output: hidden malicious content # Find ADS on a system dir /r # /r flag shows alternate data streams streams.exe -s C:\ # Sysinternals Streams tool # Create an alternate data stream echo "hidden malicious content" > legitimate_file.txt:hidden_stream # The file appears normal in directory listing dir legitimate_file.txt # Output: legitimate_file.txt (shows only the main stream's size) # The hidden content is there more < legitimate_file.txt:hidden_stream # Output: hidden malicious content # Find ADS on a system dir /r # /r flag shows alternate data streams streams.exe -s C:\ # Sysinternals Streams tool # Create an alternate data stream echo "hidden malicious content" > legitimate_file.txt:hidden_stream # The file appears normal in directory listing dir legitimate_file.txt # Output: legitimate_file.txt (shows only the main stream's size) # The hidden content is there more < legitimate_file.txt:hidden_stream # Output: hidden malicious content # Find ADS on a system dir /r # /r flag shows alternate data streams streams.exe -s C:\ # Sysinternals Streams tool [ZoneTransfer] ZoneId=3 ReferenceUrl=https://example.com/malware.exe [ZoneTransfer] ZoneId=3 ReferenceUrl=https://example.com/malware.exe [ZoneTransfer] ZoneId=3 ReferenceUrl=https://example.com/malware.exe # Modify timestamps to evade detection (Get-Item malware.exe).CreationTime = "01/01/2020 12:00:00" (Get-Item malware.exe).LastWriteTime = "01/01/2020 12:00:00" # Modify timestamps to evade detection (Get-Item malware.exe).CreationTime = "01/01/2020 12:00:00" (Get-Item malware.exe).LastWriteTime = "01/01/2020 12:00:00" # Modify timestamps to evade detection (Get-Item malware.exe).CreationTime = "01/01/2020 12:00:00" (Get-Item malware.exe).LastWriteTime = "01/01/2020 12:00:00" Disk Layout: ┌─────────────────────────────────────────────────┐ │ Superblock │ Group Descriptors │ ... │ ├─────────────┬───────────────────────────────────┤ │ Block Group 0 │ Block Group 1 │ Block Group N │ │ │ │ │ │ ┌──────────┐ │ ┌──────────┐ │ │ │ │ Inode │ │ │ Inode │ │ │ │ │ Table │ │ │ Table │ │ │ │ ├──────────┤ │ ├──────────┤ │ │ │ │ Data │ │ │ Data │ │ │ │ │ Blocks │ │ │ Blocks │ │ │ │ └──────────┘ │ └──────────┘ │ │ └─────────────────────────────────────────────────┘ Disk Layout: ┌─────────────────────────────────────────────────┐ │ Superblock │ Group Descriptors │ ... │ ├─────────────┬───────────────────────────────────┤ │ Block Group 0 │ Block Group 1 │ Block Group N │ │ │ │ │ │ ┌──────────┐ │ ┌──────────┐ │ │ │ │ Inode │ │ │ Inode │ │ │ │ │ Table │ │ │ Table │ │ │ │ ├──────────┤ │ ├──────────┤ │ │ │ │ Data │ │ │ Data │ │ │ │ │ Blocks │ │ │ Blocks │ │ │ │ └──────────┘ │ └──────────┘ │ │ └─────────────────────────────────────────────────┘ Disk Layout: ┌─────────────────────────────────────────────────┐ │ Superblock │ Group Descriptors │ ... │ ├─────────────┬───────────────────────────────────┤ │ Block Group 0 │ Block Group 1 │ Block Group N │ │ │ │ │ │ ┌──────────┐ │ ┌──────────┐ │ │ │ │ Inode │ │ │ Inode │ │ │ │ │ Table │ │ │ Table │ │ │ │ ├──────────┤ │ ├──────────┤ │ │ │ │ Data │ │ │ Data │ │ │ │ │ Blocks │ │ │ Blocks │ │ │ │ └──────────┘ │ └──────────┘ │ │ └─────────────────────────────────────────────────┘ Inode Contents: ├── File type (regular file, directory, symlink, device...) ├── Permissions (rwxrwxrwx) ├── Owner (UID) and Group (GID) ├── Timestamps (atime, mtime, ctime, crtime on ext4) ├── File size ├── Hard link count ├── Pointers to data blocks └── Extended attributes Inode Contents: ├── File type (regular file, directory, symlink, device...) ├── Permissions (rwxrwxrwx) ├── Owner (UID) and Group (GID) ├── Timestamps (atime, mtime, ctime, crtime on ext4) ├── File size ├── Hard link count ├── Pointers to data blocks └── Extended attributes Inode Contents: ├── File type (regular file, directory, symlink, device...) ├── Permissions (rwxrwxrwx) ├── Owner (UID) and Group (GID) ├── Timestamps (atime, mtime, ctime, crtime on ext4) ├── File size ├── Hard link count ├── Pointers to data blocks └── Extended attributes # View inode information stat /etc/passwd # Find a file's inode number ls -i /etc/passwd # Find all files with a specific inode (hard links) find / -inum <inode_number> 2>/dev/null # View inode information stat /etc/passwd # Find a file's inode number ls -i /etc/passwd # Find all files with a specific inode (hard links) find / -inum <inode_number> 2>/dev/null # View inode information stat /etc/passwd # Find a file's inode number ls -i /etc/passwd # Find all files with a specific inode (hard links) find / -inum <inode_number> 2>/dev/null -rwxr-xr-- 1 root wheel 4096 Jan 1 00:00 file.sh │││││││││ ││││││││└── Others: r-- (read only) │││││││└─── Others execute: no ││││││└──── Others write: no │││││└───── Group: r-x (read + execute) ││││└────── Group execute: yes │││└─────── Group write: no ││└──────── Owner: rwx (read + write + execute) │└───────── Owner execute: yes └────────── File type: - (regular file) -rwxr-xr-- 1 root wheel 4096 Jan 1 00:00 file.sh │││││││││ ││││││││└── Others: r-- (read only) │││││││└─── Others execute: no ││││││└──── Others write: no │││││└───── Group: r-x (read + execute) ││││└────── Group execute: yes │││└─────── Group write: no ││└──────── Owner: rwx (read + write + execute) │└───────── Owner execute: yes └────────── File type: - (regular file) -rwxr-xr-- 1 root wheel 4096 Jan 1 00:00 file.sh │││││││││ ││││││││└── Others: r-- (read only) │││││││└─── Others execute: no ││││││└──── Others write: no │││││└───── Group: r-x (read + execute) ││││└────── Group execute: yes │││└─────── Group write: no ││└──────── Owner: rwx (read + write + execute) │└───────── Owner execute: yes └────────── File type: - (regular file) r = 4, w = 2, x = 1 rwxr-xr-- = 754 rwxrwxrwx = 777 (dangerous — world writable and executable) rw-r--r-- = 644 (typical for config files) rwx------ = 700 (owner only, good for private scripts) r = 4, w = 2, x = 1 rwxr-xr-- = 754 rwxrwxrwx = 777 (dangerous — world writable and executable) rw-r--r-- = 644 (typical for config files) rwx------ = 700 (owner only, good for private scripts) r = 4, w = 2, x = 1 rwxr-xr-- = 754 rwxrwxrwx = 777 (dangerous — world writable and executable) rw-r--r-- = 644 (typical for config files) rwx------ = 700 (owner only, good for private scripts) # Find all SUID files on the system find / -perm -4000 -type f 2>/dev/null # Example: /usr/bin/passwd is SUID root # A normal user can change their own password because # passwd needs to write to /etc/shadow (root-only file) ls -la /usr/bin/passwd # Output: -rwsr-xr-x 1 root root ... /usr/bin/passwd # ^-- 's' means SUID is set # Find all SUID files on the system find / -perm -4000 -type f 2>/dev/null # Example: /usr/bin/passwd is SUID root # A normal user can change their own password because # passwd needs to write to /etc/shadow (root-only file) ls -la /usr/bin/passwd # Output: -rwsr-xr-x 1 root root ... /usr/bin/passwd # ^-- 's' means SUID is set # Find all SUID files on the system find / -perm -4000 -type f 2>/dev/null # Example: /usr/bin/passwd is SUID root # A normal user can change their own password because # passwd needs to write to /etc/shadow (root-only file) ls -la /usr/bin/passwd # Output: -rwsr-xr-x 1 root root ... /usr/bin/passwd # ^-- 's' means SUID is set # If bash is somehow SUID (misconfiguration): ls -la /bin/bash # -rwsr-xr-x 1 root root ... /bin/bash bash -p # -p preserves effective UID → instant root shell # If bash is somehow SUID (misconfiguration): ls -la /bin/bash # -rwsr-xr-x 1 root root ... /bin/bash bash -p # -p preserves effective UID → instant root shell # If bash is somehow SUID (misconfiguration): ls -la /bin/bash # -rwsr-xr-x 1 root root ... /bin/bash bash -p # -p preserves effective UID → instant root shell ls -la /tmp # drwxrwxrwt ... /tmp # ^-- 't' means sticky bit is set ls -la /tmp # drwxrwxrwt ... /tmp # ^-- 't' means sticky bit is set ls -la /tmp # drwxrwxrwt ... /tmp # ^-- 't' means sticky bit is set # Every running process has a directory in /proc ls /proc/ # Output includes: 1 2 3 ... <PID of every process> ... cpuinfo meminfo # Investigate a specific process cat /proc/<PID>/cmdline # Command line arguments cat /proc/<PID>/status # Detailed process status cat /proc/<PID>/maps # Memory map (address ranges, permissions) cat /proc/<PID>/net/tcp # Network connections of this process ls -la /proc/<PID>/fd/ # Open file descriptors cat /proc/<PID>/environ # Environment variables (may contain secrets!) # Every running process has a directory in /proc ls /proc/ # Output includes: 1 2 3 ... <PID of every process> ... cpuinfo meminfo # Investigate a specific process cat /proc/<PID>/cmdline # Command line arguments cat /proc/<PID>/status # Detailed process status cat /proc/<PID>/maps # Memory map (address ranges, permissions) cat /proc/<PID>/net/tcp # Network connections of this process ls -la /proc/<PID>/fd/ # Open file descriptors cat /proc/<PID>/environ # Environment variables (may contain secrets!) # Every running process has a directory in /proc ls /proc/ # Output includes: 1 2 3 ... <PID of every process> ... cpuinfo meminfo # Investigate a specific process cat /proc/<PID>/cmdline # Command line arguments cat /proc/<PID>/status # Detailed process status cat /proc/<PID>/maps # Memory map (address ranges, permissions) cat /proc/<PID>/net/tcp # Network connections of this process ls -la /proc/<PID>/fd/ # Open file descriptors cat /proc/<PID>/environ # Environment variables (may contain secrets!) Process Virtual Address → [MMU + Page Tables] → Physical RAM Address OR Page File on Disk (page fault → load) Process Virtual Address → [MMU + Page Tables] → Physical RAM Address OR Page File on Disk (page fault → load) Process Virtual Address → [MMU + Page Tables] → Physical RAM Address OR Page File on Disk (page fault → load) Stack Buffer Overflow Attack: 1. Overflow buffer on stack 2. Overwrite return address to point to attacker's shellcode on the stack 3. CPU executes shellcode directly from the stack → Game over Stack Buffer Overflow Attack: 1. Overflow buffer on stack 2. Overwrite return address to point to attacker's shellcode on the stack 3. CPU executes shellcode directly from the stack → Game over Stack Buffer Overflow Attack: 1. Overflow buffer on stack 2. Overwrite return address to point to attacker's shellcode on the stack 3. CPU executes shellcode directly from the stack → Game over Stack Buffer Overflow Attack attempt: 1. Overflow buffer on stack 2. Overwrite return address to point to attacker's shellcode on the stack 3. CPU tries to execute stack page 4. NX bit: this page is marked non-executable → CPU raises exception → Program crashes, attack fails Stack Buffer Overflow Attack attempt: 1. Overflow buffer on stack 2. Overwrite return address to point to attacker's shellcode on the stack 3. CPU tries to execute stack page 4. NX bit: this page is marked non-executable → CPU raises exception → Program crashes, attack fails Stack Buffer Overflow Attack attempt: 1. Overflow buffer on stack 2. Overwrite return address to point to attacker's shellcode on the stack 3. CPU tries to execute stack page 4. NX bit: this page is marked non-executable → CPU raises exception → Program crashes, attack fails Stack after overflow (ROP chain): [Address of gadget 1] → executes instructions, then ret [Address of gadget 2] → executes instructions, then ret [Address of gadget 3] → executes instructions, then ret [Address of syscall] → executes execve("/bin/sh") → shell Stack after overflow (ROP chain): [Address of gadget 1] → executes instructions, then ret [Address of gadget 2] → executes instructions, then ret [Address of gadget 3] → executes instructions, then ret [Address of syscall] → executes execve("/bin/sh") → shell Stack after overflow (ROP chain): [Address of gadget 1] → executes instructions, then ret [Address of gadget 2] → executes instructions, then ret [Address of gadget 3] → executes instructions, then ret [Address of syscall] → executes execve("/bin/sh") → shell Without ASLR (same every run): Stack: 0x7fff0000 libc: 0xb7e00000 Heap: 0x08048000 With ASLR (different every run): Stack: 0x7f4a2000 ← different libc: 0xb6c14000 ← different Heap: 0x55a3f000 ← different Without ASLR (same every run): Stack: 0x7fff0000 libc: 0xb7e00000 Heap: 0x08048000 With ASLR (different every run): Stack: 0x7f4a2000 ← different libc: 0xb6c14000 ← different Heap: 0x55a3f000 ← different Without ASLR (same every run): Stack: 0x7fff0000 libc: 0xb7e00000 Heap: 0x08048000 With ASLR (different every run): Stack: 0x7f4a2000 ← different libc: 0xb6c14000 ← different Heap: 0x55a3f000 ← different char *buf = malloc(256); free(buf); // buf is now a dangling pointer // Attacker allocates something else that occupies the same region // buf still points to that region strcpy(buf, attacker_data); // Writing to attacker-controlled memory char *buf = malloc(256); free(buf); // buf is now a dangling pointer // Attacker allocates something else that occupies the same region // buf still points to that region strcpy(buf, attacker_data); // Writing to attacker-controlled memory char *buf = malloc(256); free(buf); // buf is now a dangling pointer // Attacker allocates something else that occupies the same region // buf still points to that region strcpy(buf, attacker_data); // Writing to attacker-controlled memory User Mode Code: mov rax, 0 ; System call number 0 = read() mov rdi, fd ; Argument 1: file descriptor mov rsi, buffer ; Argument 2: buffer address mov rdx, count ; Argument 3: byte count syscall ; Trigger the system call [CPU switches to Ring 0 — kernel mode] Kernel: ; Looks up syscall number 0 in sys_call_table ; Validates arguments ; Performs the actual read operation ; Places return value in rax ; Returns to user mode via sysret User Mode Code: mov rax, 0 ; System call number 0 = read() mov rdi, fd ; Argument 1: file descriptor mov rsi, buffer ; Argument 2: buffer address mov rdx, count ; Argument 3: byte count syscall ; Trigger the system call [CPU switches to Ring 0 — kernel mode] Kernel: ; Looks up syscall number 0 in sys_call_table ; Validates arguments ; Performs the actual read operation ; Places return value in rax ; Returns to user mode via sysret User Mode Code: mov rax, 0 ; System call number 0 = read() mov rdi, fd ; Argument 1: file descriptor mov rsi, buffer ; Argument 2: buffer address mov rdx, count ; Argument 3: byte count syscall ; Trigger the system call [CPU switches to Ring 0 — kernel mode] Kernel: ; Looks up syscall number 0 in sys_call_table ; Validates arguments ; Performs the actual read operation ; Places return value in rax ; Returns to user mode via sysret # View system call numbers cat /usr/include/asm/unistd_64.h | grep "#define __NR_" # View system call numbers cat /usr/include/asm/unistd_64.h | grep "#define __NR_" # View system call numbers cat /usr/include/asm/unistd_64.h | grep "#define __NR_" # Trace all system calls made by a program strace /bin/ls # Trace a running process strace -p <PID> # Filter for specific syscalls strace -e trace=open,read,write,connect /bin/ls # Trace all system calls made by a program strace /bin/ls # Trace a running process strace -p <PID> # Filter for specific syscalls strace -e trace=open,read,write,connect /bin/ls # Trace all system calls made by a program strace /bin/ls # Trace a running process strace -p <PID> # Filter for specific syscalls strace -e trace=open,read,write,connect /bin/ls // Example: allow only read, write, exit, sigreturn scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); seccomp_load(ctx); // Any other syscall now kills the process // Example: allow only read, write, exit, sigreturn scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); seccomp_load(ctx); // Any other syscall now kills the process // Example: allow only read, write, exit, sigreturn scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); seccomp_load(ctx); // Any other syscall now kills the process ; Normal path (EDR can monitor this): call VirtualAllocEx → ntdll.dll → [EDR HOOK HERE] → kernel ; Direct syscall (EDR cannot monitor this): mov r10, rcx mov eax, 0x18 ; syscall number for NtAllocateVirtualMemory syscall → kernel directly, no hooks in the path ; Normal path (EDR can monitor this): call VirtualAllocEx → ntdll.dll → [EDR HOOK HERE] → kernel ; Direct syscall (EDR cannot monitor this): mov r10, rcx mov eax, 0x18 ; syscall number for NtAllocateVirtualMemory syscall → kernel directly, no hooks in the path ; Normal path (EDR can monitor this): call VirtualAllocEx → ntdll.dll → [EDR HOOK HERE] → kernel ; Direct syscall (EDR cannot monitor this): mov r10, rcx mov eax, 0x18 ; syscall number for NtAllocateVirtualMemory syscall → kernel directly, no hooks in the path Hardware (Stage 0.1) ↓ enforces Kernel (this module) ↓ enforces User Mode Applications ↓ enforces File System Permissions, Process Isolation, etc. Hardware (Stage 0.1) ↓ enforces Kernel (this module) ↓ enforces User Mode Applications ↓ enforces File System Permissions, Process Isolation, etc. Hardware (Stage 0.1) ↓ enforces Kernel (this module) ↓ enforces User Mode Applications ↓ enforces File System Permissions, Process Isolation, etc. # Install Sysinternals Process Explorer and Process Monitor # Download: https://learn.microsoft.com/en-us/sysinternals/ # Document the parent-child relationships of these processes: # - explorer.exe → what does it spawn? # - svchost.exe → how many instances? what services do they host? # - lsass.exe → what accesses it? # Using built-in tools: Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, ExecutablePath | Sort-Object ParentProcessId | Format-Table -AutoSize # Install Sysinternals Process Explorer and Process Monitor # Download: https://learn.microsoft.com/en-us/sysinternals/ # Document the parent-child relationships of these processes: # - explorer.exe → what does it spawn? # - svchost.exe → how many instances? what services do they host? # - lsass.exe → what accesses it? # Using built-in tools: Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, ExecutablePath | Sort-Object ParentProcessId | Format-Table -AutoSize # Install Sysinternals Process Explorer and Process Monitor # Download: https://learn.microsoft.com/en-us/sysinternals/ # Document the parent-child relationships of these processes: # - explorer.exe → what does it spawn? # - svchost.exe → how many instances? what services do they host? # - lsass.exe → what accesses it? # Using built-in tools: Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, ExecutablePath | Sort-Object ParentProcessId | Format-Table -AutoSize # Install and use pstree sudo apt install psmisc pstree -p -u # Show PIDs and users # Document: # - What spawns init/systemd's children? # - What processes does your shell spawn when you run a command? # - What processes does sshd spawn when you connect? # Compare process lists from /proc vs ps ls /proc | grep -E '^[0-9]+$' | sort -n > proc_pids.txt ps aux | awk '{print $2}' | tail -n +2 | sort -n > ps_pids.txt diff proc_pids.txt ps_pids.txt # In a rootkit scenario, a hidden process appears in /proc but not in ps # Install and use pstree sudo apt install psmisc pstree -p -u # Show PIDs and users # Document: # - What spawns init/systemd's children? # - What processes does your shell spawn when you run a command? # - What processes does sshd spawn when you connect? # Compare process lists from /proc vs ps ls /proc | grep -E '^[0-9]+$' | sort -n > proc_pids.txt ps aux | awk '{print $2}' | tail -n +2 | sort -n > ps_pids.txt diff proc_pids.txt ps_pids.txt # In a rootkit scenario, a hidden process appears in /proc but not in ps # Install and use pstree sudo apt install psmisc pstree -p -u # Show PIDs and users # Document: # - What spawns init/systemd's children? # - What processes does your shell spawn when you run a command? # - What processes does sshd spawn when you connect? # Compare process lists from /proc vs ps ls /proc | grep -E '^[0-9]+$' | sort -n > proc_pids.txt ps aux | awk '{print $2}' | tail -n +2 | sort -n > ps_pids.txt diff proc_pids.txt ps_pids.txt # In a rootkit scenario, a hidden process appears in /proc but not in ps # Trace what happens when you read a file strace cat /etc/hostname 2>&1 | head -50 # Answer these questions from the strace output: # 1. What syscall opens the file? # 2. What syscall reads the content? # 3. What syscall writes to your terminal? # 4. What syscall closes the file? # Trace a network connection strace -e trace=network curl https://example.com 2>&1 | head -30 # Answer: # 1. What syscall creates the socket? # 2. What syscall makes the connection? # 3. What syscall sends data? # Trace what happens when you read a file strace cat /etc/hostname 2>&1 | head -50 # Answer these questions from the strace output: # 1. What syscall opens the file? # 2. What syscall reads the content? # 3. What syscall writes to your terminal? # 4. What syscall closes the file? # Trace a network connection strace -e trace=network curl https://example.com 2>&1 | head -30 # Answer: # 1. What syscall creates the socket? # 2. What syscall makes the connection? # 3. What syscall sends data? # Trace what happens when you read a file strace cat /etc/hostname 2>&1 | head -50 # Answer these questions from the strace output: # 1. What syscall opens the file? # 2. What syscall reads the content? # 3. What syscall writes to your terminal? # 4. What syscall closes the file? # Trace a network connection strace -e trace=network curl https://example.com 2>&1 | head -30 # Answer: # 1. What syscall creates the socket? # 2. What syscall makes the connection? # 3. What syscall sends data? Download API Monitor (free): http://www.rohitab.com/apimonitor 1. Start monitoring notepad.exe 2. Open a file in Notepad 3. Find NtCreateFile, NtReadFile in the API call log 4. Examine the parameters passed to each call Download API Monitor (free): http://www.rohitab.com/apimonitor 1. Start monitoring notepad.exe 2. Open a file in Notepad 3. Find NtCreateFile, NtReadFile in the API call log 4. Examine the parameters passed to each call Download API Monitor (free): http://www.rohitab.com/apimonitor 1. Start monitoring notepad.exe 2. Open a file in Notepad 3. Find NtCreateFile, NtReadFile in the API call log 4. Examine the parameters passed to each call # Find all SUID binaries find / -perm -4000 -type f 2>/dev/null # For each one, look it up on GTFOBins: # https://gtfobins.github.io/ # Can any of them be exploited? # Find world-writable files and directories find / -perm -0002 -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null # Find files owned by root that are writable by others find / -user root -perm -0022 -not -path "/proc/*" 2>/dev/null # Check /etc/passwd and /etc/shadow permissions ls -la /etc/passwd /etc/shadow stat /etc/passwd /etc/shadow # Find all SUID binaries find / -perm -4000 -type f 2>/dev/null # For each one, look it up on GTFOBins: # https://gtfobins.github.io/ # Can any of them be exploited? # Find world-writable files and directories find / -perm -0002 -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null # Find files owned by root that are writable by others find / -user root -perm -0022 -not -path "/proc/*" 2>/dev/null # Check /etc/passwd and /etc/shadow permissions ls -la /etc/passwd /etc/shadow stat /etc/passwd /etc/shadow # Find all SUID binaries find / -perm -4000 -type f 2>/dev/null # For each one, look it up on GTFOBins: # https://gtfobins.github.io/ # Can any of them be exploited? # Find world-writable files and directories find / -perm -0002 -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null # Find files owned by root that are writable by others find / -user root -perm -0022 -not -path "/proc/*" 2>/dev/null # Check /etc/passwd and /etc/shadow permissions ls -la /etc/passwd /etc/shadow stat /etc/passwd /etc/shadow # Find writable directories in PATH (potential DLL hijacking) $env:PATH -split ';' | ForEach-Object { $path = $_ try { $acl = Get-Acl $path -ErrorAction Stop $acl.Access | Where-Object { $_.IdentityReference -match "Everyone|BUILTIN\\Users|CREATOR OWNER" -and $_.FileSystemRights -match "Write|Modify|FullControl" } | ForEach-Object { "$path - $($_.IdentityReference) - $($_.FileSystemRights)" } } catch {} } # Check service binary permissions Get-WmiObject Win32_Service | Where-Object {$_.PathName} | ForEach-Object { $path = $_.PathName -replace '"','' -split ' ' | Select-Object -First 1 if (Test-Path $path) { $acl = Get-Acl $path $acl.Access | Where-Object { $_.IdentityReference -match "Everyone|BUILTIN\\Users" -and $_.FileSystemRights -match "Write|Modify|FullControl" } | ForEach-Object { "SERVICE: $($_.name) - PATH: $path - $($_.IdentityReference)" } } } # Find writable directories in PATH (potential DLL hijacking) $env:PATH -split ';' | ForEach-Object { $path = $_ try { $acl = Get-Acl $path -ErrorAction Stop $acl.Access | Where-Object { $_.IdentityReference -match "Everyone|BUILTIN\\Users|CREATOR OWNER" -and $_.FileSystemRights -match "Write|Modify|FullControl" } | ForEach-Object { "$path - $($_.IdentityReference) - $($_.FileSystemRights)" } } catch {} } # Check service binary permissions Get-WmiObject Win32_Service | Where-Object {$_.PathName} | ForEach-Object { $path = $_.PathName -replace '"','' -split ' ' | Select-Object -First 1 if (Test-Path $path) { $acl = Get-Acl $path $acl.Access | Where-Object { $_.IdentityReference -match "Everyone|BUILTIN\\Users" -and $_.FileSystemRights -match "Write|Modify|FullControl" } | ForEach-Object { "SERVICE: $($_.name) - PATH: $path - $($_.IdentityReference)" } } } # Find writable directories in PATH (potential DLL hijacking) $env:PATH -split ';' | ForEach-Object { $path = $_ try { $acl = Get-Acl $path -ErrorAction Stop $acl.Access | Where-Object { $_.IdentityReference -match "Everyone|BUILTIN\\Users|CREATOR OWNER" -and $_.FileSystemRights -match "Write|Modify|FullControl" } | ForEach-Object { "$path - $($_.IdentityReference) - $($_.FileSystemRights)" } } catch {} } # Check service binary permissions Get-WmiObject Win32_Service | Where-Object {$_.PathName} | ForEach-Object { $path = $_.PathName -replace '"','' -split ' ' | Select-Object -First 1 if (Test-Path $path) { $acl = Get-Acl $path $acl.Access | Where-Object { $_.IdentityReference -match "Everyone|BUILTIN\\Users" -and $_.FileSystemRights -match "Write|Modify|FullControl" } | ForEach-Object { "SERVICE: $($_.name) - PATH: $path - $($_.IdentityReference)" } } } # Create a test directory mkdir C:\ADS_Test cd C:\ADS_Test # Create a file with hidden content in an ADS echo "This is visible content" > testfile.txt echo "This is HIDDEN in ADS" > testfile.txt:secret # Check the visible content (normal) type testfile.txt # The ADS is not visible in dir dir testfile.txt # But it exists and can be accessed more < testfile.txt:secret # See it with /r flag dir /r testfile.txt # Create an executable in an ADS (this is how malware hides payloads) type C:\Windows\System32\calc.exe > testfile.txt:hidden_exe # Run it from the ADS wmic process call create "C:\ADS_Test\testfile.txt:hidden_exe" # Now find and remove it streams.exe -d testfile.txt # Sysinternals streams tool # Create a test directory mkdir C:\ADS_Test cd C:\ADS_Test # Create a file with hidden content in an ADS echo "This is visible content" > testfile.txt echo "This is HIDDEN in ADS" > testfile.txt:secret # Check the visible content (normal) type testfile.txt # The ADS is not visible in dir dir testfile.txt # But it exists and can be accessed more < testfile.txt:secret # See it with /r flag dir /r testfile.txt # Create an executable in an ADS (this is how malware hides payloads) type C:\Windows\System32\calc.exe > testfile.txt:hidden_exe # Run it from the ADS wmic process call create "C:\ADS_Test\testfile.txt:hidden_exe" # Now find and remove it streams.exe -d testfile.txt # Sysinternals streams tool # Create a test directory mkdir C:\ADS_Test cd C:\ADS_Test # Create a file with hidden content in an ADS echo "This is visible content" > testfile.txt echo "This is HIDDEN in ADS" > testfile.txt:secret # Check the visible content (normal) type testfile.txt # The ADS is not visible in dir dir testfile.txt # But it exists and can be accessed more < testfile.txt:secret # See it with /r flag dir /r testfile.txt # Create an executable in an ADS (this is how malware hides payloads) type C:\Windows\System32\calc.exe > testfile.txt:hidden_exe # Run it from the ADS wmic process call create "C:\ADS_Test\testfile.txt:hidden_exe" # Now find and remove it streams.exe -d testfile.txt # Sysinternals streams tool # Linux — Examine your own shell's memory layout cat /proc/$$/maps # Identify and label each region: # - The stack (look for [stack]) # - The heap (look for [heap]) # - The executable itself # - Shared libraries (libc, etc.) # - VDSO (Virtual Dynamic Shared Object) # Run the same program twice and compare the addresses (ASLR in action) cat /proc/$$/maps | grep libc | head -1 # Open another terminal cat /proc/$$/maps | grep libc | head -1 # The addresses should be different each time # Check if ASLR is enabled cat /proc/sys/kernel/randomize_va_space # 2 = fully randomised (default) # 0 = disabled (useful for debugging exploits in a lab) # Temporarily disable ASLR for exploit development (lab only, never production) echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Run the address check again — now addresses are consistent # Re-enable immediately after: echo 2 | sudo tee /proc/sys/kernel/randomize_va_space # Linux — Examine your own shell's memory layout cat /proc/$$/maps # Identify and label each region: # - The stack (look for [stack]) # - The heap (look for [heap]) # - The executable itself # - Shared libraries (libc, etc.) # - VDSO (Virtual Dynamic Shared Object) # Run the same program twice and compare the addresses (ASLR in action) cat /proc/$$/maps | grep libc | head -1 # Open another terminal cat /proc/$$/maps | grep libc | head -1 # The addresses should be different each time # Check if ASLR is enabled cat /proc/sys/kernel/randomize_va_space # 2 = fully randomised (default) # 0 = disabled (useful for debugging exploits in a lab) # Temporarily disable ASLR for exploit development (lab only, never production) echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Run the address check again — now addresses are consistent # Re-enable immediately after: echo 2 | sudo tee /proc/sys/kernel/randomize_va_space # Linux — Examine your own shell's memory layout cat /proc/$$/maps # Identify and label each region: # - The stack (look for [stack]) # - The heap (look for [heap]) # - The executable itself # - Shared libraries (libc, etc.) # - VDSO (Virtual Dynamic Shared Object) # Run the same program twice and compare the addresses (ASLR in action) cat /proc/$$/maps | grep libc | head -1 # Open another terminal cat /proc/$$/maps | grep libc | head -1 # The addresses should be different each time # Check if ASLR is enabled cat /proc/sys/kernel/randomize_va_space # 2 = fully randomised (default) # 0 = disabled (useful for debugging exploits in a lab) # Temporarily disable ASLR for exploit development (lab only, never production) echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Run the address check again — now addresses are consistent # Re-enable immediately after: echo 2 | sudo tee /proc/sys/kernel/randomize_va_space # Linux tools sudo apt install strace ltrace procps psmisc # Volatility 3 (memory forensics) pip3 install volatility3 # pspy (monitor processes without root — great for CTFs) # Download: https://github.com/DominicBreuker/pspy # Windows — Download from Microsoft Sysinternals: # Process Explorer, Process Monitor, Autoruns, TCPView # https://learn.microsoft.com/en-us/sysinternals/ # Linux tools sudo apt install strace ltrace procps psmisc # Volatility 3 (memory forensics) pip3 install volatility3 # pspy (monitor processes without root — great for CTFs) # Download: https://github.com/DominicBreuker/pspy # Windows — Download from Microsoft Sysinternals: # Process Explorer, Process Monitor, Autoruns, TCPView # https://learn.microsoft.com/en-us/sysinternals/ # Linux tools sudo apt install strace ltrace procps psmisc # Volatility 3 (memory forensics) pip3 install volatility3 # pspy (monitor processes without root — great for CTFs) # Download: https://github.com/DominicBreuker/pspy # Windows — Download from Microsoft Sysinternals: # Process Explorer, Process Monitor, Autoruns, TCPView # https://learn.microsoft.com/en-us/sysinternals/ - Why Operating Systems Matter in Cybersecurity - What Is an Operating System and How Does It Work - The Kernel — The Heart of Everything - User Mode vs Kernel Mode - Processes and Threads - File System Structures — NTFS, ext4, FAT32 - Memory Management - System Calls - Key Takeaways and Security Mindset - Hands-On Exercises - Further Reading and Resources - Abstracts hardware — Applications do not talk to hardware directly. They talk to the OS, which talks to hardware. This is why the same Python script runs on Intel, AMD, and ARM without modification. - Manages resources — CPU time, RAM, storage, and I/O devices are shared among many processes. The OS decides who gets what and when. - Enforces isolation and security — The OS ensures one process cannot read another process's memory, one user cannot access another user's files, and unprivileged code cannot control hardware directly. - File permissions — The kernel checks if you have read/write/execute permission before allowing file access. - Process isolation — The kernel enforces that Process A cannot read Process B's memory. - Privilege enforcement — The kernel enforces that user-mode code cannot execute privileged CPU instructions. - Network filtering — Firewall rules in the OS (iptables, Windows Firewall) run in the kernel's network stack. - Hides files from directory listings - Hides processes from tools like ps and Task Manager - Hides network connections from netstat - Captures keystrokes - Intercepts and modifies system call results - Overwrite the OS kernel in memory. - Read passwords from other processes. - Disable security software by killing its process. - Directly write to disk, bypassing file system permissions. - Send arbitrary network packets, bypassing firewalls. - CVE-2021-4034 (PwnKit) — A 12-year-old vulnerability in pkexec that allowed any user to escalate to root on virtually every Linux distribution. Trivially exploitable, required no special conditions. - CVE-2020-0796 (SMBGhost) — A kernel vulnerability in Windows 10's SMB driver. Allowed unauthenticated remote code execution at kernel level. - DirtyPipe (CVE-2022-0847) — Linux kernel pipe vulnerability allowing any user to overwrite read-only files, including /etc/passwd. - Its own virtual address space — 4 GB on 32-bit, 128 TB on 64-bit - Its own set of handles — open files, network sockets, registry keys - Its own security context — the user account it runs as, its integrity level - At least one thread — the actual execution unit - The virtual address space - Open handles - The security context - Stack — local variables, function call chain, return addresses - Register state — what the CPU was doing when this thread last ran - Thread ID (TID) - Hide malicious activity under a trusted process name (svchost.exe, explorer.exe) - Inherit the security context of the target process (impersonation) - Bypass application whitelisting (code runs inside a whitelisted process) - Classic DLL injection — Write shellcode to target process memory, create remote thread - Process hollowing — Create suspended process, replace its memory with malicious image - Thread hijacking — Suspend a thread, overwrite its context to redirect execution - APC injection — Queue asynchronous procedure calls to a thread - Digital forensics — recovering deleted files, analysing timestamps, finding hidden data - Privilege escalation — exploiting misconfigured file permissions - Malware analysis — understanding where malware stores itself and what it modifies - Incident response — understanding what was accessed, modified, or deleted and when - Owner — who owns the file - DACL (Discretionary Access Control List) — who can do what - SACL (System Access Control List) — what to audit - Created ($SI_Created) - Modified ($SI_Modified) - Accessed ($SI_Accessed) - MFT Record Changed ($SI_MFTChanged) - $FN_Created, $FN_Modified, $FN_Accessed, $FN_MFTChanged - No user permissions or ownership - No journaling (data loss risk on improper unmount) - Maximum file size: 4 GB (a critical limitation) - Maximum volume size: 2 TB - No alternate data streams - USB drives and embedded systems — Most USB drives and SD cards are FAT32 for compatibility. Many embedded devices, PLCs, and industrial HMIs use FAT32 for removable media. FAT32 has no access control — anyone with physical access to the media can read everything. - UEFI EFI System Partition — The partition that UEFI reads bootloaders from is FAT32. This is why UEFI firmware can read bootloaders before any OS is loaded — UEFI has a built-in FAT32 driver. - Forensic recovery — FAT32's simple structure makes file recovery relatively straightforward with tools like Foremost and PhotoRec. - OT Devices — Many legacy industrial devices store configuration files and firmware on FAT32 formatted flash cards. These can be removed, copied, modified, and reinserted — a significant physical security concern in OT environments. - Physical RAM (for actively used pages) - The page file/swap space on disk (for infrequently used pages) - Memory-mapped files (the executable and its libraries) - The MMU checks the page table entry for that address. - If the page is in RAM (present bit set) → immediate access, fast. - If the page is not in RAM → page fault exception. - The kernel handles the page fault: loads the page from disk into RAM, updates the page table. - The instruction is retried — this time it succeeds. - Decrypted content from applications that encrypt data at rest - Passwords from memory - Encryption keys - Browser history and cached content - Information leaks — Vulnerabilities that disclose a memory address allow the attacker to calculate the base address of libraries, defeating ASLR. - Brute force — On 32-bit systems, the address space is small enough that brute force is feasible. On 64-bit systems, the space is too large. - Heap spraying — Fill large portions of memory with shellcode so that a random jump lands in it. - Create a file without calling open()/NtCreateFile() - Start a process without calling fork()/CreateProcess() - Connect to a network without calling connect()/NtConnect() - Inject into another process without calling VirtualAllocEx()/WriteProcessMemory() - The primary security enforcer — permissions, isolation, privilege levels - The primary target — every attacker tries to subvert OS mechanisms - The primary evidence source — every attack leaves traces in OS structures - RTOS (Real-Time Operating Systems) often have minimal or no user/kernel separation — everything runs at maximum privilege. This means a vulnerability anywhere in the system potentially means full compromise. - Legacy Windows versions (Windows XP, Windows 7) are common in OT environments. These lack many of the modern security features described in this module — no ASLR, no modern heap protections, outdated system call interfaces. - File system permissions on HMI configuration files, ladder logic backups, and historian databases are frequently misconfigured in OT environments. - Process monitoring is rarely implemented in OT environments — there is often no EDR, no strace-equivalent, no API monitoring. Attacks can run undetected indefinitely. - Liedtke, "On Microkernel Construction" (SOSP 1995) — foundational microkernel design - Saltzer & Schroeder, "The Protection of Information in Computer Systems" (1975) — foundational security principles, still relevant - Solar Designer, "Getting around non-executable stack (and fix)" (1997) — the ret2libc technique that preceded ROP - "Operating Systems: Three Easy Pieces" (Arpaci-Dusseau) — Free online at ostep.org, the best OS textbook. Read the virtualisation section (processes, memory) and the concurrency section (threads) at minimum. - "The Art of Memory Forensics" (Ligh, Case, Levy, Walters) — Deep dive into OS internals through a forensics lens - "Windows Internals" (Russinovich, Solomon, Ionescu) — The definitive reference for Windows OS internals - Linux man pages — man 2 <syscall_name> for any syscall (e.g., man 2 open) - Windows API documentation — docs.microsoft.com/windows/win32/api - GTFOBins (gtfobins.github.io) — SUID/sudo exploitation reference - LOLBAS (lolbas-project.github.io) — Windows Living off the Land Binaries reference - Linux Kernel Source (elixir.bootlin.com) — Browse kernel source code online - TryHackMe — "Linux Fundamentals" rooms (free), "Windows Fundamentals" rooms (free) - OverTheWire: Bandit (overthewire.org/wargames/bandit) — Linux command line and file system basics through progressive challenges - PicoCTF — Forensics challenges that directly apply NTFS and file system knowledge