A Brief(ish) Introduction to Linux Evasion Techniques

Landon Rice (Threat Researcher @ RedSense)

SAINTCON 2025 · Day 3 · Main Track 3

Overview

Landon Rice's talk, "A Brief(ish) Introduction to Linux Evasion Techniques," delivers a highly technical exploration into the specialized world of Linux malware and the sophisticated methods attackers employ to circumvent detection. Unlike the vast landscape of Windows malware, Linux threats are often fewer, highly targeted, and bespoke, demanding a deep understanding of the operating system's unique architecture. Rice, a young but experienced threat researcher, guides the audience through foundational Linux concepts, common EDR monitoring mechanisms, and then unveils novel evasion techniques he has developed.

Watch on YouTube

Visual summary for A Brief(ish) Introduction to Linux Evasion Techniques by Landon Rice
Visual summary for A Brief(ish) Introduction to Linux Evasion Techniques by Landon Rice

Key moments

  1. 0:00 Talk Introduction and Speaker Background
  2. 1:40 Why Linux Malware is Unique and Targeted
  3. 2:15 Understanding Linux: The 'Everything is a File' Philosophy
  4. 3:20 Comparing Linux and Windows OS Architecture Differences
  5. 5:30 Where to Find (or Not Find) EDR on Linux
  6. 6:20 Introduction to ELF File Format for Linux Binaries
  7. 6:40 Deep Dive into ELF Header and File Structure

A Brief(ish) Introduction to Linux Evasion Techniques

Speakers: Landon Rice, Threat Researcher, RedSense

Conference: SAINTCON

YouTube: https://www.youtube.com/watch?v=pEFjUVTd2F4

Overview

Landon Rice's talk, "A Brief(ish) Introduction to Linux Evasion Techniques," delivers a highly technical exploration into the specialized world of Linux malware and the sophisticated methods attackers employ to circumvent detection. Unlike the vast landscape of Windows malware, Linux threats are often fewer, highly targeted, and bespoke, demanding a deep understanding of the operating system's unique architecture. Rice, a young but experienced threat researcher, guides the audience through foundational Linux concepts, common EDR monitoring mechanisms, and then unveils novel evasion techniques he has developed.

The presentation serves as a critical resource for red teamers seeking to enhance their stealth capabilities on Linux systems and for blue teamers aiming to fortify their defenses against advanced threats. By dissecting the core differences between Windows and Linux malware development, examining the intricacies of the Executable and Linking Format (ELF), and detailing various process injection and kernel-level hooking methods, Rice provides a comprehensive view of the modern Linux threat landscape. The talk culminates in the disclosure of two innovative evasion strategies: an API hashing technique for hiding imports and a method for building an eBPF rootkit to conceal other eBPF programs, underscoring the constant evolution of offensive security.

This deep dive is particularly relevant in an era where Linux-based systems underpin critical infrastructure, cloud environments, and a growing number of IoT devices. The XZ backdoor incident, a high-profile supply chain attack, serves as a stark reminder of the potential impact of sophisticated Linux malware. Rice's research contributes to a deeper understanding of these specialized threats, emphasizing that effective defense requires anticipating and understanding the most advanced evasion tactics, even those operating at the kernel level.

Background

▶ Watch: Talk Introduction and Speaker Background (0:00)

Linux malware presents a distinct challenge compared to its Windows counterparts, primarily due to fundamental differences in operating system architecture and deployment patterns. While Windows environments, often dominated by Active Directory, see a high volume of generic info-stealers, Linux threats are typically more specialized and highly targeted. Examples like the XZ backdoor (discovered in 2024) and other high-tier backdoors documented by Nextron Systems highlight this trend, indicating a focus on persistence and control over widespread data exfiltration.

A cornerstone of Linux design is the philosophy that "everything is a file." This abstraction simplifies system interaction, treating diverse resources—from network sockets to hardware devices—as files that can be read from and written to. This concept extends to virtual file systems like /proc and /sys, which exist only in memory and expose kernel and process-related data as navigable file structures. Configuration management, for instance, largely revolves around editing text files in directories like /etc, a stark contrast to Windows' diverse registry, WMI, and disparate configuration mechanisms. Permissions in Linux follow a strict principle of least privilege, focusing on user and file-level access, which is generally simpler than the often convoluted token and privilege systems in Windows. Furthermore, Linux's strong emphasis on containers and secure process separation, coupled with its open-source nature, provides both unique challenges and opportunities for malware developers. The ability to inspect kernel source code and man pages offers unparalleled insight into system behavior, making reverse engineering less of a black box operation than on Windows.

When considering where Endpoint Detection and Response (EDR) solutions are deployed, Linux environments also differ. While EDRs might be found on file shares, web servers, development machines, or even in some CI/CD build environments, they are notably absent on many Linux devices. IoT devices, firewalls, access points, and the vast majority of containers typically operate without an EDR agent. This gap creates prime targets for specialized Linux malware that can operate undetected.

Understanding how Linux binaries are structured is crucial for evasion. The Executable and Linking Format (ELF) is the standard binary format for executables, shared libraries, and core dumps on Linux. An ELF file comprises several key headers:

  • The ELF header specifies the file type, architecture, and entry point, and crucially, the locations and sizes of other headers.
  • Program headers describe how the kernel should load the program into memory for execution, defining segments like code, data, and stack.
  • Section headers provide metadata about the different sections within the binary, such as .text (executable code), .data (initialized data), .rodata (read-only data), and .plt (Procedure Linkage Table) / .got (Global Offset Table).
  • A less common Notes header exists but is often not applicable for typical malware development.

A fundamental difference from Windows is Linux's approach to dynamic linking, specifically lazy binding, which utilizes the PLT and GOT. On Windows, non-lazy binding resolves all external API functions and their addresses as soon as a program is loaded. In contrast, Linux's lazy binding defers this resolution until a function is actually called. When a program first calls an external function, it jumps to an entry in the PLT, which then redirects to the GOT. Initially, the GOT entry points back to the PLT, triggering a call to the dynamic linker. The dynamic linker resolves the actual address of the external function, writes it into the GOT, and then executes the function. Subsequent calls to the same function directly use the resolved address in the GOT, bypassing the dynamic linker for efficiency. This mechanism is a key area for potential manipulation.

Linux process injection techniques, while fewer than on Windows, are potent. The primary methods include:

  1. LD_PRELOAD: An environment variable that instructs the dynamic linker to load a specified shared object (the Linux equivalent of a DLL) before any other shared libraries. This allows an attacker to interpose their own functions. Its limitation is that it only affects newly spawned processes, not already running ones.
  2. ptrace: A powerful system call designed for debugging (used by tools like GDB and strace). It allows a process to control the execution of another, examine its memory and registers, and even modify them. Attackers can use PTRACE_POKEDATA to write shellcode into a target process's memory and PTRACE_SETREGS to hijack the instruction pointer (RIP) to execute that shellcode.
  3. process_vm_writev: A more recent (circa 2011) system call specifically designed for efficiently copying data between different process address spaces. While it excels at writing memory, it lacks the control flow manipulation capabilities of ptrace, making it primarily useful for data injection rather than direct execution hijacking without additional steps.
  4. /proc filesystem (procfs): Leveraging the "everything is a file" paradigm, attackers can directly write to a target process's memory by manipulating the /proc/<pid>/mem file. This virtual file contains the entire address space of the process identified by <pid>. After writing shellcode, a small "jump trampoline" is typically injected to redirect the original instruction pointer to the newly injected code. Resources like Akamai's blog posts offer excellent deep dives into these techniques.

Key Findings

▶ Watch: Understanding Linux: The 'Everything is a File' Philosophy (2:15)

Landon Rice's core thesis emphasizes that "malware is just goodware that does stuff differently." This perspective highlights that the underlying mechanisms used by security tools (like EDRs) to monitor systems are often the same ones exploited by attackers for malicious purposes. In essence, a sufficiently advanced EDR can be "indistinguishable from a rootkit" in its operational methodology, both needing to hook system calls and manipulate kernel behavior to achieve their objectives.

The talk identifies two primary methods for collecting data for security vendors, which are also the targets and tools for evasion:

  1. Loadable Kernel Modules (LKMs): These are older, kernel-level components that can be loaded at runtime to extend kernel functionality. While flexible, LKMs are not portable across different kernel versions (due to varying kernel structures) and require privileged access. They can be detected via the sys_module virtual file system. LKMs often achieve their goals by hooking the kernel system call table or using ftrace to intercept function calls. However, their raw access to the kernel makes them prone to causing kernel panics if not developed carefully.
  2. eBPF (extended Berkeley Packet Filter): This is the modern, preferred method for kernel-level monitoring and extensibility. Evolved from the original Berkeley Packet Filter (used primarily for network packet filtering), eBPF allows for safe, efficient, and flexible execution of custom code within the kernel. Key advantages include:
  • Minimal overhead and high flexibility.
  • Portability: eBPF programs are not tied to specific kernel versions.
  • Higher-level language support: Programs can be written in C, Go, Python, Rust, or even specialized scripting languages, compiled into eBPF bytecode.
  • Isolated execution: Programs run in a sandboxed virtual machine within the kernel, preventing kernel panics.
  • Just-In-Time (JIT) compilation: eBPF bytecode is JIT-compiled into native machine code (e.g., x86-64) for optimal performance after passing stringent safety checks by the kernel verifier.

eBPF offers several powerful hooking mechanisms:

  • XDP (eXpress Data Path): Primarily for high-performance network processing.
  • kprobes and kretprobes: Allow dynamic hooking at the entry (kprobes) or exit (kretprobes) of virtually any kernel function.
  • uprobes and uretprobes: Provide similar functionality for user-space functions, enabling monitoring of applications like Nginx.
  • Tracepoints and fentry: Predefined, stable hook points exported by the kernel at compile time (fentry being the newer, more stable version).

These hooks work by overwriting the target function's first instruction with an int3 (interrupt) instruction, which then redirects execution to an eBPF-specific interrupt handler. The talk references Selian Glenn's blog post on eBPF uprobe monitoring for deeper understanding. An example eBPF program hooking the sched_process_exec tracepoint to collect process execution telemetry and send it to user space via BPF_RINGBUF illustrates the power of this framework.

Building on this foundation, Rice introduces two novel evasion techniques:

  1. Novel Import Hiding (Linux API Hashing): This technique mirrors Windows API hashing by dynamically resolving API addresses at runtime, thereby circumventing static analysis detections (e.g., Yara rules) that rely on import tables. It leverages dl_iterate_phdr, a documented function that iterates over the program headers of loaded shared objects, similar to CreateToolhelp32Snapshot on Windows. By hashing API names at compile time using C++ constexpr and then comparing these hashes against dynamically resolved function names from libc (or other libraries), an attacker can call functions like rand (or more impactful ones like read or write) without their names appearing in the binary's dynamic symbol table. This also offers a cleaner alternative to parsing /proc/<pid>/maps for finding libc in remote processes for reflective loading or injection.
  2. eBPF Rootkits: This advanced technique weaponizes eBPF against itself. Since all interactions with eBPF programs (loading, querying info, unloading) occur via the BPF_SYSCALL, an attacker can deploy their own eBPF program to hook this critical syscall. By intercepting calls like BPF_OBJ_GET_INFO_BY_FD that query information about loaded eBPF programs, the malicious eBPF program can selectively hide its own presence (or the presence of other eBPF programs) from tools like bpf_tool prog show. This creates a powerful rootkit capability, making detection extremely challenging for standard monitoring tools, requiring deep kernel function tracing to uncover.

Technical Deep Dive

▶ Watch: Comparing Linux and Windows OS Architecture Differences (3:20)

The ELF file format is central to understanding Linux binaries. Beyond the overview, the interplay of the PLT and GOT for lazy binding is critical. When an ELF binary is loaded, the dynamic linker initially populates the GOT entries for external functions with addresses that point back into the PLT. The PLT entries themselves contain a sequence of instructions: a jump to the GOT entry, followed by instructions to push an identifier for the function and then jump to the dynamic linker's resolver stub. The first time a function func() is called, the program jumps to func@plt. This PLT entry then jumps to func@got. Since func@got initially points back to the PLT's resolver, the dynamic linker is invoked. The linker identifies func(), resolves its true memory address in the loaded shared library (e.g., libc), writes this address into func@got, and then executes func(). Subsequent calls to func@plt will directly jump to func@got, which now contains the actual function address, bypassing the resolution overhead. This mechanism means that the import table, as seen in static analysis, only contains references to the PLT/GOT stubs, not the direct function addresses, which are resolved dynamically at runtime.

Linux process injection methods, while fewer, offer distinct technical approaches:

  • LD_PRELOAD: This is arguably the simplest. An attacker sets the LD_PRELOAD environment variable to the path of a malicious shared object file (e.g., export LD_PRELOAD=/tmp/malicious.so). Any new process launched in that environment will load malicious.so before other libraries. This allows the attacker to override existing functions (e.g., malloc) or execute arbitrary code via the shared object's constructor function (__attribute__((constructor))). The primary technical limitation is its inability to inject into already running processes; they must be restarted.
  • ptrace: This syscall provides fine-grained control. To inject, an attacker typically attaches to a target process using ptrace(PTRACE_ATTACH, pid, NULL, NULL). Once attached, the process is stopped. The attacker then uses ptrace(PTRACE_GETREGS, pid, NULL, &regs) to read the target's register state, particularly the instruction pointer (RIP). Memory is allocated within the target process (e.g., by calling mmap via ptrace), and shellcode is written using ptrace(PTRACE_POKEDATA, pid, addr, data). Finally, the RIP register is modified using ptrace(PTRACE_SETREGS, pid, NULL, &regs) to point to the injected shellcode. The process is then detached or continued. This method requires CAP_SYS_PTRACE capabilities.
  • process_vm_writev: This syscall (ssize_t process_vm_writev(pid_t pid, const struct iovec local_iov, unsigned long liovcnt, const struct iovec remote_iov, unsigned long riovcnt, unsigned long flags)) allows for efficient, scatter/gather writes between process address spaces. The local_iov and remote_iov structures specify arrays of buffers for the source and destination memory regions, respectively. While faster than ptrace for bulk data transfer, process_vm_writev alone cannot hijack control flow. It typically requires an additional step, such as combining it with ptrace to modify RIP or corrupting a function pointer that will eventually be called.
  • /proc/<pid>/mem: This technique directly abuses the kernel's exposure of process memory as a file. An attacker opens /proc/<pid>/mem with write permissions, seeks to the desired memory address (e.g., using lseek64), and then uses a standard write() syscall to inject shellcode. After injection, a small "jump trampoline" (e.g., a jmp instruction) is written over an existing instruction that will eventually be executed (e.g., a function prologue or a return address on the stack) to redirect execution to the injected shellcode. This is often followed by restoring the original instruction once the shellcode has executed, or by ensuring the shellcode returns gracefully to a legitimate execution path.

The talk's proposed novel import hiding technique leverages dl_iterate_phdr to perform API hashing. The process involves:

  1. Defining the function signature: Declare a function pointer with the desired signature, e.g., typedef int (*rand_func_ptr)();.
  2. Compile-time hashing: Use C++ constexpr to compute a hash (e.g., DJB2, a lightweight non-cryptographic hash) of the target function's string name (e.g., "rand") during compilation.
  3. Iterating program headers: Call dl_iterate_phdr with a custom callback function. This function receives information about each loaded shared object, including its base address and program headers.
  4. Locating libc and dynamic linker info: Within the callback, identify the libc shared object. Then, iterate through its program headers to find the PT_DYNAMIC segment, which contains information crucial for the dynamic linker.
  5. Reconstructing dynamic linker tables: Parse the PT_DYNAMIC segment to locate the string table, symbol table, and GNU hash table. These tables allow for efficient lookup of exported symbols.
  6. Hashing and comparison: Iterate through the symbols in libc's symbol table. For each symbol, retrieve its name, compute its DJB2 hash, and compare it against the pre-computed hash of "rand".
  7. Casting and calling: Upon a hash collision, the address of the matched function is retrieved from the symbol table. This address is then cast to the rand_func_ptr type, allowing the attacker to call rand() directly via the function pointer, without its name appearing in the static dynamic symbol table (.dynsym) of the malicious binary. The demo showed dl_iterate_phdr iterating through approximately 1,600 functions in libc before finding rand. This technique effectively evades static string-based and import-based detections.

The eBPF rootkit technique is a highly sophisticated evasion. It capitalizes on the fact that all user-space interaction with eBPF programs occurs through the BPF_SYSCALL. To hide a malicious eBPF program (let's say it has file descriptor 5), an attacker would:

  1. Deploy a "hiding" eBPF program: This program itself would hook the BPF_SYSCALL using an fentry or kprobe hook.
  2. Intercept BPF_OBJ_GET_INFO_BY_FD: When bpf_tool prog show or similar utilities attempt to list eBPF programs, they make calls to BPF_SYSCALL with the BPF_OBJ_GET_INFO_BY_FD command, providing the file descriptor of the program they want information about.
  3. Modify return data: The hiding eBPF program, upon intercepting such a call, checks if the requested file descriptor (fd) matches that of the malicious eBPF program (e.g., 5). If it matches, the hiding program can modify the output structure before it's returned to user space, making it appear as if the program doesn't exist or is not loaded. Alternatively, it could simply return an error code.

This makes the malicious eBPF program invisible to standard bpf_tool queries. The speaker notes the visual difficulty of demonstrating such a rootkit ("showing a blank screen isn't that exciting"), but emphasizes the need for careful safeguards to ensure the rootkit can be unloaded, preventing a persistent, undetectable state that could lead to system instability or permanent compromise.

Demo / Proof of Concept

▶ Watch: Introduction to ELF File Format for Linux Binaries (6:20)

Landon Rice provided a clear demonstration of the novel import hiding technique, showcasing its effectiveness in circumventing static analysis by dynamically resolving API calls. The proof of concept focused on hiding the rand() function, which is exported by libc.

The demonstration involved:

  1. Static Analysis Baseline: An objdump -T command was shown on a standard binary that directly calls rand(). The output clearly displayed rand in the dynamic symbol table, making it easily detectable by static analysis tools or Yara rules looking for specific imports.
  2. Compile-time Hashing: The C++ constexpr function was used to compute the DJB2 hash of the string "rand" at compile time. This hash, a numerical value like 2090679786, became the target identifier.
  3. Dynamic Resolution with dl_iterate_phdr: The custom callback function, integrated with dl_iterate_phdr, was executed. This function systematically walked through all loaded shared objects.
  4. libc Identification and API Enumeration: The callback specifically identified libc.so (the standard C library). Within libc, it then iterated through its approximately 1,600 exported functions. For each function, its name was retrieved, hashed using DJB2, and compared against the pre-computed hash for "rand."
  5. Hash Collision and Address Resolution: Once a hash collision was detected (i.e., the hash of an exported function in libc matched 2090679786), the address of that function was retrieved. The demonstration output showed the successful identification of rand at a specific hexadecimal address (e.g., 0x755).
  6. Function Call: This resolved address was then cast to a function pointer of the appropriate signature (int (*)()) and subsequently called. The output confirmed that rand() executed successfully, returning a random number.

Crucially, when objdump -T was run on the binary employing this dynamic resolution technique, the rand function was not present in the dynamic symbol table, confirming its evasion capabilities against static import analysis. While rand() itself isn't a high-impact malware function, the principle extends to any function exported by libc or other shared objects, such as read(), write(), mmap(), or socket(), which are highly relevant for malicious operations.

Regarding the eBPF rootkit concept, the speaker acknowledged the difficulty of providing a compelling visual demonstration. Hiding an eBPF program by manipulating BPF_SYSCALL would result in bpf_tool prog show simply not listing the program, which visually translates to "nothing happening" or "a blank screen," making for a less engaging live demo. However, the technical explanation of hooking the BPF_SYSCALL and modifying BPF_OBJ_GET_INFO_BY_FD return values was thoroughly detailed, outlining the mechanism by which such a rootkit would operate.

Defensive Implications

▶ Watch: Deep Dive into ELF Header and File Structure (6:40)

The specialized nature of Linux malware demands a nuanced defensive strategy that moves beyond generic endpoint protection. Defenders must understand that Linux EDRs, like their Windows counterparts, rely on kernel-level hooks (whether LKMs or eBPF) to collect telemetry, and these very mechanisms can be targeted for evasion.

For API Hashing and Import Hiding:

  • Dynamic Analysis: Relying solely on static analysis (e.g., objdump, Yara rules on import tables) is insufficient. Implement robust dynamic analysis in sandboxes or dedicated analysis environments to observe runtime API calls.
  • Monitor dl_iterate_phdr: Track calls to dl_iterate_phdr within processes, especially in contexts that are not typical for legitimate applications (e.g., in newly spawned processes, or processes with unusual parent-child relationships). While dl_iterate_phdr has legitimate uses, its presence in a suspicious binary, particularly one that doesn't explicitly link many libraries, should raise a flag.
  • Memory Scanning for Resolved Addresses: During runtime, even if an API is hidden from the import table, its resolved address will eventually reside in memory (e.g., in the GOT or directly on the stack/registers). Memory scanning for known API function signatures or common shellcode patterns can help detect dynamically loaded or resolved code.
  • Symbol Resolution Monitoring: Monitor the dynamic linker's activities. While challenging, deviations from normal symbol resolution patterns could indicate malicious activity.

For eBPF Rootkits:

  • Advanced eBPF Monitoring: Standard tools like bpf_tool prog show can be bypassed. Defenders need to implement deeper kernel-level tracing or use alternative methods to enumerate and verify the integrity of loaded eBPF programs. This might involve direct inspection of kernel data structures that store eBPF program information, or using a "trusted" eBPF program to monitor other eBPF programs.
  • Monitor BPF_SYSCALL Integrity: The BPF_SYSCALL is the attack vector. Monitor for any attempts to hook or modify the BPF_SYSCALL itself. This requires an even lower-level monitoring capability, potentially through hardware-assisted virtualization or secure boot mechanisms that ensure kernel integrity.
  • Audit Pinned eBPF Programs: Regularly audit the BPF Virtual File System (BPF VFS) for pinned eBPF programs. While pinning is a legitimate feature for persistence, any unknown or suspicious pinned programs should be investigated immediately.
  • Kernel Hardening: Implement kernel hardening measures, such as kernel lockdown mode, which restricts root from performing operations that could compromise kernel integrity, including loading unsigned kernel modules or eBPF programs.
  • Supply Chain Security: The XZ backdoor highlights the critical need for robust supply chain security. Organizations must meticulously vet open-source components, especially those deeply embedded in core system functionality or widely used libraries. Implement integrity checks and continuous monitoring for unexpected changes in dependencies.
  • Process Injection Detection: Continue to monitor for the underlying process injection techniques:
  • LD_PRELOAD: Monitor for LD_PRELOAD environment variables, especially in sensitive processes. Use tools that can inspect environment variables of running processes.
  • ptrace: Detect ptrace usage outside of legitimate debugging tools. Look for PTRACE_ATTACH, PTRACE_POKEDATA, PTRACE_SETREGS calls from non-debugger processes.
  • process_vm_writev: Monitor for process_vm_writev calls, especially those targeting unusual memory regions or from unexpected processes.
  • /proc/<pid>/mem writes: Track writes to /proc/<pid>/mem, which is a highly suspicious activity outside of very specific, legitimate debugging or introspection tools.
  • Least Privilege: Enforce strict least privilege principles for all users and services. Many advanced techniques require root or elevated privileges. Limiting these can significantly reduce the attack surface.

Ultimately, defending against advanced Linux evasion techniques requires a multi-layered approach combining static and dynamic analysis, deep kernel monitoring, robust supply chain security, and stringent privilege management.

Key Takeaways

  • Linux malware is highly specialized and targeted, often evading traditional EDRs due to unique OS architecture and deployment patterns (e.g., absence on IoT, containers).
  • The "everything is a file" philosophy and open-source nature of Linux create distinct attack and evasion vectors, leveraging virtual file systems like /proc and direct kernel insight.
  • Lazy binding via PLT/GOT is a fundamental difference from Windows dynamic linking, offering opportunities for runtime API resolution manipulation.
  • While fewer than on Windows, Linux process injection methods like LD_PRELOAD, ptrace, process_vm_writev, and direct /proc/<pid>/mem writes are powerful and require specific monitoring.
  • eBPF is the modern, flexible kernel monitoring tool, but its power can be weaponized to create sophisticated eBPF rootkits that hide other eBPF programs by hooking the BPF_SYSCALL itself.
  • Novel techniques like API hashing via dl_iterate_phdr allow malware to hide its imports from static analysis, necessitating dynamic runtime detection capabilities.

About the Speaker(s)

Landon Rice is a Threat Researcher at RedSense. Despite his young age of 19, he has quickly established himself in the cybersecurity field, having graduated high school only a year and a half to two years prior to this talk. Rice's passion for offensive security stems from his background in red teaming, an area he continues to pursue in his free time alongside his professional responsibilities in threat research. His talk at SAINTCON demonstrates a deep technical understanding of Linux internals and advanced evasion techniques, showcasing his expertise in a niche and complex domain of cybersecurity.

All talks from SAINTCON 2025