diff --git a/docs/bibliography/bibliography.bib b/docs/bibliography/bibliography.bib index 1953f53..ce0fa6b 100644 --- a/docs/bibliography/bibliography.bib +++ b/docs/bibliography/bibliography.bib @@ -574,7 +574,7 @@ AMD64 Architecture Processor Supplement}, url={https://guyinatuxedo.github.io/5.1-mitigation_aslr_pie/index.html#aslrpie-intro} }, -@online{relro_readhat, +@online{relro_redhat, title={Hardening ELF binaries using Relocation Read-Only (RELRO)}, author={Huzaifa Sidhpurwala}, date={2019-01-28}, @@ -593,7 +593,13 @@ AMD64 Architecture Processor Supplement}, author={Michael Larabel}, date={2021-07-21}, url={https://www.phoronix.com/scan.php?page=news_item&px=Intel-CET-v29} -} +}, + +@online{canary_exploit, + title={Stack Canaries}, + url={https://ir0nstone.gitbook.io/notes/types/stack/canaries} +}, + diff --git a/docs/chapters/annex.tex b/docs/chapters/annex.tex new file mode 100644 index 0000000..23de0d8 --- /dev/null +++ b/docs/chapters/annex.tex @@ -0,0 +1,142 @@ +%---------- +% ANEX +%---------- + +%M-> Mentioned putting some demos and PoCs here... +% + +%Including bpftool commands here to be referenced. Is it a good idea? + + +\chapter* {Appendix A - Bpftool commands} \label{annex:bpftool_flags_kernel} +\pagenumbering{gobble} % Las páginas de los anexos no se numeran +\section*{eBPF-related kernel compilation flags} +\begin{lstlisting}[language=bash] +$ bpftool feature +\end{lstlisting} + +\begin{verbatim} +CONFIG_BPF is set to y +CONFIG_BPF_SYSCALL is set to y +CONFIG_HAVE_EBPF_JIT is set to y +CONFIG_BPF_JIT is set to y +CONFIG_BPF_JIT_ALWAYS_ON is set to y +CONFIG_CGROUPS is set to y +CONFIG_CGROUP_BPF is set to y +CONFIG_CGROUP_NET_CLASSID is set to y +CONFIG_SOCK_CGROUP_DATA is set to y +CONFIG_BPF_EVENTS is set to y +CONFIG_KPROBE_EVENTS is set to y +CONFIG_UPROBE_EVENTS is set to y +CONFIG_TRACING is set to y +CONFIG_FTRACE_SYSCALLS is set to y +CONFIG_FUNCTION_ERROR_INJECTION is set to y +CONFIG_BPF_KPROBE_OVERRIDE is set to y +CONFIG_NET is set to y +CONFIG_XDP_SOCKETS is set to y +CONFIG_LWTUNNEL_BPF is set to y +CONFIG_NET_ACT_BPF is set to m +CONFIG_NET_CLS_BPF is set to m +CONFIG_NET_CLS_ACT is set to y +CONFIG_NET_SCH_INGRESS is set to m +CONFIG_XFRM is set to y +CONFIG_IP_ROUTE_CLASSID is set to y +CONFIG_IPV6_SEG6_BPF is set to y +CONFIG_BPF_LIRC_MODE2 is not set +CONFIG_BPF_STREAM_PARSER is set to y +CONFIG_NETFILTER_XT_MATCH_BPF is set to m +CONFIG_BPFILTER is set to y +CONFIG_BPFILTER_UMH is set to m +CONFIG_TEST_BPF is set to m +CONFIG_HZ is set to 250 +\end{verbatim} + + +\chapter* {Appendix B - Readelf commands} \label{annex:readelf_commands} +\pagenumbering{gobble} % Las páginas de los anexos no se numeran +\section*{Section headers in ELF file} \label{annexsec:readelf_sec_headers} +\begin{lstlisting}[language=bash, caption={List of ELF section headers with readelf tool of a program compiled with GCC.}, label={code:elf_sections}] +$ readelf -S simple_timer +There are 36 section headers, starting at offset 0x4120: + +Section Headers: + [Nr] Name Type Address Offset + Size EntSize Flags Link Info Align + [ 0] NULL 0000000000000000 00000000 + 0000000000000000 0000000000000000 0 0 0 + [ 1] .interp PROGBITS 0000000000400318 00000318 + 000000000000001c 0000000000000000 A 0 0 1 + [ 2] .note.gnu.pr[...] NOTE 0000000000400338 00000338 + 0000000000000030 0000000000000000 A 0 0 8 + [ 3] .note.gnu.bu[...] NOTE 0000000000400368 00000368 + 0000000000000024 0000000000000000 A 0 0 4 + [ 4] .note.ABI-tag NOTE 000000000040038c 0000038c + 0000000000000020 0000000000000000 A 0 0 4 + [ 5] .gnu.hash GNU_HASH 00000000004003b0 000003b0 + 000000000000001c 0000000000000000 A 6 0 8 + [ 6] .dynsym DYNSYM 00000000004003d0 000003d0 + 0000000000000108 0000000000000018 A 7 1 8 + [ 7] .dynstr STRTAB 00000000004004d8 000004d8 + 00000000000000ad 0000000000000000 A 0 0 1 + [ 8] .gnu.version VERSYM 0000000000400586 00000586 + 0000000000000016 0000000000000002 A 6 0 2 + [ 9] .gnu.version_r VERNEED 00000000004005a0 000005a0 + 0000000000000050 0000000000000000 A 7 1 8 + [10] .rela.dyn RELA 00000000004005f0 000005f0 + 0000000000000030 0000000000000018 A 6 0 8 + [11] .rela.plt RELA 0000000000400620 00000620 + 00000000000000c0 0000000000000018 AI 6 24 8 + [12] .init PROGBITS 0000000000401000 00001000 + 000000000000001b 0000000000000000 AX 0 0 4 + [13] .plt PROGBITS 0000000000401020 00001020 + 0000000000000090 0000000000000010 AX 0 0 16 + [14] .plt.sec PROGBITS 00000000004010b0 000010b0 + 0000000000000080 0000000000000010 AX 0 0 16 + [15] .text PROGBITS 0000000000401130 00001130 + 00000000000004c5 0000000000000000 AX 0 0 16 + [16] .fini PROGBITS 00000000004015f8 000015f8 + 000000000000000d 0000000000000000 AX 0 0 4 + [17] .rodata PROGBITS 0000000000402000 00002000 + 00000000000000a5 0000000000000000 A 0 0 8 + [18] .eh_frame_hdr PROGBITS 00000000004020a8 000020a8 + 000000000000004c 0000000000000000 A 0 0 4 + [19] .eh_frame PROGBITS 00000000004020f8 000020f8 + 0000000000000120 0000000000000000 A 0 0 8 + [20] .init_array INIT_ARRAY 0000000000403e10 00002e10 + 0000000000000008 0000000000000008 WA 0 0 8 + [21] .fini_array FINI_ARRAY 0000000000403e18 00002e18 + 0000000000000008 0000000000000008 WA 0 0 8 + [22] .dynamic DYNAMIC 0000000000403e20 00002e20 + 00000000000001d0 0000000000000010 WA 7 0 8 + [23] .got PROGBITS 0000000000403ff0 00002ff0 + 0000000000000010 0000000000000008 WA 0 0 8 + [24] .got.plt PROGBITS 0000000000404000 00003000 + 0000000000000058 0000000000000008 WA 0 0 8 + [25] .data PROGBITS 0000000000404058 00003058 + 0000000000000014 0000000000000000 WA 0 0 8 + [26] .bss NOBITS 0000000000404070 0000306c + 0000000000000020 0000000000000000 WA 0 0 16 + [27] .comment PROGBITS 0000000000000000 0000306c + 0000000000000025 0000000000000001 MS 0 0 1 + [28] .debug_aranges PROGBITS 0000000000000000 00003091 + 0000000000000030 0000000000000000 0 0 1 + [29] .debug_info PROGBITS 0000000000000000 000030c1 + 0000000000000295 0000000000000000 0 0 1 + [30] .debug_abbrev PROGBITS 0000000000000000 00003356 + 00000000000000fd 0000000000000000 0 0 1 + [31] .debug_line PROGBITS 0000000000000000 00003453 + 000000000000024d 0000000000000000 0 0 1 + [32] .debug_str PROGBITS 0000000000000000 000036a0 + 00000000000001f5 0000000000000001 MS 0 0 1 + [33] .symtab SYMTAB 0000000000000000 00003898 + 0000000000000480 0000000000000018 34 22 8 + [34] .strtab STRTAB 0000000000000000 00003d18 + 00000000000002a2 0000000000000000 0 0 1 + [35] .shstrtab STRTAB 0000000000000000 00003fba + 000000000000015f 0000000000000000 0 0 1 +Key to Flags: + W (write), A (alloc), X (execute), M (merge), S (strings), I (info), + L (link order), O (extra OS processing required), G (group), T (TLS), + C (compressed), x (unknown), o (OS specific), E (exclude), + l (large), p (processor specific) +\end{lstlisting} \ No newline at end of file diff --git a/docs/chapters/chapter1.tex b/docs/chapters/chapter1.tex new file mode 100644 index 0000000..dbcff46 --- /dev/null +++ b/docs/chapters/chapter1.tex @@ -0,0 +1,88 @@ +\chapter{Introduction} +\section{Motivation} \label{section:motivation} +%M-> SA bit long, but it summarizes and presents the ideas and background needed to understand the topic in order: +% Main idea: Malware keeps evolving -> +% -> Relevance of innovating and researching on the new techniques -> +% -> Relevance of stealth software in targeted attacks-> +% -> Introduce eBPF as the logical step of innovation in the field -> +% -> There is a need to research on this topic now. + +As the efforts of the computer security community grow to protect increasingly critical devices and networks from malware infections, so do the techniques used by malicious actors become more sophisticated. Following the incorporation of ever more capable firewalls and Intrusion Detection Systems (IDS), cybercriminals have in turn sought novel attack vectors and exploits in common software, taking advantage of an inevitably larger attack surface that keeps growing due to the continued incorporation of new programs and functionalities into modern computer systems. + +In contrast with ransomware incidents, which remained the most significant and common cyber threat faced by organizations on 2021\cite{ransomware_pwc}, a powerful class of malware called rootkits is found considerably more infrequently, yet it is usually associated to high-profile targeted attacks that lead to greatly impactful consequences. + +A rootkit is a piece of computer software characterized for its advanced stealth capabilities. Once it is installed on a system it remains invisible to the host, usually hiding its related processes and files from the user, while at the same time performing the malicious operations for which it was designed. Common operations include storing keystrokes, sniffing network traffic, exfiltrating sensitive information from the user or the system, or actively modifying critical data at the infected device. The other characteristic functionality is that rootkits seek to achieve persistence on the infected hosts, meaning that they keep running on the system even after a system reboot, without further user interaction or the need of a new compromise. +The techniques used for achieving both of these functionalities depend on the type of rootkit developed, a classification usually made depending on the level of privileges on which the rootkit operates in the system. + +\begin{itemize} +\item \textbf{User-mode} rootkits run at the same level of privilege as common user applications. They usually work by hijacking legitimate processes on which they may inject code by preloading shared libraries, thus modifying the calls issued to user APIs, on which malicious code is placed by the rootkit. Although easier to build, these rootkits are exposed to detection by common anti-malware programs. +%I am mentioning the kernel panic part because that could be considered an advantage for eBPF, there is less worry about crashing the system +\item \textbf{Kernel-mode} rootkits run at the same level of privilege as the operating system, thus enjoying unrestricted access to the whole computer. These rootkits usually come as kernel modules or device drivers and, once loaded, they reside in the kernel. This implies that special attention must be taken to avoid programming errors since they could potentially corrupt user or kernel memory, resulting in a fatal kernel panic and a subsequent system reboot, which goes against the original purpose of maintaining stealth. + +Common techniques used for the development of their malicious activities include hooking system calls made to the kernel by user applications (on which malicious code is then injected), or modifying data structures in the kernel to change the data of user programs at runtime. Therefore, trusted programs on an infected machine can no longer be trusted to operate securely. + +These rootkits are usually the most attractive (and difficult to build) option for a malicious actor, but the installation of a kernel rootkit requires of a complete previous compromise of the system, meaning that administrator or root privileges must have been already achieved by the attacker, commonly by the execution of an exploit or a local installation of a privileged user. +\end{itemize} + +Historically, kernel-mode rootkits have been tightly associated with espionage activities on governments and research institutes by Advanced Persistent Threat (APT) groups\cite{rootkit_ptsecurity}, state-sponsored or criminal organizations specialized on long-term operations to gather intelligence and gain unauthorized persistent access to computer systems. Although rootkits' functionality is tailored for each specific attack, a common set of techniques and procedures can be identified being used by these organizations. However, during the last years, a new technology called eBPF has been found to be the heart of the latest innovation on the development of rootkits. + +%Yes, I am not mentioning that eBPF comes from "Extended Berkeley Packet %Filters here since apparently it is no longer considered an acronym, we'll %tackle that on the history section +eBPF is a technology incorporated in the 3.18 version of the Linux kernel\cite{ebpf_linux318}, which provides the possibility of running code in the kernel without the need of loading a kernel module. Programs are created in a restrictive version of the C language and compiled into eBPF bytecode, which is loaded into the kernel via a new bpf() system call. After a mandatory step of verification by the kernel in which the code is checked to be safe to run, the bytecode is compiled into native machine instructions. These programs can then get access to kernel-exclusive functionalities including network traffic filtering, system calls hooking or tracing. + +Although eBPF has built an outstanding environment for the creation of networking and tracing tools, its ability to run kernel programs without the need to load a kernel module has attracted the attention of multiple APTs. On February 2022, the Chinese security team Pangu Lab reported about a NSA backdoor that remained unnoticed since 2013 that used eBPF for its networking functionality and that infected military and telecommunications systems worldwide\cite{bvp47_report}. Also on 2022, PwC reports about a China-based threat actor that has targeted telecommunications systems with a eBPF-based backdoor\cite{bpfdoor_pwc}. + +Moreover, there currently exists official efforts to extend the eBPF technology into Windows\cite{ebpf_windows} and Android systems\cite{ebpf_android}, which spreads the mentioned risks to new platforms. Therefore, we can confidently claim that there is a growing interest on researching the capabilities of eBPF in the context of offensive security, in particular given its potential on becoming a common component found of modern rootkits. This knowledge would be valuable to the computer security community, both in the context of pen-testing and for analysts which need to know about the latest trends in malware to prepare their defences. + + +\section{Project objectives} \label{section:project_objectives} +The main objective of this project is to compile a comprehensive report of the capabilities in the eBPF technology that could be weaponized by a malicious actor. In particular, we will be focusing on functionalities present in the Linux platform, given the maturity of eBPF on these environments and which therefore offers a wider range of possibilities. We will be approaching this study from the perspective of a threat actor, meaning that we will develop an eBPF-based rootkit which shows these capabilities live in a current Linux system, including proof of concepts (PoC) showing an specific feature, and also by building a realistic rootkit system which weaponizes these PoCs and operates malicious activities. + +%According to the library guide, previous research should be around here. %Is it the best place tho? +Before narrowing down our objectives and selecting an specific list of rootkit capabilities to emulate using eBPF, we needed to consider previous research. The work on this matter by Jeff Dileo from NCC Group at DEFCON 27\cite{evil_ebpf} is particularly relevant, setting the first basis of eBPF ability to overwrite userland data, highlighting the possibility of overwriting the memory of a running process and executing arbitrary code on it. + +Subsequent talks on 2021 by Pat Hogan at DEFCON 29\cite{bad_ebpf}, and by Guillaume Fournier and Sylvain Afchainthe from Datadog at DEFCON 29\cite{ebpf_friends}, research deeper on eBPF's ability to behave like a rootkit. In particular, Hogan shows how eBPF can be used to hide the rootkit's presence from the user and to modify data at system calls, whilst Fournier and Afchainthe built the first instance of an eBPF-based backdoor with command-and-control(C2) capabilities, enabling to communicate with the malicious eBPF program by sending network packets to the compromised machine. + +Taking the previous research into account, and on the basis of common functionality we described to be usually incorporated at rootkits, the objectives of our research on eBPF is set to be on the following topics: +\begin{itemize} +\item Analysing eBPF's possibilities when hooking system calls and kernel functions. +\item Learning eBPF's potential to read/write arbitrary memory. +\item Exploring networking capabilities with eBPF packet filters. +\end{itemize} + +The knowledge gathered by the previous three pillars will be then used as a basis for building our rootkit. We will present attack vectors and techniques different than the ones presented in previous research, although inevitably we will also tackle common points, which will be clearly indicated and on which we will try to perform further research. In essence, our eBPF-based rootkit aims at: +\begin{itemize} +\item Hijacking the execution of user programs while they are running, injecting libraries and executing malicious code, without impacting their normal execution. +\item Featuring a command-and-control module powered by a network backdoor, which can be operated from a remote client. This backdoor should be controlled with stealth in mind, featuring similar mechanisms to those present in rootkits found in the wild. +\item Tampering with user data at system calls, resulting in running malware-like programs and for other malicious purposes. +\item Achieving stealth, hiding rootkit-related files from the user. +\item Achieving rootkit persistence, the rootkit should run after a complete system reboot. +\ +\end{itemize} + +The rootkit will work in a fresh-install of a Linux system with the following characteristics: +\begin{itemize} +%Maybe a table for this? +\item Distribution: Ubuntu 21.04. +\item Kernel version: 5.11.0-49. +\end{itemize} + +\section{Regulatory framework} +%MARCOS-> Is this the appropiate place? Looking at other TFGs it is sometimes here and others in a final chapter + +%TODO - Leaving this for the end + +\subsection{Social and economic environment} +%M-> Mentioned talking about community outreach and its role under pentesting +%TODO Talk about the difference between having always on BPF and always on kernel modules, BPF is consider "safe" in production while it's almost as dangerous (I think this might fit here) + +%TODO - Leaving this for the end + +\subsection{Budget} +%TODO - Leaving this for the end + +\section{Structure of the document} +%TODO - Best to be done at the end + +\section{Code availability} +%TODO + diff --git a/docs/chapters/chapter2.tex b/docs/chapters/chapter2.tex new file mode 100644 index 0000000..735081d --- /dev/null +++ b/docs/chapters/chapter2.tex @@ -0,0 +1,1187 @@ +\chapter{Background} +This chapter is dedicated to an study of all the background needed for our research into offensive eBPF applications. Although our rootkit has been developed using a library that will provide us with a layer of abstraction over the underlying operations, this background is needed to understand how eBPF is embedded in the kernel and which capabilities and limits we can expect to achieve with it. + +Firstly, we will analyse the origins of the eBPF technology, understanding what it is and how it works, and discuss the reasons why it is a necessary component of the Linux kernel today. Afterwards, we will cover the main features of eBPF in detail and discuss the security features incorporated in the system, together with an study of the currently existing alternatives for developing eBPF applications. + +Finally, we will offer an overview into multiple aspects of the Linux system (memory, networking and executable files), which will be critical during the design of the offensive techniques incorporated in our rootkit. + +\section{BPF} +% Is it ok to have sections / chapters without individual intros? +In this section we will detail the origins of eBPF in the Linux kernel. By offering us background into the earlier versions of the system, the goal is to acquire insight on the design decisions included in modern versions of eBPF. + +\subsection{Introduction to the BPF system} +Nowadays eBPF is not officially considered to be an acronym anymore\cite{ebpf_io}, but it remains largely known as "extended Berkeley Packet Filters", given its roots in the Berkeley Packet Filter (BPF) technology, now known as classic BPF. + +BPF was introduced in 1992 by Steven McCanne and Van Jacobson in the paper "The BSD Packet Filter: A New Architecture for User-level Packet Capture"\cite{bpf_bsd_origin}, as a new filtering technology for network packets in the BSD platform. It was first integrated in the Linux kernel on version 2.1.75\cite{ebpf_history_opensource}. + + +\begin{figure}[H] + \centering + \includegraphics[width=12cm, keepaspectratio=true]{classic_bpf.jpg} + \caption{Sketch of the functionality of classic BPF} + \label{fig:classif_bpf} +\end{figure} + +Figure \ref{fig:classif_bpf} shows how BPF was integrated in the existing network packet processing by the kernel. After receiving a packet via the Network Interface Controller (NIC) driver, it would first be analysed by BPF filters, which are programs directly developed by the user. This filter decides whether the packet is to be accepted by analysing the packet properties, such as its length or the type and values of its headers. If a packet is accepted, the filter proceeds to decide how many bytes of the original buffer are passed to the application at the user space. Otherwise, the packet is redirected to the original network stack, where it is managed as usual. + + +\subsection{The BPF virtual machine} \label{subsection:bpf_vm} +In a technical level, BPF comprises both the BPF filter programs developed by the user and the BPF module included in the kernel which allows for loading and running the BPF filters. This BPF module in the kernel works as a virtual machine\cite{bpf_bsd_origin_bpf_page1}, meaning that it parses and interprets the filter program by providing simulated components needed for its execution, turning into a software-based CPU. Because of this reason, it is usually referred as the BPF Virtual Machine (BPF VM). The BPF VM comprises the following components: +\begin{itemize} +\item \textbf{An accumulator register}, used to store intermediate values of operations. +\item \textbf{An index register}, used to modify operand addresses, it is usually incorporated to optimize vector operations\cite{index_register}. +\item \textbf{An scratch memory store}, a temporary storage. +\item \textbf{A program counter}, used to point to the next machine instruction to execute in a filter program. +\end{itemize} + + +\subsection{Analysis of a BPF filter program} \label{subsection:analysis_bpf_filter_prog} +As we mentioned in section \ref{subsection:bpf_vm}, the components of the BPF VM are used to support running BPF filter programs. A BPF filter is implemented as a boolean function: +\begin{itemize} +\item If it returns \textit{true}, the kernel copies the packet to the application. +\item If it returns \textit{false}, the packet is not accepted by the filter (and thus the network stack will be the next to operate it). +\end{itemize} + +\begin{figure}[H] + \centering + \includegraphics[width=8cm]{cbpf_prog.jpg} + \caption{Execution of a BPF filter.} + \label{fig:cbpf_prog} +\end{figure} + +Figure \ref{fig:cbpf_prog} shows an example of a BPF filter upon receiving a packet. In the figure, green lines indicate that the condition is true and red lines that it is evaluated as false. Therefore, the execution works as a control flow graph (CFG) which ends on a boolean value\cite{bpf_bsd_origin_bpf_page5}. The figure presents an example BPF program which accepts the following frames: +\begin{itemize} +\item Frames with an IP packet as a payload directed from IP address X. +\item Frames with an IP packet as a payload directed towards IP address Y. +\item Frames belonging to the ARP protocol and from IP address Y. +\item Frames not from the ARP protocol directed from IP address Y to IP address X. +\end{itemize} + + +\subsection{BPF bytecode instruction format} +In order to implement the CFG to be run at the BPF VM, BPF filter programs are made up of BPF bytecode, which is defined by a new BPF instruction set. Therefore, a BPF filter program is an array of BPF bytecode instructions\cite{bpf_organicprogrammer_analysis}. + + +\begin{table}[H] +\begin{tabular}{|c|c|c|c|c|} +\hline +& OPCODE & JT & JF & K\\ +\hline +BITS & 16 & 8 & 8 & 32\\ +\hline +\end{tabular} +\caption{Table showing BPF instruction format. It is a fixed-length 64 bit instruction, the number of bits used by each field are indicated.} +\label{table:bpf_inst_format} +\end{table} + +Table \ref{table:bpf_inst_format} shows the format of a BPF bytecode instruction. As it can be observed, it is a compound of: +\begin{itemize} +\item An \textbf{opcode}, similar to assembly opcode, it indicates the operation to be executed. +\item Field \textbf{jt} indicates the offset to the next instruction to jump in case a condition is evaluated as \textit{true}. +\item Field \textbf{jf} indicates the offset to the next instruction to jump in case a condition is evaluated as \textit{false}. +\item Field \textbf{k} is miscellaneous and its contents vary depending on the instruction opcode. +\end{itemize} + +\begin{figure}[H] + \centering + \includegraphics[width=8cm]{bpf_instructions.png} + \caption{Table of supported classic BPF instructions, as shown by McCanne and Jacobson\cite{bpf_bsd_origin_bpf_page7}} + \label{fig:bpf_instructions} +\end{figure} + +Figure \ref{fig:bpf_instructions} shows how BPF instructions are defined according to the BPF instruction set. As we mentioned, similarly to assembly, instructions include an opcode which indicates the operation to execute, and the multiple arguments defining the arguments of the operation. The table shows, in order by rows, the following instruction types\cite{bpf_bsd_origin_bpf_page8}: +\begin{itemize} +\item Rows 1-4 are \textbf{load instructions}, copying the addressed value into the index or accumulator register. +\item Rows 4-6 are \textbf{store instructions}, copying the accumulator or index register into the scratch memory store. +\item Rows 7-11 are \textbf{jump instructions}, changing the program counter register. These are usually present on each node of the CFG, and evaluate whether the condition to be evaluated is true or not. +\item Rows 12-19 and 21-22 are \textbf{arithmetic and miscellaneous instructions}, performing operations usually needed during the program execution. +\item Row 20 is a \textbf{return instruction}, it is positioned in the final end of the CFG, and indicate whether the filter accepts the packet (returning true) or otherwise rejects it (return false). +\end{itemize} + +\begin{figure}[H] + \centering + \includegraphics[width=8cm]{bpf_address_mode.png} + \caption{Table explaining the column address modes in Figure\ref{fig:bpf_instructions}, as shown by McCanne and Jacobson\cite{bpf_bsd_origin_bpf_page8}} + \label{fig:bpf_address_mode} +\end{figure} + +The column \textit{addr modes} in figure \ref{fig:bpf_instructions} describes how the parameters of a BPF instruction are referenced depending on the opcode. The address modes are detailed in figure \ref{fig:bpf_address_mode}. As it can be observed, paremeters may consist of immediate values, offsets to memory positions or on the packet, the index register or combinations of the previous. + + +\subsection{An example of BPF filter with tcpdump} +At the time, by filtering packets before they are handled by the kernel instead of using an user-level application, BPF offered a performance improvement between 10 and 150 times the state-of-the art technologies of the moment\cite{bpf_bsd_origin_bpf_page1}. Since then, multiple popular tools began to use BPF, such as the network tracing tool \textit{tcpdump}\cite{tcpdump_page}. + +\textit{tcpdump} is a command-line tool that enables to capture and analyse the network traffic going through the system. It works by setting filters on a network interface, so that it shows the packets that are accepted by the filter. Still today, \textit{tcpdump} uses BPF for the filter implementation. We will now show an example of BPF code used by \textit{tcpdump} to implement a simple filter: + +\begin{figure}[H] + \centering + \includegraphics[width=10cm]{tcpdump_example.png} + \caption{BPF bytecode tcpdump needs to set a filter to display packets directed to port 80.} + \label{fig:bpf_tcpdump_example} +\end{figure} + +Figure \ref{fig:bpf_tcpdump_example} shows how tcpdump sets a filter to display traffic directed to all interfaces (\textit{-i any}) directed to port 80. Flag \textit{-d} instructs tcpdump to display BPF bytecode. + +In the example, using the \textit{jf} and \textit{jt} fields, we can label the nodes of the CFG described by the BPF filter. Figure \ref{fig:tcpdump_ex_sol} describes the shortest graph path that a true comparison will need to follow to be accepted by the filter. Note how instruction 010 is checking the value 80, the one our filter is looking for in the port. + +\begin{figure}[H] + \centering + \includegraphics[width=6cm]{cBPF_prog_ex_sol.png} + \caption{Shortest path in the CFG described in the example of figure \ref{fig:bpf_tcpdump_example} that a packet needs to follow to be accepted by the BPF filter set with \textit{tcpdump}.} + \label{fig:tcpdump_ex_sol} +\end{figure} + +\section{Modern eBPF} \label{section:modern_ebpf} +This section discusses the current state of eBPF in the Linux kernel. By building on the previous architecture described in classic BPF, we will be able to provide a comprehensive picture of the underlying infrastructure in which eBPF relies today. + +The addition of classic BPF in the Linux kernel set the foundations of eBPF, but nowadays it has already extended its presence to many other components other than traffic filtering. Similarly to how BPF filters were included in the networking module of the Linux kernel, we will now study the necessary changes made in the kernel to support these new program types. Table \ref{table:ebpf_history} shows the main updates that were incorporated and shaped modern eBPF of today. + +\begin{table}[H] +\begin{tabular}{|c|c|c|} +\hline +Description & Kernel version & Year\\ +\hline +\hline +\textit{BPF}: First addition in the kernel & 2.1.75 & 1997\\ +\textit{BPF+}: New JIT assembler & 3.0 & 2011\\ +\textit{eBPF}: Added eBPF support & 3.15 & 2014\\ +\textit New bpf() syscall & 3.18 & 2014\\ +\textit Introduction of eBPF maps & 3.19 & 2015\\ +\textit eBPF attached to kprobes & 4.1 & 2015\\ +\textit Introduction of Traffic Control & 4.5 & 2016\\ +\textit eBPF attached to tracepoints & 4.7 & 2016\\ +\textit Introduction of XDP & 4.8 & 2016\\ + + +\hline +\end{tabular} +\caption{Table showing relevant eBPF updates. Note that only those relevant for our research objectives are shown. This is a selection of the official complete table at \cite{ebpf_funcs_by_ver}.} +\label{table:ebpf_history} +\end{table} + +As it can be observed in the table above, the main breakthrough happened in the 3.15 version, where Alexei Starovoitov, along with Daniel Borkmann, decided to expand the capabilities of BPF by remodelling the BPF instruction set and overall architecture\cite{brendan_gregg_bpf_book}. + +Figure \ref{fig:ebpf_architecture} offers an overview of the current eBPF architecture. During the subsequent subsections, we will proceed to explain its components in detail. + +\begin{figure}[H] + \centering + \includegraphics[width=15cm]{ebpf_arch.jpg} + \caption{Figure showing overall eBPF architecture in the Linux kernel and the process of loading an eBPF program. Based on\cite{brendan_gregg_bpf_book} and \cite{ebpf_io_arch}.} + \label{fig:ebpf_architecture} +\end{figure} + +\subsection{eBPF instruction set} \label{subsection:ebpf_inst_set} +The eBPF update included a complete remodel of the instruction set architecture (ISA) of the BPF VM. Therefore, eBPF programs will need to follow the new architecture in order to be interpreted as valid and executed. + +\begin{table}[H] +\begin{tabular}{|c|c|c|c|c|c|} +\hline +& IMM & OFF & SRC & DST & OPCODE \\ +\hline +BITS & 32 & 16 & 4 & 4 & 8\\ +\hline +\end{tabular} +\caption{Table showing eBPF instruction format. It is a fixed-length 64 bit instruction, the number of bits used by each field are indicated.} +\label{table:ebpf_inst_format} +\end{table} + + +Table \ref{table:ebpf_inst_format} shows the new instruction format for eBPF programs\cite{ebpf_inst_set}. The new fields are similar to x86\_64 assembly, incorporating the typically found immediate and offset fields, and source and destination registers\cite{8664_inst_set_specs}. Similarly, the instruction set is extended to be similar to the one typically found on x86\_64 systems, the complete list can be consulted in the official documentation\cite{ebpf_inst_set}. +%Should I talk about assembly or this more in detail? + +With respect to the BPF VM registers, they get extended from 32 to 64 bits of length, and the number of registers is incremented to 10, instead of the original accumulator and index registers. These registers are also adapted to be similar to those in assembly, as it is shown in table \ref{table:ebpf_regs}. + +\begin{table}[H] +\begin{tabular}{|c|c|m{21em}|} +\hline +eBPF register & x86\_64 register & Purpose\\ +\hline +r0 & rax & Return value from functions and exit value of eBPF programs\\ +r1 & rdi & Function call argument 1\\ +r2 & rsi & Function call argument 2\\ +r3 & rdx & Function call argument 3\\ +r4 & rcx & Function call argument 4\\ +r5 & r8 & Function call argument 5\\ +r6 & rbx & Callee saved register, value preserved between calls\\ +r7 & r13 & Callee saved register, value preserved between calls\\ +r8 & r14 & Callee saved register, value preserved between calls\\ +r9 & r15 & Callee saved register, value preserved between calls\\ +r10 & rbp & Frame pointer for stack, read only\\ +\hline +\end{tabular} +\caption{Table showing eBPF registers and their purpose in the BPF VM.\cite{ebpf_inst_set}\cite{ebpf_starovo_slides}.} +\label{table:ebpf_regs} +\end{table} + +\subsection{JIT compilation} +We mentioned in subsection \ref{subsection:ebpf_inst_set} that eBPF registers and instructions describe an almost one-to-one correspondence to those in x86 assembly. This is in fact not a coincidence, but rather it is with the purpose of improving a functionality that was included in Linux kernel 3.0, called Just-in-Time (JIT) compilation\cite{ebpf_JIT}\cite{ebpf_JIT_demystify_page13}. + +JIT compiling is an extra step that optimizes the execution speed of eBPF programs. It consists of translating BPF bytecode into machine-specific instructions, so that they run as fast as native code in the kernel. Machine instructions are generated during runtime, written directly into executable memory and executed there\cite{ebpf_JIT_demystify_page14}. + +Therefore, when using JIT compiling (a setting defined by the variable \textit{bpf\_jit\_enable}\cite{jit_enable_setting}, BPF registers are translated into machine-specific registers following their one-to-one mapping and bytecode instructions are translated into machine-specific instructions\cite{ebpf_starovo_slides_page23}. There no longer exists an interpretation step by the BPF VM, since we can execute the code directly\cite{brendan_gregg_bpf_book_bpf_vm}. + +The programs developed during this project will always have JIT compiling active. + + +\subsection{The eBPF verifier} \label{subsection:ebpf_verifier} +We introduced in figure \ref{fig:ebpf_architecture} the presence of the so-called eBPF verifier. Provided that we will be loading programs in the kernel from user space, these programs need to be checked for safety before being valid to be executed. + +The verifier performs a series of tests which every eBPF program must pass in order to be accepted. Otherwise, user programs could leak privileged data, result in kernel memory corruption, or hang the kernel in an infinite loop, between others. Therefore, the verifier limits multiple aspects of eBPF programs so that they are restricted to the intended functionality, whilst at the same time offering a reasonable amount of freedom to the developer. + +The following are the most relevant checks that the verifier performs in eBPF programs\cite{ebpf_verifier_kerneldocs}\cite{ebpf_JIT_demystify_page17-22}: +\begin{itemize} +\item Tests for ensuring overall control flow safety: + \subitem No loops allowed (bounded loops accepted since kernel version 5.3\cite{ebpf_bounded_loops}. + \subitem Function call and jumps safety to known, reachable functions. + \subitem Sleep and blocking operations not allowed (to prevent hanging the kernel). +\item Tests for individual instructions: + \subitem Divisions by zero and invalid shift operations. + \subitem Invalid stack access and invalid out-of-bound access to data structures. + \subitem Reads from uninitialized registers and corruption of pointers. +\end{itemize} + +These checks are performed by two main algorithms: +\begin{itemize} +\item Build a graph representing the eBPF instructions (similar to the one shown in section \ref{subsection:analysis_bpf_filter_prog}. Check that it is in fact a direct acyclic graph (DAG), meaning that the verifier prevents loops and unreachable instructions. +\item Simulate execution flow by starting on the first instruction and following each possible path, observing at each instruction the state of every register and of the stack. +\end{itemize} + +\subsection{eBPF maps} \label{subsection:ebpf_maps} +An eBPF map is a generic storage for eBPF programs used to share data between user and kernel space, to maintain persistent data between eBPF calls and to share information between multiple eBPF programs\cite{ebpf_maps_kernel}. + +A map consists of a key + value tuple. Both fields can have an arbitrary data type, the map only needs to know the length of the key and the value field at its creation\cite{bpf_syscall}. Programs can open maps by specifying their ID, and lookup or delete elements in the map by specifying its key, also insert new ones by supplying the element value and they key to store it with. + +Therefore, creating a map requires a struct with the following fields: + +\begin{table}[H] +\begin{tabular}{|c|c|} +\hline +FIELD & VALUE\\ +\hline +type & Type of eBPF map. Described in table \ref{table:ebpf_map_types}\\ +key\_size & Size of the data structure to use as a key\\ +value\_size & Size of the data structure to use as value field\\ +max\_entries & Maximum number of elements in the map\\ +\hline +\end{tabular} +\caption{Table showing common fields for creating an eBPF map.} +\label{table:ebpf_map_struct} +\end{table} + +\begin{table}[H] +\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} +\hline +TYPE & DESCRIPTION\\ +\hline +BPF\_MAP\_TYPE\_HASH & A hast table-like storage, elements are stored in tuples.\\ +BPF\_MAP\_TYPE\_ARRAY & Elements are stored in an array.\\ +BPF\_MAP\_TYPE\_RINGBUF & Map providing alerts from kernel to user space, covered in subsection \ref{subsection:bpf_ring_buf}\\ +BPF\_MAP\_TYPE\_PROG\_ARRAY & Stores descriptors of eBPF programs\\ +\hline +\hline +\end{tabular} +\caption{Table showing types of eBPF maps. Only those used in our rootkit are displayed, the full list can be consulted in the man page \cite{bpf_syscall}} +\label{table:ebpf_map_types} +\end{table} + +Table \ref{table:ebpf_maps} describes the main types of eBPF maps that are available for use. During the development of our rootkit, we will mainly focus on hash maps (BPF\_MAP\_TYPE\_HASH), provided that they are simple to use and we do not require of any special storage for our research purposes. + +\subsection{The eBPF ring buffer} \label{subsection:bpf_ring_buf} +eBPF ring buffers are a special kind of eBPF maps, providing a one-way directional communication system, going from an eBPF program in the kernel to an user space program that subscribes to its events. + +%TODO DIAGRAM OF A TYPICAL RING BUFFER + +\subsection{The bpf() syscall} \label{subsection:bpf_syscall} +The bpf() syscall is used to issue commands from user space to kernel space in eBPF programs. This syscall is multiplexor, meaning that it can perform a great range of actions, changing its behaviour depending on the parameters. + +The main operations that can be issued are described in table \ref{table:bpf_syscall}: + +\begin{table}[H] +\begin{tabular}{|c|>{\centering\arraybackslash}p{5cm}|>{\centering\arraybackslash}p{5cm}|} +\hline +COMMAND & ATTRIBUTES & DESCRIPTION\\ +\hline +\hline +BPF\_MAP\_CREATE & Struct with map info as defined in table \ref{table:ebpf_map_struct} & Create a new map\\ +\hline +BPF\_MAP\_LOOKUP\_ELEM & Map ID, and struct with key to search in the map & Get the element on the map with an specific key\\ +\hline +BPF\_MAP\_UPDATE\_ELEM & Map ID, and struct with key and new value & Update the element of an specific key with a new value\\ +\hline +BPF\_MAP\_DELETE\_ELEM & Map ID and struct with key to search in the map & Delete the element on the map with an specific key\\ +\hline +BPF\_PROG\_LOAD & Struct describing the type of eBPF program to load & Load an eBPF program in the kernel\\ +\hline +\end{tabular} +\caption{Table showing types of syscall actions. Only those relevant to our research are shown the full list and attribute details can be consulted in the man page \cite{bpf_syscall}} +\label{table:ebpf_syscall} +\end{table} + +With respect to the program type indicated with BPF\_PROG\_LOAD, this parameter indicates the type of eBPF program, setting the context in the kernel in which it will run, and to which modules it will have access to. The types of programs relevant for our research are described in table \ref{table:ebpf_prog_types}. + +\begin{table}[H] +\begin{tabular}{|c|>{\centering\arraybackslash}p{5cm}|} +\hline +PROGRAM TYPE & DESCRIPTION\\ +\hline +\hline +BPF\_PROG\_TYPE\_KPROBE & Program to instrument code to an attached kprobe\\ +\hline +BPF\_PROG\_TYPE\_UPROBE & Program to instrument code to an attached uprobe\\ +\hline +BPF\_PROG\_TYPE\_TRACEPOINT & Program to instrument code to a syscall tracepoint\\ +\hline +BPF\_PROG\_TYPE\_XDP & Program to filter, redirect and monitor network events from the Xpress Data Path\\ +\hline +BPF\_PROG\_TYPE\_SCHED\_CLS & Program to filter, redirect and monitor events using the Traffic Control classifier\\ +\hline +\end{tabular} +\caption{Table showing types of eBPF programs. Only those relevant to our research are shown. The full list and attribute details can be consulted in the man page \cite{bpf_syscall}.} +\label{table:ebpf_prog_types} +\end{table} + +In section \ref{section:TODO}, we will proceed to analyse in detail the different program types and what capabilities` they offer. + +\subsection{eBPF helpers} \label{subsection:ebpf_helpers} +Our last component to cover of the eBPF architecture are the eBPF helpers. Since eBPF programs have limited accessibility to kernel functions (which kernel modules commonly have free access to), the eBPF system offers a set of limited functions called helpers\cite{ebpf_helpers}, which are used by eBPF programs to perform certain actions and interact with the context on which they are run. The list of helpers a program can call varies between eBPF program types, since different programs run in different contexts. + +It is important to highlight that, just like commands issued via the bpf() syscall can only be issued from the user space, eBPF helpers correspond to the kernel-side of eBPF program exclusively. Note that we will also find a symmetric correspondence to those functions of the bpf() syscall related to map operations (since these are accessible both from user and kernel space). + +Table \ref{table:ebpf_helpers} lists the most relevant general-purpose eBPF helpers we will use during the development of our project. We will later detail those helpers exclusive to an specific eBPF program type in the sections on which they are studied. + +\begin{table}[H] +\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} +\hline +eBPF helper & DESCRIPTION\\ +\hline +\hline +bpf\_map\_lookup\_elem() & Query an element with a certain key in a map\\ +\hline +bpf\_map\_delete\_elem() & Delete an element with a certain key in a map\\ +\hline +bpf\_map\_update\_elem() & Update the value of the element with a certain key in a map\\ +\hline +bpf\_probe\_read\_user() & Attempt to safely read data at an specific user address into a buffer\\ +\hline +bpf\_probe\_read\_kernel() & Attempt to safely read data at an specific kernel address into a buffer\\ +\hline +bpf\_trace\_printk() & Similarly to printk() in kernel modules, writes buffer in \/sys\/kernel\/debug\/tracing\/trace\_pipe\\ +\hline +bpf\_get\_current\_pid\_tgid() & Get the process process id (PID) and thread group id (TGID)\\ +\hline +bpf\_get\_current\_comm() & Get the name of the executable\\ +\hline +bpf\_probe\_write\_user() & Attempt to write data at a user memory address\\ +\hline +bpf\_override\_return() & Override return value of a probed function\\ +\hline +bpf\_ringbuf\_submit() & Submit data to an specific eBPF ring buffer, and notify to subscribers\\ +\hline +bpf\_tail\_call() & Jump to another eBPF program preserving the current stack\\ +\hline +\end{tabular} +\caption{Table showing common eBPF helpers. Only those relevant to our research are shown. Those helpers exclusive to an specific program type are not listed. The full list and attribute details can be consulted in the man page \cite{ebpf_helpers}.} +\label{table:ebpf_helpers} +\end{table} + + +% Is this the best title? +\section{eBPF program types} \label{section:ebpf_prog_types} +In the previous subsection \ref{subsection:bpf_syscall} we introduced the new types of eBPF programs that are supported and that we will be developing for our offensive analysis. In this section, we will analyse in greater detail how eBPF is integrated in the Linux kernel in order to support these new functionalities. + +\subsection{XDP} \label{subsection:xdp} +eXpress Data Path (XDP) programs are a novel type of eBPF program that allows for the lowest-latency traffic filtering and monitoring in the whole Linux kernel. In order to load an XDP program, a bpf() syscall with the command BPF\_PROG\_LOAD and the program type BPF\_PROG\_TYPE\_XDP must be issued. + +These programs are directly attached to the Network Interface Controller (NIC) driver, and thus they can process the packet before any other module\cite{xdp_gentle_intro}. + +\begin{figure}[H] + \centering + \includegraphics[width=15cm]{xdp_diag.jpg} + % Either this caption, or change the text afterwards. I still need to know whether to put the long explanation here or on the paragraph, it gets repetitive. + \caption{Figure showing how the eBPF XDP and TC modules are integrated in the network processing in the Linux kernel.} + \label{fig:xdp_diag} +\end{figure} + +Figure \ref{fig:xdp_diag} shows how XDP is integrated in the network processing of the Linux kernel. After receiving a raw packet (in the figure, \textit{xdp\_md}, which consists on the raw bytes plus some very basic metadata about the packet) from the incoming traffic, XDP program can perform the following actions\cite{xdp_manual}: +\begin{itemize} +\item Analyse the data between the packet buffer bounds. +\item Modify the packet contents, and modify the packet length. +\item Decide between one of the actions displayed in table \ref{table:xdp_actions_av}. +\end{itemize} + +\begin{table}[H] +\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} +\hline +ACTION & DESCRIPTION\\ +\hline +\hline +XDP\_PASS & Let packet proceed with operated modifications on it.\\ +\hline +XDP\_TX & Return the packet at the same NIC it was received from. Packet modifications are kept.\\ +\hline +XDP\_DROP & Drops the packet completely, kernel networking will not be notified.\\ +\hline +\end{tabular} +\caption{Table showing XDP relevant return values.} +\label{table:xdp_actions_av} +\end{table} + +Some of the XDP-exclusive eBPF helpers we will be discussing in later sections are shown in table \ref{table:xdp_helpers}. +\begin{table}[H] +\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} +\hline +eBPF helper & DESCRIPTION\\ +\hline +\hline +bpf\_xdp\_adjust\_head() & Enlarges or reduces the extension of a packet, by moving the address of its first byte.\\ +\hline +bpf\_xdp\_adjust\_tail() & Enlarges or reduces the extension of a packet, by moving the address of its last byte.\\ +\hline +\end{tabular} +\caption{Table showing relevant XDP-exclusive eBPF helpers.} +\label{table:xdp_helpers} +\end{table} + + +\subsection{Traffic Control} \label{subsection:tc} +Traffic Control (TC) programs are also indicated for networking instrumentation. Similarly to XDP, their module is positioned before entering the overall network processing of the kernel. However, as it can be observed in figure \ref{fig:xdp_diag}, they differ in some aspects: +\begin{itemize} +\item TC programs receive a network buffer with metadata (in the figure, \textit{sk\_buff}) about the packet in it. This renders TC programs less ideal than XDP for performing large packet modifications (like new headers), but at the same time the additional metadata fields make it easier to locate and modify specific packet fields\cite{tc_differences}. +\item TC programs can be attached to the \textit{ingress} or \textit{egress} points, meaning that an eBPF program can operate not only over incoming traffic, but also over the outgoing packets. +\end{itemize} + +With respect to how TC programs operate, the Traffic Control system in Linux is greatly complex and would require a complete section by itself. In fact, it was already a complete system before the appearance of eBPF. Full documentation can be found at \cite{tc_docs_complete}. For this document, we will explain the overall process needed to load a TC program\cite{tc_direct_action}: +\begin{enumerate} +\item The TC program defines a so-called queuing discipline (qdisc), a packet scheduler that issues packets in a First-In-First-Out (FIFO) order as soon as they are received. This qdisc will be attached to an specific network interface (e.g.: wlan0). +\item Our TC eBPF program is attached to the qdisc. It will work as a filter, being run for every of the packets dispatched by the qdisc. +\end{enumerate} + +Similarly to XDP, the TC eBPF programs can decide an action to be executed on a packet by specifying a return value. These actions are almost analogous to the ones in XDP, as it can be observed in table \ref{table:tc_actions}. + +\begin{table}[H] +\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} +\hline +ACTION & DESCRIPTION\\ +\hline +\hline +TC\_ACT\_OK & Let packet proceed with operated modifications on it.\\ +\hline +TC\_ACT\_RECLASSIFY & Return the packet to the back of the qdisc scheduling queue.\\ +\hline +TC\_ACT\_SHOT & Drops the packet completely, kernel networking will not be notified.\\ +\hline +\end{tabular} +\caption{Table showing TC relevant return values. Full list can be consulted at \cite{tc_ret_list_complete}.} +\label{table:tc_actions} +\end{table} + +Finally, as in XDP, there exists a list of useful BPF helpers that will be relevant for the creation of our rootkit. They are shown in table \ref{table:tc_helpers}. +\begin{table}[H] +\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} +\hline +eBPF helper & DESCRIPTION\\ +\hline +\hline +bpf\_l3\_csum\_replace() & Recomputes the network layer 3 (e.g.: IP) checksum of the packet.\\ +\hline +bpf\_l4\_csum\_replace() & Recomputes the network layer 4 (e.g: TCP) checksum of the packet.\\ +\hline +bpf\_skb\_store\_bytes() & Write a data buffer into the packet.\\ +\hline +bpf\_skb\_pull\_data() & Reads a sequence of packet bytes into a buffer.\\ +\hline +bpf\_skb\_change\_head() & (Only) enlarges the extension of a packet, by moving the address of its first byte.\\ +\hline +bpf\_skb\_change\_tail() & Enlarges or reduces the extension of a packet, by moving the address of its last byte.\\ +\hline +\hline +\end{tabular} +\caption{Table showing relevant TC-exclusive eBPF helpers.} +\label{table:tc_helpers} +\end{table} + + +%TODO This section might benefit from some diagrams, maybe. It was a bit to extense already, so skipping it from now +\subsection{Tracepoints} \label{subsection:tracepoints} +Tracepoints are a technology in the Linux kernel that allows to hook functions in the kernel, connecting a 'probe': a function that is executed every time the hooked function is called\cite{tp_kernel}. These tracepoints are set statically during kernel development, meaning that for a function to be hooked, it needs to have been previously marked with a tracepoint statement indicating its traceability. At the same time, this limits the number of tracepoints available. + +The list of tracepoint events available depends on the kernel version and can be visited under the directory \textit{/sys/kernel/debug/tracing/events}. + +It is particularly relevant for our later research that most of the system calls incorporate a tracepoint, both when they are called (\textit{enter} tracepoint) and when they are exited (\textit{exit} tracepoints). This means that, for a system call sys\_open, both the tracepoint sys\_enter\_open and sys\_exit\_open are available. + +Also, note that the probe functions that are called when hitting a tracepoint receive some parameters related to the context on which the tracepoint is located. In the case of syscalls, these include the parameters with which the syscall was called (only for \textit{enter} syscalls, \textit{exit} ones will only have access to the return value). The exact parameters and their format which a probe function receives can be visited in the file \textit{/sys/kernel/debug/tracing/events///format}. In the previous example with sys\_enter\_open, this is \textit{/sys/kernel/debug/tracing/events/syscalls/sys\_enter\_open/format}. + +In eBPF, a program can issue a bpf() syscall with the command BPF\_PROG\_LOAD and the program type BPF\_PROG\_TYPE\_TRACEPOINT, specifying which is the function with the tracepoint to attach to and an arbitrary function probe to call when it is hit. This function probe is defined by the user in the eBPF program submitted to the kernel. + +\subsection{Kprobes} +Kprobes are another tracing technology of the Linux kernel whose functionality has been become available to eBPF programs. Similarly to tracepoints, kprobes enable to hook functions in the kernel, with the only difference that it is dynamically attached to any arbitrary function, rather than to a set of predefined positions\cite{kprobe_manual}. It does not require that kernel developers specifically mark a function to be probed, but rather kprobes can be attached to any instruction, with a short list of blacklisted exceptions. + +As it happened with tracepoints, the probe functions have access to the parameters of the original hooked function. Also, the kernel maintains a list of kernel symbols (addresses) which are relevant for tracing and that offer us insight into which functions we can probe. It can be visited under the file \textit{/proc/kallsyms}, which exports symbols of kernel functions and loaded kernel modules\cite{kallsyms_kernel}. + +Also similarly, since tracepoints could be found in their \textit{enter} and \textit{exit} variations, kprobes have their counterpart, name kretprobes, which call the hooked probe once a return instruction is reached after the hooked symbol. This means that a kretprobe hooked to a kernel function will call the probe function once it exits. + +In eBPF, a program can issue a bpf() syscall with the command BPF\_PROG\_LOAD and the program type BPF\_PROG\_TYPE\_KPROBE, specifying which is the function with the kprobe to attach to and an arbitrary function probe to call when it is hit. This function probe is defined by the user in the eBPF program submitted to the kernel. + +\subsection{Uprobes} +Uprobes is the last of the main tracing technologies which has been become accessible to eBPF programs. They are the counterparts of Kprobes, allowing for tracing the execution of an specific instruction in the user space, instead of in the kernel. When the exeuction flow reaches a hooked instruction, a probe function is run. + +For setting an uprobe on an specific instruction of a program, we need to know three components: +\begin{itemize} +\item The name of the program. +\item The address of the function where the instruction is contained. +\item The offset at which the specific instruction is placed from the start of the function. +\end{itemize} + +Similarly to kprobes, uprobes have access to the parameters received by the hooked function. Also, the complementary uretprobes also exist, running the probe function once the hooked function returns. + +In eBPF, programs can issue a bpf() syscall with the command BPF\_PROG\_LOAD and the program type BPF\_PROG\_TYPE\_UPROBE, specifying the function with the uprobe to attach to and an arbitrary function probe to call when it is hit. This function probe is also defined by the user in the eBPF program submitted to the kernel. + +% Is this the best title? +\section{Developing eBPF programs} +In section \ref{section:modern_ebpf}, we discussed the overall architecture of the eBPF system which is now an integral part of the Linux kernel. We also studied the process which a piece of eBPF bytecode follows in order to be accepted in the kernel. However, for an eBPF developer, programming bytecode and working with bpf() calls natively is not an easy task, therefore an additional layer of abstraction was needed. + +Nowadays, there exist multiple popular alternatives for writing and running eBPF programs. We will overview which they are and proceed to analyse in further detail the option that we will use for the development of our rootkit. + +\subsection{BCC} +BPF Compiler Collection (BCC) is one of the first and well-known toolkits for eBPF programming available\cite{bcc_github}. It allows to include eBPF code into user programs. These programs are developed in python, and the eBPF code is embedded as a plain string. An example of a BCC program is included in %TODO ANNEX??? + +Although BCC offers a wide range of tools to easy the development of eBPF programs, we found it not to be the most appropriate for our large-scale eBPF project. This was in particular due to the feature of eBPF programs being stored as a python string, which leads to difficult scalability, poor development experience given that programming errors are detected at runtime (once the python program issues the compilation of the string), and simply better features from competing libraries. + +\subsection{Bpftool} +bpftool is not a development framework like BCC, but one of the most relevant tools for eBPF program development. Some of its functionalities include: +\begin{itemize} +\item Loading eBPF programs. +\item List running eBPF programs. +\item Dumping bytecode from live eBPF programs. +\item Extract program statistics and data from programs. +\item List and operate over eBPF maps. +\end{itemize} + +Although we will not be covering bpftool during our overview on the constructed eBPF rootkit, it was used extensively during the development and became a key tool for debugging eBPF programs, particularly to peek data at eBPF maps during runtime. + +\subsection{Libbpf} +libbpf\cite{libbpf_github} is a library for loading and interacting with eBPF programs, which is currently maintained in the Linux kernel source tree\cite{libbpf_upstream}. It is one of the most popular frameworks to develop eBPF applications, both because it makes eBPF programming similar to common kernel development and because it aims at reducing kernel-version dependencies, thus increasing programs portability between systems\cite{libbpf_core}. During our research, however, we will not make use of this functionalities given that a portable program is not in our research goals. + +As we discussed in section \ref{section:modern_ebpf}, eBPF programs are composed of both the eBPF code in the kernel and a user space program that can interact with it. With libbpf, the eBPF kernel program is developed in C (a real program, not a string later compiled as with BCC), while user programs are usually developed in C, Rust or GO. For our project, we will use the C version of libbpf, so both the user and kernel side of our rootkit will be developed in this language. + +% Cites in the following paragraph? +When using libbpf with the C language, both the user-side and kernel eBPF program are compiled together using the Clang/LLVM compiler, translating C instructions into eBPF bytecode. As a clarification, Clang is the front-end of the compiler, translating C instructions into an intermediate form understandable by LLVM, whilst LLVM is the back-end compiling the intermediate code into eBPF bytecode. As it can be observed in figure \ref{fig:libbpf}, the result of the compilation is a single program, comprising the user-side which will launch a user process, the eBPF bytecode to be run in the kernel, and other structures libbpf generates about eBPF maps and other meta data. This program is encapsulated as an ELF file (a common executable format). + +\begin{figure}[H] + \centering + \includegraphics[width=12cm, keepaspectratio=true]{libbpf_prog.jpg} + \caption{Sketch of the compilation and loading process of a program developed with libbpf.} + \label{fig:libbpf} +\end{figure} + +Finally, we will overview one of the main functionalities of libbpf to simplify eBPF programming, namely the BPF skeleton. This is auto-generated code by libbpf whose aim is to simplify working with eBPF from the user-side program. As a summary, it parses the eBPF programs developed (which may be using different technologies such as XDP, kprobes, TC...) and the eBPF maps used, and as a result offers a simple set of functions for dealing with these programs from the user program. In particular, it allows for loading and unloading an specific eBPF program from user space at runtime. + +Table \ref{table:libbpf_skel} describes the API offered by the BPF skeleton. Note that is subtituted by the name of the program being compiled. + +\begin{table}[H] +\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} +\hline +Function name & Description\\ +\hline +\hline +\_\_open() & Parse the eBPF programs and maps.\\ +\hline +\_\_load() & Load the eBPF map in the kernel after its validation, create the maps. However the programs are not active yet.\\ +\hline +\_\_attach() & Activate the eBPF programs, attaching them to their corresponding parts in the kernel (e.g. kprobes to kernel functions).\\ +\hline +\_\_destroy() & Detach and unload the eBPF programs from the kernel.\\ +\hline +\end{tabular} +\caption{Table showing BPF skeleton functions.} +\label{table:libbpf_skel} +\end{table} + +Note that the BPF skeleton also offers further granularity at the time of dealing with programs, so that individual programs can be loaded or attached instead of all simultaneously. This is the approach we will generally use in the development of our rootkit, as it will be explained in section \ref{TODO}. + + + +\section{Security features in eBPF} +As we have shown in section \ref{section:modern_ebpf}, eBPF has been an active part of the Linux kernel from its 3.18 version. However, as with many other components of the kernel, its availability to the user depends on the parameters with which the kernel has been compiled. Specifically, eBPF is only available to kernels compiled with the flags specified in table \ref{table:ebpf_kernel_flags}. + +\begin{table}[H] +\begin{tabular}{|c|c|>{\centering\arraybackslash}p{8cm}|} +\hline +Flag & Value & Description\\ +\hline +\hline +\multicolumn{1}{|c|}{CONFIG\_BPF} & \multicolumn{1}{|c|}{y} & \multirow{2}{*}{Basic BPF compilation (mandatory)}\\ +\cline{1-2} +\multicolumn{1}{|c|}{CONFIG\_BPF\_SYSCALL} & \multicolumn{1}{|c|}{m} & \\ +\hline +\multicolumn{1}{|c|}{CONFIG\_NET\_ACT\_BPF} & \multicolumn{1}{|c|}{m} & \multirow{2}{*}{Traffic Control functionality}\\ +\cline{1-2} +\multicolumn{1}{|c|}{CONFIG\_NET\_CLS\_BPF} & \multicolumn{1}{|c|}{y} & \\ +\hline +\multicolumn{1}{|c|}{CONFIG\_BPF\_JIT} & \multicolumn{1}{|c|}{y} & \multirow{2}{*}{Enable JIT compliation}\\ +\cline{1-2} +\multicolumn{1}{|c|}{CONFIG\_HAVE\_BPF\_JIT} & \multicolumn{1}{|c|}{y} & \\ +\hline +\multicolumn{1}{|c|}{CONFIG\_BPF\_EVENTS} & \multicolumn{1}{|c|}{y} & \multirow{4}{*}{Enable kprobes, uprobes and tracepoints}\\ +\cline{1-2} +\multicolumn{1}{|c|}{CONFIG\_KPROBE\_EVENTS} & \multicolumn{1}{|c|}{y} & \\ +\cline{1-2} +\multicolumn{1}{|c|}{CONFIG\_UPROBE\_EVENTS} & \multicolumn{1}{|c|}{y} & \\ +\cline{1-2} +\multicolumn{1}{|c|}{CONFIG\_TRACING} & \multicolumn{1}{|c|}{y} & \\ +\hline +CONFIG\_XDP\_SOCKETS & y & Enable XDP\\ +\hline +\end{tabular} +\caption{Kernel compilation flags for eBPF.} +\label{table:ebpf_kernel_flags} +\end{table} + +The above table is based on BCC's documentation\ref{table:ebpf_kernel_flags}, but the full list of eBPF-related flags can be extracted in a live system via bpftool, as detailed in Annex \ref{annex:bpftool_flags_kernel}. Nowadays, all mainstream Linux distributions include kernels with full support for eBPF. + + +\subsection{Access control} +It must be noted that, similarly to kernel modules, loading an eBPF program requires privileged access in the system. In old kernel versions, this means either an user having full root permissions, or having the Linux capability\cite{ubuntu_caps} CAP\_SYS\_ADMIN. Therefore, there existed two main options: +%TODO some words about capabilities +\begin{itemize} +\item \textbf{Privileged users} can load any kind of eBPF program and use any functionality. +\item \textbf{Unprivileged users} can only load and attach eBPF programs of type BPF\_PROG\_TYPE\_SOCKET\_FILTER\cite{evil_ebpf_p9}, offering the very limited functionality of filtering packets received on a socket. +\end{itemize} + +More recently, in an effort to further granulate the permissions needed for loading, attaching and running eBPF programs, CAP\_SYS\_ADMIN has been substituted by more specific capabilities\cite{ebpf_caps_intro}\cite{ebpf_caps_lwn}. The current system is therefore described in table \ref{table:ebpf_caps_current}. + +\begin{table}[H] +\begin{tabular}{|>{\centering\arraybackslash}p{4cm}|>{\centering\arraybackslash}p{10cm}|} +\hline +Capabilities & eBPF functionality\\ +\hline +\hline +No capabilities & Load and attach BPF\_PROG\_TYPE\_SOCKET\_FILTER, load BPF\_PROG\_TYPE\_CGROUP\_SKB programs.\\ +\hline +CAP\_BPF & Load (but not attach) any type of program, create most types of eBPF map and access them if their id is known\\ +\hline +CAP\_NET\_ADMIN & Attach networking programs (Traffic Control, XDP, ...)\\ +\hline +CAP\_PERFMON & Attaching kprobes, uprobes and tracepoints. Read access to kernel memory.\\ +\hline +CAP\_SYS\_ADMIN & Privileged eBPF. Includes iterating over eBPF maps, and CAP\_BPF, CAP\_NET\_ADMIN, CAP\_PERFMON functionalities.\\ +\hline +\end{tabular} +\caption{Capabilities needed for eBPF.} +\label{table:ebpf_caps_current} +\end{table} + +Therefore, eBPF network programs usually require both CAP\_BPF and CAP\_NET\_ADMIN, whilst tracing programs require CAP\_BPF and CAP\_PERFMON. CAP\_SYS\_ADMIN still remains as the (non-preferred) capability to assign to eBPF programs with complete access in the system. + +Although for a long time there have existed efforts towards enhancing unprivileged eBPF, it remains a worrying feature\cite{unprivileged_ebpf}. The main issue is that the verifier must be prepared to detect any attempt to extract kernel memory access or user memory modification by unprivileged eBPF programs, which is a complex task. In fact, there have existed numerous security vulnerabilities which allow for privilege escalation using eBPF, that is, execution of privileged eBPF programs by exploiting vulnerabilities in unprivileged eBPF\cite{cve_unpriv_ebpf}. + +This influx of security vulnerabilities leads to the recent inclusion of an attribute into the kernel which allows for setting whether unprivileged eBPF is allowed in the system or not. This parameter is named \textit{kernel.unprivileged\_bpf\_disabled}, its values can be seen in table \ref{table:unpriv_ebpf_values}. + +\begin{table}[H] +\begin{tabular}{|>{\centering\arraybackslash}p{4cm}|>{\centering\arraybackslash}p{10cm}|} +\hline +Value & Meaning\\ +\hline +\hline +0 & Unprivileged eBPF is enabled.\\ +\hline +1 & Unprivileged eBPF is disabled. A system reboot is needed to enable it after changing this value.\\ +\hline +2 & Unprivileged eBPF is disabled. A system reboot is not needed to enable it after changing this value.\\ +\hline +\end{tabular} +\caption{Values for unprivileged eBPF kernel parameter.} +\label{table:unpriv_ebpf_values} +\end{table} + +Nowadays, most Linux distributions have set value 1 to this parameter, therefore disallowing unprivileged eBPF completely. These include Ubuntu\cite{unpriv_ebpf_ubuntu}, Suse Linux\cite{unpriv_ebpf_suse} or Red Hat Linux\cite{unpriv_ebpf_redhat}, between others. + + + +\section{Memory management in Linux} +Multiple of the techniques incorporated in our rootkit require a deep understanding into how memory is managed in a Linux process. Therefore, in this section we will present all the background about memory management needed for our later discussion of the offensive capabilities of eBPF in this context. + +\subsection{Memory pages and faults} +Linux systems divide the available random access memory (RAM) into 'pages', subsections of an specific length, usually 4 KB. The collection of all pages is called physical memory. + +Likewise, individual memory sections need to be assigned to each running process in the system, but instead of assigning a set of pages from physical memory, a new address space is defined, named virtual memory, which is divided into pages as well. These virtual memory pages are related to physical memory pages via a page table, so that each virtual memory address of a process can be translated into a real, physical memory address in RAM\cite{mem_page_arch}. Figure \ref{fig:mem_arch_pages} shows a diagram of the described architecture. + +\begin{figure}[H] + \centering + \includegraphics[width=13cm]{mem_arch_pages.jpg} + \caption{Memory translation of virtual pages to physical pages.} + \label{fig:mem_arch_pages} +\end{figure} + +As we can observe in the figure, each virtual page is related to one physical page. However, RAM needs to maintain multiple processes and data simultaneously, and therefore sometimes the operating system (OS) will remove them from physical memory when it believes they are no longer being used. This leads to the occurrence of two type of memory events\cite{page_faults}: +\begin{itemize} +\item \textbf{Major page faults} occur when a process tries to access a virtual page, but the related physical page has been removed from RAM. In this case, the OS will need to request a secondary storage (such as a hard disk) for the data removed, and allocate a new physical page for the virtual page. Figure \ref{fig:mem_major_page_fault} illustrates a major page fault. +\begin{figure}[H] + \centering + \includegraphics[width=11cm]{mem_major_page_fault.jpg} + \caption{Major page fault after a page was removed from RAM.} + \label{fig:mem_major_page_fault} +\end{figure} +\item \textbf{Minor page faults} occur when a process tries to access a virtual page, and although the related physical page exists, the connection in the page table has not been completed. A common event when these fault happen is on fork() calls, since with the purpose of making the call more efficient, the page table of the parent is not always completely copied into the child, leading into multiple minor page faults once the child tries to access the data on them. Figure \ref{fig:mem_minor_page_fault} illustrates a minor page fault after a fork. +\end{itemize} +\begin{figure}[H] + \centering + \includegraphics[width=11cm]{mem_minor_page_fault.jpg} + \caption{Minor page fault after a fork() in which the page table was not copied completely.} + \label{fig:mem_minor_page_fault} +\end{figure} + +\subsection{Process virtual memory} +In the previous subsection we have studied that each process disposes of a virtual address space. We will now describe how this virtual memory is organized in a Linux system. + +\begin{figure}[H] + \centering + \includegraphics[width=6cm]{memory.jpg} + \caption{Virtual memory architecture of a process\cite{mem_arch_proc}.} + \label{fig:mem_proc_arch} +\end{figure} + +Figure \ref{fig:mem_proc_arch} describes how virtual memory is distributed within a process in the x86\_64 architecture. As we can observe, it is partitioned into multiple sections: +\begin{itemize} +\item Lower and upper memory addresses are reserved for the kernel. +\item A section where shared libraries code is stored. +\item A .text section, which contains the code of the program being run. +\item A .data section, containing initialized static and global variables. +\item A .bss section, which contains global and static variables which are unitialized or initialized to zero. +\item The heap, a section which grows from lower to higher memory addresses, and which contains memory dynamically allocated by the program. +\item The stack, a section which grows from higher to lower memory addresses, towards the heap. It is a Last In First Out (LIFO) structure used to store local variables, function parameters and return addresses. +\item Right at the start of the stack we can find the arguments with which the programs has been executed. +\end{itemize} + +\subsection{The process stack} \label{subsection:stack} +Between all the sections we identified in a process virtual memory, the stack will be particularly relevant during our research. We will therefore study it now in detail. + +Firstly, we will present how the stack is structured, and which operations can be executed on it. Figure \ref{fig:stack_pres} presents a stack during the execution of a program. Table \ref{table:systemv_abi_other} explains the purpose of the most relevant registers related to the stack and program execution: + +\begin{figure}[H] + \centering + \includegraphics[width=14cm]{stack_pres.jpg} + \caption{Simplified stack representation showing only stack frames.} + \label{fig:stack_pres} +\end{figure} + +\begin{table}[H] +\begin{tabular}{|>{\centering\arraybackslash}p{2cm}|>{\centering\arraybackslash}p{10cm}|} +\hline +Register & Purpose\\ +\hline +\hline +rip & Instruction Pointer - Memory address of the next instruction to execute\\ +\hline +rsp & Stack Pointer - Memory address where next stack operation takes place\\ +\hline +rbp & Base/Frame Pointer - Memory address of the start of the stack frame\\ +\hline +\end{tabular} +\caption{Relevant registers in x86\_64 for the stack and control flow and their purpose.} +\label{table:systemv_abi_other} +\end{table} + +As it can be observed in figure \ref{fig:stack_pres}, the stack grows towards lower memory addresses, and it is organized in stack frames, delimited by the registers rsp and rbp. An stack frame is a division of the stack which contains all the data (variables, call arguments...) belonging to a single function execution. When a function is exited, its stack frame is removed, and if a function calls a nested function, then its stack frame is preserved and a new stack frame is inserted into the stack. + +As table \ref{table:systemv_abi_other} explains, the rbp and rsp registers are used for keeping track of the starting and final position of the current stack frame respectively. We can see in figure \ref{fig:stack_pres} that their value is a memory address pointing to their stack positions. On the other hand, the rip register does not point to the stack, but rather to the .text section (see figure \ref{fig:mem_proc_arch}), where it points to the next instruction to be executed. However, as we will now see, its value must also be stored in the stack frame when a nested function is called, since after the nested function exits we need to restore the execution in the same instruction of the original function. + +As with any LIFO structure, the stack supports two main operations: \textit{push} and \textit{pop}. In the x86\_64 architecture, it operates with chunks of data of either 16, 32 or 64 bytes. +\begin{itemize} +\item A \textbf{push} operation writes data in the free memory pointed by register rsp. It then moves the value of rsp to point to the new end of the stack. +\item A \textbf{pop} operation moves the value of rsp by 16, 32 or 64 bytes, and reads the data previously saved in that position. +\end{itemize} + +\begin{figure}[H] + \centering + \includegraphics[width=10cm]{stack_ops.jpg} + \caption{Representation of push and pop operations in the stack.} + \label{fig:stack_ops} +\end{figure} + + + +As we mentioned, the stack stores function parameters, return addresses and local variables inside a stack frame. We will now study how the processor uses the stack in order to call, execute, and exit a function. To illustrate this process, we will simulate the execution of function \lstinline{func(char* a, char* b, char* c)} \lstinline{}: + +\begin{figure}[H] + \centering + \includegraphics[width=14cm]{stack_before.jpg} + \caption{Stack representation right before starting the function call process.} + \label{fig:stack_before} +\end{figure} + +\begin{figure}[H] + \centering + \includegraphics[width=14cm]{stack.jpg} + \caption{Stack representation right after the function preamble.} + \label{fig:stack} +\end{figure} + +\begin{enumerate} +\item The function arguments are pushed into the stack. We can see them in the stack in reverse order. +\item The function is called: +\begin{enumerate} + \item The value of register rip is pushed into the stack, so that it is saved for when the function exists. We can see it on the figure as 'ret'. + \item The value of rip changes to point to the first instruction of the called function. +\item We execute what is called as the \textit{function preamble}\cite{8664_params_abi_p18}, which prepares the stack frame for the called function: +\begin{enumerate} + \item The value of rbp is pushed into the stack, so that we can restore the previous stack frame when the function exits. We can see it on the figure as the 'saved frame pointer'. + \item The value of rsp is moved into rbp. Therefore, now rbp points to the end of the previous stack frame. + \item The value of rsp is usually decremented (since the stack needs to go to lower memory addresses) so that we allocate some space for function variables. +\end{enumerate} +\end{enumerate} +\item The function instructions are executed. The stack may be further modified, but on its end rsp must point to the same address of the beginning. Register rbp always keeps pointing to the end of the stack. +\item We execute what is called the \textit{function epilogue}, which removes the stack frame and restores the original function: +\begin{enumerate} + \item The value of rbp is moved into rsp, so that rsp points to the start of the previous stack frame. All data allocated in the previous stack frame is considered to be free. + \item The value of the saved frame pointer is popped and stored into rbp, so that rbp now points to the start of the previous stack frame. + \item The value of the saved rip value is popped into register rip, so that the next instruction to execute is the instruction right after the function call. +\end{enumerate} +\item Since the function arguments where pushed into the stack, they are popped now. +\end{enumerate} + + +\section{Attacks at the stack} \label{section:attacks_stack} +In section \ref{subsection:stack}, we studied how the stack works and which is the process that a program follows in order to call a function. As we saw in figure \ref{fig:stack}, the processor pushes into the stack several data which is used to restore the context of the original function once the called function exits. These pushed arguments included: +\begin{itemize} +\item The arguments with which the function is being called (if they need to be passed in the stack, such as byte arrays). +\item The original value of the rip register (ret), to restore the execution on the original function. +\item The original value of the rbp register (sfp), to restore the frame pointer of the original stack frame. +\end{itemize} + +Although this process is simple enough, it opens the possibility for an attacker to easily hijack the flow of execution if it can modify the value of ret, as it is shown in figure \ref{fig:stack_ret_hij_simple}: +\begin{figure}[H] + \centering + \includegraphics[width=15cm]{stack_ret_hij_simple.jpg} + \caption{Execution hijack overwriting saved rip value.} + \label{fig:stack_ret_hij_simple} +\end{figure} + +In the figure, we can observe how, during the execution of the called function, the attacker overwrites the value of ret in the stack. Once the function exists, as we explained in section \ref{subsection:stack}, during the function epilogue the value of ret will be popped and moved into rip, so that the execution is directed to the original next instruction. However, because the value was modified, the attacker controls which instructions are executed next. + +Attackers have historically used multiple techniques to overwrite the ret value in the stack. In this section, we will present two of the most popular techniques, which will be used as a basis for designing our own attacks using eBPF. + +\subsection{Buffer overflow} \label{subsection: buf_overflow} +The stack buffer overflow is one of the most popular exploitation techniques to overwrite data at the stack. In this technique, an attacker takes advantage of a program receiving an user value stored in a buffer whose capacity is smaller of that of the supplied value. Code snippet \ref{code:vuln_overflow} shows an example of a vulnerable program: + +\begin{lstlisting}[language=C, caption={Program vulnerable to buffer overflow.}, label={code:vuln_overflow}] +void foo(char *bar){ // bar may be larger than 12 characters + char buffer[12]; + strcpy(buffer, bar); //no bounds checking +} + +int main(int argc, char *argv[]){ + foo(argv[1]); + return 0; +} +\end{lstlisting} + +During the execution of the above program, since the char array \textit{buffer} is a buffer of length 12 stored in the stack, then if the value of \textit{bar} is larger than 12 bytes it will overflow the allocated space in the stack. This is usually the case of using unsafe functions for processing user input such as strcpy(), which does not check whether the array fits in the buffer. Figure \ref{fig:buffer_overflow} shows how the overflow happens in the stack. + +\begin{figure}[H] + \centering + \includegraphics[width=15cm]{buffer_overflow.jpg} + \caption{Stack buffer overflow overwriting ret value.} + \label{fig:buffer_overflow} +\end{figure} + +As we can observe in the figure, the new data written into the buffer has also overwritten other fields which were pushed into the stack, such as sfp and ret, resulting in changing the flow of execution once the function exists. + +Usually, an attacker exploiting a program vulnerable to stack buffer overflow is interested in running arbitrary (malicious) code. For this, the attacker follows the process shown in figure \ref{fig:buffer_overflow_shellcode}: + +\begin{figure}[H] + \centering + \includegraphics[width=15cm]{buffer_overflow_shellcode.jpg} + \caption{Executing arbitrary code exploiting a buffer overflow vulnerability.} + \label{fig:buffer_overflow_shellcode} +\end{figure} + +As we can observe in the figure, the attacker will take advantage of the buffer overflow to overwrite not only ret, but also the rest of the current stack frame and sfp with malicious code. This code is known as shellcode, consisting on instruction opcodes (machine assembly instructions translated to their representation in hexadecimal values) which the processor will execute. We will briefly explain how to write shellcode in section \ref{TODO probably an Annex}. Therefore, in this technique the attacker will: +\begin{itemize} +\item Introduce a byte array that overflows the buffer, consisting on SHELLCODE + the address of the buffer. +\begin{itemize} + \item The shellcode overwrites the buffer and all data until ret. + \item ret is overwritten by the value of the address where the buffer starts. +\end{itemize} +\item When the function exits and ret is popped from the stack, the register rip will now point to the address of the buffer at the stack, processing the stack data as instructions part of a program. The malicious code will be executed. +\end{itemize} + +Although the classic buffer overflow is one of the best-known techniques in binary exploitation, it is also one of the oldest and thus numerous protections have historically been incorporated to mitigate these type of exploits. This is why the attack presented here does not work work in a modern system any more. + +The reason is that one of the protections consits on the prohibition of executing code from the stack. By marking the stack as non-executable, in the case of rip pointing to an address in the stack any malicious code will not be run, even if an application was vulnerable to a buffer overflow. We will explain more in detail the main protections that nowadays are incorporated in modern systems in section \ref{TODO}. + +\subsection{Return oriented programming attacks} \label{subsection:rop} +After the stack was marked non-executable, a new refined technique was invented to circumvent this restriction and adapt the classic buffer overflow to modern systems. In the end, attackers still maintained the ability to overflow the buffer in the stack of vulnerable applications, writing shellcode and overwriting ret, the only issue was that the shellcode could not be executed. + +Return Oriented Programming (ROP) is an exploitation technique that takes advantage of the fact that, even if malicious code in the stack cannot be executed, the attacker can still redirect the flow of execution by modifying ret to any other piece of executable code. The challenge for the attacker is executing malicious code, since any available executable instructions are either at the .text section (which will correspond to the normal functioning of the program) or at shared libraries, but none are useful for malware. + +ROP tackles this challenge by designing a method of reconstructing malicious code from parts of already-existing code, as in a 'collage'. Assembly instructions are selected from multiple places, so that, when put together and executed sequentially, they recreate the shellcode which the attacker wants to execute. These pieces of code are called ROP gadgets, and consist of a set of arbitrary instructions followed by a final \textit{ret} instruction, which triggers the function exit and pops the value of ret. These gadgets may belong to any code in the process memory, usually selected between the code of the shared libraries (see figure \ref{fig:stack}) to which the process is linked. + +Finding ROP gadgets and writing ROP-compatible payloads manually is hard, thus multiple programs exist that automatically scan the system libraries and construct provide the gadgets given the shellcode to execute\cite{rop_prog_finder}. + +However, we will now illustrate how ROP works with an example. Suppose that an attacker has discovered a buffer overflow vulnerability, but the stack is marked as not executable. The attacker wants to execute the assembly code shown in snippet \ref{code:rop_ex}: + +\begin{lstlisting}[language=C, caption={Sample program to run using ROP.}, label={code:rop_ex}] +mov rdx, 10 +mov rax, [rsp] +\end{lstlisting} + +After finding the address of the ROP gadgets manually or using an automated tool, the attacker takes advantage of a buffer overflow (or, in our case, a direct write using eBPF's bpf\_probe\_write\_user()) to overwrite the vale of ret with the address of the first ROP gadget, and also additional data in the stack. Figure \ref{fig:rop_compund} shows how we can execute the original program using ROP: + +\begin{figure}[H] + \centering + \includegraphics[width=16cm]{ROPcompound.jpg} + \caption{Steps for executing code sample using ROP.} + \label{fig:rop_compund} +\end{figure} + +The steps described in the figure are the following: +\begin{enumerate} +\item First step shows the two gadgets located and their addresses, and the overwritten data in the stack. The function has already exited and, because ret was overwritten with the address of the first gadget, register rip now points to that location, and thus it is the next instruction to execute. Register rsp, in turn, now points to the bottom address of the current stack frame, which is right next to the old ret (see section \ref{subsection:stack} for stack frames functioning). +\item The first instruction of the gadget is executed, popping the value from the stack (which also moves register rsp, see stack push and pop operations in section \ref{subsection:stack}). As we can observe, the value "10" was specifically put in that position by the attacker, so that, according to the instruction to execute \lstinline{mov rdx, 10} \lstinline{}, we now have loaded that data into register rdx. +\item The return instruction is executed, which pops from the stack what is supposed to be the value of the saved rip, but in turn the attacker has placed the address of the next gadget there. Now, rip has jumped to the address of the second gadget. By continuing with this process, we can chain an infinite number of gadgets. +\item Finally, we repeated the same process as before, using a pop instruction to load a value from the stack. This illustrates that push and pop instructions, commonly used on most programs, are also possible to be using ROP. + +After this step, the return instruction will be executed. Note that, at this point, if the attacker wants to be stealthy and avoid crashing the program (since we overwrote the original data in the stack), the original stack must be restored, together with the value of the registers before the malicious code execution. We will see an example of a technique for reconstructing the original state during our explanation of the library injection in section \ref{TODO}. +\end{enumerate} + + + +\section{Networking fundamentals in Linux} +This section presents an overview on the most relevant aspects of the network system in Linux, which will be needed to tackle multiple of the techniques discussed during the design of the network capabilities of our rootkit. In particular, we will be focusing on the Ethernet, IP and TCP protocols. + +\subsection{An overview on the network layer} +Firstly, we will describe the data structure we will be dealing with in networking programs. This will be Ethernet frames containing TCP/IP packets. Figure \ref{fig:frame} shows the frame in its completeness: + +\begin{figure}[H] + \centering + \includegraphics[width=14cm]{frame.jpg} + \caption{Ethernet frame with TCP/IP packet.} + \label{fig:frame} +\end{figure} + +As we can observe, we can distinguish five different network layers in the frame. This division is made according to the OSI model\cite{network_layers}: +\begin{itemize} +\item Layer 1 corresponds to the physical layer, and it is processed by the NIC hardware, even before it reaches the XDP module (see figure \ref{fig:xdp_diag}). Therefore, this layer is discarded and completely invisible to the kernel. Note that it does not only include a header, but also a trailer (a Frame Check Sequence, a redundancy check included to check frame integrity). +\item Layer 2 is the data layer, it is in charge of transporting the frame via physical media, in our case an Ethernet connection. Most relevant fields are the MAC destination and source, used for performing physical addressing. +\item Layer 3 is the network layer, in charge of packet forwarding and routing. In our case, packets will be using the IP protocol. Most relevant fields are the source and destination IP, used to indicate the host that sent the packet and who is the receiver. +\item Layer 4 is the transport layer, in charge of providing end-to-end connection services to applications in a host. We will be focusing on TCP during our research. Relevant fields include the source and destination port, which indicate the ports involved in the communication on which the application on each host are listening and sending packets. +\item The last layer is the payload of the TCP packet, which contains, according to the OSI model, all layers belong to application data. +\end{itemize} + + +\subsection{Introduction to the TCP protocol} \label{subsection:tcp} +We will now focus our view on the transport layer, specifically on the TCP protocol, since it will be a major concern at the time of designing the network capabilities of our rootkit. + +Firstly, since TCP aims to offer a reliable and ordered packet transmission\cite{tcp_reliable}, it includes sequence numbers (see table \ref{fig:frame}) which mark the order in which they are transmitted. However, since the physical medium may corrupt or lose packets during the transmission, TCP must incorporate mechanisms for ensuring the order and delivery of all packets: +\begin{itemize} +\item Mechanism for opening and establishing a reliable connection between two parties. +\item Mechanism for ensuring that packets are retransmitted in case of an error during the connection. +\end{itemize} + +With respect to the establishment of a reliable connection, this is achieved via a 3-way handshake, in which certain TCP flags will be set in a series of interchanged packets (see in figure \ref{fig:frame} the field TCP flags). Most relevant TCP flags are described in table \ref{table:tcp_flags}. + +\begin{table}[H] +\begin{tabular}{|>{\centering\arraybackslash}p{4cm}|>{\centering\arraybackslash}p{10cm}|} +\hline +Flag & Purpose\\ +\hline +\hline +ACK & Acknowledges that a packet has been successfully received. In the acknowledgment number (see figure \ref{fig:frame}), it is stored the sequence number of the packet being acknowledged + 1. \\ +\hline +SYN & Used during the 3-way handshake, indicates request for establishing a connection.\\ +\hline +FIN & Used to request a connection termination.\\ +\hline +RST & Abruptly terminates the connection, usually sent when a host receives an unexpected or unrecognized packet.\\ +\hline +\end{tabular} +\caption{Relevant TCP flags and their purpose.} +\label{table:tcp_flags} +\end{table} + +Taking the above into account, figure \ref{fig:tcp_conn} shows a depiction of the 3-way handshake\cite{tcp_handshake}: +\begin{figure}[H] + \centering + \includegraphics[width=12cm]{tcp_conn.jpg} + \caption{TCP 3-way handshake.} + \label{fig:tcp_conn} +\end{figure} + +As we can observe in the figure, the hosts interchange a sequence of SYN, SYN+ACK, ACK packets, after which the communication starts. During this communication, the sender transmits packets with data (and no flags set), to which it expects an ACK packet acknowledging having received it. + +With respect to maintaining the integrity of the connection once it starts, TCP works using timers, as it is illustrated in figure \ref{fig:tcp_retransmission}: +\begin{enumerate} +\item A data packet with sequence number X is sent. The timer starts. +\item The destination host receives the packet and returns an ACK packet with acknowledgment number X+1. +\item The sender receives the ACK packet and stops the timer. If, for any reason, the ACK packet is not received before the timer ends, then the same packet is retransmitted. +\end{enumerate} + +\begin{figure}[H] + \centering + \includegraphics[width=12cm]{tcp_retransmission.jpg} + \caption{TCP packet retransmission on timeout.} + \label{fig:tcp_retransmission} +\end{figure} + +\section{ELF binaries} \label{section:elf} +This section details the Executable and Linkable Format (ELF)\cite{elf}, the format in which we find executable files (between other file types) in Linux systems. We will perform an analysis from a security standpoint, that is, mainly oriented to describe the most relevant sections and the permissions incorporated into them. We will also focus on several of these sections which will be relevant for designing our attack. + +After that, we will overview the security hardening techniques that have been historically incorporated into Linux to mitigate possible exploitation techniques when running ELF executables (such as the stack buffer overflow we explained in section \ref{subsection: buf_overflow}). During the design of our rootkit, we will attempt to bypass these techniques using multiple workarounds. + +\subsection{The ELF format and Lazy Binding} \label{subsection:elf_lazy_binding} +Linux supports multiple tools that enable a deep inspection of ELF binaries and its sections. Table \ref{table:elf_tools} shows the main tools we will use during this analysis: + +\begin{table}[H] +\begin{tabular}{|>{\centering\arraybackslash}p{3cm}|>{\centering\arraybackslash}p{10cm}|} +\hline +Tool & Purposes\\ +\hline +\hline +Readelf & Display information about ELF files\\ +\hline +Objdump & Display information about object files, mainly used for decompiling programs\\ +\hline +GDB & The GNU Project Debugger, allows for debugging programs during runtime\\ +\hline +GDB-peda & The Python Exploit Development Assistance for GDB, allows for multiple advanced operations that ease exploit development, such as showing register values, the stack state or memory information. It works as a plugin for GDB.\\ +\hline +\end{tabular} +\caption{Tools used for analysis of ELF programs.} +\label{table:elf_tools} +\end{table} + +Firstly, we will analyse the main sections we can find in an ELF executable. We will approach this study using a sample program that has been compiled using Clang/LLVM: TODO %TODO How do I explain which progrm it is? It is an example I developed, src/helpers/simple_timer.c. Shoud I write the code somewhere? Seems excesive + +The commands used and complete list of headers can be found in Annex \ref{annexsec:readelf_sec_headers}. The most relevant sections are described in table \ref{table:elf_sec_headers}: + +\begin{table}[H] +\begin{tabular}{|>{\centering\arraybackslash}p{1cm}|>{\centering\arraybackslash}p{9cm}|>{\centering\arraybackslash}p{2cm}|} +\hline +Tool & Purpose & Permissions\\ +\hline +\hline +.init & Contains instructions executed before the \textit{main} function of the program & Alloc, Executable\\ +\hline +.plt & Procedure Linkage Table (PLT), contains code stubs that use the addresses at .got.plt for jumping to position-independent code & Alloc, Executable\\ +\hline +.got & Global Offset Table (GOT), it contains addresses of global variables and functions once the linker resolves them at runtime & Alloc, Writable\\ +\hline +.got.plt & A subset of .got section separated from .got with some compilers, it contains only the target addresses of position-independent code once the linker loads them at runtime, used by .plt section. & Alloc, Writable\\ +\hline +.plt.got & Generated depending on compiler options, it is a PLT section which does not use lazy binding. & Alloc, Executable\\ +\hline +.text & Stores executable instructions. & Alloc, Executable\\ +\hline +.data & Contains initialized static and global variables. & Alloc, Writable\\ +\hline +.bss & Contains global and static variables which are unitialized or initialized to zero. & Alloc, Writable\\ +\hline +\end{tabular} +\caption{Tools used for analysis of ELF programs.} +\label{table:elf_sec_headers} +\end{table} + +As it can be observed in table \ref{table:elf_sec_headers}, we can find that all sections have the Alloc flag, meaning they will be loaded into process memory during runtime (see table \ref{TODO}, they have not been shown in previous diagrams for simpleness). + +Apart from those we have already discussed previously, we can find the GOT and PLT sections, whose purpose is to support Position Independent Code (PIC), that is, instructions whose address in virtual memory is not hardcoded by the compiler into the executable, but rather they are not known until resolved at runtime. This is usually the case of shared libraries, which can be loaded into virtual memory starting at any address\cite{plt_got_overlord}. + +Therefore, in order to call a function of a shared library, the dynamic linker follows a process called 'Lazy binding'\cite{plt_got_technovelty}: +\begin{enumerate} +\item From the .text section, instead of calling a direct absolute address as usual, a PLT stub (in the .plt section) is called. Snippet \ref{code:lazy_bind_1} shows a call to the function timerfd\_settime, implemented by the shared library glibc and thus using a PLT: +\begin{lstlisting}[language=C, caption={Call to PLT stub seen from objdump.}, label={code:lazy_bind_1}] +$ objdump -d simple_timer +4014cb: b9 00 00 00 00 mov $0x0,%ecx +4014d0: be 01 00 00 00 mov $0x1,%esi +4014d5: 89 c7 mov %eax,%edi +4014d7: e8 44 fc ff ff call 401120 +\end{lstlisting} + +\item In the PLT stub, the flow of execution jumps to an address which is stored in the GOT section, which is the absolute address of the function at glibc. This address must be written there by the dynamic linker but, according to lazy binding, the first time to call this function the linker has not calculated that address yet. + +\begin{figure}[H] + \centering + \includegraphics[width=15.5cm]{sch_gdb_plt.png} + \caption{PLT stub for timerfd\_settime, seen from gdb-peda.} + \label{fig:lazy_bind_2} +\end{figure} + +\begin{figure}[H] + \centering + \includegraphics[width=15.5cm]{sch_gdb_got_prev.png} + \caption{Inspecting address stored in GOT section before dynamic linking, seen from gdb-peda.} + \label{fig:lazy_bind_3} +\end{figure} + +\item As we can see in figures \ref{fig:lazy_bind_2} and \ref{fig:lazy_bind_3}, the PLT stub calls address 0x4010a0, which leads to a dynamic linking routine, which proceeds to write the address into the GOT section and jump back to the start of the PLT stub. This time, the memory address at GOT to which the PLT jumps is already loaded with the address to the function at the shared library, as shown by figure \ref{fig:lazy_bind_4}. + +\begin{figure}[H] + \centering + \includegraphics[width=15.5cm]{sch_gdb_got_after.png} + \caption{Inspecting address stored in GOT section after dynamic linking, seen from gdb-peda.} + \label{fig:lazy_bind_4} +\end{figure} + +\begin{figure}[H] + \centering + \includegraphics[width=15.5cm]{sch_glibc_func.png} + \caption{Glibc function to which PLT jumps using address stored at GOT, seen from gdb-peda.} + \label{fig:lazy_bind_5} +\end{figure} + +\end{enumerate} + +Therefore, in essence, when using lazy binding the dynamic linker will individually load into GOT the addresses of the functions at the shared libraries, during the first time they are called in the program. After that, the address will remain in the GOT section and will be used by the PLT for all subsequent calls. + +The reason lazy binding matters to us is because, as we will explain section \ref{subsection:got_attack}, the GOT section is actually writable from an eBPF program. This is because this section specifically must be writeable at runtime for the dynamic linker to store the address once they are resolved. Therefore, we would be able to modify the GOT section from eBPF, redirecting the address at which the PLT jumps, and thus controlling the flow of execution in the program. + +\subsection{Hardening ELF binaries} \label{subsection:hardening_elf} +During section \ref{section:attacks_stack}, we presented multiple of the classic attacks at the stack such as buffer overflow and ROP. However, as we mentioned, during the years multiple hardening measures have been introduced into modern compilers, which attempt to mitigate these and other techniques. We will now present them so that, during the design of our rootkit, we can attempt to bypass all of these. + +Table \ref{table:compilers} shows the compilers that we will be considering during this study. We will be exclusively looking at those security features that are included by default. + +\begin{table}[H] +\begin{tabular}{|>{\centering\arraybackslash}p{5cm}|>{\centering\arraybackslash}p{8cm}|} +\hline +Compiler & Security features by default\\ +\hline +\hline +Clang/LLVM 12.0.0 (2021) & Stack canaries, DEP/NX\\ +\hline +GCC 10.3.0 (2021) & Stack canaries, DEP/NX, PIE, Full RELRO\\ +\hline +\end{tabular} +\caption{Security features in C compilers used in the study.} +\label{table:compilers} +\end{table} + +\textbf{Stack canaries}\\ +Stack canaries are random data that is pushed into the stack before calling potentially vulnerable functions (such as strcpy()) that attempts to prevent attacks at the stack by ensuring that their value is the same before and after the execution of the called function. It is particularly useful at detecting buffer overflow attacks. + +If a stack canary is present and a buffer overflow happened, it would potentially overwrite the value of the canary, therefore alerting of the attack, in which case the processor halts the execution of the program. + +\textbf{DEP/NX}\\ +Data Execution Prevention, also known as No Execute, is the option of marking the stack as non executable. This prevents, as we explained in section \ref{subsection: buf_overflow}, the possibility of executing injected shellcode in the stack after modifying the value of the saved rip. + +The creation of advanced techniques like ROP is one reaction to this mitigation, that circumvents this protection. + +\textbf{ASLR}\\ +Address Space Layout Randomization is a technique that randomizes the position of memory sections in a process virtual memory, including the heap, stack and libraries, so that an attacker cannot rely on known addresses during exploitation (e.g: libraries are loaded at a different memory address each time the program is run, so ROP gadgets change their position)\cite{aslr_pie_intro}. + +In the context of a stack buffer overflow attack, the memory position of the stack is random, and therefore even if shellcode is injected into the stack by an attacker, the address at which it resides cannot be written into the saved value of rip in order to hijack the flow of execution. + +\textbf{PIE}\\ +Position Independent Executable is a mitigation introduced to reduce the ability of an attacker to locate symbols in virtual memory by randomizing the base address at which the program itself (including the .text section) is loaded. This base address determines an offset which is added to all memory addresses in the code, so that each instruction is located at an address + this offset. Therefore, all jumps are made using relative addresses \cite{aslr_pie_intro}. + +\textbf{RELRO}\\ +Relocation Read-Only is a hardening technique that mitigates the possibility of an attacker overwriting the GOT section, as we explained at section \ref{subsection:elf_lazy_binding}. In order to achieve the lazy binding process is substituted by the linker resolving all entries in the GOT section right after the beginning of the execution, and then marking the .got section as read-only. + +Two settings for RELRO are the most widespread, either Partial RELRO (which only marks sections of the .got section not related to the PLT as read-only, leaving .got.plt writeable) or Full RELRO (which marks the .got section as read-only completely). Binaries with only Partial RELRO are still non-secure, as the address at which the PLT section jumps can still be overwriten (including from eBPF, as we will explain) \cite{relro_redhat}. + +\textbf{Intel CET}\\ +Intel Control-flow Enforcement Technology is a hardening feature fully incorporated in Windows 10 systems \cite{cet_windows} and a work in progress in Linux\cite{cet_linux}. Its purpose is to defeat ROP attacks and other derivates (e.g: Jump-oriented programming, JOP), by adding a strict kernel-supported control of the return addresses and strong restrictions over jump and call instructions. + +In Linux, the kernel will support a hidden 'shadow stack' that will save the return addresses for each call. This prevents modifying the saved value of rip in the stack, since the kernel would realise that the flow of execution has been modified. We can also find that modern compilers (such as GCC 10.3.0) already generate Intel CET-related instructions such as \textit{endbr64}, whose purpose is to be placed at the start of functions, marking that as the only address to which an indirect jump can land (otherwise, jumps will be rejected if not landing at \textit{endbr64}). + +As mentioned, we will not consider this feature since it is not active in the Linux kernel. + diff --git a/docs/chapters/chapter3.tex b/docs/chapters/chapter3.tex new file mode 100644 index 0000000..8214f8f --- /dev/null +++ b/docs/chapters/chapter3.tex @@ -0,0 +1,373 @@ +\chapter{Analysis of offensive capabilities} \label{chapter:analysis_offensive_capabilities} +In the previous chapter, we detailed which functionalities eBPF offers and studied its underlying architecture. As with every technology, a prior deep understanding is fundamental for discussing its security implications. + +Therefore, given the previous background, this chapter is dedicated to an analysis in detail of the security implications of a malicious use of eBPF. For this, we will firstly explore the security features incorporated in the eBPF system. Then, we will identify the fundamental pillars onto which malware can build their functionality. As we mentioned during the project goals, these main topics of research will be the following: +\begin{itemize} +\item Analysing eBPF's possibilities when hooking system calls and kernel functions. +\item Learning eBPF's potential to read/write arbitrary memory. +\item Exploring networking capabilities with eBPF packet filters. +\end{itemize} + + +%TODO if this is finally not included, change the intro +Finally, we will study in detail some of the malicious applications that previous researchers have proposed to take advantage of these capabilities of eBPF. In the next chapter, we will proceed to elaborate on these ideas, find new purposes and design our own rootkit. + + +\section{eBPF maps security} +In table \ref{table:ebpf_caps_current}, we observed that only programs with CAP\_SYS\_ADMIN are allowed to iterate over eBPF maps. The reason why this is restricted to privileged programs is because it is functionality that is a potential security vulnerability, which we will now proceed to analyse. + +In subsection \ref{subsection:ebpf_maps} we mentioned that eBPF maps are opened by specifying an ID (which works similarly to the typical file descriptors), while in table \ref{table:ebpf_map_types} we showed that, for performing operations over eBPF maps using the bpf() syscall, the map ID must be specified too. + +Map IDs are known by a program after creating the eBPF map, however, a program can also explore all the available maps in the system by using the BPF\_MAP\_GET\_NEXT\_ID operation in the bpf() syscall, which allows for iterating through a complete hidden list of all the maps created. This means that privileged programs can find and have read and write access to any eBPF map used by any program in the system. + +Therefore, a malicious privileged eBPF program can access and modify other programs' maps, which can lead to: +\begin{itemize} +\item Modify data used for the program operation. This is the case for maps which mainly store data structures, such as BPF\_MAP\_TYPE\_HASH. +\item Modify the program control flow, altering the instructions executed by an eBPF program. This can be achieved if a program is using the bpf\_tail\_call() helper (introduced in table \ref{table:ebpf_helpers}) which is taking data from a map storing eBPF programs (BPF\_MAP\_TYPE\_PROG\_ARRAY, introduced in table \ref{table:ebpf_map_types}). +\end{itemize} + + +\section{Abusing tracing programs} +eBPF tracing programs (kprobes, uprobes and tracepoints) are hooked to specific points in the kernel or in the user space, and call probe functions once the flow of execution reaches the instruction to which they are attached. This section details the main security concerns regarding this type of programs. + +\subsection{Access to function arguments} +As we saw in section \ref{section:ebpf_prog_types}, tracing programs receive as a parameter those arguments with which the hooked function originally was called. These parameters are read-only and thus, in principle, they cannot be modified inside the tracing program (we will show this is not entirely true in section \ref{section:mem_corruption}). The next code snippets show the format in which parameters are received when using libbpf (Note that libbpf also includes some macros that offer an alternative format, but the parameters are the same). + + +\begin{lstlisting}[language=C, caption={Probe function for a kprobe on the kernel function vfs\_write.}, label={code:format_kprobe}] +SEC("kprobe/vfs_write") +int kprobe_vfs_write(struct pt_regs* ctx){ +\end{lstlisting} + +\begin{lstlisting}[language=C, caption={Probe function for an uprobe, execute\_command is defined from user space.}, label={code:format_uprobe}] +SEC("uprobe/execute_command") +int uprobe_execute_command(struct pt_regs *ctx){ +\end{lstlisting} + +\begin{lstlisting}[language=C, caption={Probe function for a tracepoint on the start of the syscall sys\_read.}, label={code:format_tracepoint}] +SEC("tp/syscalls/sys_enter_read") +int tp_sys_enter_read(struct sys_read_enter_ctx *ctx) { +\end{lstlisting} + +In code snippets \ref{code:format_kprobe} and \ref{code:format_uprobe} we can identify that the parameters are passed to kprobe and uprobe programs as a pointer to a \textit{struct pt\_regs*}. This struct contains as many attributes as registers exist in the system architecture, in our case x86\_64. Therefore, on each probe function, we will receive the state of the registers at the original hooked function. This explains the format of the \textit{struct pt\_regs}, shown in code snippet \ref{code:format_ptregs}: + +\begin{lstlisting}[language=C, caption={Format of struct pt\_regs.}, label={code:format_ptregs}] +struct pt_regs { + long unsigned int r15; + long unsigned int r14; + long unsigned int r13; + long unsigned int r12; + long unsigned int bp; + long unsigned int bx; + long unsigned int r11; + long unsigned int r10; + long unsigned int r9; + long unsigned int r8; + long unsigned int ax; + long unsigned int cx; + long unsigned int dx; + long unsigned int si; + long unsigned int di; + long unsigned int orig_ax; + long unsigned int ip; + long unsigned int cs; + long unsigned int flags; + long unsigned int sp; + long unsigned int ss; +}; +\end{lstlisting} + +By observing the value of the registers, we are able to extract the parameters of the original hooked function. This can be done by using the System V AMD64 ABI\cite{8664_params_abi}, the calling convention used in Linux. Depending on whether we are in the kernel or in user space, the registers used to store the values of the function arguments are different. Table \ref{table:systemv_abi} summarizes these two interfaces. + +\begin{table}[H] +\begin{tabular}{|>{\centering\arraybackslash}p{2cm}|>{\centering\arraybackslash}p{3cm}|} +\hline +\multicolumn{2}{|c|}{User interface}\\ +\hline +Register & Purpose\\ +\hline +\hline +rdi & 1st argument\\ +\hline +rsi & 2nd argument\\ +\hline +rdx & 3rd argument\\ +\hline +rcx & 4th argument\\ +\hline +r8 & 5th argument\\ +\hline +r9 & 6th argument\\ +\hline +rax & Return value\\ +\hline +\end{tabular} +\quad +\begin{tabular}{|>{\centering\arraybackslash}p{2cm}|>{\centering\arraybackslash}p{3cm}|} +\hline +\multicolumn{2}{|c|}{Kernel interface}\\ +\hline +Register & Purpose\\ +\hline +\hline +rdi & 1st argument\\ +\hline +rsi & 2nd argument\\ +\hline +rdx & 3rd argument\\ +\hline +r10 & 4th argument\\ +\hline +r8 & 5th argument\\ +\hline +r9 & 6th argument\\ +\hline +rax & Return value\\ +\hline +\end{tabular} +\caption{Argument passing convention of registers for function calls in user and kernel space respectively.} +\label{table:systemv_abi} +\end{table} + +In the case of tracepoints, we can see in code snippet \ref{code:format_tracepoint} that it receives a \textit{struct sys\_read\_enter\_ctx*}. This struct must be manually defined, as explained in \ref{subsection:tracepoints}, by looking at the file \textit{/sys/kernel/debug/tracing/events/syscalls/sys\_enter\_read/format}. Code snippet \ref{code:sys_enter_read_tp} shows the format of the struct. + +\begin{lstlisting}[language=C, caption={Format for parameters in sys\_enter\_read specified at the format file.}, label={code:sys_enter_read_tp_format}] +field:unsigned short common_type; offset:0; size:2; signed:0; +field:unsigned char common_flags; offset:2; size:1; signed:0; +field:unsigned char common_preempt_count; offset:3; size:1; signed:0; +field:int common_pid; offset:4; size:4; signed:1; +field:int __syscall_nr; offset:8; size:4; signed:1; +field:unsigned int fd; offset:16; size:8; signed:0; +field:char * buf; offset:24; size:8; signed:0; +field:size_t count; offset:32; size:8; signed:0; +\end{lstlisting} + +\begin{lstlisting}[language=C, caption={Format of custom struct sys\_read\_enter\_ctx.}, label={code:sys_enter_read_tp}] +struct sys_read_enter_ctx { + unsigned long long pt_regs; + int __syscall_nr; + unsigned int padding; + unsigned long fd; + char* buf; + size_t count; +}; +\end{lstlisting} + +As we can observe, we are given a set of attributes which include the parameters with which the syscall was called. Moreover, we can still obtain an address pointing to another \textit{struct pt\_regs}, as in kprobes and uprobes, by combining the first four fields and considering it as a 32-bit long address. This means we will still be able to extract the value of the rest of the registers too. + +It must be noted that, in syscalls, in addition to use the kernel parameter passing convention specified in table \ref{table:systemv_abi}, the number specifying the syscall must be passed in register rax too. + +On a final note, as we mentioned in section \ref{section:ebpf_prog_types}, there exist differences in the parameters received in probe functions depending on the two variations of tracing programs. Therefore: +\begin{itemize} +\item kprobe, uprobe and \textit{enter} tracepoints will receive the full parameters as we specified before, but not the return value of the function (since it is not executed yet). +\item kretprobes, uretprobes and \textit{exit} tracepoints will still receive the \textit{struct pt\_regs}, but without any of the parameters and with only the return value of the function. +\end{itemize} + +Taking into account all the previous, the fact that tracing programs have read-only access to function arguments can be considered an useful and needed feature for tracing applications, but malicious eBPF can use this for purposes such as: +\begin{itemize} +\item Gather kernel and user data passed to a function as a parameter. In many cases this information can be potentially interesting for an attacker, such as passwords. +\item Store in eBPF maps information about system activities, to be used by other malicious eBPF programs. +\end{itemize} + +Usually, since many function arguments are pointers to user or kernel addresses (such as buffers where a string or a struct with data is located), eBPF tracing programs can use two eBPF helpers that enable to read large byte arrays from both kernel and user space: +\begin{itemize} +\item bpf\_probe\_read\_user() +\item bpf\_probe\_read\_kernel() +\end{itemize} + +These helpers, previously introduced in table \ref{table:ebpf_helpers}, enable to read an arbitrary number of bytes from an user or kernel address respectively, allowing us to extract the information pointed by the parameters received by eBPF programs. + +\subsection{Reading memory out of bounds} \label{subsection:out_read_bounds} +As we introduced in the previous subsection, the bpf\_probe\_read\_user() and bpf\_probe\_read\_kernel() helpers can be used to access memory of pointers received as parameters in the hooked functions. + +However, although in general the eBPF verifier attempts to reject illegal memory accesses, it does not prevent a malicious program from passing an arbitrary memory address (in kernel or user space) to the above helpers. This means that an eBPF program can potentially read any address in user or kernel space, (as long as it is marked as readable in the corresponding memory pages). Furthermore, an attacker can locate specific data structures and memory sections by taking the function parameter as a reference point in memory. + +A particularly relevant case (which we will later use for our rootkit) involves accessing user memory via the parameters of tracepoints attached at system calls. Provided the nature of syscalls, whose purpose is to communicate user and kernel space, all parameters received will belong to the user space, and therefore any pointer passed will be an address in user memory. This enables an eBPF program to get a foothold into the virtual address space of the process calling the syscall, which it can proceed to scan looking for data or specific instructions. This technique will be further elaborated in section \ref{subsection_bpf_probe_write_apps}. + +\subsection{Overriding function return values} +A potentially dangerous functionality in eBPF tracing programs is the ability to modify the return value of kernel functions\cite{ebpf_friends_p15}\cite{ebpf_override_return}. This can be done via the eBPF helper bpf\_override\_return, and it works exclusively from kretprobes. + +Apart from only working on kretprobes, additional restrictions are applied to this helper. It will only work if the kernel was compiled with the CONFIG\_BPF\_KPROBE\_OVERRIDE flag, and only if the kretprobe is attached to a function to which, during the kernel development, the macro ALLOW\_ERROR\_INJECTION() has been indicated. Currently, only a small selection of functions include this macro, but most system calls can be found to implement it. The following code snippets show how a system call like sys\_open is defined in kernel v5.11: + +\begin{lstlisting}[language=C, caption={Definition of the syscall sys\_open in the kernel \cite{code_kernel_open}}, label={code:override_return_1}] +SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) +{ + if (force_o_largefile()) + flags |= O_LARGEFILE; + return do_sys_open(AT_FDCWD, filename, flags, mode); +} +\end{lstlisting} + +\begin{lstlisting}[language=C, caption={Definition of the macro for creating syscalls, containing the error injection macro. Only relevant instructions included, complete macro can be found in the kernel \cite{code_kernel_syscall}}, label={code:override_return_2}] +#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) +#ifndef __SYSCALL_DEFINEx +#define __SYSCALL_DEFINEx(x, name, ...)\ + [...] + ALLOW_ERROR_INJECTION(sys##name, ERRNO);\ + [...] +\end{lstlisting} + + +By looking at snippets \ref{code:override_return_1} and \ref{code:override_return_2}, we can observe that the system call sys\_open involves the inclusion of the ALLOW\_ERROR\_INJECTION macro. Therefore, any kretprobe attached to a system call function will be able to modify its return value. + +In order to be able to modify the return value of functions, the aforementioned eBPF helper makes use of the fault injection framework of the Linux kernel\cite{fault_injection}, which was created before eBPF itself, and whose original purpose is to allow for generating errors in kernel programs for debugging purposes. + +Taking the previous information into account, we can find that a malicious eBPF program, by tampering with the kernel-user space interface which are system calls, can mislead user programs, which trust the output of kernel code. This can lead to: +\begin{itemize} +\item A program believes a system call exited with an error, while in reality the kernel completed the operation with success, or viceversa. For instance, the result of a call to sys\_open can mislead a user program into thinking that a file does not exist. +\item A program receives incorrect data on purpose. For instance, a buffer may look empty or of a reduced size upon a sys\_read call, while in reality more data is available to be read. +\end{itemize} + +\subsection{Sending signals to user programs} +Another eBPF helper that is subject to malicious purposes is bpf\_send\_signal. This helper enables to send an arbitrary signal to the thread of the process running a hooked function. + +Therefore, this helper can be used to forcefully terminate running user processes, by sending the SIGKILL signal. In this way, combined with the observability into the parameters received at a function call, malicious eBPF can kill and deactivate processes to favour its malicious purposes. + +\subsection{Takeaways} \label{subsection:tracing_attacks_conclusion} +As a summary, a malicious eBPF program loaded and attached as a tracing program undermines the existing trust between user programs and the kernel space. + +Its ability to access sensitive data in function parameters and reading arbitrary memory can lead to gathering extensive information on the running processes of a system, whilst the malicious use of eBPF helpers enables the modification of the data passed to the user space from the kernel, and the control over which programs are allowed to be running on the system. + +\section{Memory corruption} \label{section:mem_corruption} +In the previous section we described how tracing programs can read user memory out of the bounds of function parameters via the helpers bpf\_probe\_read\_user() and bpf\_probe\_read\_kernel(). In this section, we will analyse another eBPF helper can be found to be the heart of malicious programs. + +Privileged eBPF programs (or those with at least CAP\_BPF + CAP\_PERFMON capabilities) have the potential to use an experimental (it is labelled as so \cite{ebpf_helpers}) helper called bpf\_probe\_write\_user(). This helper enables to write into user memory from within an eBPF program. + +However, this helper has certain limitations that restrict its use. We will now proceed to review some background into how user memory works and, afterwards, we will analyse the restrictions and possible uses of this eBPF helper in the context of malicious applications. + + +\subsection{Attacks and limitations of bpf\_probe\_write\_user()} \label{subsection:bpf_probe_write_apps} +Provided the background into memory architecture and the stack operation, we will now study the offensive capabilities of the bpf\_probe\_write\_user() helper and which restrictions are imposed into its use by eBPF programs. + +The bpf\_probe\_write\_user() helper, when used from a tracing eBPF program, can write into any memory address in the user space of the process responsible from calling the hooked function. However, the write operation fails has some restrictions: +\begin{itemize} +\item{The operation fails if the memory space pointed by the address is marked as non-writeable by the user space process. For instance, if we try to write into the .text section, the helpers fails because this section is only marked as readable and executable (for protection reasons).} Therefore, the process must indicate a writeable flag in the memory section for the helper to succeed. +\item{The operation fails if the memory page is served with a minor or major page fault. As we saw in section \ref{subsection:ebpf_verifier}, eBPF programs are restricted from executing any sleeping or blocking operations, to prevent hanging the kernel. Therefore, since during a page fault the operating system needs to block the execution and write into the page table or retrieve data from the secondary disk, bpf\_probe\_write\_user() is defined as a non-faulting helper\cite{write_helper_non_fault}, meaning that instead of issuing a page fault for accessing data, it will just return and fail.} +\item{Each time the helper is called, an alert message is written into the kernel logs, alerting that a potentially dangerous eBPF program is making use of the helper. Note that this message appears when the eBPF program is attached, and not each time the helper is called. This will be particularly relevant since we will be able to bypass this alert by taking advantage of this.} +\end{itemize} + +Although we will not be able to modify kernel memory or the instructions of a program, this eBPF helper opens a range of possible attacks: +\begin{itemize} +\item Modify any of the arguments with which a system call is called (either with a tracepoint or a kprobe). Therefore, a malicious program can hijack any call to the kernel with its own arguments. +\item Modify user-provided arguments in kernel functions. When reading kernel code, we can find that data provided by the user is marked with the keyword \textit{\_\_user}. For instance, an internal kernel function in a nested call of the system call sys\_read receives an user buffer: +\begin{lstlisting}[language=C, caption={Definition of kernel function vfs\_read. \cite{code_vfs_read}}, label={code:vfs_read}] +ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) +\end{lstlisting} +Then, if we attach a kprobe to vfs\_read, we would be able to modify the value of the buffer. +\item Modify process memory by taking function parameters as a reference and scanning the stack. This technique, first introduced in section \ref{subsection:out_read_bounds} when we mentioned that tracing programs can read any user memory location with the bpf\_probe\_read\_user() helper, and which was publicly first used by Jeff Dileo at his talk in DEFCON 27\cite{evil_ebpf_p6974}, consists of: +\begin{enumerate} +\item Take an user-passed parameter received on a tracing program. The parameter must be a pointer to a memory location (such as a pointer to a buffer), so that we can use that memory address as the reference point in user space. According to the x86\_64 documentation, this parameter will be stored in the stack\cite{8664_params_abi_p1922}, so we will receive an stack address. +\item Locate the target data which we aim to write. There are two main methods for this: +\begin{itemize} + \item Sequentially read the stack, using bpf\_probe\_read\_user(), until we locate the bytes we are looking for. This requires knowing which data we want to overwrite. + \item By previously reverse engineering the user program, we can calculate the offset at which an specific data section will be stored in virtual memory with respect to the reference address we received as a parameter. +\end{itemize} +\item Overwrite the memory buffer using bpf\_probe\_write\_user(). +\end{enumerate} +\end{itemize} + +Figure \ref{fig:stack_scan_write_tech} illustrates a high-level overview of the stack scanning technique previously described: +%TODO i just noticed I included SFP outside the current stack frame, correct it here and everywhere +\begin{figure}[H] + \centering + \includegraphics[width=16cm]{stack_scan_write_tech.jpg} + \caption{Overview of stack scanning and writing technique.} + \label{fig:stack_scan_write_tech} +\end{figure} + +The above figure shows process memory executing a program similar to the following: +\begin{lstlisting}[language=C, caption={Sample program being executed on figure \ref{fig:stack_scan_write_tech}.}, label={code:stack_scan_write_tech}] +void func(char* a, char* b, char* c){ + int fd = open("FILE", 0); + write(fd, a, 1); +} + +int main(){ + char a[] = "AAA"; + char b[] = "BBB"; + char c[] = "CCC"; + func(a, b, c); +} +\end{lstlisting} + +In the figure, we can clearly observe how the technique is used to overwrite an specific buffer. The attacker goal is to overwrite buffer \textit{c} with some other bytes, but the kprobe program only has direct access to buffer \textit{a}: +\begin{enumerate} +\item By reverse engineering the program (we will see how this process works in section \ref{TODO}) we notice that buffer \textit{c} is stored 8 bytes lower on the stack than buffer \textit{a}. +\item When register rip points to the write() instruction, the processor executes the instruction and a system call is issued to sys\_write(). +\item The kprobe eBPF program hooked to the syscall hijacks the program execution. Since it has access to the memory address of buffer \textit{a} and it knows the relative position of buffer \textit{c}, it writes to that location whatever it wants (e.g.: "DDD") with the bpf\_probe\_write\_user() helper. +\item The eBPF program ends and the control flow goes back to the system call. It ends its execution successfully, and returns a value to the user space. The result of the program is that 1 byte has been written into file "FILE", and that buffer \textit{c} now contains "DDD". +\end{enumerate} + +\subsection{Takeaways} +As a summary, the bpf\_probe\_write\_user() helper is one of the main attack vectors for malicious eBPF programs. Although it does contain some restrictions, its ability to overwrite any user parameter enables it to, in practice, execute arbitrary code by hijacking that of others. When it is combined with tracing programs' ability to read memory out of bounds, it unlocks a wide range of attacks, since any writeable section of the process memory is a possible target. + +Therefore, if on the conclusion of section \ref{subsection:tracing_attacks_conclusion} we discussed that the ability to change the return value of kernel functions and kill processes hinders the trust between the user and kernel space (since what the kernel returns may not be a correct result), then the ability to directly overwrite process data is a complete disrupt of trust in any of the data in the user space itself, since it is subject to the control of a malicious eBPF program. + +Moreover, in the next sections we will discuss how we can create advanced attacks on the basis of the background and techniques previously discussed. We will research further into which sections of a process memory are writeable and whether they can lead to new attack vectors. + + +\section{Abusing networking programs}\label{section:abusing_networking} +The final main piece of a malicious eBPF program comes from taking advantage of the networking capabilities of TC and XDP programs. As we mentioned during sections \ref{subsection:xdp} and \ref{subsection:tc}, these type of programs have access to network traffic: +\begin{itemize} +\item Traffic Control programs can be placed either on egress or ingress traffic, and receive a struct \textit{sk\_buff}, containing the packet bytes and meta data that helps operating on it. +\item External Data Path programs can only be attached to ingress traffic, but in turn they receive the packet before any kernel processing (as a struct \textit{xdp\_md}) being able to access the raw data directly. +\end{itemize} + +Networking eBPF programs not only have read access to the network packets, but also write access: +\begin{itemize} +\item XDP programs can directly modify the raw packet via memcpy() operations. They can also increment or reduce the size of the packet at any of its ends (adding bytes before the head or after the packet tail). This is done via the multiple helpers previously presented on table \ref{table:xdp_helpers}. +\item TC programs can also modify the packet via the helpers presented on table \ref{table:tc_helpers}. The packet can be expanded or reduced via these eBPF helpers too. +\end{itemize} + +Apart from write access to the packet, the other critical feature of networking programs is their ability to drop packets. As we presented in tables \ref{table:xdp_actions_av} and \ref{table:tc_actions}, this can be achieved by returning specific values. + + +\subsection{Attacks and limitations of networking programs} +Based on the previous background, we will now proceed to explore which limitations exist on which actions a network eBPF program can perform: +\begin{itemize} +\item Read and write access to the packet is heavily controlled by the eBPF verifier. It is not possible to read or write data out of bounds. Extreme care must also be taken before attempting to read any data inside the packet, since the verifier first requires making lots of checks beforehand. For any access to take place, the program must first classify the packet according to the network protocol it belongs, and later check that every header of every layer is well defined (e.g: Ethernet, IP and TCP). Only after that, the headers can be modified. + +If the program also wants to modify the packet payload, then it must be checked to be between the bounds of the packet and well defined according to the packet headers(using fields IHL, packet length and data offset, in figure \ref{fig:frame}). Also, after using any of the helpers that enlarge or reduce the size of the packet, all check operations must be repeated again before any subsequent operation. + +Finally, note that after any modification in the packet, some network protocols (such as IP and TCP) require to recalculate their checksum fields. + +\item XDP and TC programs are not able to create packets, they can only operate over existing traffic. + +\item If an XDP program modifies an incoming packet, the kernel will not know about the original data, but if an egress TC program modifies a packet being sent, the kernel will be able to notice the modification. +\end{itemize} + +Having the previous restrictions in mind, we can find multiple possible malicious uses of an XDP/TC program: +\begin{itemize} +\item \textbf{Spy all network connections} in the system. An XDP or TC ingress program can read any packet from any interface, therefore achieving a comprehensive view on which are the running communications and opened ports (even if protocols with encryption are being used) and gathering transmitted data (if the connection is also in plaintext). +\item \textbf{Hide arbitrary traffic} from the host. If an XDP program drops a packet, the kernel will not be able to know any packet was received in the first place. This can be used to hide malicious incoming traffic. However, as we will mention in section{TODO}, malicious traffic may still be detected by other external devices, such as network-wide firewalls. +\item \textbf{Modify incoming traffic} with XDP programs. Every packet can be modified (as we mentioned at the beginning of section \ref{section:abusing_networking}), and any modification will be unnoticeable to the kernel, meaning that we will have complete, invisible control over the packets received by the kernel. +\item \textbf{Modify outgoing traffic} with TC egress programs. Since every packet can be modified at will, we will therefore have complete control over any packet sent by the host. This can be used to enable a malicious program to communicate over the network and exfiltrate data, since even if we cannot create a new connection from eBPF, we can still modify existing packets, writing any payload and headers on it (thus being able to, for instance, change the destination of the packet). + +Notice, however, that these modifications are not transparent to the kernel as with XDP, and thus an internal firewall may detect our malicious traffic. +\end{itemize} + +Although we mention the possibility of modifying outgoing traffic as an alternative to the impossibility of sending new packets from eBPF, there exists a major disadvantage by doing this, since the original packet of the application will be lost, and we will thus be disrupting the normal functioning of the system (which in a rootkit is unacceptable, as we mentioned in section \ref{section:motivation}, stealth is a priority). + +There exists, however, a simple way of duplicating a packet so that the original packet is not lost but we can still send our overwritten packet. This technique, first presented by Guillaume Fournier and Sylvain Afchainthe in their DEFCON talk, consists of taking advantage of TCP retransmissions we described on section \ref{subsection:tcp}. Figure \ref{fig:tcp_exfiltrate_retrans} shows this process: + +\begin{figure}[H] + \centering + \includegraphics[width=15cm]{tcp_exfiltrate_retrans.jpg} + \caption{Technique to duplicate a packet for exfiltrating data.} + \label{fig:tcp_exfiltrate_retrans} +\end{figure} + +In the figure, we can observe a host infected by a malicious TC egress program. An user space application at some point needs to send a packet (in this case a simple ping), and the TC program will overwrite it (in this case, it writes a password which it has been able to find, and substitutes the destination IP address with that of a listening attacker. +After the timer runs out, the TCP protocol itself will retransmit the same packet as previously and thus the original data is delivered too. + +Using this technique, we will be able to send our own packets every time an application sends outgoing traffic. And, unless the network is being monitored, this attack will go unnoticed, provided that the delay of the original packet is similar to that when a single packet lost. + +\subsection{Takeaways} +As a summary, networking eBPF programs offer complete control over incoming and outgoing traffic. If tracing programs and memory corruption techniques served to disrupt the trust in the execution of both any user or kernel program, then a malicious networking program has the potential to do the same with any communication, since any packet is under the control of eBPF. + +Ultimately, the capabilities discussed in this section unlock complete freedom for the design of malicious programs. As we will explain in the next chapter, one particularly relevant type of application can be built: +\begin{itemize} +\item A \textbf{backdoor}, a stealthy program which listens on the network interface and waits for secret instructions from a remote attacker-controlled client program. This backdoor can have \textbf{Command and Control (C2)} capabilities, meaning that it can process commands sent by the attacker and received at the backdoor, executing a series of actions corresponding to the request received, and (when needed) answering the attacker with the result of the command. +\end{itemize} + +%TODO maybe a conclusion for this section? diff --git a/docs/chapters/chapter4.tex b/docs/chapters/chapter4.tex new file mode 100644 index 0000000..2ec0ad3 --- /dev/null +++ b/docs/chapters/chapter4.tex @@ -0,0 +1,135 @@ +\chapter{Design of a malicious eBPF rootkit} +In the previous chapter, we discussed the functionality of eBPF programs from a security standpoint, detailing which helpers and program types are particularly useful for developing malicious programs, and analysing some techniques (stack scanning, overwriting packets together with TCP retransmissions) which helps us circumvent some of the restrictions of eBPF and find new attack vectors. + +Taking as a basis these capabilities, this chapter is now dedicated to a comprehensive description of the advanced techniques and functionalities implemented in our eBPF rootkit, which show how these capabilities can lead to the creation of a real malicious application. As we mentioned during the project objectives, our goals for our rootkit include the following: +\begin{itemize} +\item Hijacking the execution of user programs while they are running, injecting libraries and executing malicious code, without impacting their normal execution. +\item Featuring a command-and-control module powered by a network backdoor, which can be operated from a remote client. This backdoor should be controlled with stealth in mind, featuring similar mechanisms to those present in rootkits found in the wild. +\item Tampering with user data at system calls, resulting in running malware-like programs and for other malicious purposes. +\item Achieving stealth, hiding rootkit-related files from the user. +\item Achieving rootkit persistence, the rootkit should run after a complete system reboot. + +\end{itemize} +%TODO maybe this is the place to mention that, on top of those, explaining some of the DEFCON techniques will be done too. Im particular interested on the one of hiding the kernel log message of bpf_probe_write_user and on ROP. + +We will be exploring each functionality individually, presenting the necessary background on each of them, and offering a final comprehensive view on how each of the systems work. + +\section{Library injection attacks} +In this section, we will discuss how to hijack an user process running in the system so that it executes arbitrary code instructed from an eBPF program. For this, we will be injecting a library which will be executed by taking advantage of the fact that the GOT section in ELFs is flagged as writable (as we introduced in section \ref{subsection:elf_lazy_binding} and using the stack scanning technique covered in section \ref{subsection:bpf_probe_write_apps}. This injection will be stealthy (it must not crash the process), and will be able to hijack privileged programs such as systemd, so that the code is executed as root. + +We will also research how to circumvent the protections which modern compilers have set in order to prevent similar attacks (when performed without eBPF). + +This technique has some advantages and disadvantages to the one described by Jeff Dileo at DEFCON 27\cite{evil_ebpf_p6974}, which we will briefly cover before presenting ours. Both techniques will be later compared in section \ref{TODO EVALUATION}. + + +\subsection{ROP with eBPF} \label{subsection:rop_ebpf} +In 2019, Jeff Dileo presented in DEFCON 27 the first technique to achieve arbitrary code execution using eBPF\cite{evil_ebpf_p6974}. For this, he used the ROP technique we described in section \ref{subsection:rop} to inject malicious code into a process. We will present an overview on his technique, in order to later compare it to the one we will develop for our rootkit, and find advantages and disadvantages. Note that this is a summary and some aspects have been simplified, however we will go in full detail during the explanation of our own technique. + +\begin{figure}[H] + \centering + \includegraphics[width=15cm]{rop_evil_ebpf_1.jpg} + \caption{Initial setup for the ROP with eBPF technique.} + \label{fig:rop_evil_ebpf_1} +\end{figure} + +Figure \ref{fig:rop_evil_ebpf_1} shows an overview on the process memory and the eBPF programs loaded. For this injection, we will use the stack scanning technique (section \ref{subsection:bpf_probe_write_apps}) using the arguments of a system call whose arguments are passed using the stack (sys\_timerfd\_settime, which receives two structs utmr and otmr). Therefore, a kprobe is attached to the system call, so that it can start to scan for the return address of the system call, which we know is the original value of register rip which was pushed into the stack (ret). + +%TODO Maybe the glibc bit, because of its importance, is better somewhere else +An additional aspect must be introduced now (we will cover it more in detail in section \ref{TODO}): system calls are not directly called by the instructions in the .text section, but rather user programs in C make use of the C Standard Library to delegate the actual syscall, which in this case is the GNU Standard Library (glibc)\cite{glibc}. Therefore, a program calls a function in glibc (in this case timerfd\_settime) in which the syscall is performed, and the kernel executes it. + +This means that, during the stack scanning technique, if we start from struct utmr and scan forward in the stack, what we will find in ret is the return address of the function of glibc, and not directly that of the syscall to the kernel. Therefore, our goal is, for every data in the stack while scanning forward, check whether it is the real return address of glibc. For an address to be the real return address, we will follow the next steps: +\begin{enumerate} +\item Take an address from the stack. If that is the return address (the old rip), then the instruction that called the function in glibc must be the previous instruction (rip - 1). +\item We now have a \textit{call} instruction, that directs us to the function at glibc. We check in the instruction to which address it moves the flow of execution, that is the address of timerfd\_settime in glibc. +\item We scan forward, inside timerfd\_settime of glibc, until we find a \textit{syscall} instruction. That is the point where the flow of execution moves to the kernel, so we have checked that the return address we found in the stack truly is the one we are looking for. +\end{enumerate} + +Now that we have found the return address, we save a backup of the stack (to recover the original data later) and we proceed to overwrite the stack using bpf\_probe\_write\_user(), setting it for the ROP technique. For this, some gadgets (G0, G1 ... GN) have been previously discovered in the glibc library. Figure \ref{fig:rop_evil_ebpf_2} shows process memory after this overwrite: + +\begin{figure}[H] + \centering + \includegraphics[width=15cm]{rop_evil_ebpf_2.jpg} + \caption{Process memory after syscall exits and ROP code overwrites the stack.} + \label{fig:rop_evil_ebpf_2} +\end{figure} + +As we can see in the figure, the function has already exited, and ret has been popped into register rip. As we explained in section \ref{subsection:rop}, the attacker places in that position the address of the first ROP gadget. After that, the attacker can execute arbitrary code. Jeff Dileo, for instance, loads a malicious library into the process (we will do the same and explain this process in the next sections). + +Once the attacker has finished executing the injected code, the stack must be restored to the original position so that the program can continue without crashing. A simplified view of this procedure consists of attaching a kprobe to a random system call (in this case, sys\_close()) so that, from the ROP code, we can alert the eBPF program when it is time to remove the ROP code and restore the original stack. Figure \ref{fig:rop_evil_ebpf_3} shows this final step: + +\begin{figure}[H] + \centering + \includegraphics[width=15cm]{rop_evil_ebpf_3.jpg} + \caption{Stack data is restored and program continues its execution.} + \label{fig:rop_evil_ebpf_3} +\end{figure} + +As we can see, eBPF writes back the original stack and thus the execution can continue. Note that, in practice, some final gadgets must also be executed in order to restore the state of rip and rsp, the stack data for this is written in the free memory zone, so that it does not need to be removed. + + +%TODO Eligible to writing more. This was merged with the explanation of each feature before, so it was more extense, but now it might need some more info?? +\subsection{Bypassing hardening features in ELFs} +During section \ref{subsection:hardening_elf}, we presented multiple security hardening measures that have been introduced to prevent common exploitation techniques (such as stack buffer overflows) and that nowadays can be incorporated, usually by default, in ELF binaries generated using modern compilers. We will now explore how to bypass these features, so that we can later design an injection technique that can target any process in the system, independently on whether it was compiled using these mitigations. + +\textbf{Stack canaries}\\ +Since stack canaries will be checked after the vulnerable function returns, an attacker seeking to overwrite the stack must ensure that the value of the canary remains constant. In the context of a buffer overflow attack, this can be achieved by leaking the value of the canary and incorporating it into the overflowing data at the stack, so that the same value is written on the same address\cite{canary_exploit}. + +In our rootkit, unlike in the ROP technique presented in section \ref{subsection:rop_ebpf}, we will avoid overwriting the value of the saved rip in the stack completely. Therefore, as long as our eBPF program leaves all registers and stack data in the same state as before calling the function, we will not trigger any alerts. + +\textbf{DEP/NX}\\ +The only alternative for an attacker upon a non-executable stack is either injecting shellcode at any other executable memory address, or the use of advanced techniques like ROP that fully circumvent this mitigation since the data at the stack is not directly executed at any step. + +In our rootkit, we will choose the first option, scanning the process virtual memory for an executable page where we will inject our shellcode. This process is usually known as finding 'code caves'. + +\textbf{ASLR}\\ +In order to bypass ASLR, attackers must take into account that, although the address at which, for instance, a library is loaded is random, the internal structure of the library remains unchanged, with all symbols in the same relative position, as figure \ref{table:aslr_offset} shows. + +%TODO Add the .data section here +\begin{figure}[H] + \centering + \includegraphics[width=13cm]{aslr_offset.jpg} + \caption{Two runs of the same executable using ASLR, showing a library and two symbols.} + \label{fig:alsr_offset} +\end{figure} + +As we can observe in the figure, although glibc is loaded at a different base address each run, the offset between the functions it implements, malloc() and free(), remains constant. Therefore, a method for bypassing ASLR is to gather information about the absolute address of any symbol, which can then easily lead to knowing the address of any other if the attacker decompiles the executable and calculates the offset between a pair of addresses where one is known. This is the chosen method for our technique. + +\textbf{PIE}\\ +Similarly to ASLR, although the starting base address of each memory section is random, the internal structure of each section remains the same. Therefore, if an attacker is able to leak the address of some symbol in a section, and by knowing the offset at which it is located with respect to the base address of the section, then the address of any other symbol in the same section can be calculated\cite{pie_exploit}. This is the technique we will incorporate in our rootkit. + +\textbf{RELRO}\\ +If an executable was compiled using Partial RELRO, then the value of GOT can still be overwritten. If in turn it was compiled using Full RELRO, this stops any attempt of GOT hijacking, unless an attacker finds an alternative method for writing into the virtual memory of a process that bypasses the read-only flag. + +In our rootkit, we will directly write using eBPF the value of GOT if it was compiled with Partial RELRO, and use an alternative technique for writing into the virtual memory of a process whenever it was compiled using Full RELRO. + + +\subsection{Library injection via GOT hijacking} \label{subsection:got_attack} +Taking into account the background about stack attacks, ELF's lazy binding and hardening features for binaries we presented in section \ref{section:elf}, we will now present the exploitation technique incorporated in our rootkit to inject a malicious library into a running process. + +This attack is based on the possibility of overwriting the data at the GOT section. As we have mentioned previously, this section is marked as writeable if the program was compiled using Partial RELRO, meaning that we will be able to overwrite its value from an eBPF program using the helper bpf\_probe\_write\_user(). After modifying the value of GOT, a PLT stub will take the new value as the jump address (as we explained in section \ref{subsection:elf_lazy_binding}), effectively hijacking the flow of execution of the program. In the case that a program was compiled with Full RELRO (which will be the case of many programs running by default in a Linux system such as systemd), we will make use of the /proc filesystem for overwriting this value. + +The rootkit will inject the library only after the second time that an specific syscall is called by a process, since the first time we will wait for the GOT address to be loaded by the dynamic linker. This is a necessary step because eBPF will need to validate that it really is the GOT section to overwrite. + +This technique works both in compilers with low hardening fetaures by default (Clang) and also on a compiler with all of them active (GCC), see table \ref{table:compilers}. On each of the steps, we will detail the different existing methods depending on the compiler features. + +For this research work, the rootkit is prepared to perform this attack on any process that makes use of either the system call sys\_openat or sys\_timerfd\_settime, which are called by the standard library glibc. + +\textbf{Stage 1: eBPF tracing and scan the stack}\\ +We load and attach a tracepoint eBPF program at the \textit{enter} position of syscall sys\_timerfd\_settime. Firstly we must ensure that the process calling the tracepoint is one of the processes to hijack. + +We will then proceed with the stack scanning technique, as we explained in section \ref{subsection:bpf_probe_write_apps}. In this case, the algorithm will go as follows: +\begin{enumerate} +\item Take one of the syscall parameters and scan forward in the scan. For each iteration, we must check if the data at the stack corresponds to the saved rip: +\begin{enumerate} +\item Check that the previous instruction is a call instruction, by checking the instruction length and opcodes (call instructions always start with e8, and the length is 5 bytes, see figure \ref{fig:firstcall}). +\begin{figure}[H] + \centering + \includegraphics[width=13cm]{sch_firstcall.png} + \caption{Call to the glibc function, using objdump} + \label{fig:firstcall} +\end{figure} +\item Now that we know we localized a call instruction, we take the address at which it jumps. That should be an address in a PLT stub. +\item We analyze the instruction at the PLT stub. If the program was compiled with GCC, it will be an \textit{endbr64} instruction followed by the PLT jump instruction using the address at GOT (since it generates Intel CET-compatible programs, see table \ref{table:compilers}). Otherwise, if using Clang, the first instruction is the PLT jump. +%TODO Continue +\end{enumerate} +\end{enumerate} \ No newline at end of file diff --git a/docs/chapters/chapter5.tex b/docs/chapters/chapter5.tex new file mode 100644 index 0000000..cd38c55 --- /dev/null +++ b/docs/chapters/chapter5.tex @@ -0,0 +1,3 @@ +\chapter{Evaluation} +\section{Developed capabilities} +\section{Rootkit use cases} \ No newline at end of file diff --git a/docs/chapters/chapter6.tex b/docs/chapters/chapter6.tex new file mode 100644 index 0000000..b8040b7 --- /dev/null +++ b/docs/chapters/chapter6.tex @@ -0,0 +1,4 @@ +\chapter{Related work} +% Comparison of the rootkit with other eBPF and non eBPF rootkits. + +%Move here part of the rootkit section at the intro. \ No newline at end of file diff --git a/docs/chapters/chapter7.tex b/docs/chapters/chapter7.tex new file mode 100644 index 0000000..65046d6 --- /dev/null +++ b/docs/chapters/chapter7.tex @@ -0,0 +1 @@ +\chapter{Conclusions} \ No newline at end of file diff --git a/docs/document.aux b/docs/document.aux index 7c7f926..57fe287 100644 --- a/docs/document.aux +++ b/docs/document.aux @@ -54,16 +54,17 @@ \@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {1.3.1}Social and economic environment}{4}{subsection.1.3.1}\protected@file@percent } \@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {1.3.2}Budget}{4}{subsection.1.3.2}\protected@file@percent } \@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {1.4}Structure of the document}{4}{section.1.4}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {1.5}Code availability}{4}{section.1.5}\protected@file@percent } \abx@aux@cite{ebpf_io} \abx@aux@segm{0}{0}{ebpf_io} \abx@aux@cite{bpf_bsd_origin} \abx@aux@segm{0}{0}{bpf_bsd_origin} \abx@aux@cite{ebpf_history_opensource} \abx@aux@segm{0}{0}{ebpf_history_opensource} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {2}State of the art}{5}{chapter.2}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {2}Background}{5}{chapter.2}\protected@file@percent } \@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {2.1}eBPF history - Classic BPF}{5}{section.2.1}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {2.1}BPF}{5}{section.2.1}\protected@file@percent } \@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.1.1}Introduction to the BPF system}{5}{subsection.2.1.1}\protected@file@percent } \abx@aux@cite{bpf_bsd_origin_bpf_page1} \abx@aux@segm{0}{0}{bpf_bsd_origin_bpf_page1} @@ -108,8 +109,8 @@ \abx@aux@segm{0}{0}{ebpf_funcs_by_ver} \@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.6}{\ignorespaces Shortest path in the CFG described in the example of figure \ref {fig:bpf_tcpdump_example} that a packet needs to follow to be accepted by the BPF filter set with \textit {tcpdump}.\relax }}{11}{figure.caption.13}\protected@file@percent } \newlabel{fig:tcpdump_ex_sol}{{2.6}{11}{Shortest path in the CFG described in the example of figure \ref {fig:bpf_tcpdump_example} that a packet needs to follow to be accepted by the BPF filter set with \textit {tcpdump}.\relax }{figure.caption.13}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {2.2}Analysis of modern eBPF}{11}{section.2.2}\protected@file@percent } -\newlabel{section:modern_ebpf}{{2.2}{11}{Analysis of modern eBPF}{section.2.2}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {2.2}Modern eBPF}{11}{section.2.2}\protected@file@percent } +\newlabel{section:modern_ebpf}{{2.2}{11}{Modern eBPF}{section.2.2}{}} \abx@aux@cite{brendan_gregg_bpf_book} \abx@aux@segm{0}{0}{brendan_gregg_bpf_book} \abx@aux@cite{brendan_gregg_bpf_book} @@ -257,11 +258,6 @@ \newlabel{fig:libbpf}{{2.9}{25}{Sketch of the compilation and loading process of a program developed with libbpf.\relax }{figure.caption.28}{}} \@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {2.14}{\ignorespaces Table showing BPF skeleton functions.\relax }}{25}{table.caption.29}\protected@file@percent } \newlabel{table:libbpf_skel}{{2.14}{25}{Table showing BPF skeleton functions.\relax }{table.caption.29}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {3}Analysis of offensive capabilities}{27}{chapter.3}\protected@file@percent } -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\addvspace {10\p@ }} -\newlabel{chapter:analysis_offensive_capabilities}{{3}{27}{Analysis of offensive capabilities}{chapter.3}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {3.1}Security features in eBPF}{27}{section.3.1}\protected@file@percent } \abx@aux@cite{ubuntu_caps} \abx@aux@segm{0}{0}{ubuntu_caps} \abx@aux@cite{evil_ebpf_p9} @@ -270,9 +266,10 @@ \abx@aux@segm{0}{0}{ebpf_caps_intro} \abx@aux@cite{ebpf_caps_lwn} \abx@aux@segm{0}{0}{ebpf_caps_lwn} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {3.1}{\ignorespaces Kernel compilation flags for eBPF.\relax }}{28}{table.caption.30}\protected@file@percent } -\newlabel{table:ebpf_kernel_flags}{{3.1}{28}{Kernel compilation flags for eBPF.\relax }{table.caption.30}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.1.1}Access control}{28}{subsection.3.1.1}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {2.5}Security features in eBPF}{26}{section.2.5}\protected@file@percent } +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {2.15}{\ignorespaces Kernel compilation flags for eBPF.\relax }}{26}{table.caption.30}\protected@file@percent } +\newlabel{table:ebpf_kernel_flags}{{2.15}{26}{Kernel compilation flags for eBPF.\relax }{table.caption.30}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.5.1}Access control}{26}{subsection.2.5.1}\protected@file@percent } \abx@aux@cite{unprivileged_ebpf} \abx@aux@segm{0}{0}{unprivileged_ebpf} \abx@aux@cite{cve_unpriv_ebpf} @@ -283,221 +280,235 @@ \abx@aux@segm{0}{0}{unpriv_ebpf_suse} \abx@aux@cite{unpriv_ebpf_redhat} \abx@aux@segm{0}{0}{unpriv_ebpf_redhat} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {3.2}{\ignorespaces Capabilities needed for eBPF.\relax }}{29}{table.caption.31}\protected@file@percent } -\newlabel{table:ebpf_caps_current}{{3.2}{29}{Capabilities needed for eBPF.\relax }{table.caption.31}{}} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {3.3}{\ignorespaces Values for unprivileged eBPF kernel parameter.\relax }}{29}{table.caption.32}\protected@file@percent } -\newlabel{table:unpriv_ebpf_values}{{3.3}{29}{Values for unprivileged eBPF kernel parameter.\relax }{table.caption.32}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.1.2}eBPF maps security}{30}{subsection.3.1.2}\protected@file@percent } -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {3.2}Abusing tracing programs}{30}{section.3.2}\protected@file@percent } -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.1}Access to function arguments}{30}{subsection.3.2.1}\protected@file@percent } -\abx@aux@cite{8664_params_abi} -\abx@aux@segm{0}{0}{8664_params_abi} -\newlabel{code:format_kprobe}{{3.1}{31}{Probe function for a kprobe on the kernel function vfs\_write}{lstlisting.3.1}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.1}Probe function for a kprobe on the kernel function vfs\_write.}{31}{lstlisting.3.1}\protected@file@percent } -\newlabel{code:format_uprobe}{{3.2}{31}{Probe function for an uprobe, execute\_command is defined from user space}{lstlisting.3.2}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.2}Probe function for an uprobe, execute\_command is defined from user space.}{31}{lstlisting.3.2}\protected@file@percent } -\newlabel{code:format_tracepoint}{{3.3}{31}{Probe function for a tracepoint on the start of the syscall sys\_read}{lstlisting.3.3}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.3}Probe function for a tracepoint on the start of the syscall sys\_read.}{31}{lstlisting.3.3}\protected@file@percent } -\newlabel{code:format_ptregs}{{3.4}{31}{Format of struct pt\_regs}{lstlisting.3.4}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.4}Format of struct pt\_regs.}{31}{lstlisting.3.4}\protected@file@percent } -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {3.4}{\ignorespaces Argument passing convention of registers for function calls in user and kernel space respectively.\relax }}{32}{table.caption.33}\protected@file@percent } -\newlabel{table:systemv_abi}{{3.4}{32}{Argument passing convention of registers for function calls in user and kernel space respectively.\relax }{table.caption.33}{}} -\newlabel{code:sys_enter_read_tp_format}{{3.5}{32}{Format for parameters in sys\_enter\_read specified at the format file}{lstlisting.3.5}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.5}Format for parameters in sys\_enter\_read specified at the format file.}{32}{lstlisting.3.5}\protected@file@percent } -\newlabel{code:sys_enter_read_tp}{{3.6}{32}{Format of custom struct sys\_read\_enter\_ctx}{lstlisting.3.6}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.6}Format of custom struct sys\_read\_enter\_ctx.}{32}{lstlisting.3.6}\protected@file@percent } -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.2}Reading memory out of bounds}{33}{subsection.3.2.2}\protected@file@percent } -\newlabel{subsection:out_read_bounds}{{3.2.2}{33}{Reading memory out of bounds}{subsection.3.2.2}{}} -\abx@aux@cite{ebpf_friends_p15} -\abx@aux@segm{0}{0}{ebpf_friends_p15} -\abx@aux@cite{ebpf_override_return} -\abx@aux@segm{0}{0}{ebpf_override_return} -\abx@aux@cite{code_kernel_open} -\abx@aux@segm{0}{0}{code_kernel_open} -\abx@aux@cite{code_kernel_open} -\abx@aux@segm{0}{0}{code_kernel_open} -\abx@aux@cite{code_kernel_syscall} -\abx@aux@segm{0}{0}{code_kernel_syscall} -\abx@aux@cite{code_kernel_syscall} -\abx@aux@segm{0}{0}{code_kernel_syscall} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.3}Overriding function return values}{34}{subsection.3.2.3}\protected@file@percent } -\newlabel{code:override_return_1}{{3.7}{34}{Definition of the syscall sys\_open in the kernel \cite {code_kernel_open}}{lstlisting.3.7}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.7}Definition of the syscall sys\_open in the kernel \cite {code_kernel_open}}{34}{lstlisting.3.7}\protected@file@percent } -\newlabel{code:override_return_2}{{3.8}{34}{Definition of the macro for creating syscalls, containing the error injection macro. Only relevant instructions included, complete macro can be found in the kernel \cite {code_kernel_syscall}}{lstlisting.3.8}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.8}Definition of the macro for creating syscalls, containing the error injection macro. Only relevant instructions included, complete macro can be found in the kernel \cite {code_kernel_syscall}}{34}{lstlisting.3.8}\protected@file@percent } -\abx@aux@cite{fault_injection} -\abx@aux@segm{0}{0}{fault_injection} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.4}Sending signals to user programs}{35}{subsection.3.2.4}\protected@file@percent } -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.5}Conclusion}{35}{subsection.3.2.5}\protected@file@percent } -\newlabel{subsection:tracing_attacks_conclusion}{{3.2.5}{35}{Conclusion}{subsection.3.2.5}{}} -\abx@aux@cite{ebpf_helpers} -\abx@aux@segm{0}{0}{ebpf_helpers} +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {2.16}{\ignorespaces Capabilities needed for eBPF.\relax }}{27}{table.caption.31}\protected@file@percent } +\newlabel{table:ebpf_caps_current}{{2.16}{27}{Capabilities needed for eBPF.\relax }{table.caption.31}{}} +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {2.17}{\ignorespaces Values for unprivileged eBPF kernel parameter.\relax }}{27}{table.caption.32}\protected@file@percent } +\newlabel{table:unpriv_ebpf_values}{{2.17}{27}{Values for unprivileged eBPF kernel parameter.\relax }{table.caption.32}{}} \abx@aux@cite{mem_page_arch} \abx@aux@segm{0}{0}{mem_page_arch} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {3.3}Memory corruption}{36}{section.3.3}\protected@file@percent } -\newlabel{section:mem_corruption}{{3.3}{36}{Memory corruption}{section.3.3}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.1}Memory management in Linux}{36}{subsection.3.3.1}\protected@file@percent } \abx@aux@cite{page_faults} \abx@aux@segm{0}{0}{page_faults} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.1}{\ignorespaces Memory translation of virtual pages to physical pages.\relax }}{37}{figure.caption.34}\protected@file@percent } -\newlabel{fig:mem_arch_pages}{{3.1}{37}{Memory translation of virtual pages to physical pages.\relax }{figure.caption.34}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {2.6}Memory management in Linux}{28}{section.2.6}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.6.1}Memory pages and faults}{28}{subsection.2.6.1}\protected@file@percent } +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.10}{\ignorespaces Memory translation of virtual pages to physical pages.\relax }}{28}{figure.caption.33}\protected@file@percent } +\newlabel{fig:mem_arch_pages}{{2.10}{28}{Memory translation of virtual pages to physical pages.\relax }{figure.caption.33}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.11}{\ignorespaces Major page fault after a page was removed from RAM.\relax }}{29}{figure.caption.34}\protected@file@percent } +\newlabel{fig:mem_major_page_fault}{{2.11}{29}{Major page fault after a page was removed from RAM.\relax }{figure.caption.34}{}} \abx@aux@cite{mem_arch_proc} \abx@aux@segm{0}{0}{mem_arch_proc} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.2}{\ignorespaces Major page fault after a page was removed from RAM.\relax }}{38}{figure.caption.35}\protected@file@percent } -\newlabel{fig:mem_major_page_fault}{{3.2}{38}{Major page fault after a page was removed from RAM.\relax }{figure.caption.35}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.3}{\ignorespaces Minor page fault after a fork() in which the page table was not copied completely.\relax }}{38}{figure.caption.36}\protected@file@percent } -\newlabel{fig:mem_minor_page_fault}{{3.3}{38}{Minor page fault after a fork() in which the page table was not copied completely.\relax }{figure.caption.36}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.2}Process virtual memory}{39}{subsection.3.3.2}\protected@file@percent } -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.4}{\ignorespaces Virtual memory architecture of a process\cite {mem_arch_proc}.\relax }}{39}{figure.caption.37}\protected@file@percent } -\newlabel{fig:mem_proc_arch}{{3.4}{39}{Virtual memory architecture of a process\cite {mem_arch_proc}.\relax }{figure.caption.37}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.3}The process stack}{40}{subsection.3.3.3}\protected@file@percent } -\newlabel{subsection:stack}{{3.3.3}{40}{The process stack}{subsection.3.3.3}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.5}{\ignorespaces Simplified stack representation showing only stack frames.\relax }}{40}{figure.caption.38}\protected@file@percent } -\newlabel{fig:stack_pres}{{3.5}{40}{Simplified stack representation showing only stack frames.\relax }{figure.caption.38}{}} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {3.5}{\ignorespaces Relevant registers in x86\_64 for the stack and control flow and their purpose.\relax }}{40}{table.caption.39}\protected@file@percent } -\newlabel{table:systemv_abi_other}{{3.5}{40}{Relevant registers in x86\_64 for the stack and control flow and their purpose.\relax }{table.caption.39}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.6}{\ignorespaces Representation of push and pop operations in the stack.\relax }}{42}{figure.caption.40}\protected@file@percent } -\newlabel{fig:stack_ops}{{3.6}{42}{Representation of push and pop operations in the stack.\relax }{figure.caption.40}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.7}{\ignorespaces Stack representation right before starting the function call process.\relax }}{42}{figure.caption.41}\protected@file@percent } -\newlabel{fig:stack_before}{{3.7}{42}{Stack representation right before starting the function call process.\relax }{figure.caption.41}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.12}{\ignorespaces Minor page fault after a fork() in which the page table was not copied completely.\relax }}{30}{figure.caption.35}\protected@file@percent } +\newlabel{fig:mem_minor_page_fault}{{2.12}{30}{Minor page fault after a fork() in which the page table was not copied completely.\relax }{figure.caption.35}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.6.2}Process virtual memory}{30}{subsection.2.6.2}\protected@file@percent } +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.13}{\ignorespaces Virtual memory architecture of a process\cite {mem_arch_proc}.\relax }}{31}{figure.caption.36}\protected@file@percent } +\newlabel{fig:mem_proc_arch}{{2.13}{31}{Virtual memory architecture of a process\cite {mem_arch_proc}.\relax }{figure.caption.36}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.6.3}The process stack}{32}{subsection.2.6.3}\protected@file@percent } +\newlabel{subsection:stack}{{2.6.3}{32}{The process stack}{subsection.2.6.3}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.14}{\ignorespaces Simplified stack representation showing only stack frames.\relax }}{32}{figure.caption.37}\protected@file@percent } +\newlabel{fig:stack_pres}{{2.14}{32}{Simplified stack representation showing only stack frames.\relax }{figure.caption.37}{}} +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {2.18}{\ignorespaces Relevant registers in x86\_64 for the stack and control flow and their purpose.\relax }}{32}{table.caption.38}\protected@file@percent } +\newlabel{table:systemv_abi_other}{{2.18}{32}{Relevant registers in x86\_64 for the stack and control flow and their purpose.\relax }{table.caption.38}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.15}{\ignorespaces Representation of push and pop operations in the stack.\relax }}{33}{figure.caption.39}\protected@file@percent } +\newlabel{fig:stack_ops}{{2.15}{33}{Representation of push and pop operations in the stack.\relax }{figure.caption.39}{}} \abx@aux@cite{8664_params_abi_p18} \abx@aux@segm{0}{0}{8664_params_abi_p18} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.8}{\ignorespaces Stack representation right after the function preamble.\relax }}{43}{figure.caption.42}\protected@file@percent } -\newlabel{fig:stack}{{3.8}{43}{Stack representation right after the function preamble.\relax }{figure.caption.42}{}} -\abx@aux@cite{write_helper_non_fault} -\abx@aux@segm{0}{0}{write_helper_non_fault} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.4}Attacks and limitations of bpf\_probe\_write\_user()}{44}{subsection.3.3.4}\protected@file@percent } -\newlabel{subsection:bpf_probe_write_apps}{{3.3.4}{44}{Attacks and limitations of bpf\_probe\_write\_user()}{subsection.3.3.4}{}} -\abx@aux@cite{code_vfs_read} -\abx@aux@segm{0}{0}{code_vfs_read} -\abx@aux@cite{code_vfs_read} -\abx@aux@segm{0}{0}{code_vfs_read} -\abx@aux@cite{evil_ebpf_p6974} -\abx@aux@segm{0}{0}{evil_ebpf_p6974} -\abx@aux@cite{8664_params_abi_p1922} -\abx@aux@segm{0}{0}{8664_params_abi_p1922} -\newlabel{code:vfs_read}{{3.9}{45}{Definition of kernel function vfs\_read. \cite {code_vfs_read}}{lstlisting.3.9}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.9}Definition of kernel function vfs\_read. \cite {code_vfs_read}}{45}{lstlisting.3.9}\protected@file@percent } -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.9}{\ignorespaces Overview of stack scanning and writing technique.\relax }}{46}{figure.caption.43}\protected@file@percent } -\newlabel{fig:stack_scan_write_tech}{{3.9}{46}{Overview of stack scanning and writing technique.\relax }{figure.caption.43}{}} -\newlabel{code:stack_scan_write_tech}{{3.10}{46}{Sample program being executed on figure \ref {fig:stack_scan_write_tech}}{lstlisting.3.10}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.10}Sample program being executed on figure \ref {fig:stack_scan_write_tech}.}{46}{lstlisting.3.10}\protected@file@percent } -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.5}Conclusion}{47}{subsection.3.3.5}\protected@file@percent } -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {3.4}Abusing networking programs}{47}{section.3.4}\protected@file@percent } -\newlabel{section:abusing_networking}{{3.4}{47}{Abusing networking programs}{section.3.4}{}} -\abx@aux@cite{network_layers} -\abx@aux@segm{0}{0}{network_layers} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.1}An overview on the network layer}{48}{subsection.3.4.1}\protected@file@percent } -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.10}{\ignorespaces Ethernet frame with TCP/IP packet.\relax }}{48}{figure.caption.44}\protected@file@percent } -\newlabel{fig:frame}{{3.10}{48}{Ethernet frame with TCP/IP packet.\relax }{figure.caption.44}{}} -\abx@aux@cite{tcp_reliable} -\abx@aux@segm{0}{0}{tcp_reliable} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.2}Introduction to the TCP protocol}{49}{subsection.3.4.2}\protected@file@percent } -\newlabel{subsection:tcp}{{3.4.2}{49}{Introduction to the TCP protocol}{subsection.3.4.2}{}} -\abx@aux@cite{tcp_handshake} -\abx@aux@segm{0}{0}{tcp_handshake} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {3.6}{\ignorespaces Relevant TCP flags and their purpose.\relax }}{50}{table.caption.45}\protected@file@percent } -\newlabel{table:tcp_flags}{{3.6}{50}{Relevant TCP flags and their purpose.\relax }{table.caption.45}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.11}{\ignorespaces TCP 3-way handshake.\relax }}{50}{figure.caption.46}\protected@file@percent } -\newlabel{fig:tcp_conn}{{3.11}{50}{TCP 3-way handshake.\relax }{figure.caption.46}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.12}{\ignorespaces TCP packet retransmission on timeout.\relax }}{51}{figure.caption.47}\protected@file@percent } -\newlabel{fig:tcp_retransmission}{{3.12}{51}{TCP packet retransmission on timeout.\relax }{figure.caption.47}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.3}Attacks and limitations of networking programs}{51}{subsection.3.4.3}\protected@file@percent } -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.13}{\ignorespaces Technique to duplicate a packet for exfiltrating data.\relax }}{53}{figure.caption.48}\protected@file@percent } -\newlabel{fig:tcp_exfiltrate_retrans}{{3.13}{53}{Technique to duplicate a packet for exfiltrating data.\relax }{figure.caption.48}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.4}Conclusion}{54}{subsection.3.4.4}\protected@file@percent } -\abx@aux@cite{evil_ebpf_p6974} -\abx@aux@segm{0}{0}{evil_ebpf_p6974} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {4}Design of a malicious eBPF rootkit}{55}{chapter.4}\protected@file@percent } -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {4.1}Library injection via GOT hijacking}{55}{section.4.1}\protected@file@percent } -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.1}Attacks at the stack: buffer overflow}{56}{subsection.4.1.1}\protected@file@percent } -\newlabel{subsection: buf_overflow}{{4.1.1}{56}{Attacks at the stack: buffer overflow}{subsection.4.1.1}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.1}{\ignorespaces Execution hijack overwriting saved rip value.\relax }}{57}{figure.caption.49}\protected@file@percent } -\newlabel{fig:stack_ret_hij_simple}{{4.1}{57}{Execution hijack overwriting saved rip value.\relax }{figure.caption.49}{}} -\newlabel{code:vuln_overflow}{{4.1}{57}{Program vulnerable to buffer overflow}{lstlisting.4.1}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {4.1}Program vulnerable to buffer overflow.}{57}{lstlisting.4.1}\protected@file@percent } -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.2}{\ignorespaces Stack buffer overflow overwriting ret value.\relax }}{58}{figure.caption.50}\protected@file@percent } -\newlabel{fig:buffer_overflow}{{4.2}{58}{Stack buffer overflow overwriting ret value.\relax }{figure.caption.50}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.3}{\ignorespaces Executing arbitrary code exploiting a buffer overflow vulnerability.\relax }}{59}{figure.caption.51}\protected@file@percent } -\newlabel{fig:buffer_overflow_shellcode}{{4.3}{59}{Executing arbitrary code exploiting a buffer overflow vulnerability.\relax }{figure.caption.51}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.16}{\ignorespaces Stack representation right before starting the function call process.\relax }}{34}{figure.caption.40}\protected@file@percent } +\newlabel{fig:stack_before}{{2.16}{34}{Stack representation right before starting the function call process.\relax }{figure.caption.40}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.17}{\ignorespaces Stack representation right after the function preamble.\relax }}{34}{figure.caption.41}\protected@file@percent } +\newlabel{fig:stack}{{2.17}{34}{Stack representation right after the function preamble.\relax }{figure.caption.41}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {2.7}Attacks at the stack}{35}{section.2.7}\protected@file@percent } +\newlabel{section:attacks_stack}{{2.7}{35}{Attacks at the stack}{section.2.7}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.18}{\ignorespaces Execution hijack overwriting saved rip value.\relax }}{36}{figure.caption.42}\protected@file@percent } +\newlabel{fig:stack_ret_hij_simple}{{2.18}{36}{Execution hijack overwriting saved rip value.\relax }{figure.caption.42}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.7.1}Buffer overflow}{36}{subsection.2.7.1}\protected@file@percent } +\newlabel{subsection: buf_overflow}{{2.7.1}{36}{Buffer overflow}{subsection.2.7.1}{}} +\newlabel{code:vuln_overflow}{{2.1}{37}{Program vulnerable to buffer overflow}{lstlisting.2.1}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {2.1}Program vulnerable to buffer overflow.}{37}{lstlisting.2.1}\protected@file@percent } +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.19}{\ignorespaces Stack buffer overflow overwriting ret value.\relax }}{37}{figure.caption.43}\protected@file@percent } +\newlabel{fig:buffer_overflow}{{2.19}{37}{Stack buffer overflow overwriting ret value.\relax }{figure.caption.43}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.20}{\ignorespaces Executing arbitrary code exploiting a buffer overflow vulnerability.\relax }}{38}{figure.caption.44}\protected@file@percent } +\newlabel{fig:buffer_overflow_shellcode}{{2.20}{38}{Executing arbitrary code exploiting a buffer overflow vulnerability.\relax }{figure.caption.44}{}} \abx@aux@cite{rop_prog_finder} \abx@aux@segm{0}{0}{rop_prog_finder} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.2}Return oriented programming attacks}{60}{subsection.4.1.2}\protected@file@percent } -\newlabel{subsection:rop}{{4.1.2}{60}{Return oriented programming attacks}{subsection.4.1.2}{}} -\newlabel{code:rop_ex}{{4.2}{60}{Sample program to run using ROP}{lstlisting.4.2}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {4.2}Sample program to run using ROP.}{60}{lstlisting.4.2}\protected@file@percent } -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.4}{\ignorespaces Steps for executing code sample using ROP.\relax }}{61}{figure.caption.52}\protected@file@percent } -\newlabel{fig:rop_compund}{{4.4}{61}{Steps for executing code sample using ROP.\relax }{figure.caption.52}{}} -\abx@aux@cite{evil_ebpf_p6974} -\abx@aux@segm{0}{0}{evil_ebpf_p6974} -\abx@aux@cite{glibc} -\abx@aux@segm{0}{0}{glibc} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.3}ROP with eBPF}{62}{subsection.4.1.3}\protected@file@percent } -\newlabel{subsection:rop_ebpf}{{4.1.3}{62}{ROP with eBPF}{subsection.4.1.3}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.5}{\ignorespaces Initial setup for the ROP with eBPF technique.\relax }}{62}{figure.caption.53}\protected@file@percent } -\newlabel{fig:rop_evil_ebpf_1}{{4.5}{62}{Initial setup for the ROP with eBPF technique.\relax }{figure.caption.53}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.6}{\ignorespaces Process memory after syscall exits and ROP code overwrites the stack.\relax }}{63}{figure.caption.54}\protected@file@percent } -\newlabel{fig:rop_evil_ebpf_2}{{4.6}{63}{Process memory after syscall exits and ROP code overwrites the stack.\relax }{figure.caption.54}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.7.2}Return oriented programming attacks}{39}{subsection.2.7.2}\protected@file@percent } +\newlabel{subsection:rop}{{2.7.2}{39}{Return oriented programming attacks}{subsection.2.7.2}{}} +\newlabel{code:rop_ex}{{2.2}{39}{Sample program to run using ROP}{lstlisting.2.2}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {2.2}Sample program to run using ROP.}{39}{lstlisting.2.2}\protected@file@percent } +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.21}{\ignorespaces Steps for executing code sample using ROP.\relax }}{40}{figure.caption.45}\protected@file@percent } +\newlabel{fig:rop_compund}{{2.21}{40}{Steps for executing code sample using ROP.\relax }{figure.caption.45}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {2.8}Networking fundamentals in Linux}{41}{section.2.8}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.8.1}An overview on the network layer}{41}{subsection.2.8.1}\protected@file@percent } +\abx@aux@cite{network_layers} +\abx@aux@segm{0}{0}{network_layers} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.22}{\ignorespaces Ethernet frame with TCP/IP packet.\relax }}{42}{figure.caption.46}\protected@file@percent } +\newlabel{fig:frame}{{2.22}{42}{Ethernet frame with TCP/IP packet.\relax }{figure.caption.46}{}} +\abx@aux@cite{tcp_reliable} +\abx@aux@segm{0}{0}{tcp_reliable} +\abx@aux@cite{tcp_handshake} +\abx@aux@segm{0}{0}{tcp_handshake} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.8.2}Introduction to the TCP protocol}{43}{subsection.2.8.2}\protected@file@percent } +\newlabel{subsection:tcp}{{2.8.2}{43}{Introduction to the TCP protocol}{subsection.2.8.2}{}} +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {2.19}{\ignorespaces Relevant TCP flags and their purpose.\relax }}{43}{table.caption.47}\protected@file@percent } +\newlabel{table:tcp_flags}{{2.19}{43}{Relevant TCP flags and their purpose.\relax }{table.caption.47}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.23}{\ignorespaces TCP 3-way handshake.\relax }}{44}{figure.caption.48}\protected@file@percent } +\newlabel{fig:tcp_conn}{{2.23}{44}{TCP 3-way handshake.\relax }{figure.caption.48}{}} \abx@aux@cite{elf} \abx@aux@segm{0}{0}{elf} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.7}{\ignorespaces Stack data is restored and program continues its execution.\relax }}{64}{figure.caption.55}\protected@file@percent } -\newlabel{fig:rop_evil_ebpf_3}{{4.7}{64}{Stack data is restored and program continues its execution.\relax }{figure.caption.55}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.4}The ELF format and Lazy Binding}{64}{subsection.4.1.4}\protected@file@percent } -\newlabel{subsection:elf_lazy_binding}{{4.1.4}{64}{The ELF format and Lazy Binding}{subsection.4.1.4}{}} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {4.1}{\ignorespaces Tools used for analysis of ELF programs.\relax }}{65}{table.caption.56}\protected@file@percent } -\newlabel{table:elf_tools}{{4.1}{65}{Tools used for analysis of ELF programs.\relax }{table.caption.56}{}} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {4.2}{\ignorespaces Tools used for analysis of ELF programs.\relax }}{65}{table.caption.57}\protected@file@percent } -\newlabel{table:elf_sec_headers}{{4.2}{65}{Tools used for analysis of ELF programs.\relax }{table.caption.57}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.24}{\ignorespaces TCP packet retransmission on timeout.\relax }}{45}{figure.caption.49}\protected@file@percent } +\newlabel{fig:tcp_retransmission}{{2.24}{45}{TCP packet retransmission on timeout.\relax }{figure.caption.49}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {2.9}ELF binaries}{45}{section.2.9}\protected@file@percent } +\newlabel{section:elf}{{2.9}{45}{ELF binaries}{section.2.9}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.9.1}The ELF format and Lazy Binding}{45}{subsection.2.9.1}\protected@file@percent } +\newlabel{subsection:elf_lazy_binding}{{2.9.1}{45}{The ELF format and Lazy Binding}{subsection.2.9.1}{}} +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {2.20}{\ignorespaces Tools used for analysis of ELF programs.\relax }}{46}{table.caption.50}\protected@file@percent } +\newlabel{table:elf_tools}{{2.20}{46}{Tools used for analysis of ELF programs.\relax }{table.caption.50}{}} \abx@aux@cite{plt_got_overlord} \abx@aux@segm{0}{0}{plt_got_overlord} \abx@aux@cite{plt_got_technovelty} \abx@aux@segm{0}{0}{plt_got_technovelty} -\newlabel{code:lazy_bind_1}{{4.3}{66}{Call to PLT stub seen from objdump}{lstlisting.4.3}{}} -\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {4.3}Call to PLT stub seen from objdump.}{66}{lstlisting.4.3}\protected@file@percent } -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.8}{\ignorespaces PLT stub for timerfd\_settime, seen from gdb-peda.\relax }}{66}{figure.caption.58}\protected@file@percent } -\newlabel{fig:lazy_bind_2}{{4.8}{66}{PLT stub for timerfd\_settime, seen from gdb-peda.\relax }{figure.caption.58}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.9}{\ignorespaces Inspecting address stored in GOT section before dynamic linking, seen from gdb-peda.\relax }}{66}{figure.caption.59}\protected@file@percent } -\newlabel{fig:lazy_bind_3}{{4.9}{66}{Inspecting address stored in GOT section before dynamic linking, seen from gdb-peda.\relax }{figure.caption.59}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.10}{\ignorespaces Inspecting address stored in GOT section after dynamic linking, seen from gdb-peda.\relax }}{67}{figure.caption.60}\protected@file@percent } -\newlabel{fig:lazy_bind_4}{{4.10}{67}{Inspecting address stored in GOT section after dynamic linking, seen from gdb-peda.\relax }{figure.caption.60}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.11}{\ignorespaces Glibc function to which PLT jumps using address stored at GOT, seen from gdb-peda.\relax }}{67}{figure.caption.61}\protected@file@percent } -\newlabel{fig:lazy_bind_5}{{4.11}{67}{Glibc function to which PLT jumps using address stored at GOT, seen from gdb-peda.\relax }{figure.caption.61}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.5}Hardening ELF binaries and possible bypasses}{67}{subsection.4.1.5}\protected@file@percent } +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {2.21}{\ignorespaces Tools used for analysis of ELF programs.\relax }}{47}{table.caption.51}\protected@file@percent } +\newlabel{table:elf_sec_headers}{{2.21}{47}{Tools used for analysis of ELF programs.\relax }{table.caption.51}{}} +\newlabel{code:lazy_bind_1}{{2.3}{47}{Call to PLT stub seen from objdump}{lstlisting.2.3}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {2.3}Call to PLT stub seen from objdump.}{47}{lstlisting.2.3}\protected@file@percent } +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.25}{\ignorespaces PLT stub for timerfd\_settime, seen from gdb-peda.\relax }}{48}{figure.caption.52}\protected@file@percent } +\newlabel{fig:lazy_bind_2}{{2.25}{48}{PLT stub for timerfd\_settime, seen from gdb-peda.\relax }{figure.caption.52}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.26}{\ignorespaces Inspecting address stored in GOT section before dynamic linking, seen from gdb-peda.\relax }}{48}{figure.caption.53}\protected@file@percent } +\newlabel{fig:lazy_bind_3}{{2.26}{48}{Inspecting address stored in GOT section before dynamic linking, seen from gdb-peda.\relax }{figure.caption.53}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.27}{\ignorespaces Inspecting address stored in GOT section after dynamic linking, seen from gdb-peda.\relax }}{48}{figure.caption.54}\protected@file@percent } +\newlabel{fig:lazy_bind_4}{{2.27}{48}{Inspecting address stored in GOT section after dynamic linking, seen from gdb-peda.\relax }{figure.caption.54}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {2.28}{\ignorespaces Glibc function to which PLT jumps using address stored at GOT, seen from gdb-peda.\relax }}{48}{figure.caption.55}\protected@file@percent } +\newlabel{fig:lazy_bind_5}{{2.28}{48}{Glibc function to which PLT jumps using address stored at GOT, seen from gdb-peda.\relax }{figure.caption.55}{}} \abx@aux@cite{aslr_pie_intro} \abx@aux@segm{0}{0}{aslr_pie_intro} -\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {4.3}{\ignorespaces Security features in C compilers used in the study.\relax }}{68}{table.caption.62}\protected@file@percent } -\newlabel{table:compilers}{{4.3}{68}{Security features in C compilers used in the study.\relax }{table.caption.62}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {2.9.2}Hardening ELF binaries}{49}{subsection.2.9.2}\protected@file@percent } +\newlabel{subsection:hardening_elf}{{2.9.2}{49}{Hardening ELF binaries}{subsection.2.9.2}{}} +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {2.22}{\ignorespaces Security features in C compilers used in the study.\relax }}{49}{table.caption.56}\protected@file@percent } +\newlabel{table:compilers}{{2.22}{49}{Security features in C compilers used in the study.\relax }{table.caption.56}{}} \abx@aux@cite{aslr_pie_intro} \abx@aux@segm{0}{0}{aslr_pie_intro} -\abx@aux@cite{pie_exploit} -\abx@aux@segm{0}{0}{pie_exploit} \abx@aux@cite{relro_redhat} \abx@aux@segm{0}{0}{relro_redhat} \abx@aux@cite{cet_windows} \abx@aux@segm{0}{0}{cet_windows} \abx@aux@cite{cet_linux} \abx@aux@segm{0}{0}{cet_linux} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.12}{\ignorespaces Two runs of the same executable using ASLR, showing a library and two symbols.\relax }}{69}{figure.caption.63}\protected@file@percent } -\newlabel{fig:alsr_offset}{{4.12}{69}{Two runs of the same executable using ASLR, showing a library and two symbols.\relax }{figure.caption.63}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.6}Design of our attack}{70}{subsection.4.1.6}\protected@file@percent } -\newlabel{subsection:got_attack}{{4.1.6}{70}{Design of our attack}{subsection.4.1.6}{}} -\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.13}{\ignorespaces Call to the glibc function, using objdump\relax }}{71}{figure.caption.64}\protected@file@percent } -\newlabel{fig:firstcall}{{4.13}{71}{Call to the glibc function, using objdump\relax }{figure.caption.64}{}} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {5}Results}{72}{chapter.5}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {3}Analysis of offensive capabilities}{52}{chapter.3}\protected@file@percent } \@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {6}Conclusion and future work}{73}{chapter.6}\protected@file@percent } +\newlabel{chapter:analysis_offensive_capabilities}{{3}{52}{Analysis of offensive capabilities}{chapter.3}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {3.1}eBPF maps security}{52}{section.3.1}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {3.2}Abusing tracing programs}{53}{section.3.2}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.1}Access to function arguments}{53}{subsection.3.2.1}\protected@file@percent } +\newlabel{code:format_kprobe}{{3.1}{53}{Probe function for a kprobe on the kernel function vfs\_write}{lstlisting.3.1}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.1}Probe function for a kprobe on the kernel function vfs\_write.}{53}{lstlisting.3.1}\protected@file@percent } +\newlabel{code:format_uprobe}{{3.2}{53}{Probe function for an uprobe, execute\_command is defined from user space}{lstlisting.3.2}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.2}Probe function for an uprobe, execute\_command is defined from user space.}{53}{lstlisting.3.2}\protected@file@percent } +\newlabel{code:format_tracepoint}{{3.3}{53}{Probe function for a tracepoint on the start of the syscall sys\_read}{lstlisting.3.3}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.3}Probe function for a tracepoint on the start of the syscall sys\_read.}{53}{lstlisting.3.3}\protected@file@percent } +\abx@aux@cite{8664_params_abi} +\abx@aux@segm{0}{0}{8664_params_abi} +\newlabel{code:format_ptregs}{{3.4}{54}{Format of struct pt\_regs}{lstlisting.3.4}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.4}Format of struct pt\_regs.}{54}{lstlisting.3.4}\protected@file@percent } +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\contentsline {table}{\numberline {3.1}{\ignorespaces Argument passing convention of registers for function calls in user and kernel space respectively.\relax }}{54}{table.caption.57}\protected@file@percent } +\newlabel{table:systemv_abi}{{3.1}{54}{Argument passing convention of registers for function calls in user and kernel space respectively.\relax }{table.caption.57}{}} +\newlabel{code:sys_enter_read_tp_format}{{3.5}{55}{Format for parameters in sys\_enter\_read specified at the format file}{lstlisting.3.5}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.5}Format for parameters in sys\_enter\_read specified at the format file.}{55}{lstlisting.3.5}\protected@file@percent } +\newlabel{code:sys_enter_read_tp}{{3.6}{55}{Format of custom struct sys\_read\_enter\_ctx}{lstlisting.3.6}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.6}Format of custom struct sys\_read\_enter\_ctx.}{55}{lstlisting.3.6}\protected@file@percent } +\abx@aux@cite{ebpf_friends_p15} +\abx@aux@segm{0}{0}{ebpf_friends_p15} +\abx@aux@cite{ebpf_override_return} +\abx@aux@segm{0}{0}{ebpf_override_return} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.2}Reading memory out of bounds}{56}{subsection.3.2.2}\protected@file@percent } +\newlabel{subsection:out_read_bounds}{{3.2.2}{56}{Reading memory out of bounds}{subsection.3.2.2}{}} +\abx@aux@cite{code_kernel_open} +\abx@aux@segm{0}{0}{code_kernel_open} +\abx@aux@cite{code_kernel_open} +\abx@aux@segm{0}{0}{code_kernel_open} +\abx@aux@cite{code_kernel_syscall} +\abx@aux@segm{0}{0}{code_kernel_syscall} +\abx@aux@cite{code_kernel_syscall} +\abx@aux@segm{0}{0}{code_kernel_syscall} +\abx@aux@cite{fault_injection} +\abx@aux@segm{0}{0}{fault_injection} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.3}Overriding function return values}{57}{subsection.3.2.3}\protected@file@percent } +\newlabel{code:override_return_1}{{3.7}{57}{Definition of the syscall sys\_open in the kernel \cite {code_kernel_open}}{lstlisting.3.7}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.7}Definition of the syscall sys\_open in the kernel \cite {code_kernel_open}}{57}{lstlisting.3.7}\protected@file@percent } +\newlabel{code:override_return_2}{{3.8}{57}{Definition of the macro for creating syscalls, containing the error injection macro. Only relevant instructions included, complete macro can be found in the kernel \cite {code_kernel_syscall}}{lstlisting.3.8}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.8}Definition of the macro for creating syscalls, containing the error injection macro. Only relevant instructions included, complete macro can be found in the kernel \cite {code_kernel_syscall}}{57}{lstlisting.3.8}\protected@file@percent } +\abx@aux@cite{ebpf_helpers} +\abx@aux@segm{0}{0}{ebpf_helpers} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.4}Sending signals to user programs}{58}{subsection.3.2.4}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.5}Conclusion}{58}{subsection.3.2.5}\protected@file@percent } +\newlabel{subsection:tracing_attacks_conclusion}{{3.2.5}{58}{Conclusion}{subsection.3.2.5}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {3.3}Memory corruption}{58}{section.3.3}\protected@file@percent } +\newlabel{section:mem_corruption}{{3.3}{58}{Memory corruption}{section.3.3}{}} +\abx@aux@cite{write_helper_non_fault} +\abx@aux@segm{0}{0}{write_helper_non_fault} +\abx@aux@cite{code_vfs_read} +\abx@aux@segm{0}{0}{code_vfs_read} +\abx@aux@cite{code_vfs_read} +\abx@aux@segm{0}{0}{code_vfs_read} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.1}Attacks and limitations of bpf\_probe\_write\_user()}{59}{subsection.3.3.1}\protected@file@percent } +\newlabel{subsection:bpf_probe_write_apps}{{3.3.1}{59}{Attacks and limitations of bpf\_probe\_write\_user()}{subsection.3.3.1}{}} +\abx@aux@cite{evil_ebpf_p6974} +\abx@aux@segm{0}{0}{evil_ebpf_p6974} +\abx@aux@cite{8664_params_abi_p1922} +\abx@aux@segm{0}{0}{8664_params_abi_p1922} +\newlabel{code:vfs_read}{{3.9}{60}{Definition of kernel function vfs\_read. \cite {code_vfs_read}}{lstlisting.3.9}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.9}Definition of kernel function vfs\_read. \cite {code_vfs_read}}{60}{lstlisting.3.9}\protected@file@percent } +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.1}{\ignorespaces Overview of stack scanning and writing technique.\relax }}{60}{figure.caption.58}\protected@file@percent } +\newlabel{fig:stack_scan_write_tech}{{3.1}{60}{Overview of stack scanning and writing technique.\relax }{figure.caption.58}{}} +\newlabel{code:stack_scan_write_tech}{{3.10}{61}{Sample program being executed on figure \ref {fig:stack_scan_write_tech}}{lstlisting.3.10}{}} +\@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {3.10}Sample program being executed on figure \ref {fig:stack_scan_write_tech}.}{61}{lstlisting.3.10}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.2}Conclusion}{61}{subsection.3.3.2}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {3.4}Abusing networking programs}{62}{section.3.4}\protected@file@percent } +\newlabel{section:abusing_networking}{{3.4}{62}{Abusing networking programs}{section.3.4}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.1}Attacks and limitations of networking programs}{62}{subsection.3.4.1}\protected@file@percent } +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {3.2}{\ignorespaces Technique to duplicate a packet for exfiltrating data.\relax }}{64}{figure.caption.59}\protected@file@percent } +\newlabel{fig:tcp_exfiltrate_retrans}{{3.2}{64}{Technique to duplicate a packet for exfiltrating data.\relax }{figure.caption.59}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.2}Conclusion}{65}{subsection.3.4.2}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {4}Design of a malicious eBPF rootkit}{66}{chapter.4}\protected@file@percent } \@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{Bibliography}{74}{chapter.6}\protected@file@percent } +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {section}{\numberline {4.1}Library injection attacks}{66}{section.4.1}\protected@file@percent } +\abx@aux@cite{evil_ebpf_p6974} +\abx@aux@segm{0}{0}{evil_ebpf_p6974} +\abx@aux@cite{evil_ebpf_p6974} +\abx@aux@segm{0}{0}{evil_ebpf_p6974} +\abx@aux@cite{glibc} +\abx@aux@segm{0}{0}{glibc} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.1}ROP with eBPF}{67}{subsection.4.1.1}\protected@file@percent } +\newlabel{subsection:rop_ebpf}{{4.1.1}{67}{ROP with eBPF}{subsection.4.1.1}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.1}{\ignorespaces Initial setup for the ROP with eBPF technique.\relax }}{67}{figure.caption.60}\protected@file@percent } +\newlabel{fig:rop_evil_ebpf_1}{{4.1}{67}{Initial setup for the ROP with eBPF technique.\relax }{figure.caption.60}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.2}{\ignorespaces Process memory after syscall exits and ROP code overwrites the stack.\relax }}{68}{figure.caption.61}\protected@file@percent } +\newlabel{fig:rop_evil_ebpf_2}{{4.2}{68}{Process memory after syscall exits and ROP code overwrites the stack.\relax }{figure.caption.61}{}} +\abx@aux@cite{canary_exploit} +\abx@aux@segm{0}{0}{canary_exploit} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.3}{\ignorespaces Stack data is restored and program continues its execution.\relax }}{69}{figure.caption.62}\protected@file@percent } +\newlabel{fig:rop_evil_ebpf_3}{{4.3}{69}{Stack data is restored and program continues its execution.\relax }{figure.caption.62}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.2}Bypassing hardening features in ELFs}{69}{subsection.4.1.2}\protected@file@percent } +\abx@aux@cite{pie_exploit} +\abx@aux@segm{0}{0}{pie_exploit} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.4}{\ignorespaces Two runs of the same executable using ASLR, showing a library and two symbols.\relax }}{70}{figure.caption.63}\protected@file@percent } +\newlabel{fig:alsr_offset}{{4.4}{70}{Two runs of the same executable using ASLR, showing a library and two symbols.\relax }{figure.caption.63}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.3}Library injection via GOT hijacking}{71}{subsection.4.1.3}\protected@file@percent } +\newlabel{subsection:got_attack}{{4.1.3}{71}{Library injection via GOT hijacking}{subsection.4.1.3}{}} +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\contentsline {figure}{\numberline {4.5}{\ignorespaces Call to the glibc function, using objdump\relax }}{72}{figure.caption.64}\protected@file@percent } +\newlabel{fig:firstcall}{{4.5}{72}{Call to the glibc function, using objdump\relax }{figure.caption.64}{}} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {5}Evaluation}{73}{chapter.5}\protected@file@percent } +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\addvspace {10\p@ }} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{\numberline {6}Related work}{74}{chapter.6}\protected@file@percent } +\@writefile{lof}{\defcounter {refsection}{0}\relax }\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\defcounter {refsection}{0}\relax }\@writefile{lot}{\addvspace {10\p@ }} +\@writefile{toc}{\defcounter {refsection}{0}\relax }\@writefile{toc}{\contentsline {chapter}{Bibliography}{75}{chapter.6}\protected@file@percent } \newlabel{annex:bpftool_flags_kernel}{{6}{}{Appendix A - Bpftool commands}{chapter*.66}{}} \newlabel{annex:readelf_commands}{{6}{}{Appendix B - Readelf commands}{chapter*.67}{}} \newlabel{annexsec:readelf_sec_headers}{{6}{}{}{chapter*.67}{}} \newlabel{code:elf_sections}{{6.1}{}{List of ELF section headers with readelf tool of a program compiled with GCC}{lstlisting.6.1}{}} \@writefile{lol}{\defcounter {refsection}{0}\relax }\@writefile{lol}{\contentsline {lstlisting}{\numberline {6.1}List of ELF section headers with readelf tool of a program compiled with GCC.}{}{lstlisting.6.1}\protected@file@percent } -\abx@aux@read@bbl@mdfivesum{DAEC68472698FE766A5D65F3ABD46C28} +\abx@aux@read@bbl@mdfivesum{073A2C7C705B80891C5D9DCBDBB01C38} \abx@aux@read@bblrerun \abx@aux@refcontextdefaultsdone \abx@aux@defaultrefcontext{0}{ransomware_pwc}{none/global//global/global} @@ -551,6 +562,21 @@ \abx@aux@defaultrefcontext{0}{libbpf_github}{none/global//global/global} \abx@aux@defaultrefcontext{0}{libbpf_upstream}{none/global//global/global} \abx@aux@defaultrefcontext{0}{libbpf_core}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{mem_page_arch}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{page_faults}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{mem_arch_proc}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{8664_params_abi_p18}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{rop_prog_finder}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{network_layers}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{tcp_reliable}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{tcp_handshake}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{elf}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{plt_got_overlord}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{plt_got_technovelty}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{aslr_pie_intro}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{relro_redhat}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{cet_windows}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{cet_linux}{none/global//global/global} \abx@aux@defaultrefcontext{0}{ubuntu_caps}{none/global//global/global} \abx@aux@defaultrefcontext{0}{evil_ebpf_p9}{none/global//global/global} \abx@aux@defaultrefcontext{0}{ebpf_caps_intro}{none/global//global/global} @@ -566,23 +592,12 @@ \abx@aux@defaultrefcontext{0}{code_kernel_open}{none/global//global/global} \abx@aux@defaultrefcontext{0}{code_kernel_syscall}{none/global//global/global} \abx@aux@defaultrefcontext{0}{fault_injection}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{mem_page_arch}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{page_faults}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{mem_arch_proc}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{8664_params_abi_p18}{none/global//global/global} \abx@aux@defaultrefcontext{0}{write_helper_non_fault}{none/global//global/global} \abx@aux@defaultrefcontext{0}{code_vfs_read}{none/global//global/global} \abx@aux@defaultrefcontext{0}{evil_ebpf_p6974}{none/global//global/global} \abx@aux@defaultrefcontext{0}{8664_params_abi_p1922}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{network_layers}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{tcp_reliable}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{tcp_handshake}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{rop_prog_finder}{none/global//global/global} \abx@aux@defaultrefcontext{0}{glibc}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{elf}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{plt_got_overlord}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{plt_got_technovelty}{none/global//global/global} -\abx@aux@defaultrefcontext{0}{aslr_pie_intro}{none/global//global/global} +\abx@aux@defaultrefcontext{0}{canary_exploit}{none/global//global/global} \abx@aux@defaultrefcontext{0}{pie_exploit}{none/global//global/global} \ttl@finishall -\gdef \@abspage@last{100} +\gdef \@abspage@last{102} diff --git a/docs/document.bbl b/docs/document.bbl index 3769d60..c914b45 100644 --- a/docs/document.bbl +++ b/docs/document.bbl @@ -1154,9 +1154,385 @@ \verb https://facebookmicrosites.github.io/bpf/blog/2020/02/19/bpf-portability-and-co-re.html \endverb \endentry - \entry{ubuntu_caps}{manual}{} + \entry{mem_page_arch}{online}{} + \name{author}{1}{}{% + {{hash=47635127541392c1419dbc4a4d3153c6}{% + family={Lameter}, + familyi={L\bibinitperiod}, + given={Christopher}, + giveni={C\bibinitperiod}}}% + } + \list{institution}{1}{% + {Jump Trading LLC}% + } + \list{organization}{1}{% + {The Linux Foundation Open Source Summit}% + } + \strng{namehash}{47635127541392c1419dbc4a4d3153c6} + \strng{fullhash}{47635127541392c1419dbc4a4d3153c6} + \strng{bibnamehash}{47635127541392c1419dbc4a4d3153c6} + \strng{authorbibnamehash}{47635127541392c1419dbc4a4d3153c6} + \strng{authornamehash}{47635127541392c1419dbc4a4d3153c6} + \strng{authorfullhash}{47635127541392c1419dbc4a4d3153c6} \field{sortinit}{8} \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{1} + \field{month}{12} + \field{title}{Memory Management 101: Introduction to Memory Management in Linux} + \field{year}{2017} + \field{dateera}{ce} + \verb{urlraw} + \verb https://events19.linuxfoundation.org/wp-content/uploads/2017/12/MM-101-Introduction-to-Linux-Memory-Management-Christoph-Lameter-Jump-Trading-LLC-1.pdf + \endverb + \verb{url} + \verb https://events19.linuxfoundation.org/wp-content/uploads/2017/12/MM-101-Introduction-to-Linux-Memory-Management-Christoph-Lameter-Jump-Trading-LLC-1.pdf + \endverb + \endentry + \entry{page_faults}{online}{} + \name{author}{1}{}{% + {{hash=28efc25c8eae7f3d05fad64c4679158f}{% + family={Breaker}, + familyi={B\bibinitperiod}, + given={Doug}, + giveni={D\bibinitperiod}}}% + } + \strng{namehash}{28efc25c8eae7f3d05fad64c4679158f} + \strng{fullhash}{28efc25c8eae7f3d05fad64c4679158f} + \strng{bibnamehash}{28efc25c8eae7f3d05fad64c4679158f} + \strng{authorbibnamehash}{28efc25c8eae7f3d05fad64c4679158f} + \strng{authornamehash}{28efc25c8eae7f3d05fad64c4679158f} + \strng{authorfullhash}{28efc25c8eae7f3d05fad64c4679158f} + \field{sortinit}{8} + \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{19} + \field{month}{8} + \field{title}{Understanding page faults and memory swap-in/outs} + \field{year}{2019} + \field{dateera}{ce} + \verb{urlraw} + \verb https://scoutapm.com/blog/understanding-page-faults-and-memory-swap-in-outs-when-should-you-worry + \endverb + \verb{url} + \verb https://scoutapm.com/blog/understanding-page-faults-and-memory-swap-in-outs-when-should-you-worry + \endverb + \endentry + \entry{mem_arch_proc}{online}{} + \name{author}{1}{}{% + {{hash=c6b49e9e6fbe96fdd89720e842dc0b03}{% + family={Bajo}, + familyi={B\bibinitperiod}, + given={Marcos\bibnamedelima Sánchez}, + giveni={M\bibinitperiod\bibinitdelim S\bibinitperiod}}}% + } + \strng{namehash}{c6b49e9e6fbe96fdd89720e842dc0b03} + \strng{fullhash}{c6b49e9e6fbe96fdd89720e842dc0b03} + \strng{bibnamehash}{c6b49e9e6fbe96fdd89720e842dc0b03} + \strng{authorbibnamehash}{c6b49e9e6fbe96fdd89720e842dc0b03} + \strng{authornamehash}{c6b49e9e6fbe96fdd89720e842dc0b03} + \strng{authorfullhash}{c6b49e9e6fbe96fdd89720e842dc0b03} + \field{sortinit}{8} + \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{23} + \field{month}{5} + \field{title}{Stack-based Buffer Overflow - Part 1} + \field{year}{2021} + \field{dateera}{ce} + \verb{urlraw} + \verb https://h3xduck.github.io/exploit/2021/05/23/stackbufferoverflow-part1.html + \endverb + \verb{url} + \verb https://h3xduck.github.io/exploit/2021/05/23/stackbufferoverflow-part1.html + \endverb + \endentry + \entry{8664_params_abi_p18}{manual}{} + \name{author}{1}{}{% + {{hash=871f02558cb7234c22cde24811cf53a7}{% + family={al.}, + familyi={a\bibinitperiod}, + given={H.J.\bibnamedelimi Lu}, + giveni={H\bibinitperiod\bibinitdelim L\bibinitperiod}, + prefix={et}, + prefixi={e\bibinitperiod}}}% + } + \strng{namehash}{871f02558cb7234c22cde24811cf53a7} + \strng{fullhash}{871f02558cb7234c22cde24811cf53a7} + \strng{bibnamehash}{871f02558cb7234c22cde24811cf53a7} + \strng{authorbibnamehash}{871f02558cb7234c22cde24811cf53a7} + \strng{authornamehash}{871f02558cb7234c22cde24811cf53a7} + \strng{authorfullhash}{871f02558cb7234c22cde24811cf53a7} + \field{extraname}{1} + \field{sortinit}{8} + \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{28} + \field{month}{1} + \field{title}{System V Application Binary Interface AMD64 Architecture Processor Supplement} + \field{year}{2018} + \field{dateera}{ce} + \field{pages}{18} + \range{pages}{1} + \verb{urlraw} + \verb https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf + \endverb + \verb{url} + \verb https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf + \endverb + \endentry + \entry{rop_prog_finder}{online}{} + \field{sortinit}{8} + \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{labeltitlesource}{title} + \field{title}{ROPgadget Tool} + \verb{urlraw} + \verb https://github.com/JonathanSalwan/ROPgadget + \endverb + \verb{url} + \verb https://github.com/JonathanSalwan/ROPgadget + \endverb + \endentry + \entry{network_layers}{online}{} + \name{author}{1}{}{% + {{hash=ed79ecb3ff4a83522b186b5e3fa37b0d}{% + family={Alienor}, + familyi={A\bibinitperiod}}}% + } + \strng{namehash}{ed79ecb3ff4a83522b186b5e3fa37b0d} + \strng{fullhash}{ed79ecb3ff4a83522b186b5e3fa37b0d} + \strng{bibnamehash}{ed79ecb3ff4a83522b186b5e3fa37b0d} + \strng{authorbibnamehash}{ed79ecb3ff4a83522b186b5e3fa37b0d} + \strng{authornamehash}{ed79ecb3ff4a83522b186b5e3fa37b0d} + \strng{authorfullhash}{ed79ecb3ff4a83522b186b5e3fa37b0d} + \field{sortinit}{8} + \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{28} + \field{month}{11} + \field{title}{The Network Layers Explained [with examples]} + \field{year}{2018} + \field{dateera}{ce} + \verb{urlraw} + \verb https://www.plixer.com/blog/network-layers-explained/ + \endverb + \verb{url} + \verb https://www.plixer.com/blog/network-layers-explained/ + \endverb + \endentry + \entry{tcp_reliable}{online}{} + \list{organization}{1}{% + {IBM}% + } + \field{sortinit}{8} + \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{labeltitlesource}{title} + \field{day}{19} + \field{month}{4} + \field{title}{Transmission Control Protocol} + \field{year}{2022} + \field{dateera}{ce} + \verb{urlraw} + \verb https://www.ibm.com/docs/en/aix/7.2?topic=protocols-transmission-control-protocol + \endverb + \verb{url} + \verb https://www.ibm.com/docs/en/aix/7.2?topic=protocols-transmission-control-protocol + \endverb + \endentry + \entry{tcp_handshake}{online}{} + \field{sortinit}{8} + \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{labeltitlesource}{title} + \field{title}{Three-Way Handshake} + \verb{urlraw} + \verb https://www.sciencedirect.com/topics/computer-science/three-way-handshake + \endverb + \verb{url} + \verb https://www.sciencedirect.com/topics/computer-science/three-way-handshake + \endverb + \endentry + \entry{elf}{manual}{} + \field{sortinit}{9} + \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{labeltitlesource}{title} + \field{title}{ELF} + \verb{urlraw} + \verb https://wiki.osdev.org/ELF + \endverb + \verb{url} + \verb https://wiki.osdev.org/ELF + \endverb + \endentry + \entry{plt_got_overlord}{online}{} + \name{author}{1}{}{% + {{hash=9724da855997a02e74ee77d11b4d64e2}{% + family={Tomaschik}, + familyi={T\bibinitperiod}, + given={David}, + giveni={D\bibinitperiod}}}% + } + \strng{namehash}{9724da855997a02e74ee77d11b4d64e2} + \strng{fullhash}{9724da855997a02e74ee77d11b4d64e2} + \strng{bibnamehash}{9724da855997a02e74ee77d11b4d64e2} + \strng{authorbibnamehash}{9724da855997a02e74ee77d11b4d64e2} + \strng{authornamehash}{9724da855997a02e74ee77d11b4d64e2} + \strng{authorfullhash}{9724da855997a02e74ee77d11b4d64e2} + \field{sortinit}{9} + \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{19} + \field{month}{3} + \field{title}{GOT and PLT for pwning.} + \field{year}{2017} + \field{dateera}{ce} + \verb{urlraw} + \verb https://systemoverlord.com/2017/03/19/got-and-plt-for-pwning.html + \endverb + \verb{url} + \verb https://systemoverlord.com/2017/03/19/got-and-plt-for-pwning.html + \endverb + \endentry + \entry{plt_got_technovelty}{online}{} + \name{author}{1}{}{% + {{hash=4e4902d108d0796e7e54d06a47cfe1ee}{% + family={Wienand}, + familyi={W\bibinitperiod}, + given={Ian}, + giveni={I\bibinitperiod}}}% + } + \strng{namehash}{4e4902d108d0796e7e54d06a47cfe1ee} + \strng{fullhash}{4e4902d108d0796e7e54d06a47cfe1ee} + \strng{bibnamehash}{4e4902d108d0796e7e54d06a47cfe1ee} + \strng{authorbibnamehash}{4e4902d108d0796e7e54d06a47cfe1ee} + \strng{authornamehash}{4e4902d108d0796e7e54d06a47cfe1ee} + \strng{authorfullhash}{4e4902d108d0796e7e54d06a47cfe1ee} + \field{sortinit}{9} + \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{11} + \field{month}{5} + \field{title}{PLT and GOT - the key to code sharing and dynamic libraries} + \field{year}{2011} + \field{dateera}{ce} + \verb{urlraw} + \verb https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html + \endverb + \verb{url} + \verb https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html + \endverb + \endentry + \entry{aslr_pie_intro}{online}{} + \field{sortinit}{9} + \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{labeltitlesource}{title} + \field{title}{aslr/pie intro} + \verb{urlraw} + \verb https://guyinatuxedo.github.io/5.1-mitigation_aslr_pie/index.html#aslrpie-intro + \endverb + \verb{url} + \verb https://guyinatuxedo.github.io/5.1-mitigation_aslr_pie/index.html#aslrpie-intro + \endverb + \endentry + \entry{relro_redhat}{online}{} + \name{author}{1}{}{% + {{hash=b77619d1671f5a819a9a13e8e0f51723}{% + family={Sidhpurwala}, + familyi={S\bibinitperiod}, + given={Huzaifa}, + giveni={H\bibinitperiod}}}% + } + \strng{namehash}{b77619d1671f5a819a9a13e8e0f51723} + \strng{fullhash}{b77619d1671f5a819a9a13e8e0f51723} + \strng{bibnamehash}{b77619d1671f5a819a9a13e8e0f51723} + \strng{authorbibnamehash}{b77619d1671f5a819a9a13e8e0f51723} + \strng{authornamehash}{b77619d1671f5a819a9a13e8e0f51723} + \strng{authorfullhash}{b77619d1671f5a819a9a13e8e0f51723} + \field{sortinit}{9} + \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{28} + \field{month}{1} + \field{title}{Hardening ELF binaries using Relocation Read-Only (RELRO)} + \field{year}{2019} + \field{dateera}{ce} + \verb{urlraw} + \verb https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro + \endverb + \verb{url} + \verb https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro + \endverb + \endentry + \entry{cet_windows}{online}{} + \name{author}{1}{}{% + {{hash=3de76fe0797950a06f4be8a7bf380d22}{% + family={Yarden\bibnamedelima Shafir}, + familyi={Y\bibinitperiod\bibinitdelim S\bibinitperiod}, + given={Alex\bibnamedelima Ionescu}, + giveni={A\bibinitperiod\bibinitdelim I\bibinitperiod}}}% + } + \strng{namehash}{3de76fe0797950a06f4be8a7bf380d22} + \strng{fullhash}{3de76fe0797950a06f4be8a7bf380d22} + \strng{bibnamehash}{3de76fe0797950a06f4be8a7bf380d22} + \strng{authorbibnamehash}{3de76fe0797950a06f4be8a7bf380d22} + \strng{authornamehash}{3de76fe0797950a06f4be8a7bf380d22} + \strng{authorfullhash}{3de76fe0797950a06f4be8a7bf380d22} + \field{sortinit}{9} + \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{1} + \field{month}{5} + \field{title}{R.I.P ROP: CET Internals in Windows 20H1} + \field{year}{2020} + \field{dateera}{ce} + \verb{urlraw} + \verb https://windows-internals.com/cet-on-windows/ + \endverb + \verb{url} + \verb https://windows-internals.com/cet-on-windows/ + \endverb + \endentry + \entry{cet_linux}{online}{} + \name{author}{1}{}{% + {{hash=b51b9464b5589cf5380e3b897d0a43b6}{% + family={Larabel}, + familyi={L\bibinitperiod}, + given={Michael}, + giveni={M\bibinitperiod}}}% + } + \strng{namehash}{b51b9464b5589cf5380e3b897d0a43b6} + \strng{fullhash}{b51b9464b5589cf5380e3b897d0a43b6} + \strng{bibnamehash}{b51b9464b5589cf5380e3b897d0a43b6} + \strng{authorbibnamehash}{b51b9464b5589cf5380e3b897d0a43b6} + \strng{authornamehash}{b51b9464b5589cf5380e3b897d0a43b6} + \strng{authorfullhash}{b51b9464b5589cf5380e3b897d0a43b6} + \field{sortinit}{9} + \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{labelnamesource}{author} + \field{labeltitlesource}{title} + \field{day}{21} + \field{month}{7} + \field{title}{Another Round Of Intel CET Patches, Still Working Toward Linux Kernel Integration} + \field{year}{2021} + \field{dateera}{ce} + \verb{urlraw} + \verb https://www.phoronix.com/scan.php?page=news_item&px=Intel-CET-v29 + \endverb + \verb{url} + \verb https://www.phoronix.com/scan.php?page=news_item&px=Intel-CET-v29 + \endverb + \endentry + \entry{ubuntu_caps}{manual}{} + \field{sortinit}{9} + \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} \field{labeltitlesource}{title} \field{title}{capabilities - overview of Linux capabilities} \verb{urlraw} @@ -1187,8 +1563,8 @@ \strng{authornamehash}{5142e68c748eb70cb619b21160eb7f72} \strng{authorfullhash}{5142e68c748eb70cb619b21160eb7f72} \field{extraname}{2} - \field{sortinit}{8} - \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{sortinit}{9} + \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} \field{labelnamesource}{author} \field{eventtitle}{Evil eBPF Practical Abuses of an In-Kernel Bytecode Runtime} \field{pages}{9} @@ -1201,8 +1577,8 @@ \endverb \endentry \entry{ebpf_caps_intro}{online}{} - \field{sortinit}{8} - \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} \field{title}{[PATCH v7 bpf-next 1/3] bpf, capability: Introduce CAP\_BPF} \verb{urlraw} @@ -1213,8 +1589,8 @@ \endverb \endentry \entry{ebpf_caps_lwn}{online}{} - \field{sortinit}{8} - \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} \field{title}{capability: introduce CAP\_BPF and CAP\_TRACING} \verb{urlraw} @@ -1225,8 +1601,8 @@ \endverb \endentry \entry{unprivileged_ebpf}{online}{} - \field{sortinit}{8} - \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} \field{title}{Reconsidering unprivileged BPF} \verb{urlraw} @@ -1237,8 +1613,8 @@ \endverb \endentry \entry{cve_unpriv_ebpf}{online}{} - \field{sortinit}{8} - \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} \field{title}{CVE-2021-4204: Linux Kernel eBPF Improper Input Validation Vulnerability} \verb{urlraw} @@ -1249,8 +1625,8 @@ \endverb \endentry \entry{unpriv_ebpf_ubuntu}{online}{} - \field{sortinit}{8} - \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} \field{title}{Unprivileged eBPF disabled by default for Ubuntu 20.04 LTS, 18.04 LTS, 16.04 ESM} \verb{urlraw} @@ -1261,8 +1637,8 @@ \endverb \endentry \entry{unpriv_ebpf_suse}{online}{} - \field{sortinit}{8} - \field{sortinithash}{1b24cab5087933ef0826a7cd3b99e994} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} \field{title}{Security Hardening: Use of eBPF by unprivileged users has been disabled by default} \verb{urlraw} @@ -1273,8 +1649,8 @@ \endverb \endentry \entry{unpriv_ebpf_redhat}{online}{} - \field{sortinit}{9} - \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} \field{title}{CVE-2022-0002} \verb{urlraw} @@ -1300,9 +1676,9 @@ \strng{authorbibnamehash}{871f02558cb7234c22cde24811cf53a7} \strng{authornamehash}{871f02558cb7234c22cde24811cf53a7} \strng{authorfullhash}{871f02558cb7234c22cde24811cf53a7} - \field{extraname}{1} - \field{sortinit}{9} - \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{extraname}{2} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labelnamesource}{author} \field{labeltitlesource}{title} \field{day}{28} @@ -1340,8 +1716,8 @@ \strng{authornamehash}{2994fc802c0b46f7289cf001e2c26cfe} \strng{authorfullhash}{2994fc802c0b46f7289cf001e2c26cfe} \field{extraname}{2} - \field{sortinit}{9} - \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labelnamesource}{author} \field{eventtitle}{Cyber Threats 2021: A year in Retrospect} \field{pages}{15} @@ -1354,8 +1730,8 @@ \endverb \endentry \entry{ebpf_override_return}{online}{} - \field{sortinit}{9} - \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} \field{title}{BPF-based error injection for the kernel} \verb{urlraw} @@ -1366,8 +1742,8 @@ \endverb \endentry \entry{code_kernel_open}{online}{} - \field{sortinit}{9} - \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{indextitle}{Linux kernel source code} \verb{urlraw} \verb https://elixir.bootlin.com/linux/v5.11/source/fs/open.c#L1192 @@ -1377,8 +1753,8 @@ \endverb \endentry \entry{code_kernel_syscall}{online}{} - \field{sortinit}{9} - \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{indextitle}{Linux kernel source code} \verb{urlraw} \verb https://elixir.bootlin.com/linux/v5.11/source/include/linux/syscalls.h#L233 @@ -1388,8 +1764,8 @@ \endverb \endentry \entry{fault_injection}{online}{} - \field{sortinit}{9} - \field{sortinithash}{54047ffb55bdefa0694bbd554c1b11a0} + \field{sortinit}{1} + \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} \field{day}{4} \field{month}{11} @@ -1403,137 +1779,6 @@ \verb https://lwn.net/Articles/209257/ \endverb \endentry - \entry{mem_page_arch}{online}{} - \name{author}{1}{}{% - {{hash=47635127541392c1419dbc4a4d3153c6}{% - family={Lameter}, - familyi={L\bibinitperiod}, - given={Christopher}, - giveni={C\bibinitperiod}}}% - } - \list{institution}{1}{% - {Jump Trading LLC}% - } - \list{organization}{1}{% - {The Linux Foundation Open Source Summit}% - } - \strng{namehash}{47635127541392c1419dbc4a4d3153c6} - \strng{fullhash}{47635127541392c1419dbc4a4d3153c6} - \strng{bibnamehash}{47635127541392c1419dbc4a4d3153c6} - \strng{authorbibnamehash}{47635127541392c1419dbc4a4d3153c6} - \strng{authornamehash}{47635127541392c1419dbc4a4d3153c6} - \strng{authorfullhash}{47635127541392c1419dbc4a4d3153c6} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labelnamesource}{author} - \field{labeltitlesource}{title} - \field{day}{1} - \field{month}{12} - \field{title}{Memory Management 101: Introduction to Memory Management in Linux} - \field{year}{2017} - \field{dateera}{ce} - \verb{urlraw} - \verb https://events19.linuxfoundation.org/wp-content/uploads/2017/12/MM-101-Introduction-to-Linux-Memory-Management-Christoph-Lameter-Jump-Trading-LLC-1.pdf - \endverb - \verb{url} - \verb https://events19.linuxfoundation.org/wp-content/uploads/2017/12/MM-101-Introduction-to-Linux-Memory-Management-Christoph-Lameter-Jump-Trading-LLC-1.pdf - \endverb - \endentry - \entry{page_faults}{online}{} - \name{author}{1}{}{% - {{hash=28efc25c8eae7f3d05fad64c4679158f}{% - family={Breaker}, - familyi={B\bibinitperiod}, - given={Doug}, - giveni={D\bibinitperiod}}}% - } - \strng{namehash}{28efc25c8eae7f3d05fad64c4679158f} - \strng{fullhash}{28efc25c8eae7f3d05fad64c4679158f} - \strng{bibnamehash}{28efc25c8eae7f3d05fad64c4679158f} - \strng{authorbibnamehash}{28efc25c8eae7f3d05fad64c4679158f} - \strng{authornamehash}{28efc25c8eae7f3d05fad64c4679158f} - \strng{authorfullhash}{28efc25c8eae7f3d05fad64c4679158f} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labelnamesource}{author} - \field{labeltitlesource}{title} - \field{day}{19} - \field{month}{8} - \field{title}{Understanding page faults and memory swap-in/outs} - \field{year}{2019} - \field{dateera}{ce} - \verb{urlraw} - \verb https://scoutapm.com/blog/understanding-page-faults-and-memory-swap-in-outs-when-should-you-worry - \endverb - \verb{url} - \verb https://scoutapm.com/blog/understanding-page-faults-and-memory-swap-in-outs-when-should-you-worry - \endverb - \endentry - \entry{mem_arch_proc}{online}{} - \name{author}{1}{}{% - {{hash=c6b49e9e6fbe96fdd89720e842dc0b03}{% - family={Bajo}, - familyi={B\bibinitperiod}, - given={Marcos\bibnamedelima Sánchez}, - giveni={M\bibinitperiod\bibinitdelim S\bibinitperiod}}}% - } - \strng{namehash}{c6b49e9e6fbe96fdd89720e842dc0b03} - \strng{fullhash}{c6b49e9e6fbe96fdd89720e842dc0b03} - \strng{bibnamehash}{c6b49e9e6fbe96fdd89720e842dc0b03} - \strng{authorbibnamehash}{c6b49e9e6fbe96fdd89720e842dc0b03} - \strng{authornamehash}{c6b49e9e6fbe96fdd89720e842dc0b03} - \strng{authorfullhash}{c6b49e9e6fbe96fdd89720e842dc0b03} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labelnamesource}{author} - \field{labeltitlesource}{title} - \field{day}{23} - \field{month}{5} - \field{title}{Stack-based Buffer Overflow - Part 1} - \field{year}{2021} - \field{dateera}{ce} - \verb{urlraw} - \verb https://h3xduck.github.io/exploit/2021/05/23/stackbufferoverflow-part1.html - \endverb - \verb{url} - \verb https://h3xduck.github.io/exploit/2021/05/23/stackbufferoverflow-part1.html - \endverb - \endentry - \entry{8664_params_abi_p18}{manual}{} - \name{author}{1}{}{% - {{hash=871f02558cb7234c22cde24811cf53a7}{% - family={al.}, - familyi={a\bibinitperiod}, - given={H.J.\bibnamedelimi Lu}, - giveni={H\bibinitperiod\bibinitdelim L\bibinitperiod}, - prefix={et}, - prefixi={e\bibinitperiod}}}% - } - \strng{namehash}{871f02558cb7234c22cde24811cf53a7} - \strng{fullhash}{871f02558cb7234c22cde24811cf53a7} - \strng{bibnamehash}{871f02558cb7234c22cde24811cf53a7} - \strng{authorbibnamehash}{871f02558cb7234c22cde24811cf53a7} - \strng{authornamehash}{871f02558cb7234c22cde24811cf53a7} - \strng{authorfullhash}{871f02558cb7234c22cde24811cf53a7} - \field{extraname}{2} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labelnamesource}{author} - \field{labeltitlesource}{title} - \field{day}{28} - \field{month}{1} - \field{title}{System V Application Binary Interface AMD64 Architecture Processor Supplement} - \field{year}{2018} - \field{dateera}{ce} - \field{pages}{18} - \range{pages}{1} - \verb{urlraw} - \verb https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf - \endverb - \verb{url} - \verb https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf - \endverb - \endentry \entry{write_helper_non_fault}{online}{} \field{sortinit}{1} \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} @@ -1626,77 +1871,6 @@ \verb https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf \endverb \endentry - \entry{network_layers}{online}{} - \name{author}{1}{}{% - {{hash=ed79ecb3ff4a83522b186b5e3fa37b0d}{% - family={Alienor}, - familyi={A\bibinitperiod}}}% - } - \strng{namehash}{ed79ecb3ff4a83522b186b5e3fa37b0d} - \strng{fullhash}{ed79ecb3ff4a83522b186b5e3fa37b0d} - \strng{bibnamehash}{ed79ecb3ff4a83522b186b5e3fa37b0d} - \strng{authorbibnamehash}{ed79ecb3ff4a83522b186b5e3fa37b0d} - \strng{authornamehash}{ed79ecb3ff4a83522b186b5e3fa37b0d} - \strng{authorfullhash}{ed79ecb3ff4a83522b186b5e3fa37b0d} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labelnamesource}{author} - \field{labeltitlesource}{title} - \field{day}{28} - \field{month}{11} - \field{title}{The Network Layers Explained [with examples]} - \field{year}{2018} - \field{dateera}{ce} - \verb{urlraw} - \verb https://www.plixer.com/blog/network-layers-explained/ - \endverb - \verb{url} - \verb https://www.plixer.com/blog/network-layers-explained/ - \endverb - \endentry - \entry{tcp_reliable}{online}{} - \list{organization}{1}{% - {IBM}% - } - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labeltitlesource}{title} - \field{day}{19} - \field{month}{4} - \field{title}{Transmission Control Protocol} - \field{year}{2022} - \field{dateera}{ce} - \verb{urlraw} - \verb https://www.ibm.com/docs/en/aix/7.2?topic=protocols-transmission-control-protocol - \endverb - \verb{url} - \verb https://www.ibm.com/docs/en/aix/7.2?topic=protocols-transmission-control-protocol - \endverb - \endentry - \entry{tcp_handshake}{online}{} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labeltitlesource}{title} - \field{title}{Three-Way Handshake} - \verb{urlraw} - \verb https://www.sciencedirect.com/topics/computer-science/three-way-handshake - \endverb - \verb{url} - \verb https://www.sciencedirect.com/topics/computer-science/three-way-handshake - \endverb - \endentry - \entry{rop_prog_finder}{online}{} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labeltitlesource}{title} - \field{title}{ROPgadget Tool} - \verb{urlraw} - \verb https://github.com/JonathanSalwan/ROPgadget - \endverb - \verb{url} - \verb https://github.com/JonathanSalwan/ROPgadget - \endverb - \endentry \entry{glibc}{online}{} \field{sortinit}{1} \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} @@ -1709,88 +1883,16 @@ \verb https://www.gnu.org/software/libc/ \endverb \endentry - \entry{elf}{manual}{} + \entry{canary_exploit}{online}{} \field{sortinit}{1} \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} \field{labeltitlesource}{title} - \field{title}{ELF} + \field{title}{Stack Canaries} \verb{urlraw} - \verb https://wiki.osdev.org/ELF + \verb https://ir0nstone.gitbook.io/notes/types/stack/canaries \endverb \verb{url} - \verb https://wiki.osdev.org/ELF - \endverb - \endentry - \entry{plt_got_overlord}{online}{} - \name{author}{1}{}{% - {{hash=9724da855997a02e74ee77d11b4d64e2}{% - family={Tomaschik}, - familyi={T\bibinitperiod}, - given={David}, - giveni={D\bibinitperiod}}}% - } - \strng{namehash}{9724da855997a02e74ee77d11b4d64e2} - \strng{fullhash}{9724da855997a02e74ee77d11b4d64e2} - \strng{bibnamehash}{9724da855997a02e74ee77d11b4d64e2} - \strng{authorbibnamehash}{9724da855997a02e74ee77d11b4d64e2} - \strng{authornamehash}{9724da855997a02e74ee77d11b4d64e2} - \strng{authorfullhash}{9724da855997a02e74ee77d11b4d64e2} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labelnamesource}{author} - \field{labeltitlesource}{title} - \field{day}{19} - \field{month}{3} - \field{title}{GOT and PLT for pwning.} - \field{year}{2017} - \field{dateera}{ce} - \verb{urlraw} - \verb https://systemoverlord.com/2017/03/19/got-and-plt-for-pwning.html - \endverb - \verb{url} - \verb https://systemoverlord.com/2017/03/19/got-and-plt-for-pwning.html - \endverb - \endentry - \entry{plt_got_technovelty}{online}{} - \name{author}{1}{}{% - {{hash=4e4902d108d0796e7e54d06a47cfe1ee}{% - family={Wienand}, - familyi={W\bibinitperiod}, - given={Ian}, - giveni={I\bibinitperiod}}}% - } - \strng{namehash}{4e4902d108d0796e7e54d06a47cfe1ee} - \strng{fullhash}{4e4902d108d0796e7e54d06a47cfe1ee} - \strng{bibnamehash}{4e4902d108d0796e7e54d06a47cfe1ee} - \strng{authorbibnamehash}{4e4902d108d0796e7e54d06a47cfe1ee} - \strng{authornamehash}{4e4902d108d0796e7e54d06a47cfe1ee} - \strng{authorfullhash}{4e4902d108d0796e7e54d06a47cfe1ee} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labelnamesource}{author} - \field{labeltitlesource}{title} - \field{day}{11} - \field{month}{5} - \field{title}{PLT and GOT - the key to code sharing and dynamic libraries} - \field{year}{2011} - \field{dateera}{ce} - \verb{urlraw} - \verb https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html - \endverb - \verb{url} - \verb https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html - \endverb - \endentry - \entry{aslr_pie_intro}{online}{} - \field{sortinit}{1} - \field{sortinithash}{50c6687d7fc80f50136d75228e3c59ba} - \field{labeltitlesource}{title} - \field{title}{aslr/pie intro} - \verb{urlraw} - \verb https://guyinatuxedo.github.io/5.1-mitigation_aslr_pie/index.html#aslrpie-intro - \endverb - \verb{url} - \verb https://guyinatuxedo.github.io/5.1-mitigation_aslr_pie/index.html#aslrpie-intro + \verb https://ir0nstone.gitbook.io/notes/types/stack/canaries \endverb \endentry \entry{pie_exploit}{online}{} diff --git a/docs/document.bcf b/docs/document.bcf index 1a9cef8..e6f814c 100644 --- a/docs/document.bcf +++ b/docs/document.bcf @@ -2425,40 +2425,41 @@ unpriv_ebpf_ubuntu unpriv_ebpf_suse unpriv_ebpf_redhat - 8664_params_abi - ebpf_friends_p15 - ebpf_override_return - code_kernel_open - code_kernel_open - code_kernel_syscall - code_kernel_syscall - fault_injection - ebpf_helpers - mem_page_arch - page_faults - mem_arch_proc - 8664_params_abi_p18 - write_helper_non_fault - code_vfs_read - code_vfs_read - evil_ebpf_p6974 - 8664_params_abi_p1922 - network_layers - tcp_reliable - tcp_handshake - evil_ebpf_p6974 - rop_prog_finder - evil_ebpf_p6974 - glibc - elf - plt_got_overlord - plt_got_technovelty - aslr_pie_intro - aslr_pie_intro - pie_exploit - relro_redhat - cet_windows - cet_linux + mem_page_arch + page_faults + mem_arch_proc + 8664_params_abi_p18 + rop_prog_finder + network_layers + tcp_reliable + tcp_handshake + elf + plt_got_overlord + plt_got_technovelty + aslr_pie_intro + aslr_pie_intro + relro_redhat + cet_windows + cet_linux + 8664_params_abi + ebpf_friends_p15 + ebpf_override_return + code_kernel_open + code_kernel_open + code_kernel_syscall + code_kernel_syscall + fault_injection + ebpf_helpers + write_helper_non_fault + code_vfs_read + code_vfs_read + evil_ebpf_p6974 + 8664_params_abi_p1922 + evil_ebpf_p6974 + evil_ebpf_p6974 + glibc + canary_exploit + pie_exploit diff --git a/docs/document.blg b/docs/document.blg index c4f80fe..6dbf10a 100644 --- a/docs/document.blg +++ b/docs/document.blg @@ -1,103 +1,107 @@ [0] Config.pm:311> INFO - This is Biber 2.16 [0] Config.pm:314> INFO - Logfile is 'document.blg' -[58] biber:340> INFO - === Thu Jun 9, 2022, 20:18:28 -[70] Biber.pm:415> INFO - Reading 'document.bcf' -[146] Biber.pm:952> INFO - Found 84 citekeys in bib section 0 -[160] Biber.pm:4340> INFO - Processing section 0 -[170] Biber.pm:4531> INFO - Looking for bibtex format file 'bibliography/bibliography.bib' for section 0 -[172] bibtex.pm:1689> INFO - LaTeX decoding ... -[203] bibtex.pm:1494> INFO - Found BibTeX data source 'bibliography/bibliography.bib' -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 9, warning: 1 characters of junk seen at toplevel -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 15, warning: 1 characters of junk seen at toplevel -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 22, warning: 1 characters of junk seen at toplevel -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 28, warning: 1 characters of junk seen at toplevel -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 35, warning: 1 characters of junk seen at toplevel -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 42, warning: 1 characters of junk seen at toplevel -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 50, warning: 1 characters of junk seen at toplevel -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 58, warning: 1 characters of junk seen at toplevel -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 65, warning: 1 characters of junk seen at toplevel -[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 70, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 77, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 85, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 94, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 103, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 112, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 121, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 127, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 132, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 137, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 142, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 153, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 158, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 164, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 170, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 175, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 184, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 191, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 199, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 206, warning: 1 characters of junk seen at toplevel -[404] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 215, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 224, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 233, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 239, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 244, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 249, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 256, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 261, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 266, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 271, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 276, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 283, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 288, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 295, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 302, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 309, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 315, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 321, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 327, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 334, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 339, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 344, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 349, warning: 1 characters of junk seen at toplevel -[405] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 356, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 361, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 366, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 375, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 380, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 385, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 390, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 395, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 400, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 405, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 410, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 419, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 428, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 433, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 438, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 443, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 449, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 459, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 466, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 473, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 482, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 487, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 492, warning: 1 characters of junk seen at toplevel -[406] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 501, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 508, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 515, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 520, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 529, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 538, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 543, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 548, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 555, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 562, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 567, warning: 1 characters of junk seen at toplevel -[407] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_QNOy/f4d088b3f9f145b5c3058da33afd57d4_14805.utf8, line 572, warning: 1 characters of junk seen at toplevel -[456] UCollate.pm:68> INFO - Overriding locale 'en-US' defaults 'normalization = NFD' with 'normalization = prenormalized' +[59] biber:340> INFO - === Sat Jun 11, 2022, 12:41:51 +[75] Biber.pm:415> INFO - Reading 'document.bcf' +[153] Biber.pm:952> INFO - Found 88 citekeys in bib section 0 +[171] Biber.pm:4340> INFO - Processing section 0 +[180] Biber.pm:4531> INFO - Looking for bibtex format file 'bibliography/bibliography.bib' for section 0 +[183] bibtex.pm:1689> INFO - LaTeX decoding ... +[216] bibtex.pm:1494> INFO - Found BibTeX data source 'bibliography/bibliography.bib' +[398] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 9, warning: 1 characters of junk seen at toplevel +[398] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 15, warning: 1 characters of junk seen at toplevel +[398] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 22, warning: 1 characters of junk seen at toplevel +[398] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 28, warning: 1 characters of junk seen at toplevel +[398] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 35, warning: 1 characters of junk seen at toplevel +[398] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 42, warning: 1 characters of junk seen at toplevel +[398] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 50, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 58, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 65, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 70, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 77, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 85, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 94, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 103, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 112, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 121, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 127, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 132, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 137, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 142, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 153, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 158, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 164, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 170, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 175, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 184, warning: 1 characters of junk seen at toplevel +[399] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 191, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 199, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 206, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 215, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 224, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 233, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 239, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 244, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 249, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 256, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 261, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 266, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 271, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 276, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 283, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 288, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 295, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 302, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 309, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 315, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 321, warning: 1 characters of junk seen at toplevel +[400] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 327, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 334, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 339, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 344, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 349, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 356, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 361, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 366, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 375, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 380, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 385, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 390, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 395, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 400, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 405, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 410, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 419, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 428, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 433, warning: 1 characters of junk seen at toplevel +[401] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 438, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 443, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 449, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 459, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 466, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 473, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 482, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 487, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 492, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 501, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 508, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 515, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 520, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 529, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 538, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 543, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 548, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 555, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 562, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 567, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 572, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 577, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 584, warning: 1 characters of junk seen at toplevel +[402] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 591, warning: 1 characters of junk seen at toplevel +[403] Utils.pm:384> WARN - BibTeX subsystem: /tmp/biber_tmp_l5xw/f4d088b3f9f145b5c3058da33afd57d4_19342.utf8, line 598, warning: 1 characters of junk seen at toplevel +[455] UCollate.pm:68> INFO - Overriding locale 'en-US' defaults 'normalization = NFD' with 'normalization = prenormalized' [456] UCollate.pm:68> INFO - Overriding locale 'en-US' defaults 'variable = shifted' with 'variable = non-ignorable' [456] Biber.pm:4168> INFO - Sorting list 'none/global//global/global' of type 'entry' with template 'none' and locale 'en-US' [456] Biber.pm:4174> INFO - No sort tailoring available for locale 'en-US' -[502] bbl.pm:654> INFO - Writing 'document.bbl' with encoding 'UTF-8' -[521] bbl.pm:757> INFO - Output to document.bbl -[521] Biber.pm:128> INFO - WARNINGS: 87 +[503] bbl.pm:654> INFO - Writing 'document.bbl' with encoding 'UTF-8' +[523] bbl.pm:757> INFO - Output to document.bbl +[524] Biber.pm:128> INFO - WARNINGS: 91 diff --git a/docs/document.fdb_latexmk b/docs/document.fdb_latexmk index 6f2b440..0a1c37a 100644 --- a/docs/document.fdb_latexmk +++ b/docs/document.fdb_latexmk @@ -1,32 +1,38 @@ # Fdb version 3 -["biber document"] 1653095942 "document.bcf" "document.bbl" "document" 1653095945 - "bibliography/bibliography.bib" 1653092614 766 09ec68d5fc14d72b3af96f6127cd94b1 "" - "document.bcf" 1653095944 106340 83305561fc186c7c1b66144e110833f4 "pdflatex" +["biber document"] 1654942894 "document.bcf" "document.bbl" "document" 1654942909 + "bibliography/bibliography.bib" 1654855012 17898 4449d891eca50db2bc784728c4927241 "" + "document.bcf" 1654942909 112735 e361b1bed81aebb7598fbdc9521e00e0 "pdflatex" (generated) - "document.bbl" "document.blg" -["pdflatex"] 1653095944 "document.tex" "document.pdf" "document" 1653095945 + "document.bbl" +["pdflatex"] 1654942903 "document.tex" "document.pdf" "document" 1654942909 "/etc/texmf/web2c/texmf.cnf" 1651100307 475 c0e671620eb5563b2130f56340a5fde8 "" "/usr/share/texlive/texmf-dist/fonts/enc/dvips/base/8r.enc" 1165713224 4850 80dc9bab7f31fb78a000ccfed0e27cab "" "/usr/share/texlive/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr12.tfm" 1136768653 1288 655e228510b4c2a1abe905c368440826 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtcxi.tfm" 1136768653 1448 dc0698441d5ba2c7e36c4762c89d2a6f "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtcxr.tfm" 1136768653 1368 7af309acf53bb727783600185f629f47 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxb.tfm" 1136768653 1020 c53143d3e3747b5c1149bd9a5ecd7b55 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxbss.tfm" 1136768653 952 8af6d4411025237a8a19c5fe76c48519 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxi.tfm" 1136768653 1048 a97cff5f6b833b712079817ce7a40d4c "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxphvb.tfm" 1136768653 4548 1ffa7e4f8cec4f54428bd6e887feff07 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxphvr.tfm" 1136768653 4748 767b775b8de19d97ba9256ce2b48e057 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxphvro.tfm" 1136768653 4964 9484ade2f7ca166fd2b0a8266351209c "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmb.tfm" 1136768653 4572 2c370d27bbb031f7592de9d41dc8cfca "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmr.tfm" 1136768653 4452 0fd0a792eaab7113e4d4f1b941ff0367 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmri.tfm" 1136768653 4640 ce59980bcbe9e6236fab46d0b5212c7e "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxr.tfm" 1136768653 1004 c0e991f864f31f017ea4ff9e451b76d4 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxss.tfm" 1136768653 952 9553fec7f8724dea5f23bcd5d8725907 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxsssl.tfm" 1136768653 1012 8cc6548f651cb7d6018c40ec4a405a18 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xb.tfm" 1136768653 6892 772bf8e6c154137db8568fa8a47a6ceb "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xbss.tfm" 1136768653 6700 9f7ab5807b4ea0f94f86ef51654456a0 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xbtt.tfm" 1136768653 1436 f00b2a275be56a8355f5c3b07a5a7a4c "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xi.tfm" 1136768653 6956 cab20301c4a0fe2075f774c8a2433c5d "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xr.tfm" 1136768653 6716 6d25a377562601272906e3bfe6b2817a "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xss.tfm" 1136768653 7096 d4068737d849c31bd955cec162cc9c1f "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xsssl.tfm" 1136768653 7320 442528840b39263f05b2bb9418cb055c "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xtt.tfm" 1136768653 1384 8943063000d26272532f74ca134dfecd "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/tcxi.tfm" 1136768653 1584 f7a2838338e782052f0de0fc45c1740c "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/tcxr.tfm" 1136768653 1468 26982ed5d4aefc6c98ed466c7d6869d8 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txex.tfm" 1136768653 1080 b674b4ba143004461509a754a0984b67 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txexa.tfm" 1136768653 688 f56006d6e56f46e63d9f63252958b828 "" @@ -38,18 +44,25 @@ "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsya.tfm" 1136768653 972 2c9ffac4bbd20f91c01aaef9bf3f8710 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyb.tfm" 1136768653 988 098ca7e8cc5647b9ac21b82dbdce1f01 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyc.tfm" 1136768653 1084 75e807e9e71f7a312e4e1187dce5e93b "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtcxi.pfb" 1136849748 14910 452a1524b0b6aca73bffd0ee2ad31c2e "" "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtcxr.pfb" 1136849748 14606 238072bd1ce11e3dff8451a5a2608194 "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtxb.pfb" 1136849748 6330 bdd610a36762742dd8a518bf9f97b968 "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtxi.pfb" 1136849748 6787 30821c47455d94d84f9e6f5bfecd086a "" "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtxr.pfb" 1136849748 6339 e2b78706efdc360ee6aec9b6e20211a7 "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xbtt.pfb" 1136849748 26580 8886cc7827569e05fd10df25f221aef6 "" "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xtt.pfb" 1136849748 26301 f08b3c26ea42c3177a262c2ac37d6a91 "" "/usr/share/texlive/texmf-dist/fonts/type1/urw/helvetic/uhvb8a.pfb" 1136849748 35941 f27169cc74234d5bd5e4cca5abafaabb "" "/usr/share/texlive/texmf-dist/fonts/type1/urw/helvetic/uhvr8a.pfb" 1136849748 44648 23115b2a545ebfe2c526c3ca99db8b95 "" "/usr/share/texlive/texmf-dist/fonts/type1/urw/times/utmb8a.pfb" 1136849748 44729 811d6c62865936705a31c797a1d5dada "" "/usr/share/texlive/texmf-dist/fonts/type1/urw/times/utmr8a.pfb" 1136849748 46026 6dab18b61c907687b520c72847215a68 "" + "/usr/share/texlive/texmf-dist/fonts/type1/urw/times/utmri8a.pfb" 1136849748 45458 a3faba884469519614ca56ba5f6b1de1 "" "/usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xb.vf" 1136768653 2144 bab2875eda5b2344ea7b1db74ccc03a4 "" "/usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xbss.vf" 1136768653 2140 53a6b204134ca23b688a5eb135473f18 "" + "/usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xi.vf" 1136768653 2120 35084608d79b6b13dd746dfcffe98243 "" "/usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xr.vf" 1136768653 2140 99e5b3a34695df6221a167ffa8b498d6 "" "/usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xss.vf" 1136768653 2140 1f9dbe1be7b322ce3d2dc5796a8e88ed "" "/usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xsssl.vf" 1136768653 2148 3b03d03d82cf6e8c21b92d2903f15dc8 "" + "/usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/tcxi.vf" 1136768653 988 94d927596240fbacbfb7297449727f1c "" "/usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/tcxr.vf" 1136768653 988 4f41b8c123e4537adb7f2dbb638d2981 "" "/usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii" 1461363279 71627 94eb9990bed73c364d7f53f960cc8c5b "" "/usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty" 1575674566 24708 5584a51a7101caf7e6bbf1fc27d8f7b1 "" @@ -152,6 +165,7 @@ "/usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty" 1575499565 5766 13a9e8766c47f30327caf893ece86ac8 "" "/usr/share/texlive/texmf-dist/tex/latex/listings/listings.cfg" 1585170648 1830 e31effa752c61538383451ae21332364 "" "/usr/share/texlive/texmf-dist/tex/latex/listings/listings.sty" 1585170648 80964 64e57373f36316e4a09b517cbf1aba2e "" + "/usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty" 1585170648 204271 bae5b2d457283e99567249c1990510be "" "/usr/share/texlive/texmf-dist/tex/latex/listings/lstmisc.sty" 1585170648 77022 ee25ce086f4a79d8cf73bac6f94c02a5 "" "/usr/share/texlive/texmf-dist/tex/latex/logreq/logreq.def" 1284153563 1620 fb1c32b818f2058eca187e5c41dfae77 "" "/usr/share/texlive/texmf-dist/tex/latex/logreq/logreq.sty" 1284153563 6187 b27afc771af565d3a9ff1ca7d16d0d46 "" @@ -189,25 +203,67 @@ "/usr/share/texmf/web2c/texmf.cnf" 1613593815 38841 799d1dd9682a55ce442e10c99777ecc1 "" "/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map" 1651100317 128028 f533b797fba58d231669ea19e894e23e "" "/var/lib/texmf/web2c/pdftex/pdflatex.fmt" 1651100326 1334284 230f0b70f00981bccbdb458564f1009e "" - "document.aux" 1653095944 4305 28f1ef1486041d38fe3222215f27bd15 "pdflatex" - "document.bbl" 1653095942 1903 06b912ee459fe111d955fba417607bd1 "biber document" - "document.lof" 1653095944 419 65e977773db8f33e78f36376c2ad29c2 "pdflatex" - "document.lot" 1653095944 419 65e977773db8f33e78f36376c2ad29c2 "pdflatex" - "document.out" 1653095944 645 22937790bee0f30769157dc04627a687 "pdflatex" - "document.run.xml" 1653095944 2445 b409c18254f7f5782630d13a05948f21 "pdflatex" - "document.tex" 1653095911 12133 218b36bd219171d09644622cdc0d0b49 "" - "document.toc" 1653095944 1329 daebe7d2e5303951de100f07e19de20e "pdflatex" + "chapters/annex.tex" 1654942022 7244 529cbb32d3e651576b8b59f587b12ca7 "" + "chapters/chapter1.tex" 1654942427 11443 47a32930700b882ae00123de9261e211 "" + "chapters/chapter2.tex" 1654942827 54083 3ad1b2ddf80c992578d1017c39ed1128 "" + "chapters/chapter3.tex" 1654942812 44397 23633e76820182b9375fed24892da81a "" + "chapters/chapter4.tex" 1654907124 34837 aebe2df6aebf5e0bb6957ee38a061539 "" + "chapters/chapter5.tex" 1654941579 20 b9bf1a6cc1f320bfe01b8d488d2ded14 "" + "chapters/chapter6.tex" 1654941594 22 a4763c43dfb96d01585aff2eaff0ccbe "" + "document.aux" 1654942909 60576 86eaa0b701ca0506b6ef9fd0e11eb3f6 "pdflatex" + "document.bbl" 1654942896 73417 0278de2a07b515b57955b64a1f5bd851 "biber document" + "document.lof" 1654942909 7233 f53b6bec69e38cfc89457a8a5b38451c "pdflatex" + "document.lot" 1654942909 5361 771dd7d79ed4c15da4ae237011a6548e "pdflatex" + "document.out" 1654942909 5406 ce2aa95f08fbe7ebddaeb67089365827 "pdflatex" + "document.run.xml" 1654942909 2445 b409c18254f7f5782630d13a05948f21 "pdflatex" + "document.tex" 1654942068 6713 eb3647ce32b19002e48c2c97d8fb2840 "" + "document.toc" 1654942909 8699 ba841e8da4ee1740b24ec705fa08ca20 "pdflatex" "images//Portada_Logo.png" 1651111039 22996 c527860321fd85a49ffef78eb664cfb0 "" + "images//ROPcompound.jpg" 1654626518 189399 440667572df7b1c6adea87e1316fdedd "" + "images//aslr_offset.jpg" 1654821383 24380 09a1b8196c0d4095853e0abbc94fde03 "" + "images//bpf_address_mode.png" 1653295904 120159 3b61bb23c08976d443e2209f5feef027 "" + "images//bpf_instructions.png" 1653295887 87235 e2e9ebd3abbf4217b218593154586119 "" + "images//buffer_overflow.jpg" 1654613585 33233 234ad1a2a4578fdcf964f37d7032a589 "" + "images//buffer_overflow_shellcode.jpg" 1654618293 45561 e57c00ba99ba0b80368cdc0aa64101ff "" + "images//cBPF_prog_ex_sol.png" 1653307584 18612 5639fbf3851c7aefb0ab2f0d747d39e4 "" + "images//classic_bpf.jpg" 1653251787 32269 cb640fa8b95ef6388c3c400ff34c08f0 "" + "images//ebpf_arch.jpg" 1653529995 60229 575955dd95319abfdfe746dc0da29d14 "" + "images//frame.jpg" 1654533510 102536 baf3b44ff116a7448c5d35e25e7eda97 "" + "images//libbpf_prog.jpg" 1653741812 40113 69ec9fd9f1dfded5f622ae05141130a9 "" + "images//mem_arch_pages.jpg" 1654343079 46103 3b6ed2f695590d91d1ce517a7518ba14 "" + "images//mem_major_page_fault.jpg" 1654345015 34926 900a506f60da0b26c50f0ec9daa9b295 "" + "images//mem_minor_page_fault.jpg" 1654345021 49534 278ecdf64e412a950f4d809dfea89dc9 "" + "images//memory.jpg" 1654594805 26028 033e8d676afa0c083a4f3b90a6784395 "" + "images//rop_evil_ebpf_1.jpg" 1654690993 80272 893c8a309177ea30436b1cb0e0a4f3ba "" + "images//rop_evil_ebpf_2.jpg" 1654691288 72075 f0114fb8746bb65ea72a81a9679fa908 "" + "images//rop_evil_ebpf_3.jpg" 1654692503 58582 2a0db73e0ff01342847ed343d4f7319b "" + "images//sch_firstcall.png" 1654828322 19347 58cc1ca504090e433ec03e2bcdc1dd91 "" + "images//sch_gdb_got_after.png" 1654802017 8525 d7df884a144a977c8e070c4056c50a17 "" + "images//sch_gdb_got_prev.png" 1654801658 7756 9b217037d291e83cadef8d77809bc139 "" + "images//sch_gdb_plt.png" 1654800731 45200 a5e1aa28ce6e0d6cc4f11867d24f0878 "" + "images//sch_glibc_func.png" 1654802737 24202 c6b923d8354ca57c6350b66ee21b4eef "" + "images//stack.jpg" 1654430376 30015 ebcf3f3c62c8155291ef4aa1b05eb653 "" + "images//stack_before.jpg" 1654430798 17097 0dc9f22472a2102f109b99907037aa7a "" + "images//stack_ops.jpg" 1654428621 55409 345bc5b1d0950544bc7335b3f4e05912 "" + "images//stack_pres.jpg" 1654424859 23003 259a6a4815d4424ca6d882bc71ce84f6 "" + "images//stack_ret_hij_simple.jpg" 1654594575 101721 a311e1bef2e2c6740f21a25c4889372f "" + "images//stack_scan_write_tech.jpg" 1654464032 61226 fc4f89080b9a91d93f5bd49f7e00897a "" + "images//tcp_conn.jpg" 1654543456 30833 0823efc5e1ea3d9eba2edf6ede288273 "" + "images//tcp_exfiltrate_retrans.jpg" 1654558715 42839 2a5972a5a88efc5905fcc081dec5cfae "" + "images//tcp_retransmission.jpg" 1654549976 42205 caa4b3bc55b46b4ad80f3e1b0f5df520 "" + "images//tcpdump_example.png" 1653302033 71021 900c1544b6afc012fb7b3448e2e237e3 "" + "images//xdp_diag.jpg" 1653602902 43089 4e9dfc5caf229d9d24a8459475c563f4 "" + "images/cBPF_prog.jpg" 1653294568 37580 becaaa0d8a6a16353948a17c8ecd2bb8 "" "images/creativecommons.png" 1651111039 20748 2d1005dcab1cdcb889ee17a8f3b8cbcb "" - "pdfa.xmpi" 1653095944 5042 bc88ba8ea8d65c0809b1b834aadbdbb1 "pdflatex" + "pdfa.xmpi" 1654942903 5042 d0c2490e023f3d1613b9dde05d541626 "pdflatex" (generated) - "pdfa.xmpi" - "document.bcf" - "document.out" - "document.log" - "document.pdf" - "document.aux" - "document.lof" - "document.run.xml" "document.lot" + "document.aux" + "document.bcf" + "document.pdf" "document.toc" + "document.lof" + "pdfa.xmpi" + "document.log" + "document.out" + "document.run.xml" diff --git a/docs/document.fls b/docs/document.fls index 76cd766..ec93fd8 100644 --- a/docs/document.fls +++ b/docs/document.fls @@ -1181,11 +1181,76 @@ OUTPUT document.toc INPUT ./document.lof INPUT document.lof INPUT document.lof +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ot1txr.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ot1txr.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ot1txr.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ot1txr.fd +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txr.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txr.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txr.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmi.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmi.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmi.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsy.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsy.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsy.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txex.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txex.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txex.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsya.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsya.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsya.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsya.fd +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsya.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsya.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsya.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyb.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyb.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyb.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyb.fd +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyb.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyb.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyb.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txi.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txi.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txi.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxmia.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxmia.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxmia.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxmia.fd +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmia.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmia.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmia.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyc.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyc.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyc.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyc.fd +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyc.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyc.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyc.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txexa.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txexa.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txexa.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xi.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xi.vf +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmri.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxi.tfm OUTPUT document.lof INPUT ./document.lot INPUT document.lot INPUT document.lot OUTPUT document.lot +INPUT ./chapters/chapter1.tex +INPUT ./chapters/chapter1.tex +INPUT ./chapters/chapter1.tex +INPUT ./chapters/chapter1.tex +INPUT ./chapters/chapter1.tex +INPUT chapters/chapter1.tex +INPUT ./chapters/chapter1.tex +INPUT ./chapters/chapter1.tex +INPUT ./chapters/chapter1.tex +INPUT ./chapters/chapter1.tex +INPUT chapters/chapter1.tex INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txr.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txr.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txr.fd @@ -1193,72 +1258,302 @@ INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txr.fd INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/tcxr.tfm INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/tcxr.vf INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtcxr.tfm +INPUT ./chapters/chapter2.tex +INPUT ./chapters/chapter2.tex +INPUT ./chapters/chapter2.tex +INPUT ./chapters/chapter2.tex +INPUT ./chapters/chapter2.tex +INPUT chapters/chapter2.tex +INPUT ./chapters/chapter2.tex +INPUT ./chapters/chapter2.tex +INPUT ./chapters/chapter2.tex +INPUT ./chapters/chapter2.tex +INPUT chapters/chapter2.tex +INPUT ./images//classic_bpf.jpg +INPUT ./images//classic_bpf.jpg +INPUT images//classic_bpf.jpg +INPUT ./images//classic_bpf.jpg +INPUT ./images//classic_bpf.jpg +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xr.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xr.vf +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmr.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxr.tfm +INPUT ./images/cBPF_prog.jpg +INPUT ./images/cBPF_prog.jpg +INPUT images/cBPF_prog.jpg +INPUT ./images/cBPF_prog.jpg +INPUT ./images/cBPF_prog.jpg +INPUT ./images//bpf_instructions.png +INPUT ./images//bpf_instructions.png +INPUT images//bpf_instructions.png +INPUT ./images//bpf_instructions.png +INPUT ./images//bpf_instructions.png +INPUT ./images//bpf_address_mode.png +INPUT ./images//bpf_address_mode.png +INPUT images//bpf_address_mode.png +INPUT ./images//bpf_address_mode.png +INPUT ./images//bpf_address_mode.png +INPUT ./images//tcpdump_example.png +INPUT ./images//tcpdump_example.png +INPUT images//tcpdump_example.png +INPUT ./images//tcpdump_example.png +INPUT ./images//tcpdump_example.png +INPUT ./images//cBPF_prog_ex_sol.png +INPUT ./images//cBPF_prog_ex_sol.png +INPUT images//cBPF_prog_ex_sol.png +INPUT ./images//cBPF_prog_ex_sol.png +INPUT ./images//cBPF_prog_ex_sol.png +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xi.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xi.vf +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmri.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxi.tfm +INPUT ./images//ebpf_arch.jpg +INPUT ./images//ebpf_arch.jpg +INPUT images//ebpf_arch.jpg +INPUT ./images//ebpf_arch.jpg +INPUT ./images//ebpf_arch.jpg +INPUT ./images//xdp_diag.jpg +INPUT ./images//xdp_diag.jpg +INPUT images//xdp_diag.jpg +INPUT ./images//xdp_diag.jpg +INPUT ./images//xdp_diag.jpg +INPUT ./images//libbpf_prog.jpg +INPUT ./images//libbpf_prog.jpg +INPUT images//libbpf_prog.jpg +INPUT ./images//libbpf_prog.jpg +INPUT ./images//libbpf_prog.jpg +INPUT ./images//mem_arch_pages.jpg +INPUT ./images//mem_arch_pages.jpg +INPUT images//mem_arch_pages.jpg +INPUT ./images//mem_arch_pages.jpg +INPUT ./images//mem_arch_pages.jpg +INPUT ./images//mem_major_page_fault.jpg +INPUT ./images//mem_major_page_fault.jpg +INPUT images//mem_major_page_fault.jpg +INPUT ./images//mem_major_page_fault.jpg +INPUT ./images//mem_major_page_fault.jpg +INPUT ./images//mem_minor_page_fault.jpg +INPUT ./images//mem_minor_page_fault.jpg +INPUT images//mem_minor_page_fault.jpg +INPUT ./images//mem_minor_page_fault.jpg +INPUT ./images//mem_minor_page_fault.jpg +INPUT ./images//memory.jpg +INPUT ./images//memory.jpg +INPUT images//memory.jpg +INPUT ./images//memory.jpg +INPUT ./images//memory.jpg +INPUT ./images//stack_pres.jpg +INPUT ./images//stack_pres.jpg +INPUT images//stack_pres.jpg +INPUT ./images//stack_pres.jpg +INPUT ./images//stack_pres.jpg +INPUT ./images//stack_ops.jpg +INPUT ./images//stack_ops.jpg +INPUT images//stack_ops.jpg +INPUT ./images//stack_ops.jpg +INPUT ./images//stack_ops.jpg INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xtt.tfm -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ot1txr.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ot1txr.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ot1txr.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ot1txr.fd -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txr.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txr.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txr.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmi.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmi.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmi.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsy.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsy.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsy.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txex.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txex.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txex.tfm -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsya.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsya.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsya.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsya.fd -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsya.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsya.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsya.tfm -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyb.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyb.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyb.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyb.fd -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyb.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyb.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyb.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txi.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txi.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txi.tfm -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxmia.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxmia.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxmia.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxmia.fd -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmia.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmia.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txmia.tfm -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyc.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyc.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyc.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/utxsyc.fd -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyc.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyc.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txsyc.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txexa.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txexa.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/txexa.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xtt.tfm +INPUT ./images//stack_before.jpg +INPUT ./images//stack_before.jpg +INPUT images//stack_before.jpg +INPUT ./images//stack_before.jpg +INPUT ./images//stack_before.jpg +INPUT ./images//stack.jpg +INPUT ./images//stack.jpg +INPUT images//stack.jpg +INPUT ./images//stack.jpg +INPUT ./images//stack.jpg +INPUT ./chapters/chapter3.tex +INPUT ./chapters/chapter3.tex +INPUT ./chapters/chapter3.tex +INPUT ./chapters/chapter3.tex +INPUT ./chapters/chapter3.tex +INPUT chapters/chapter3.tex +INPUT ./chapters/chapter3.tex +INPUT ./chapters/chapter3.tex +INPUT ./chapters/chapter3.tex +INPUT ./chapters/chapter3.tex +INPUT chapters/chapter3.tex +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstmisc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstmisc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstmisc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstmisc.sty +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xr.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xr.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xbtt.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/t1xr.vf +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmr.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxr.tfm +INPUT ./images//stack_scan_write_tech.jpg +INPUT ./images//stack_scan_write_tech.jpg +INPUT images//stack_scan_write_tech.jpg +INPUT ./images//stack_scan_write_tech.jpg +INPUT ./images//stack_scan_write_tech.jpg +INPUT ./images//frame.jpg +INPUT ./images//frame.jpg +INPUT images//frame.jpg +INPUT ./images//frame.jpg +INPUT ./images//frame.jpg +INPUT ./images//tcp_conn.jpg +INPUT ./images//tcp_conn.jpg +INPUT images//tcp_conn.jpg +INPUT ./images//tcp_conn.jpg +INPUT ./images//tcp_conn.jpg +INPUT ./images//tcp_retransmission.jpg +INPUT ./images//tcp_retransmission.jpg +INPUT images//tcp_retransmission.jpg +INPUT ./images//tcp_retransmission.jpg +INPUT ./images//tcp_retransmission.jpg +INPUT ./images//tcp_exfiltrate_retrans.jpg +INPUT ./images//tcp_exfiltrate_retrans.jpg +INPUT images//tcp_exfiltrate_retrans.jpg +INPUT ./images//tcp_exfiltrate_retrans.jpg +INPUT ./images//tcp_exfiltrate_retrans.jpg +INPUT ./chapters/chapter4.tex +INPUT ./chapters/chapter4.tex +INPUT ./chapters/chapter4.tex +INPUT ./chapters/chapter4.tex +INPUT ./chapters/chapter4.tex +INPUT chapters/chapter4.tex +INPUT ./chapters/chapter4.tex +INPUT ./chapters/chapter4.tex +INPUT ./chapters/chapter4.tex +INPUT ./chapters/chapter4.tex +INPUT chapters/chapter4.tex +INPUT ./images//stack_ret_hij_simple.jpg +INPUT ./images//stack_ret_hij_simple.jpg +INPUT images//stack_ret_hij_simple.jpg +INPUT ./images//stack_ret_hij_simple.jpg +INPUT ./images//stack_ret_hij_simple.jpg +INPUT ./images//buffer_overflow.jpg +INPUT ./images//buffer_overflow.jpg +INPUT images//buffer_overflow.jpg +INPUT ./images//buffer_overflow.jpg +INPUT ./images//buffer_overflow.jpg +INPUT ./images//buffer_overflow_shellcode.jpg +INPUT ./images//buffer_overflow_shellcode.jpg +INPUT images//buffer_overflow_shellcode.jpg +INPUT ./images//buffer_overflow_shellcode.jpg +INPUT ./images//buffer_overflow_shellcode.jpg +INPUT ./images//ROPcompound.jpg +INPUT ./images//ROPcompound.jpg +INPUT images//ROPcompound.jpg +INPUT ./images//ROPcompound.jpg +INPUT ./images//ROPcompound.jpg +INPUT ./images//rop_evil_ebpf_1.jpg +INPUT ./images//rop_evil_ebpf_1.jpg +INPUT images//rop_evil_ebpf_1.jpg +INPUT ./images//rop_evil_ebpf_1.jpg +INPUT ./images//rop_evil_ebpf_1.jpg +INPUT ./images//rop_evil_ebpf_2.jpg +INPUT ./images//rop_evil_ebpf_2.jpg +INPUT images//rop_evil_ebpf_2.jpg +INPUT ./images//rop_evil_ebpf_2.jpg +INPUT ./images//rop_evil_ebpf_2.jpg +INPUT ./images//rop_evil_ebpf_3.jpg +INPUT ./images//rop_evil_ebpf_3.jpg +INPUT images//rop_evil_ebpf_3.jpg +INPUT ./images//rop_evil_ebpf_3.jpg +INPUT ./images//rop_evil_ebpf_3.jpg +INPUT ./images//sch_gdb_plt.png +INPUT ./images//sch_gdb_plt.png +INPUT images//sch_gdb_plt.png +INPUT ./images//sch_gdb_plt.png +INPUT ./images//sch_gdb_plt.png +INPUT ./images//sch_gdb_got_prev.png +INPUT ./images//sch_gdb_got_prev.png +INPUT images//sch_gdb_got_prev.png +INPUT ./images//sch_gdb_got_prev.png +INPUT ./images//sch_gdb_got_prev.png +INPUT ./images//sch_gdb_got_after.png +INPUT ./images//sch_gdb_got_after.png +INPUT images//sch_gdb_got_after.png +INPUT ./images//sch_gdb_got_after.png +INPUT ./images//sch_gdb_got_after.png +INPUT ./images//sch_glibc_func.png +INPUT ./images//sch_glibc_func.png +INPUT images//sch_glibc_func.png +INPUT ./images//sch_glibc_func.png +INPUT ./images//sch_glibc_func.png +INPUT ./images//aslr_offset.jpg +INPUT ./images//aslr_offset.jpg +INPUT images//aslr_offset.jpg +INPUT ./images//aslr_offset.jpg +INPUT ./images//aslr_offset.jpg +INPUT ./images//sch_firstcall.png +INPUT ./images//sch_firstcall.png +INPUT images//sch_firstcall.png +INPUT ./images//sch_firstcall.png +INPUT ./images//sch_firstcall.png +INPUT ./chapters/chapter5.tex +INPUT ./chapters/chapter5.tex +INPUT ./chapters/chapter5.tex +INPUT ./chapters/chapter5.tex +INPUT ./chapters/chapter5.tex +INPUT chapters/chapter5.tex +INPUT ./chapters/chapter5.tex +INPUT ./chapters/chapter5.tex +INPUT ./chapters/chapter5.tex +INPUT ./chapters/chapter5.tex +INPUT chapters/chapter5.tex +INPUT ./chapters/chapter6.tex +INPUT ./chapters/chapter6.tex +INPUT ./chapters/chapter6.tex +INPUT ./chapters/chapter6.tex +INPUT ./chapters/chapter6.tex +INPUT chapters/chapter6.tex +INPUT ./chapters/chapter6.tex +INPUT ./chapters/chapter6.tex +INPUT ./chapters/chapter6.tex +INPUT ./chapters/chapter6.tex +INPUT chapters/chapter6.tex +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/tcxi.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/tcxi.vf +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtcxi.tfm +INPUT ./chapters/annex.tex +INPUT ./chapters/annex.tex +INPUT ./chapters/annex.tex +INPUT ./chapters/annex.tex +INPUT ./chapters/annex.tex +INPUT chapters/annex.tex +INPUT ./chapters/annex.tex +INPUT ./chapters/annex.tex +INPUT ./chapters/annex.tex +INPUT ./chapters/annex.tex +INPUT chapters/annex.tex +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty INPUT document.aux INPUT ./document.out INPUT ./document.out INPUT document.run.xml OUTPUT document.run.xml INPUT /usr/share/texlive/texmf-dist/fonts/enc/dvips/base/8r.enc +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtcxi.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtcxr.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtxb.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtxi.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/rtxr.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xbtt.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xtt.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/urw/helvetic/uhvb8a.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/urw/helvetic/uhvr8a.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/urw/helvetic/uhvr8a.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/urw/times/utmb8a.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/urw/times/utmr8a.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/urw/times/utmri8a.pfb diff --git a/docs/document.lof b/docs/document.lof index 187a687..680c3f6 100644 --- a/docs/document.lof +++ b/docs/document.lof @@ -23,61 +23,61 @@ \defcounter {refsection}{0}\relax \contentsline {figure}{\numberline {2.9}{\ignorespaces Sketch of the compilation and loading process of a program developed with libbpf.\relax }}{25}{figure.caption.28}% \defcounter {refsection}{0}\relax -\addvspace {10\p@ } +\contentsline {figure}{\numberline {2.10}{\ignorespaces Memory translation of virtual pages to physical pages.\relax }}{28}{figure.caption.33}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.1}{\ignorespaces Memory translation of virtual pages to physical pages.\relax }}{37}{figure.caption.34}% +\contentsline {figure}{\numberline {2.11}{\ignorespaces Major page fault after a page was removed from RAM.\relax }}{29}{figure.caption.34}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.2}{\ignorespaces Major page fault after a page was removed from RAM.\relax }}{38}{figure.caption.35}% +\contentsline {figure}{\numberline {2.12}{\ignorespaces Minor page fault after a fork() in which the page table was not copied completely.\relax }}{30}{figure.caption.35}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.3}{\ignorespaces Minor page fault after a fork() in which the page table was not copied completely.\relax }}{38}{figure.caption.36}% +\contentsline {figure}{\numberline {2.13}{\ignorespaces Virtual memory architecture of a process\cite {mem_arch_proc}.\relax }}{31}{figure.caption.36}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.4}{\ignorespaces Virtual memory architecture of a process\cite {mem_arch_proc}.\relax }}{39}{figure.caption.37}% +\contentsline {figure}{\numberline {2.14}{\ignorespaces Simplified stack representation showing only stack frames.\relax }}{32}{figure.caption.37}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.5}{\ignorespaces Simplified stack representation showing only stack frames.\relax }}{40}{figure.caption.38}% +\contentsline {figure}{\numberline {2.15}{\ignorespaces Representation of push and pop operations in the stack.\relax }}{33}{figure.caption.39}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.6}{\ignorespaces Representation of push and pop operations in the stack.\relax }}{42}{figure.caption.40}% +\contentsline {figure}{\numberline {2.16}{\ignorespaces Stack representation right before starting the function call process.\relax }}{34}{figure.caption.40}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.7}{\ignorespaces Stack representation right before starting the function call process.\relax }}{42}{figure.caption.41}% +\contentsline {figure}{\numberline {2.17}{\ignorespaces Stack representation right after the function preamble.\relax }}{34}{figure.caption.41}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.8}{\ignorespaces Stack representation right after the function preamble.\relax }}{43}{figure.caption.42}% +\contentsline {figure}{\numberline {2.18}{\ignorespaces Execution hijack overwriting saved rip value.\relax }}{36}{figure.caption.42}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.9}{\ignorespaces Overview of stack scanning and writing technique.\relax }}{46}{figure.caption.43}% +\contentsline {figure}{\numberline {2.19}{\ignorespaces Stack buffer overflow overwriting ret value.\relax }}{37}{figure.caption.43}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.10}{\ignorespaces Ethernet frame with TCP/IP packet.\relax }}{48}{figure.caption.44}% +\contentsline {figure}{\numberline {2.20}{\ignorespaces Executing arbitrary code exploiting a buffer overflow vulnerability.\relax }}{38}{figure.caption.44}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.11}{\ignorespaces TCP 3-way handshake.\relax }}{50}{figure.caption.46}% +\contentsline {figure}{\numberline {2.21}{\ignorespaces Steps for executing code sample using ROP.\relax }}{40}{figure.caption.45}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.12}{\ignorespaces TCP packet retransmission on timeout.\relax }}{51}{figure.caption.47}% +\contentsline {figure}{\numberline {2.22}{\ignorespaces Ethernet frame with TCP/IP packet.\relax }}{42}{figure.caption.46}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {3.13}{\ignorespaces Technique to duplicate a packet for exfiltrating data.\relax }}{53}{figure.caption.48}% +\contentsline {figure}{\numberline {2.23}{\ignorespaces TCP 3-way handshake.\relax }}{44}{figure.caption.48}% +\defcounter {refsection}{0}\relax +\contentsline {figure}{\numberline {2.24}{\ignorespaces TCP packet retransmission on timeout.\relax }}{45}{figure.caption.49}% +\defcounter {refsection}{0}\relax +\contentsline {figure}{\numberline {2.25}{\ignorespaces PLT stub for timerfd\_settime, seen from gdb-peda.\relax }}{48}{figure.caption.52}% +\defcounter {refsection}{0}\relax +\contentsline {figure}{\numberline {2.26}{\ignorespaces Inspecting address stored in GOT section before dynamic linking, seen from gdb-peda.\relax }}{48}{figure.caption.53}% +\defcounter {refsection}{0}\relax +\contentsline {figure}{\numberline {2.27}{\ignorespaces Inspecting address stored in GOT section after dynamic linking, seen from gdb-peda.\relax }}{48}{figure.caption.54}% +\defcounter {refsection}{0}\relax +\contentsline {figure}{\numberline {2.28}{\ignorespaces Glibc function to which PLT jumps using address stored at GOT, seen from gdb-peda.\relax }}{48}{figure.caption.55}% \defcounter {refsection}{0}\relax \addvspace {10\p@ } \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.1}{\ignorespaces Execution hijack overwriting saved rip value.\relax }}{57}{figure.caption.49}% +\contentsline {figure}{\numberline {3.1}{\ignorespaces Overview of stack scanning and writing technique.\relax }}{60}{figure.caption.58}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.2}{\ignorespaces Stack buffer overflow overwriting ret value.\relax }}{58}{figure.caption.50}% +\contentsline {figure}{\numberline {3.2}{\ignorespaces Technique to duplicate a packet for exfiltrating data.\relax }}{64}{figure.caption.59}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.3}{\ignorespaces Executing arbitrary code exploiting a buffer overflow vulnerability.\relax }}{59}{figure.caption.51}% +\addvspace {10\p@ } \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.4}{\ignorespaces Steps for executing code sample using ROP.\relax }}{61}{figure.caption.52}% +\contentsline {figure}{\numberline {4.1}{\ignorespaces Initial setup for the ROP with eBPF technique.\relax }}{67}{figure.caption.60}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.5}{\ignorespaces Initial setup for the ROP with eBPF technique.\relax }}{62}{figure.caption.53}% +\contentsline {figure}{\numberline {4.2}{\ignorespaces Process memory after syscall exits and ROP code overwrites the stack.\relax }}{68}{figure.caption.61}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.6}{\ignorespaces Process memory after syscall exits and ROP code overwrites the stack.\relax }}{63}{figure.caption.54}% +\contentsline {figure}{\numberline {4.3}{\ignorespaces Stack data is restored and program continues its execution.\relax }}{69}{figure.caption.62}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.7}{\ignorespaces Stack data is restored and program continues its execution.\relax }}{64}{figure.caption.55}% +\contentsline {figure}{\numberline {4.4}{\ignorespaces Two runs of the same executable using ASLR, showing a library and two symbols.\relax }}{70}{figure.caption.63}% \defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.8}{\ignorespaces PLT stub for timerfd\_settime, seen from gdb-peda.\relax }}{66}{figure.caption.58}% -\defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.9}{\ignorespaces Inspecting address stored in GOT section before dynamic linking, seen from gdb-peda.\relax }}{66}{figure.caption.59}% -\defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.10}{\ignorespaces Inspecting address stored in GOT section after dynamic linking, seen from gdb-peda.\relax }}{67}{figure.caption.60}% -\defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.11}{\ignorespaces Glibc function to which PLT jumps using address stored at GOT, seen from gdb-peda.\relax }}{67}{figure.caption.61}% -\defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.12}{\ignorespaces Two runs of the same executable using ASLR, showing a library and two symbols.\relax }}{69}{figure.caption.63}% -\defcounter {refsection}{0}\relax -\contentsline {figure}{\numberline {4.13}{\ignorespaces Call to the glibc function, using objdump\relax }}{71}{figure.caption.64}% +\contentsline {figure}{\numberline {4.5}{\ignorespaces Call to the glibc function, using objdump\relax }}{72}{figure.caption.64}% \defcounter {refsection}{0}\relax \addvspace {10\p@ } \defcounter {refsection}{0}\relax diff --git a/docs/document.log b/docs/document.log index ce66c2f..8764466 100644 --- a/docs/document.log +++ b/docs/document.log @@ -1,4 +1,4 @@ -This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020/Debian) (preloaded format=pdflatex 2022.4.27) 9 JUN 2022 22:56 +This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020/Debian) (preloaded format=pdflatex 2022.4.27) 11 JUN 2022 12:59 entering extended mode restricted \write18 enabled. %&-line parsing enabled. @@ -1089,7 +1089,7 @@ File: t1txss.fd 2000/12/15 v3.1 ) LaTeX Font Info: Font shape `T1/txss/m/n' will be (Font) scaled to size 11.39996pt on input line 186. - + File: images//Portada_Logo.png Graphic file (type png) Package pdftex.def Info: images//Portada_Logo.png used on input line 190. @@ -1102,7 +1102,7 @@ LaTeX Font Info: Font shape `T1/txss/m/n' will be (Font) scaled to size 23.63593pt on input line 201. LaTeX Font Info: Font shape `T1/txss/m/n' will be (Font) scaled to size 19.70294pt on input line 205. - + File: images/creativecommons.png Graphic file (type png) Package pdftex.def Info: images/creativecommons.png used on input line 215. @@ -1193,90 +1193,87 @@ File: utxsyc.fd 2000/12/15 v3.1 \tf@lot=\write8 \openout8 = `document.lot'. - [15] [16] + [15] [16] (./chapters/chapter1.tex Chapter 1. -LaTeX Font Info: Trying to load font information for TS1+txr on input line 3 -30. +LaTeX Font Info: Trying to load font information for TS1+txr on input line 1 +8. (/usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txr.fd File: ts1txr.fd 2000/12/15 v3.1 ) [1 ] [2] -Overfull \hbox (0.50073pt too wide) in paragraph at lines 355--356 +Overfull \hbox (0.50073pt too wide) in paragraph at lines 43--44 []\T1/txr/m/n/12 Subsequent talks on 2021 by Pat Hogan at DE-F-CON 29[[][]9[][] ], and by Guil-laume Fournier [] -[3] [4] +[3]) (./chapters/chapter2.tex [4] Chapter 2. - -LaTeX Warning: Reference `section:TODO' on page 5 undefined on input line 413. - - + File: images//classic_bpf.jpg Graphic file (type jpg) -Package pdftex.def Info: images//classic_bpf.jpg used on input line 427. +Package pdftex.def Info: images//classic_bpf.jpg used on input line 20. (pdftex.def) Requested size: 341.43306pt x 251.12224pt. [5 ] [6 <./images//classic_bpf.jpg>] - + File: images//cbpf_prog.jpg Graphic file (type jpg) -Package pdftex.def Info: images//cbpf_prog.jpg used on input line 454. +Package pdftex.def Info: images//cbpf_prog.jpg used on input line 47. (pdftex.def) Requested size: 227.62204pt x 254.80415pt. [7 <./images/cBPF_prog.jpg>] - + File: images//bpf_instructions.png Graphic file (type png) -Package pdftex.def Info: images//bpf_instructions.png used on input line 494. +Package pdftex.def Info: images//bpf_instructions.png used on input line 87. (pdftex.def) Requested size: 227.62204pt x 283.99998pt. [8 <./images//bpf_instructions.png>] - + File: images//bpf_address_mode.png Graphic file (type png) -Package pdftex.def Info: images//bpf_address_mode.png used on input line 510. +Package pdftex.def Info: images//bpf_address_mode.png used on input line 103. (pdftex.def) Requested size: 227.62204pt x 171.19905pt. [9 <./images//bpf_address_mode.png>] - + File: images//tcpdump_example.png Graphic file (type png) -Package pdftex.def Info: images//tcpdump_example.png used on input line 525. +Package pdftex.def Info: images//tcpdump_example.png used on input line 118. (pdftex.def) Requested size: 284.52756pt x 241.82869pt. - + File: images//cBPF_prog_ex_sol.png Graphic file (type png) -Package pdftex.def Info: images//cBPF_prog_ex_sol.png used on input line 536. +Package pdftex.def Info: images//cBPF_prog_ex_sol.png used on input line 129. (pdftex.def) Requested size: 170.71652pt x 225.74026pt. [10 <./images//tcpdump_example.png>] [11 <./images//cBPF_prog_ex_sol.png>] - + File: images//ebpf_arch.jpg Graphic file (type jpg) -Package pdftex.def Info: images//ebpf_arch.jpg used on input line 575. +Package pdftex.def Info: images//ebpf_arch.jpg used on input line 168. (pdftex.def) Requested size: 426.79134pt x 272.75464pt. [12 <./images//ebpf_arch.jpg>] -Overfull \hbox (3.10062pt too wide) in paragraph at lines 602--619 +Overfull \hbox (3.10062pt too wide) in paragraph at lines 195--212 [][] [] [13] -Overfull \hbox (17.02478pt too wide) in paragraph at lines 628--629 +Overfull \hbox (17.02478pt too wide) in paragraph at lines 221--222 []\T1/txr/m/n/12 Therefore, when us-ing JIT com-pil-ing (a set-ting de-fined by the vari-able \T1/txr/m/it/12 bpf_jit_enable\T1/txr/m/n/12 [[][]30[][]], [] [14] -Overfull \hbox (56.55217pt too wide) in paragraph at lines 679--690 +Overfull \hbox (56.55217pt too wide) in paragraph at lines 272--283 [][] [] -LaTeX Warning: Reference `table:ebpf_maps' on page 15 undefined on input line 6 -94. +LaTeX Warning: Reference `table:ebpf_maps' on page 15 undefined on input line 2 +87. -Overfull \hbox (11.26865pt too wide) in paragraph at lines 694--695 +Overfull \hbox (11.26865pt too wide) in paragraph at lines 287--288 \T1/txr/m/n/12 de-vel-op-ment of our rootkit, we will mainly fo-cus on hash map s (BPF_MAP_TYPE_HASH), [] @@ -1284,71 +1281,130 @@ s (BPF_MAP_TYPE_HASH), [15] LaTeX Warning: Reference `table:bpf_syscall' on page 16 undefined on input line - 704. + 297. -Overfull \hbox (42.01218pt too wide) in paragraph at lines 707--723 +Overfull \hbox (42.01218pt too wide) in paragraph at lines 300--316 [][] [] [16] -LaTeX Warning: Reference `section:TODO' on page 17 undefined on input line 750. +LaTeX Warning: Reference `section:TODO' on page 17 undefined on input line 343. -Overfull \hbox (13.5802pt too wide) in paragraph at lines 760--790 +Overfull \hbox (13.5802pt too wide) in paragraph at lines 353--383 [][] [] [17] - + File: images//xdp_diag.jpg Graphic file (type jpg) -Package pdftex.def Info: images//xdp_diag.jpg used on input line 806. +Package pdftex.def Info: images//xdp_diag.jpg used on input line 399. (pdftex.def) Requested size: 426.79134pt x 310.69934pt. [18] [19 <./images//xdp_diag.jpg>] -Overfull \hbox (5.80417pt too wide) in paragraph at lines 869--881 +Overfull \hbox (5.80417pt too wide) in paragraph at lines 462--474 [][] [] [20] [21] [22] [23] - + File: images//libbpf_prog.jpg Graphic file (type jpg) -Package pdftex.def Info: images//libbpf_prog.jpg used on input line 979. +Package pdftex.def Info: images//libbpf_prog.jpg used on input line 572. (pdftex.def) Requested size: 341.43306pt x 316.20142pt. [24] -LaTeX Warning: Reference `TODO' on page 25 undefined on input line 1007. +LaTeX Warning: Reference `TODO' on page 25 undefined on input line 600. -[25 <./images//libbpf_prog.jpg>] [26] -Chapter 3. - -Overfull \hbox (15.27466pt too wide) in paragraph at lines 1030--1058 +[25 <./images//libbpf_prog.jpg>] +Overfull \hbox (15.27466pt too wide) in paragraph at lines 608--636 [][] [] -[27 -] -Overfull \hbox (144.2746pt too wide) in paragraph at lines 1070--1071 +Overfull \hbox (144.2746pt too wide) in paragraph at lines 648--649 []\T1/txr/bx/n/12 Unprivileged users \T1/txr/m/n/12 can only load and at-tach e -BPF pro-grams of type BPF_PROG_TYPE_SOCKET_FILTER[[][]53[][]], +BPF pro-grams of type BPF_PROG_TYPE_SOCKET_FILTER[[][]68[][]], [] -[28] -Overfull \hbox (33.33205pt too wide) in paragraph at lines 1096--1097 +[26] +Overfull \hbox (33.33205pt too wide) in paragraph at lines 674--675 []\T1/txr/m/n/12 Therefore, eBPF net-work pro-grams usu-ally re-quire both CAP_ BPF and CAP_NET_ADMIN, [] -[29] -Overfull \hbox (18.75664pt too wide) in paragraph at lines 1126--1127 -\T1/txr/m/n/12 can also ex-plore all the avail-able maps in the sys-tem by us-i -ng the BPF_MAP_GET_NEXT_ID +[27] + +File: images//mem_arch_pages.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//mem_arch_pages.jpg used on input line 711. +(pdftex.def) Requested size: 369.88582pt x 271.00914pt. + [28 <./images//mem_arch_pages.jpg>] + +File: images//mem_major_page_fault.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//mem_major_page_fault.jpg used on input line 7 +21. +(pdftex.def) Requested size: 312.9803pt x 208.32661pt. + +File: images//mem_minor_page_fault.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//mem_minor_page_fault.jpg used on input line 7 +29. +(pdftex.def) Requested size: 312.9803pt x 265.45834pt. + [29 <./images//mem_major_page_fault.jpg>] + +File: images//memory.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//memory.jpg used on input line 739. +(pdftex.def) Requested size: 170.71652pt x 313.25488pt. + [30 <./images//mem_minor_page_fault.jpg>] +Overfull \hbox (0.23746pt too wide) in paragraph at lines 744--745 +[]\T1/txr/m/n/12 Figure [][]2.13[][] de-scribes how vir-tual mem-ory is dis-tri +buted within a pro-cess in the x86_64 [] +[31 <./images//memory.jpg>] + +File: images//stack_pres.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//stack_pres.jpg used on input line 763. +(pdftex.def) Requested size: 398.33858pt x 159.33606pt. + [32 <./images//stack_pres.jpg>] + +File: images//stack_ops.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//stack_ops.jpg used on input line 797. +(pdftex.def) Requested size: 284.52756pt x 376.47473pt. +LaTeX Font Info: Trying to load font information for T1+txtt on input line 8 +04. + +(/usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd +File: t1txtt.fd 2000/12/15 v3.1 +) + +File: images//stack_before.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//stack_before.jpg used on input line 808. +(pdftex.def) Requested size: 398.33858pt x 176.16635pt. + [33 <./images//stack_ops.jpg>] + +File: images//stack.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//stack.jpg used on input line 815. +(pdftex.def) Requested size: 398.33858pt x 214.70816pt. + [34 <./images//stack_before.jpg> <./images//stack.jpg>] + +File: images//stack_ret_hij_simple.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//stack_ret_hij_simple.jpg used on input line 8 +55. +(pdftex.def) Requested size: 426.79134pt x 371.51205pt. + [35] +[36 <./images//stack_ret_hij_simple.jpg>] (/usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty File: lstlang1.sty 2020/03/24 1.8d listings language file ) @@ -1356,456 +1412,399 @@ File: lstlang1.sty 2020/03/24 1.8d listings language file File: lstmisc.sty 2020/03/24 1.8d (Carsten Heinz) ) Package hyperref Info: bookmark level for unknown lstlisting defaults to 0 on i -nput line 1142. - [30] -LaTeX Font Info: Trying to load font information for T1+txtt on input line 1 -142. - -(/usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd -File: t1txtt.fd 2000/12/15 v3.1 -) +nput line 867. LaTeX Font Info: Font shape `T1/txtt/b/n' in size <10> not available -(Font) Font shape `T1/txtt/bx/n' tried instead on input line 1144. - - [31] [32] -Overfull \hbox (55.2727pt too wide) in paragraph at lines 1286--1287 -\T1/txr/m/n/12 As we in-tro-duced in the pre-vi-ous sub-sec-tion, the bpf_probe -_read_user() and bpf_probe_read_kernel() - [] - -[33] - -LaTeX Warning: Reference `subsection_bpf_probe_write_apps' on page 34 undefined - on input line 1290. - - -Overfull \hbox (47.97661pt too wide) in paragraph at lines 1295--1296 -\T1/txr/m/n/12 helper. It will only work if the ker-nel was com-piled with the -CON-FIG_BPF_KPROBE_OVERRIDE - [] - -[34] -Overfull \hbox (62.0767pt too wide) in paragraph at lines 1337--1338 -\T1/txr/m/n/12 the bounds of func-tion pa-ram-e-ters via the helpers bpf_probe_ -read_user() and bpf_probe_read_kernel(). - [] - -[35] - -File: images//mem_arch_pages.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//mem_arch_pages.jpg used on input line 1350. -(pdftex.def) Requested size: 369.88582pt x 271.00914pt. - [36] - -File: images//mem_major_page_fault.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//mem_major_page_fault.jpg used on input line 1 -360. -(pdftex.def) Requested size: 312.9803pt x 208.32661pt. - [37 <./images//mem_arch_pages.jpg>] - -File: images//mem_minor_page_fault.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//mem_minor_page_fault.jpg used on input line 1 -368. -(pdftex.def) Requested size: 312.9803pt x 265.45834pt. - -File: images//memory.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//memory.jpg used on input line 1379. -(pdftex.def) Requested size: 170.71652pt x 313.25488pt. - [38 <./images//mem_major_page_fault.jpg> <./images//mem_minor_page_fault.jpg>] - [39 <./images//memory.jpg>] - -File: images//stack_pres.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//stack_pres.jpg used on input line 1403. -(pdftex.def) Requested size: 398.33858pt x 159.33606pt. - -[40 <./images//stack_pres.jpg>] - -File: images//stack_ops.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//stack_ops.jpg used on input line 1437. -(pdftex.def) Requested size: 284.52756pt x 376.47473pt. - [41] - -File: images//stack_before.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//stack_before.jpg used on input line 1448. -(pdftex.def) Requested size: 398.33858pt x 176.16635pt. - -File: images//stack.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//stack.jpg used on input line 1455. -(pdftex.def) Requested size: 398.33858pt x 214.70816pt. - [42 <./images//stack_ops.jpg> <./images//stack_before.jpg>] [43 <./images//sta -ck.jpg>] [44] -Overfull \hbox (3.09538pt too wide) in paragraph at lines 1499--1500 -\T1/txr/m/n/12 trac-ing pro-grams can read any user mem-ory lo-ca-tion with the - bpf_probe_read_user() - [] - - -File: images//stack_scan_write_tech.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//stack_scan_write_tech.jpg used on input line -1515. -(pdftex.def) Requested size: 455.24408pt x 173.0548pt. - -Overfull \hbox (28.45273pt too wide) in paragraph at lines 1515--1516 - [][] - [] - -[45] - -LaTeX Warning: Reference `TODO' on page 46 undefined on input line 1537. - -[46 <./images//stack_scan_write_tech.jpg>] [47] - -File: images//frame.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//frame.jpg used on input line 1573. -(pdftex.def) Requested size: 398.33858pt x 404.07954pt. - [48 <./images//frame.jpg>] -[49] - -File: images//tcp_conn.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//tcp_conn.jpg used on input line 1621. -(pdftex.def) Requested size: 341.43306pt x 305.84947pt. - -Overfull \hbox (30.78944pt too wide) in paragraph at lines 1626--1627 -[]\T1/txr/m/n/12 As we can ob-serve in the fig-ure, the hosts in-ter-change a s -e-quence of , , - [] - -[50 <./images//tcp_conn.jpg>] - -File: images//tcp_retransmission.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//tcp_retransmission.jpg used on input line 163 -7. -(pdftex.def) Requested size: 341.43306pt x 316.58401pt. - [51 <./images//tcp_retransmission.jpg>] [52] - -File: images//tcp_exfiltrate_retrans.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//tcp_exfiltrate_retrans.jpg used on input line - 1674. -(pdftex.def) Requested size: 426.79134pt x 320.60597pt. - -[53 <./images//tcp_exfiltrate_retrans.jpg>] [54] -Chapter 4. -[55 - -] - -File: images//stack_ret_hij_simple.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//stack_ret_hij_simple.jpg used on input line 1 -730. -(pdftex.def) Requested size: 426.79134pt x 371.51205pt. - [56] [57 <./images//stack_ret_hij_simple.jpg>] - +(Font) Font shape `T1/txtt/bx/n' tried instead on input line 868. + File: images//buffer_overflow.jpg Graphic file (type jpg) -Package pdftex.def Info: images//buffer_overflow.jpg used on input line 1755. +Package pdftex.def Info: images//buffer_overflow.jpg used on input line 883. (pdftex.def) Requested size: 426.79134pt x 207.03964pt. - + File: images//buffer_overflow_shellcode.jpg Graphic file (type jpg) Package pdftex.def Info: images//buffer_overflow_shellcode.jpg used on input l -ine 1766. +ine 894. (pdftex.def) Requested size: 426.79134pt x 228.8333pt. - [58 <./images//buffer_overflow.jpg>] + [37 <./images//buffer_overflow.jpg>] -LaTeX Warning: Reference `TODO probably an Annex' on page 59 undefined on input - line 1771. +LaTeX Warning: Reference `TODO probably an Annex' on page 38 undefined on input + line 899. -LaTeX Warning: Reference `TODO' on page 59 undefined on input line 1781. +LaTeX Warning: Reference `TODO' on page 38 undefined on input line 911. -[59 <./images//buffer_overflow_shellcode.jpg>] - +[38 <./images//buffer_overflow_shellcode.jpg>] + File: images//ROPcompound.jpg Graphic file (type jpg) -Package pdftex.def Info: images//ROPcompound.jpg used on input line 1803. +Package pdftex.def Info: images//ROPcompound.jpg used on input line 933. (pdftex.def) Requested size: 455.24408pt x 277.65909pt. -Overfull \hbox (28.45273pt too wide) in paragraph at lines 1803--1804 +Overfull \hbox (28.45273pt too wide) in paragraph at lines 933--934 [][] [] -[60] +[39] -LaTeX Warning: Reference `TODO' on page 61 undefined on input line 1815. +LaTeX Warning: Reference `TODO' on page 40 undefined on input line 945. -[61 <./images//ROPcompound.jpg>] - -File: images//rop_evil_ebpf_1.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//rop_evil_ebpf_1.jpg used on input line 1824. -(pdftex.def) Requested size: 426.79134pt x 213.66933pt. - - -LaTeX Warning: Reference `TODO' on page 62 undefined on input line 1831. - -[62 <./images//rop_evil_ebpf_1.jpg>] -Overfull \hbox (4.42868pt too wide) in paragraph at lines 1840--1841 -\T1/txr/m/n/12 the orig-i-nal data later) and we pro-ceed to over-write the sta -ck us-ing bpf_probe_write_user(), +[40 <./images//ROPcompound.jpg>] + +File: images//frame.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//frame.jpg used on input line 958. +(pdftex.def) Requested size: 398.33858pt x 404.07954pt. + [41] [42 <./images//frame.jpg>] + +File: images//tcp_conn.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//tcp_conn.jpg used on input line 1006. +(pdftex.def) Requested size: 341.43306pt x 305.84947pt. + [43] +Overfull \hbox (0.11748pt too wide) in paragraph at lines 1011--1012 +[]\T1/txr/m/n/12 As we can ob-serve in the fig-ure, the hosts in-ter-change a s +e-quence of SYN, SYN+ACK, [] - -File: images//rop_evil_ebpf_2.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//rop_evil_ebpf_2.jpg used on input line 1844. -(pdftex.def) Requested size: 426.79134pt x 213.66933pt. -[63 <./images//rop_evil_ebpf_2.jpg>] - -File: images//rop_evil_ebpf_3.jpg Graphic file (type jpg) - -Package pdftex.def Info: images//rop_evil_ebpf_3.jpg used on input line 1855. -(pdftex.def) Requested size: 426.79134pt x 199.5693pt. - [64 <./images//rop_evil_ebpf_3.jpg>] -Overfull \hbox (1.1025pt too wide) in paragraph at lines 1895--1896 + +File: images//tcp_retransmission.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//tcp_retransmission.jpg used on input line 102 +2. +(pdftex.def) Requested size: 341.43306pt x 316.58401pt. +[44 <./images//tcp_conn.jpg>] [45 <./images//tcp_retransmission.jpg>] +Overfull \hbox (1.1025pt too wide) in paragraph at lines 1061--1062 []|\T1/txr/m/n/12 Permissions| [] -Overfull \hbox (5.55525pt too wide) in paragraph at lines 1904--1904 +Overfull \hbox (5.55525pt too wide) in paragraph at lines 1070--1070 []|\T1/txr/m/n/12 .got.plt| [] -Overfull \hbox (5.55525pt too wide) in paragraph at lines 1906--1906 +Overfull \hbox (5.55525pt too wide) in paragraph at lines 1072--1072 []|\T1/txr/m/n/12 .plt.got| [] +[46] -LaTeX Warning: Reference `TODO' on page 65 undefined on input line 1919. +LaTeX Warning: Reference `TODO' on page 47 undefined on input line 1085. -[65] -Overfull \hbox (26.32735pt too wide) in paragraph at lines 1925--1926 -\T1/txr/m/n/12 stub (in the .plt sec-tion) is called. Snip-pet [][]4.3[][] show + +Overfull \hbox (26.32735pt too wide) in paragraph at lines 1091--1092 +\T1/txr/m/n/12 stub (in the .plt sec-tion) is called. Snip-pet [][]2.3[][] show s a call to the func-tion timerfd_settime, [] - +[47] + File: images//sch_gdb_plt.png Graphic file (type png) -Package pdftex.def Info: images//sch_gdb_plt.png used on input line 1938. +Package pdftex.def Info: images//sch_gdb_plt.png used on input line 1104. (pdftex.def) Requested size: 441.01772pt x 62.09065pt. -Overfull \hbox (14.22636pt too wide) in paragraph at lines 1938--1939 +Overfull \hbox (14.22636pt too wide) in paragraph at lines 1104--1105 [][] [] - + File: images//sch_gdb_got_prev.png Graphic file (type png) -Package pdftex.def Info: images//sch_gdb_got_prev.png used on input line 1945. +Package pdftex.def Info: images//sch_gdb_got_prev.png used on input line 1111. (pdftex.def) Requested size: 441.01772pt x 32.57559pt. -Overfull \hbox (14.22636pt too wide) in paragraph at lines 1945--1946 +Overfull \hbox (14.22636pt too wide) in paragraph at lines 1111--1112 [][] [] -[66 <./images//sch_gdb_plt.png> <./images//sch_gdb_got_prev.png>] - + File: images//sch_gdb_got_after.png Graphic file (type png) -Package pdftex.def Info: images//sch_gdb_got_after.png used on input line 1954 +Package pdftex.def Info: images//sch_gdb_got_after.png used on input line 1120 . (pdftex.def) Requested size: 441.01772pt x 34.05334pt. -Overfull \hbox (14.22636pt too wide) in paragraph at lines 1954--1955 +Overfull \hbox (14.22636pt too wide) in paragraph at lines 1120--1121 [][] [] - + File: images//sch_glibc_func.png Graphic file (type png) -Package pdftex.def Info: images//sch_glibc_func.png used on input line 1961. +Package pdftex.def Info: images//sch_glibc_func.png used on input line 1127. (pdftex.def) Requested size: 441.01772pt x 67.32729pt. -Overfull \hbox (14.22636pt too wide) in paragraph at lines 1961--1962 +Overfull \hbox (14.22636pt too wide) in paragraph at lines 1127--1128 [][] [] -[67 <./images//sch_gdb_got_after.png> <./images//sch_glibc_func.png>] +[48 <./images//sch_gdb_plt.png> <./images//sch_gdb_got_prev.png> <./images//sch +_gdb_got_after.png> <./images//sch_glibc_func.png>] [49] [50]) +(./chapters/chapter3.tex [51] +Chapter 3. -LaTeX Warning: Reference `table:aslr_offset' on page 68 undefined on input line - 2008. +Overfull \hbox (18.75664pt too wide) in paragraph at lines 21--22 +\T1/txr/m/n/12 can also ex-plore all the avail-able maps in the sys-tem by us-i +ng the BPF_MAP_GET_NEXT_ID + [] - +[52 + +] [53] [54] [55] +Overfull \hbox (55.2727pt too wide) in paragraph at lines 181--182 +\T1/txr/m/n/12 As we in-tro-duced in the pre-vi-ous sub-sec-tion, the bpf_probe +_read_user() and bpf_probe_read_kernel() + [] + + +LaTeX Warning: Reference `subsection_bpf_probe_write_apps' on page 56 undefined + on input line 185. + +[56] +Overfull \hbox (47.97661pt too wide) in paragraph at lines 190--191 +\T1/txr/m/n/12 helper. It will only work if the ker-nel was com-piled with the +CON-FIG_BPF_KPROBE_OVERRIDE + [] + +[57] +Overfull \hbox (62.0767pt too wide) in paragraph at lines 232--233 +\T1/txr/m/n/12 the bounds of func-tion pa-ram-e-ters via the helpers bpf_probe_ +read_user() and bpf_probe_read_kernel(). + [] + +[58] [59] +Overfull \hbox (3.09538pt too wide) in paragraph at lines 257--258 +\T1/txr/m/n/12 trac-ing pro-grams can read any user mem-ory lo-ca-tion with the + bpf_probe_read_user() + [] + + +File: images//stack_scan_write_tech.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//stack_scan_write_tech.jpg used on input line +273. +(pdftex.def) Requested size: 455.24408pt x 173.0548pt. + +Overfull \hbox (28.45273pt too wide) in paragraph at lines 273--274 + [][] + [] + +[60 <./images//stack_scan_write_tech.jpg>] + +LaTeX Warning: Reference `TODO' on page 61 undefined on input line 295. + +[61] [62] [63] + +File: images//tcp_exfiltrate_retrans.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//tcp_exfiltrate_retrans.jpg used on input line + 355. +(pdftex.def) Requested size: 426.79134pt x 320.60597pt. + [64 <./images//tcp_exfiltrate_retrans.jpg>]) +(./chapters/chapter4.tex [65] +Chapter 4. +[66 + +] + +LaTeX Warning: Reference `TODO EVALUATION' on page 67 undefined on input line 2 +2. + + +File: images//rop_evil_ebpf_1.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//rop_evil_ebpf_1.jpg used on input line 30. +(pdftex.def) Requested size: 426.79134pt x 213.66933pt. + +LaTeX Warning: Reference `TODO' on page 67 undefined on input line 38. + +[67 <./images//rop_evil_ebpf_1.jpg>] +Overfull \hbox (4.42868pt too wide) in paragraph at lines 47--48 +\T1/txr/m/n/12 the orig-i-nal data later) and we pro-ceed to over-write the sta +ck us-ing bpf_probe_write_user(), + [] + + +File: images//rop_evil_ebpf_2.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//rop_evil_ebpf_2.jpg used on input line 51. +(pdftex.def) Requested size: 426.79134pt x 213.66933pt. +[68 <./images//rop_evil_ebpf_2.jpg>] + +File: images//rop_evil_ebpf_3.jpg Graphic file (type jpg) + +Package pdftex.def Info: images//rop_evil_ebpf_3.jpg used on input line 62. +(pdftex.def) Requested size: 426.79134pt x 199.5693pt. + [69 <./images//rop_evil_ebpf_3.jpg>] + +LaTeX Warning: Reference `table:aslr_offset' on page 70 undefined on input line + 85. + + File: images//aslr_offset.jpg Graphic file (type jpg) -Package pdftex.def Info: images//aslr_offset.jpg used on input line 2013. +Package pdftex.def Info: images//aslr_offset.jpg used on input line 90. (pdftex.def) Requested size: 369.88582pt x 169.0915pt. -[68] - -LaTeX Warning: Citation 'relro_redhat' on page 69 undefined on input line 2026. - - - -LaTeX Warning: Citation 'cet_windows' on page 69 undefined on input line 2032. - - -LaTeX Warning: Citation 'cet_linux' on page 69 undefined on input line 2032. - -[69 <./images//aslr_offset.jpg>] -Overfull \hbox (0.26146pt too wide) in paragraph at lines 2042--2043 +[70 <./images//aslr_offset.jpg>] +Overfull \hbox (0.26146pt too wide) in paragraph at lines 113--114 []\T1/txr/m/n/12 This tech-nique works both in com-pil-ers with low hard-en-ing fe-tau-res by de-fault (Clang) [] -Overfull \hbox (38.05193pt too wide) in paragraph at lines 2046--2048 +Overfull \hbox (38.05193pt too wide) in paragraph at lines 117--119 \T1/txr/m/n/12 We load and at-tach a tra-ce-point eBPF pro-gram at the \T1/txr/ m/it/12 en-ter \T1/txr/m/n/12 po-si-tion of syscall sys_timerfd_settime. [] - +[71] + File: images//sch_firstcall.png Graphic file (type png) -Package pdftex.def Info: images//sch_firstcall.png used on input line 2056. +Package pdftex.def Info: images//sch_firstcall.png used on input line 127. (pdftex.def) Requested size: 369.88582pt x 52.51244pt. -[70] [71 <./images//sch_firstcall.png>] +) (./chapters/chapter5.tex [72 <./images//sch_firstcall.png>] Chapter 5. -[72 +) (./chapters/chapter6.tex [73 ] Chapter 6. -[73 +) [74 ] -Overfull \hbox (5.34976pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (5.34976pt too wide) in paragraph at lines 338--338 \T1/txtt/m/n/12 threat -[] intelligence / cyber -[] year -[] in -[] retrospect / yir -[] cyber -[] threats -[] [] -[74 +[75 ] -Overfull \hbox (6.22696pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (6.22696pt too wide) in paragraph at lines 338--338 []\T1/txr/m/it/12 Bpf fea-tures by linux ker-nel ver-sion\T1/txr/m/n/12 , io-vi -sor. [On-line]. Avail-able: [][]$\T1/txtt/m/n/12 https : / / github . [] -Overfull \hbox (7.34976pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (7.34976pt too wide) in paragraph at lines 338--338 [][]$\T1/txtt/m/n/12 https : / / ebpf . io / what -[] is -[] ebpf / #loader -[] -[] verification -[] architecture$[][]\T1/txr/m/n/12 . [] -Overfull \hbox (21.24973pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (21.24973pt too wide) in paragraph at lines 338--338 \T1/txtt/m/n/12 vger . kernel . org / netconf2015Starovoitov -[] bpf _ collabsu mmit _ 2015feb20 . [] -[75] -Overfull \hbox (9.14975pt too wide) in paragraph at lines 2102--2102 +[76] +Overfull \hbox (9.14975pt too wide) in paragraph at lines 338--338 \T1/txtt/m/n/12 ch02 . xhtml# :-[]: text = With % 20JIT % 20compiled % 20code % 2C % 20i ,[] %20other % [] -Overfull \hbox (6.49615pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (6.49615pt too wide) in paragraph at lines 338--338 []\T1/txr/m/n/12 D. Lavie. ^^P A gen-tle in-tro-duc-tion to xdp.^^Q (Feb. 3, 2 022), [On-line]. Avail-able: [][]$\T1/txtt/m/n/12 https : [] -[76] -Overfull \hbox (0.76683pt too wide) in paragraph at lines 2102--2102 +[77] +Overfull \hbox (0.76683pt too wide) in paragraph at lines 338--338 []\T1/txr/m/n/12 ^^P Bpf next ker-nel tree.^^Q (), [On-line]. Avail-able: [][] $\T1/txtt/m/n/12 https : / / kernel . googlesource . [] -Overfull \hbox (14.49278pt too wide) in paragraph at lines 2102--2102 -[]\T1/txr/m/it/12 Capabilities - overview of linux ca-pa-bil-i-ties\T1/txr/m/n/ -12 . [On-line]. Avail-able: [][]$\T1/txtt/m/n/12 http : / / manpages . - [] - -[77] -Overfull \hbox (53.32059pt too wide) in paragraph at lines 2102--2102 -\T1/txr/m/it/12 sup-ple-ment\T1/txr/m/n/12 , Jan. 28, 2018, p. 148. [On-line]. -Avail-able: [][]$\T1/txtt/m/n/12 https : / / raw . githubusercontent . - [] - - -Overfull \hbox (33.3497pt too wide) in paragraph at lines 2102--2102 -\T1/txtt/m/n/12 20CON % 2029 % 20presentations / Guillaume % 20Fournier % 20Syl -vain % 20Afchain % - [] - - -Overfull \hbox (9.33742pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (9.33742pt too wide) in paragraph at lines 338--338 \T1/txr/m/n/12 Avail-able: [][]$\T1/txtt/m/n/12 https : / / events19 . linuxfou ndation . org / wp -[] content / uploads / [] -Overfull \hbox (18.44974pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (18.44974pt too wide) in paragraph at lines 338--338 \T1/txtt/m/n/12 2017 / 12 / MM -[] 101 -[] Introduction -[] to -[] Linux -[] Me mory -[] Management -[] Christoph -[] [] -Overfull \hbox (5.92503pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (5.92503pt too wide) in paragraph at lines 338--338 []\T1/txr/m/n/12 D. Breaker. ^^P Un-der-stand-ing page faults and mem-ory swap -in/outs.^^Q (Aug. 19, 2019), [] -Overfull \hbox (40.56133pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (40.56133pt too wide) in paragraph at lines 338--338 \T1/txr/m/n/12 able: [][]$\T1/txtt/m/n/12 https : / / h3xduck . github . io / e xploit / 2021 / 05 / 23 / stackbufferoverflow -[] [] -Overfull \hbox (47.32059pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (47.32059pt too wide) in paragraph at lines 338--338 \T1/txr/m/it/12 sup-ple-ment\T1/txr/m/n/12 , Jan. 28, 2018, p. 18. [On-line]. A vail-able: [][]$\T1/txtt/m/n/12 https : / / raw . githubusercontent . [] -[78] -Overfull \hbox (11.10025pt too wide) in paragraph at lines 2102--2102 -\T1/txr/m/n/12 DE-F-CON 27, pp. 69^^U74. [On-line]. Avail-able: [][]$\T1/txtt/m -/n/12 https : / / raw . githubusercontent . + +Overfull \hbox (18.27475pt too wide) in paragraph at lines 338--338 +[]\T1/txr/m/n/12 ^^P Rop-gad-get tool.^^Q (), [On-line]. Avail-able: [][]$\T1/ +txtt/m/n/12 https : / / github . com / JonathanSalwan / [] -Overfull \hbox (39.98859pt too wide) in paragraph at lines 2102--2102 -\T1/txr/m/it/12 ment\T1/txr/m/n/12 , Jan. 28, 2018, pp. 19^^U22. [On-line]. Ava -il-able: [][]$\T1/txtt/m/n/12 https : / / raw . githubusercontent . - [] - - -Overfull \hbox (21.2149pt too wide) in paragraph at lines 2102--2102 +Overfull \hbox (21.2149pt too wide) in paragraph at lines 338--338 \T1/txr/m/n/12 line]. Avail-able: [][]$\T1/txtt/m/n/12 https : / / www . plixer . com / blog / network -[] layers -[] explained/$[][]\T1/txr/m/n/12 . [] - -Overfull \hbox (4.29944pt too wide) in paragraph at lines 2102--2102 +[78] +Overfull \hbox (4.29944pt too wide) in paragraph at lines 338--338 []\T1/txr/m/n/12 ^^P Trans-mis-sion con-trol pro-to-col,^^Q IBM. (Apr. 19, 202 2), [On-line]. Avail-able: [][]$\T1/txtt/m/n/12 https : [] -Overfull \hbox (18.27475pt too wide) in paragraph at lines 2102--2102 -[]\T1/txr/m/n/12 ^^P Rop-gad-get tool.^^Q (), [On-line]. Avail-able: [][]$\T1/ -txtt/m/n/12 https : / / github . com / JonathanSalwan / +Overfull \hbox (6.53491pt too wide) in paragraph at lines 338--338 +[]\T1/txr/m/n/12 H. Sidh-pur-wala. ^^P Hard-en-ing elf bi-na-ries us-ing re-lo +-ca-tion read-only (relro).^^Q (Jan. 28, [] -[79] (/usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty + +Overfull \hbox (14.49278pt too wide) in paragraph at lines 338--338 +[]\T1/txr/m/it/12 Capabilities - overview of linux ca-pa-bil-i-ties\T1/txr/m/n/ +12 . [On-line]. Avail-able: [][]$\T1/txtt/m/n/12 http : / / manpages . + [] + +[79] +Overfull \hbox (53.32059pt too wide) in paragraph at lines 338--338 +\T1/txr/m/it/12 sup-ple-ment\T1/txr/m/n/12 , Jan. 28, 2018, p. 148. [On-line]. +Avail-able: [][]$\T1/txtt/m/n/12 https : / / raw . githubusercontent . + [] + + +Overfull \hbox (33.3497pt too wide) in paragraph at lines 338--338 +\T1/txtt/m/n/12 20CON % 2029 % 20presentations / Guillaume % 20Fournier % 20Syl +vain % 20Afchain % + [] + + +Overfull \hbox (11.10025pt too wide) in paragraph at lines 338--338 +\T1/txr/m/n/12 DE-F-CON 27, pp. 69^^U74. [On-line]. Avail-able: [][]$\T1/txtt/m +/n/12 https : / / raw . githubusercontent . + [] + + +Overfull \hbox (39.98859pt too wide) in paragraph at lines 338--338 +\T1/txr/m/it/12 ment\T1/txr/m/n/12 , Jan. 28, 2018, pp. 19^^U22. [On-line]. Ava +il-able: [][]$\T1/txtt/m/n/12 https : / / raw . githubusercontent . + [] + +[80] (./chapters/annex.tex [81] +(/usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty File: lstlang1.sty 2020/03/24 1.8d listings language file ) (/usr/share/texlive/texmf-dist/tex/latex/listings/lstlang1.sty @@ -1816,21 +1815,21 @@ File: lstlang1.sty 2020/03/24 1.8d listings language file been already used, duplicate ignored \relax -l.2205 [18] - .eh_frame_hdr PROGBITS 00000000004020a8 000020a8 +l.101 [18] + .eh_frame_hdr PROGBITS 00000000004020a8 000020a8 [1 -]pdfTeX warning (ext4): destination with the same identifier (name{page.}) has -been already used, duplicate ignored +])pdfTeX warning (ext4): destination with the same identifier (name{page.}) has + been already used, duplicate ignored \relax -l.2252 \end{document} - [2] (./document.aux) +l.346 \end{document} + [2] (./document.aux) LaTeX Warning: There were undefined references. Package rerunfilecheck Info: File `document.out' has not changed. -(rerunfilecheck) Checksum: 4E37FDD1973E38DDD66887454329F958;5045. +(rerunfilecheck) Checksum: 73080A21CC6BDDF13751F7DFC4130C5D;5364. Package biblatex Warning: Please (re)run Biber on the file: (biblatex) document @@ -1841,13 +1840,13 @@ Package logreq Info: Writing requests to 'document.run.xml'. ) Here is how much of TeX's memory you used: - 29132 strings out of 481209 - 463847 string characters out of 5914747 - 1625209 words of memory out of 5000000 - 45076 multiletter control sequences out of 15000+600000 + 29191 strings out of 481209 + 465022 string characters out of 5914747 + 1628963 words of memory out of 5000000 + 45101 multiletter control sequences out of 15000+600000 459242 words of font info for 106 fonts, out of 8000000 for 9000 36 hyphenation exceptions out of 8191 - 88i,12n,90p,1029b,3693s stack positions out of 5000i,500n,10000p,200000b,80000s + 88i,12n,90p,1029b,3715s stack positions out of 5000i,500n,10000p,200000b,80000s {/usr/share/texlive/texmf-dist/fonts/enc/dvips/base/8r.enc} -Output written on document.pdf (100 pages, 2207026 bytes). +Output written on document.pdf (102 pages, 2221224 bytes). PDF statistics: - 1915 PDF objects out of 2073 (max. 8388607) - 533 named destinations out of 1000 (max. 500000) - 710 words of extra memory for PDF output out of 10000 (max. 10000000) + 1984 PDF objects out of 2073 (max. 8388607) + 545 named destinations out of 1000 (max. 500000) + 758 words of extra memory for PDF output out of 10000 (max. 10000000) diff --git a/docs/document.lot b/docs/document.lot index a934b2a..7dc954f 100644 --- a/docs/document.lot +++ b/docs/document.lot @@ -33,27 +33,27 @@ \defcounter {refsection}{0}\relax \contentsline {table}{\numberline {2.14}{\ignorespaces Table showing BPF skeleton functions.\relax }}{25}{table.caption.29}% \defcounter {refsection}{0}\relax -\addvspace {10\p@ } +\contentsline {table}{\numberline {2.15}{\ignorespaces Kernel compilation flags for eBPF.\relax }}{26}{table.caption.30}% \defcounter {refsection}{0}\relax -\contentsline {table}{\numberline {3.1}{\ignorespaces Kernel compilation flags for eBPF.\relax }}{28}{table.caption.30}% +\contentsline {table}{\numberline {2.16}{\ignorespaces Capabilities needed for eBPF.\relax }}{27}{table.caption.31}% \defcounter {refsection}{0}\relax -\contentsline {table}{\numberline {3.2}{\ignorespaces Capabilities needed for eBPF.\relax }}{29}{table.caption.31}% +\contentsline {table}{\numberline {2.17}{\ignorespaces Values for unprivileged eBPF kernel parameter.\relax }}{27}{table.caption.32}% \defcounter {refsection}{0}\relax -\contentsline {table}{\numberline {3.3}{\ignorespaces Values for unprivileged eBPF kernel parameter.\relax }}{29}{table.caption.32}% +\contentsline {table}{\numberline {2.18}{\ignorespaces Relevant registers in x86\_64 for the stack and control flow and their purpose.\relax }}{32}{table.caption.38}% \defcounter {refsection}{0}\relax -\contentsline {table}{\numberline {3.4}{\ignorespaces Argument passing convention of registers for function calls in user and kernel space respectively.\relax }}{32}{table.caption.33}% +\contentsline {table}{\numberline {2.19}{\ignorespaces Relevant TCP flags and their purpose.\relax }}{43}{table.caption.47}% \defcounter {refsection}{0}\relax -\contentsline {table}{\numberline {3.5}{\ignorespaces Relevant registers in x86\_64 for the stack and control flow and their purpose.\relax }}{40}{table.caption.39}% +\contentsline {table}{\numberline {2.20}{\ignorespaces Tools used for analysis of ELF programs.\relax }}{46}{table.caption.50}% \defcounter {refsection}{0}\relax -\contentsline {table}{\numberline {3.6}{\ignorespaces Relevant TCP flags and their purpose.\relax }}{50}{table.caption.45}% +\contentsline {table}{\numberline {2.21}{\ignorespaces Tools used for analysis of ELF programs.\relax }}{47}{table.caption.51}% +\defcounter {refsection}{0}\relax +\contentsline {table}{\numberline {2.22}{\ignorespaces Security features in C compilers used in the study.\relax }}{49}{table.caption.56}% \defcounter {refsection}{0}\relax \addvspace {10\p@ } \defcounter {refsection}{0}\relax -\contentsline {table}{\numberline {4.1}{\ignorespaces Tools used for analysis of ELF programs.\relax }}{65}{table.caption.56}% +\contentsline {table}{\numberline {3.1}{\ignorespaces Argument passing convention of registers for function calls in user and kernel space respectively.\relax }}{54}{table.caption.57}% \defcounter {refsection}{0}\relax -\contentsline {table}{\numberline {4.2}{\ignorespaces Tools used for analysis of ELF programs.\relax }}{65}{table.caption.57}% -\defcounter {refsection}{0}\relax -\contentsline {table}{\numberline {4.3}{\ignorespaces Security features in C compilers used in the study.\relax }}{68}{table.caption.62}% +\addvspace {10\p@ } \defcounter {refsection}{0}\relax \addvspace {10\p@ } \defcounter {refsection}{0}\relax diff --git a/docs/document.out b/docs/document.out index 3ad78fd..b0a4386 100644 --- a/docs/document.out +++ b/docs/document.out @@ -5,60 +5,66 @@ \BOOKMARK [2][-]{subsection.1.3.1}{Social\040and\040economic\040environment}{section.1.3}% 5 \BOOKMARK [2][-]{subsection.1.3.2}{Budget}{section.1.3}% 6 \BOOKMARK [1][-]{section.1.4}{Structure\040of\040the\040document}{chapter.1}% 7 -\BOOKMARK [0][-]{chapter.2}{State\040of\040the\040art}{}% 8 -\BOOKMARK [1][-]{section.2.1}{eBPF\040history\040-\040Classic\040BPF}{chapter.2}% 9 -\BOOKMARK [2][-]{subsection.2.1.1}{Introduction\040to\040the\040BPF\040system}{section.2.1}% 10 -\BOOKMARK [2][-]{subsection.2.1.2}{The\040BPF\040virtual\040machine}{section.2.1}% 11 -\BOOKMARK [2][-]{subsection.2.1.3}{Analysis\040of\040a\040BPF\040filter\040program}{section.2.1}% 12 -\BOOKMARK [2][-]{subsection.2.1.4}{BPF\040bytecode\040instruction\040format}{section.2.1}% 13 -\BOOKMARK [2][-]{subsection.2.1.5}{An\040example\040of\040BPF\040filter\040with\040tcpdump}{section.2.1}% 14 -\BOOKMARK [1][-]{section.2.2}{Analysis\040of\040modern\040eBPF}{chapter.2}% 15 -\BOOKMARK [2][-]{subsection.2.2.1}{eBPF\040instruction\040set}{section.2.2}% 16 -\BOOKMARK [2][-]{subsection.2.2.2}{JIT\040compilation}{section.2.2}% 17 -\BOOKMARK [2][-]{subsection.2.2.3}{The\040eBPF\040verifier}{section.2.2}% 18 -\BOOKMARK [2][-]{subsection.2.2.4}{eBPF\040maps}{section.2.2}% 19 -\BOOKMARK [2][-]{subsection.2.2.5}{The\040eBPF\040ring\040buffer}{section.2.2}% 20 -\BOOKMARK [2][-]{subsection.2.2.6}{The\040bpf\(\)\040syscall}{section.2.2}% 21 -\BOOKMARK [2][-]{subsection.2.2.7}{eBPF\040helpers}{section.2.2}% 22 -\BOOKMARK [1][-]{section.2.3}{eBPF\040program\040types}{chapter.2}% 23 -\BOOKMARK [2][-]{subsection.2.3.1}{XDP}{section.2.3}% 24 -\BOOKMARK [2][-]{subsection.2.3.2}{Traffic\040Control}{section.2.3}% 25 -\BOOKMARK [2][-]{subsection.2.3.3}{Tracepoints}{section.2.3}% 26 -\BOOKMARK [2][-]{subsection.2.3.4}{Kprobes}{section.2.3}% 27 -\BOOKMARK [2][-]{subsection.2.3.5}{Uprobes}{section.2.3}% 28 -\BOOKMARK [1][-]{section.2.4}{Developing\040eBPF\040programs}{chapter.2}% 29 -\BOOKMARK [2][-]{subsection.2.4.1}{BCC}{section.2.4}% 30 -\BOOKMARK [2][-]{subsection.2.4.2}{Bpftool}{section.2.4}% 31 -\BOOKMARK [2][-]{subsection.2.4.3}{Libbpf}{section.2.4}% 32 -\BOOKMARK [0][-]{chapter.3}{Analysis\040of\040offensive\040capabilities}{}% 33 -\BOOKMARK [1][-]{section.3.1}{Security\040features\040in\040eBPF}{chapter.3}% 34 -\BOOKMARK [2][-]{subsection.3.1.1}{Access\040control}{section.3.1}% 35 -\BOOKMARK [2][-]{subsection.3.1.2}{eBPF\040maps\040security}{section.3.1}% 36 -\BOOKMARK [1][-]{section.3.2}{Abusing\040tracing\040programs}{chapter.3}% 37 -\BOOKMARK [2][-]{subsection.3.2.1}{Access\040to\040function\040arguments}{section.3.2}% 38 -\BOOKMARK [2][-]{subsection.3.2.2}{Reading\040memory\040out\040of\040bounds}{section.3.2}% 39 -\BOOKMARK [2][-]{subsection.3.2.3}{Overriding\040function\040return\040values}{section.3.2}% 40 -\BOOKMARK [2][-]{subsection.3.2.4}{Sending\040signals\040to\040user\040programs}{section.3.2}% 41 -\BOOKMARK [2][-]{subsection.3.2.5}{Conclusion}{section.3.2}% 42 -\BOOKMARK [1][-]{section.3.3}{Memory\040corruption}{chapter.3}% 43 -\BOOKMARK [2][-]{subsection.3.3.1}{Memory\040management\040in\040Linux}{section.3.3}% 44 -\BOOKMARK [2][-]{subsection.3.3.2}{Process\040virtual\040memory}{section.3.3}% 45 -\BOOKMARK [2][-]{subsection.3.3.3}{The\040process\040stack}{section.3.3}% 46 -\BOOKMARK [2][-]{subsection.3.3.4}{Attacks\040and\040limitations\040of\040bpf_probe_write_user\(\)}{section.3.3}% 47 -\BOOKMARK [2][-]{subsection.3.3.5}{Conclusion}{section.3.3}% 48 -\BOOKMARK [1][-]{section.3.4}{Abusing\040networking\040programs}{chapter.3}% 49 -\BOOKMARK [2][-]{subsection.3.4.1}{An\040overview\040on\040the\040network\040layer}{section.3.4}% 50 -\BOOKMARK [2][-]{subsection.3.4.2}{Introduction\040to\040the\040TCP\040protocol}{section.3.4}% 51 -\BOOKMARK [2][-]{subsection.3.4.3}{Attacks\040and\040limitations\040of\040networking\040programs}{section.3.4}% 52 -\BOOKMARK [2][-]{subsection.3.4.4}{Conclusion}{section.3.4}% 53 -\BOOKMARK [0][-]{chapter.4}{Design\040of\040a\040malicious\040eBPF\040rootkit}{}% 54 -\BOOKMARK [1][-]{section.4.1}{Library\040injection\040via\040GOT\040hijacking}{chapter.4}% 55 -\BOOKMARK [2][-]{subsection.4.1.1}{Attacks\040at\040the\040stack:\040buffer\040overflow}{section.4.1}% 56 -\BOOKMARK [2][-]{subsection.4.1.2}{Return\040oriented\040programming\040attacks}{section.4.1}% 57 -\BOOKMARK [2][-]{subsection.4.1.3}{ROP\040with\040eBPF}{section.4.1}% 58 -\BOOKMARK [2][-]{subsection.4.1.4}{The\040ELF\040format\040and\040Lazy\040Binding}{section.4.1}% 59 -\BOOKMARK [2][-]{subsection.4.1.5}{Hardening\040ELF\040binaries\040and\040possible\040bypasses}{section.4.1}% 60 -\BOOKMARK [2][-]{subsection.4.1.6}{Design\040of\040our\040attack}{section.4.1}% 61 -\BOOKMARK [0][-]{chapter.5}{Results}{}% 62 -\BOOKMARK [0][-]{chapter.6}{Conclusion\040and\040future\040work}{}% 63 -\BOOKMARK [0][-]{chapter.6}{Bibliography}{}% 64 +\BOOKMARK [1][-]{section.1.5}{Code\040availability}{chapter.1}% 8 +\BOOKMARK [0][-]{chapter.2}{Background}{}% 9 +\BOOKMARK [1][-]{section.2.1}{BPF}{chapter.2}% 10 +\BOOKMARK [2][-]{subsection.2.1.1}{Introduction\040to\040the\040BPF\040system}{section.2.1}% 11 +\BOOKMARK [2][-]{subsection.2.1.2}{The\040BPF\040virtual\040machine}{section.2.1}% 12 +\BOOKMARK [2][-]{subsection.2.1.3}{Analysis\040of\040a\040BPF\040filter\040program}{section.2.1}% 13 +\BOOKMARK [2][-]{subsection.2.1.4}{BPF\040bytecode\040instruction\040format}{section.2.1}% 14 +\BOOKMARK [2][-]{subsection.2.1.5}{An\040example\040of\040BPF\040filter\040with\040tcpdump}{section.2.1}% 15 +\BOOKMARK [1][-]{section.2.2}{Modern\040eBPF}{chapter.2}% 16 +\BOOKMARK [2][-]{subsection.2.2.1}{eBPF\040instruction\040set}{section.2.2}% 17 +\BOOKMARK [2][-]{subsection.2.2.2}{JIT\040compilation}{section.2.2}% 18 +\BOOKMARK [2][-]{subsection.2.2.3}{The\040eBPF\040verifier}{section.2.2}% 19 +\BOOKMARK [2][-]{subsection.2.2.4}{eBPF\040maps}{section.2.2}% 20 +\BOOKMARK [2][-]{subsection.2.2.5}{The\040eBPF\040ring\040buffer}{section.2.2}% 21 +\BOOKMARK [2][-]{subsection.2.2.6}{The\040bpf\(\)\040syscall}{section.2.2}% 22 +\BOOKMARK [2][-]{subsection.2.2.7}{eBPF\040helpers}{section.2.2}% 23 +\BOOKMARK [1][-]{section.2.3}{eBPF\040program\040types}{chapter.2}% 24 +\BOOKMARK [2][-]{subsection.2.3.1}{XDP}{section.2.3}% 25 +\BOOKMARK [2][-]{subsection.2.3.2}{Traffic\040Control}{section.2.3}% 26 +\BOOKMARK [2][-]{subsection.2.3.3}{Tracepoints}{section.2.3}% 27 +\BOOKMARK [2][-]{subsection.2.3.4}{Kprobes}{section.2.3}% 28 +\BOOKMARK [2][-]{subsection.2.3.5}{Uprobes}{section.2.3}% 29 +\BOOKMARK [1][-]{section.2.4}{Developing\040eBPF\040programs}{chapter.2}% 30 +\BOOKMARK [2][-]{subsection.2.4.1}{BCC}{section.2.4}% 31 +\BOOKMARK [2][-]{subsection.2.4.2}{Bpftool}{section.2.4}% 32 +\BOOKMARK [2][-]{subsection.2.4.3}{Libbpf}{section.2.4}% 33 +\BOOKMARK [1][-]{section.2.5}{Security\040features\040in\040eBPF}{chapter.2}% 34 +\BOOKMARK [2][-]{subsection.2.5.1}{Access\040control}{section.2.5}% 35 +\BOOKMARK [1][-]{section.2.6}{Memory\040management\040in\040Linux}{chapter.2}% 36 +\BOOKMARK [2][-]{subsection.2.6.1}{Memory\040pages\040and\040faults}{section.2.6}% 37 +\BOOKMARK [2][-]{subsection.2.6.2}{Process\040virtual\040memory}{section.2.6}% 38 +\BOOKMARK [2][-]{subsection.2.6.3}{The\040process\040stack}{section.2.6}% 39 +\BOOKMARK [1][-]{section.2.7}{Attacks\040at\040the\040stack}{chapter.2}% 40 +\BOOKMARK [2][-]{subsection.2.7.1}{Buffer\040overflow}{section.2.7}% 41 +\BOOKMARK [2][-]{subsection.2.7.2}{Return\040oriented\040programming\040attacks}{section.2.7}% 42 +\BOOKMARK [1][-]{section.2.8}{Networking\040fundamentals\040in\040Linux}{chapter.2}% 43 +\BOOKMARK [2][-]{subsection.2.8.1}{An\040overview\040on\040the\040network\040layer}{section.2.8}% 44 +\BOOKMARK [2][-]{subsection.2.8.2}{Introduction\040to\040the\040TCP\040protocol}{section.2.8}% 45 +\BOOKMARK [1][-]{section.2.9}{ELF\040binaries}{chapter.2}% 46 +\BOOKMARK [2][-]{subsection.2.9.1}{The\040ELF\040format\040and\040Lazy\040Binding}{section.2.9}% 47 +\BOOKMARK [2][-]{subsection.2.9.2}{Hardening\040ELF\040binaries}{section.2.9}% 48 +\BOOKMARK [0][-]{chapter.3}{Analysis\040of\040offensive\040capabilities}{}% 49 +\BOOKMARK [1][-]{section.3.1}{eBPF\040maps\040security}{chapter.3}% 50 +\BOOKMARK [1][-]{section.3.2}{Abusing\040tracing\040programs}{chapter.3}% 51 +\BOOKMARK [2][-]{subsection.3.2.1}{Access\040to\040function\040arguments}{section.3.2}% 52 +\BOOKMARK [2][-]{subsection.3.2.2}{Reading\040memory\040out\040of\040bounds}{section.3.2}% 53 +\BOOKMARK [2][-]{subsection.3.2.3}{Overriding\040function\040return\040values}{section.3.2}% 54 +\BOOKMARK [2][-]{subsection.3.2.4}{Sending\040signals\040to\040user\040programs}{section.3.2}% 55 +\BOOKMARK [2][-]{subsection.3.2.5}{Conclusion}{section.3.2}% 56 +\BOOKMARK [1][-]{section.3.3}{Memory\040corruption}{chapter.3}% 57 +\BOOKMARK [2][-]{subsection.3.3.1}{Attacks\040and\040limitations\040of\040bpf_probe_write_user\(\)}{section.3.3}% 58 +\BOOKMARK [2][-]{subsection.3.3.2}{Conclusion}{section.3.3}% 59 +\BOOKMARK [1][-]{section.3.4}{Abusing\040networking\040programs}{chapter.3}% 60 +\BOOKMARK [2][-]{subsection.3.4.1}{Attacks\040and\040limitations\040of\040networking\040programs}{section.3.4}% 61 +\BOOKMARK [2][-]{subsection.3.4.2}{Conclusion}{section.3.4}% 62 +\BOOKMARK [0][-]{chapter.4}{Design\040of\040a\040malicious\040eBPF\040rootkit}{}% 63 +\BOOKMARK [1][-]{section.4.1}{Library\040injection\040attacks}{chapter.4}% 64 +\BOOKMARK [2][-]{subsection.4.1.1}{ROP\040with\040eBPF}{section.4.1}% 65 +\BOOKMARK [2][-]{subsection.4.1.2}{Bypassing\040hardening\040features\040in\040ELFs}{section.4.1}% 66 +\BOOKMARK [2][-]{subsection.4.1.3}{Library\040injection\040via\040GOT\040hijacking}{section.4.1}% 67 +\BOOKMARK [0][-]{chapter.5}{Evaluation}{}% 68 +\BOOKMARK [0][-]{chapter.6}{Related\040work}{}% 69 +\BOOKMARK [0][-]{chapter.6}{Bibliography}{}% 70 diff --git a/docs/document.pdf b/docs/document.pdf index d6d56bb..336f9db 100644 Binary files a/docs/document.pdf and b/docs/document.pdf differ diff --git a/docs/document.synctex.gz b/docs/document.synctex.gz index dc74f86..0e7cb9d 100644 Binary files a/docs/document.synctex.gz and b/docs/document.synctex.gz differ diff --git a/docs/document.tex b/docs/document.tex index 4b0ac1b..93c929a 100644 --- a/docs/document.tex +++ b/docs/document.tex @@ -310,1781 +310,17 @@ hmargin=3cm \clearpage \pagenumbering{arabic} -\chapter{Introduction} -\section{Motivation} \label{section:motivation} -%M-> SA bit long, but it summarizes and presents the ideas and background needed to understand the topic in order: -% Main idea: Malware keeps evolving -> -% -> Relevance of innovating and researching on the new techniques -> -% -> Relevance of stealth software in targeted attacks-> -% -> Introduce eBPF as the logical step of innovation in the field -> -% -> There is a need to research on this topic now. +\input{chapters/chapter1} +\input{chapters/chapter2} +\input{chapters/chapter3} +\input{chapters/chapter4} +\input{chapters/chapter5} +\input{chapters/chapter6} -As the efforts of the computer security community grow to protect increasingly critical devices and networks from malware infections, so do the techniques used by malicious actors become more sophisticated. Following the incorporation of ever more capable firewalls and Intrusion Detection Systems (IDS), cybercriminals have in turn sought novel attack vectors and exploits in common software, taking advantage of an inevitably larger attack surface that keeps growing due to the continued incorporation of new programs and functionalities into modern computer systems. -In contrast with ransomware incidents, which remained the most significant and common cyber threat faced by organizations on 2021\cite{ransomware_pwc}, a powerful class of malware called rootkits is found considerably more infrequently, yet it is usually associated to high-profile targeted attacks that lead to greatly impactful consequences. -A rootkit is a piece of computer software characterized for its advanced stealth capabilities. Once it is installed on a system it remains invisible to the host, usually hiding its related processes and files from the user, while at the same time performing the malicious operations for which it was designed. Common operations include storing keystrokes, sniffing network traffic, exfiltrating sensitive information from the user or the system, or actively modifying critical data at the infected device. The other characteristic functionality is that rootkits seek to achieve persistence on the infected hosts, meaning that they keep running on the system even after a system reboot, without further user interaction or the need of a new compromise. -The techniques used for achieving both of these functionalities depend on the type of rootkit developed, a classification usually made depending on the level of privileges on which the rootkit operates in the system. -\begin{itemize} -\item \textbf{User-mode} rootkits run at the same level of privilege as common user applications. They usually work by hijacking legitimate processes on which they may inject code by preloading shared libraries, thus modifying the calls issued to user APIs, on which malicious code is placed by the rootkit. Although easier to build, these rootkits are exposed to detection by common anti-malware programs. -%I am mentioning the kernel panic part because that could be considered an advantage for eBPF, there is less worry about crashing the system -\item \textbf{Kernel-mode} rootkits run at the same level of privilege as the operating system, thus enjoying unrestricted access to the whole computer. These rootkits usually come as kernel modules or device drivers and, once loaded, they reside in the kernel. This implies that special attention must be taken to avoid programming errors since they could potentially corrupt user or kernel memory, resulting in a fatal kernel panic and a subsequent system reboot, which goes against the original purpose of maintaining stealth. -Common techniques used for the development of their malicious activities include hooking system calls made to the kernel by user applications (on which malicious code is then injected), or modifying data structures in the kernel to change the data of user programs at runtime. Therefore, trusted programs on an infected machine can no longer be trusted to operate securely. - -These rootkits are usually the most attractive (and difficult to build) option for a malicious actor, but the installation of a kernel rootkit requires of a complete previous compromise of the system, meaning that administrator or root privileges must have been already achieved by the attacker, commonly by the execution of an exploit or a local installation of a privileged user. -\end{itemize} - -Historically, kernel-mode rootkits have been tightly associated with espionage activities on governments and research institutes by Advanced Persistent Threat (APT) groups\cite{rootkit_ptsecurity}, state-sponsored or criminal organizations specialized on long-term operations to gather intelligence and gain unauthorized persistent access to computer systems. Although rootkits' functionality is tailored for each specific attack, a common set of techniques and procedures can be identified being used by these organizations. However, during the last years, a new technology called eBPF has been found to be the heart of the latest innovation on the development of rootkits. - -%Yes, I am not mentioning that eBPF comes from "Extended Berkeley Packet %Filters here since apparently it is no longer considered an acronym, we'll %tackle that on the history section -eBPF is a technology incorporated in the 3.18 version of the Linux kernel\cite{ebpf_linux318}, which provides the possibility of running code in the kernel without the need of loading a kernel module. Programs are created in a restrictive version of the C language and compiled into eBPF bytecode, which is loaded into the kernel via a new bpf() system call. After a mandatory step of verification by the kernel in which the code is checked to be safe to run, the bytecode is compiled into native machine instructions. These programs can then get access to kernel-exclusive functionalities including network traffic filtering, system calls hooking or tracing. - -Although eBPF has built an outstanding environment for the creation of networking and tracing tools, its ability to run kernel programs without the need to load a kernel module has attracted the attention of multiple APTs. On February 2022, the Chinese security team Pangu Lab reported about a NSA backdoor that remained unnoticed since 2013 that used eBPF for its networking functionality and that infected military and telecommunications systems worldwide\cite{bvp47_report}. Also on 2022, PwC reports about a China-based threat actor that has targeted telecommunications systems with a eBPF-based backdoor\cite{bpfdoor_pwc}. - -Moreover, there currently exists official efforts to extend the eBPF technology into Windows\cite{ebpf_windows} and Android systems\cite{ebpf_android}, which spreads the mentioned risks to new platforms. Therefore, we can confidently claim that there is a growing interest on researching the capabilities of eBPF in the context of offensive security, in particular given its potential on becoming a common component found of modern rootkits. This knowledge would be valuable to the computer security community, both in the context of pen-testing and for analysts which need to know about the latest trends in malware to prepare their defences. - - -\section{Project objectives} \label{section:project_objectives} -The main objective of this project is to compile a comprehensive report of the capabilities in the eBPF technology that could be weaponized by a malicious actor. In particular, we will be focusing on functionalities present in the Linux platform, given the maturity of eBPF on these environments and which therefore offers a wider range of possibilities. We will be approaching this study from the perspective of a threat actor, meaning that we will develop an eBPF-based rootkit which shows these capabilities live in a current Linux system, including proof of concepts (PoC) showing an specific feature, and also by building a realistic rootkit system which weaponizes these PoCs and operates malicious activities. - -%According to the library guide, previous research should be around here. %Is it the best place tho? -Before narrowing down our objectives and selecting an specific list of rootkit capabilities to emulate using eBPF, we needed to consider previous research. The work on this matter by Jeff Dileo from NCC Group at DEFCON 27\cite{evil_ebpf} is particularly relevant, setting the first basis of eBPF ability to overwrite userland data, highlighting the possibility of overwriting the memory of a running process and executing arbitrary code on it. - -Subsequent talks on 2021 by Pat Hogan at DEFCON 29\cite{bad_ebpf}, and by Guillaume Fournier and Sylvain Afchainthe from Datadog at DEFCON 29\cite{ebpf_friends}, research deeper on eBPF's ability to behave like a rootkit. In particular, Hogan shows how eBPF can be used to hide the rootkit's presence from the user and to modify data at system calls, whilst Fournier and Afchainthe built the first instance of an eBPF-based backdoor with command-and-control(C2) capabilities, enabling to communicate with the malicious eBPF program by sending network packets to the compromised machine. - -Taking the previous research into account, and on the basis of common functionality we described to be usually incorporated at rootkits, the objectives of our research on eBPF is set to be on the following topics: -\begin{itemize} -\item Analysing eBPF's possibilities when hooking system calls and kernel functions. -\item Learning eBPF's potential to read/write arbitrary memory. -\item Exploring networking capabilities with eBPF packet filters. -\end{itemize} - -The knowledge gathered by the previous three pillars will be then used as a basis for building our rootkit. We will present attack vectors and techniques different than the ones presented in previous research, although inevitably we will also tackle common points, which will be clearly indicated and on which we will try to perform further research. In essence, our eBPF-based rootkit aims at: -\begin{itemize} -\item Hijacking the execution of user programs while they are running, injecting libraries and executing malicious code, without impacting their normal execution. -\item Featuring a command-and-control module powered by a network backdoor, which can be operated from a remote client. This backdoor should be controlled with stealth in mind, featuring similar mechanisms to those present in rootkits found in the wild. -\item Tampering with user data at system calls, resulting in running malware-like programs and for other malicious purposes. -\item Achieving stealth, hiding rootkit-related files from the user. -\item Achieving rootkit persistence, the rootkit should run after a complete system reboot. -\ -\end{itemize} - -The rootkit will work in a fresh-install of a Linux system with the following characteristics: -\begin{itemize} -%Maybe a table for this? -\item Distribution: Ubuntu 21.04. -\item Kernel version: 5.11.0-49. -\end{itemize} - -\section{Regulatory framework} -%MARCOS-> Is this the appropiate place? Looking at other TFGs it is sometimes here and others in a final chapter - -%TODO - Leaving this for the end - -\subsection{Social and economic environment} -%M-> Mentioned talking about community outreach and its role under pentesting -%TODO Talk about the difference between having always on BPF and always on kernel modules, BPF is consider "safe" in production while it's almost as dangerous (I think this might fit here) - -%TODO - Leaving this for the end - -\subsection{Budget} -%TODO - Leaving this for the end - -\section{Structure of the document} -%TODO - Best to be done at the end - - -%%%%%%%%%%%%%%% -%TODO IMPORTANT- Clearly structure eveything, for instance I am not sure about the "Methods" section. Maybe a "State of the Art"+"Analysis of offensive capabilities"+"Implementation of a rootkit" is more suitable? -%I'm following that for now, we can join it together afterwards if it was not a good idea. -% -% In the end, we need to talk about 3 main points before the conclusion at least: -% 1- Background on eBPF, what it is, how it works. How we will develop applications on it(libbpf). -% 2- Offensive capabilities of ebpf -% 3- Our rootkit in ebpf with the previous section as the basis. The idea is to show diagrams with the components and describe the functionality. However, the library injection part is long and requires quite a background by itself. Should we introduce the background on a different section?? -%%%%%%%%%%%%%% - -\chapter{State of the art} -% I WILL NOT INCLUDE A ROOTKIT BACKGROUND, considering that a deep study of that is not fully relevant for us. I explained what it is, its two main types (should we include bootkits, maybe?) and its relation with eBPF in the introduction, since it is needed to introduce the overall context. Should we do otherwise? -This chapter is dedicated to an study of the eBPF technology. Firstly, we will analyse its origins, understanding what it is and how it works, and discuss the reasons why it is a necessary component of the Linux kernel today. Afterwards, we will cover the main features of eBPF in detail. Finally, an study of the existing alternatives for developing eBPF applications will be also included. - -Although during our discussion of the offensive capabilities of eBPF in section\ref{section:TODO} we will use a library that will provide us with a layer of abstraction over the underlying operations, this background is needed to understand how eBPF is embedded in the kernel and which capabilities and limits we can expect to achieve with it. - -\section{eBPF history - Classic BPF} -% Is it ok to have sections / chapters without individual intros? -In this section we will detail the origins of eBPF in the Linux kernel. By offering us background into the earlier versions of the system, the goal is to acquire insight on the design decisions included in modern versions of eBPF. - -\subsection{Introduction to the BPF system} -Nowadays eBPF is not officially considered to be an acronym anymore\cite{ebpf_io}, but it remains largely known as "extended Berkeley Packet Filters", given its roots in the Berkeley Packet Filter (BPF) technology, now known as classic BPF. - -BPF was introduced in 1992 by Steven McCanne and Van Jacobson in the paper "The BSD Packet Filter: A New Architecture for User-level Packet Capture"\cite{bpf_bsd_origin}, as a new filtering technology for network packets in the BSD platform. It was first integrated in the Linux kernel on version 2.1.75\cite{ebpf_history_opensource}. - - -\begin{figure}[H] - \centering - \includegraphics[width=12cm, keepaspectratio=true]{classic_bpf.jpg} - \caption{Sketch of the functionality of classic BPF} - \label{fig:classif_bpf} -\end{figure} - -Figure \ref{fig:classif_bpf} shows how BPF was integrated in the existing network packet processing by the kernel. After receiving a packet via the Network Interface Controller (NIC) driver, it would first be analysed by BPF filters, which are programs directly developed by the user. This filter decides whether the packet is to be accepted by analysing the packet properties, such as its length or the type and values of its headers. If a packet is accepted, the filter proceeds to decide how many bytes of the original buffer are passed to the application at the user space. Otherwise, the packet is redirected to the original network stack, where it is managed as usual. - - -\subsection{The BPF virtual machine} \label{subsection:bpf_vm} -In a technical level, BPF comprises both the BPF filter programs developed by the user and the BPF module included in the kernel which allows for loading and running the BPF filters. This BPF module in the kernel works as a virtual machine\cite{bpf_bsd_origin_bpf_page1}, meaning that it parses and interprets the filter program by providing simulated components needed for its execution, turning into a software-based CPU. Because of this reason, it is usually referred as the BPF Virtual Machine (BPF VM). The BPF VM comprises the following components: -\begin{itemize} -\item \textbf{An accumulator register}, used to store intermediate values of operations. -\item \textbf{An index register}, used to modify operand addresses, it is usually incorporated to optimize vector operations\cite{index_register}. -\item \textbf{An scratch memory store}, a temporary storage. -\item \textbf{A program counter}, used to point to the next machine instruction to execute in a filter program. -\end{itemize} - - -\subsection{Analysis of a BPF filter program} \label{subsection:analysis_bpf_filter_prog} -As we mentioned in section \ref{subsection:bpf_vm}, the components of the BPF VM are used to support running BPF filter programs. A BPF filter is implemented as a boolean function: -\begin{itemize} -\item If it returns \textit{true}, the kernel copies the packet to the application. -\item If it returns \textit{false}, the packet is not accepted by the filter (and thus the network stack will be the next to operate it). -\end{itemize} - -\begin{figure}[H] - \centering - \includegraphics[width=8cm]{cbpf_prog.jpg} - \caption{Execution of a BPF filter.} - \label{fig:cbpf_prog} -\end{figure} - -Figure \ref{fig:cbpf_prog} shows an example of a BPF filter upon receiving a packet. In the figure, green lines indicate that the condition is true and red lines that it is evaluated as false. Therefore, the execution works as a control flow graph (CFG) which ends on a boolean value\cite{bpf_bsd_origin_bpf_page5}. The figure presents an example BPF program which accepts the following frames: -\begin{itemize} -\item Frames with an IP packet as a payload directed from IP address X. -\item Frames with an IP packet as a payload directed towards IP address Y. -\item Frames belonging to the ARP protocol and from IP address Y. -\item Frames not from the ARP protocol directed from IP address Y to IP address X. -\end{itemize} - - -\subsection{BPF bytecode instruction format} -In order to implement the CFG to be run at the BPF VM, BPF filter programs are made up of BPF bytecode, which is defined by a new BPF instruction set. Therefore, a BPF filter program is an array of BPF bytecode instructions\cite{bpf_organicprogrammer_analysis}. - - -\begin{table}[H] -\begin{tabular}{|c|c|c|c|c|} -\hline -& OPCODE & JT & JF & K\\ -\hline -BITS & 16 & 8 & 8 & 32\\ -\hline -\end{tabular} -\caption{Table showing BPF instruction format. It is a fixed-length 64 bit instruction, the number of bits used by each field are indicated.} -\label{table:bpf_inst_format} -\end{table} - -Table \ref{table:bpf_inst_format} shows the format of a BPF bytecode instruction. As it can be observed, it is a compound of: -\begin{itemize} -\item An \textbf{opcode}, similar to assembly opcode, it indicates the operation to be executed. -\item Field \textbf{jt} indicates the offset to the next instruction to jump in case a condition is evaluated as \textit{true}. -\item Field \textbf{jf} indicates the offset to the next instruction to jump in case a condition is evaluated as \textit{false}. -\item Field \textbf{k} is miscellaneous and its contents vary depending on the instruction opcode. -\end{itemize} - -\begin{figure}[H] - \centering - \includegraphics[width=8cm]{bpf_instructions.png} - \caption{Table of supported classic BPF instructions, as shown by McCanne and Jacobson\cite{bpf_bsd_origin_bpf_page7}} - \label{fig:bpf_instructions} -\end{figure} - -Figure \ref{fig:bpf_instructions} shows how BPF instructions are defined according to the BPF instruction set. As we mentioned, similarly to assembly, instructions include an opcode which indicates the operation to execute, and the multiple arguments defining the arguments of the operation. The table shows, in order by rows, the following instruction types\cite{bpf_bsd_origin_bpf_page8}: -\begin{itemize} -\item Rows 1-4 are \textbf{load instructions}, copying the addressed value into the index or accumulator register. -\item Rows 4-6 are \textbf{store instructions}, copying the accumulator or index register into the scratch memory store. -\item Rows 7-11 are \textbf{jump instructions}, changing the program counter register. These are usually present on each node of the CFG, and evaluate whether the condition to be evaluated is true or not. -\item Rows 12-19 and 21-22 are \textbf{arithmetic and miscellaneous instructions}, performing operations usually needed during the program execution. -\item Row 20 is a \textbf{return instruction}, it is positioned in the final end of the CFG, and indicate whether the filter accepts the packet (returning true) or otherwise rejects it (return false). -\end{itemize} - -\begin{figure}[H] - \centering - \includegraphics[width=8cm]{bpf_address_mode.png} - \caption{Table explaining the column address modes in Figure\ref{fig:bpf_instructions}, as shown by McCanne and Jacobson\cite{bpf_bsd_origin_bpf_page8}} - \label{fig:bpf_address_mode} -\end{figure} - -The column \textit{addr modes} in figure \ref{fig:bpf_instructions} describes how the parameters of a BPF instruction are referenced depending on the opcode. The address modes are detailed in figure \ref{fig:bpf_address_mode}. As it can be observed, paremeters may consist of immediate values, offsets to memory positions or on the packet, the index register or combinations of the previous. - - -\subsection{An example of BPF filter with tcpdump} -At the time, by filtering packets before they are handled by the kernel instead of using an user-level application, BPF offered a performance improvement between 10 and 150 times the state-of-the art technologies of the moment\cite{bpf_bsd_origin_bpf_page1}. Since then, multiple popular tools began to use BPF, such as the network tracing tool \textit{tcpdump}\cite{tcpdump_page}. - -\textit{tcpdump} is a command-line tool that enables to capture and analyse the network traffic going through the system. It works by setting filters on a network interface, so that it shows the packets that are accepted by the filter. Still today, \textit{tcpdump} uses BPF for the filter implementation. We will now show an example of BPF code used by \textit{tcpdump} to implement a simple filter: - -\begin{figure}[H] - \centering - \includegraphics[width=10cm]{tcpdump_example.png} - \caption{BPF bytecode tcpdump needs to set a filter to display packets directed to port 80.} - \label{fig:bpf_tcpdump_example} -\end{figure} - -Figure \ref{fig:bpf_tcpdump_example} shows how tcpdump sets a filter to display traffic directed to all interfaces (\textit{-i any}) directed to port 80. Flag \textit{-d} instructs tcpdump to display BPF bytecode. - -In the example, using the \textit{jf} and \textit{jt} fields, we can label the nodes of the CFG described by the BPF filter. Figure \ref{fig:tcpdump_ex_sol} describes the shortest graph path that a true comparison will need to follow to be accepted by the filter. Note how instruction 010 is checking the value 80, the one our filter is looking for in the port. - -\begin{figure}[H] - \centering - \includegraphics[width=6cm]{cBPF_prog_ex_sol.png} - \caption{Shortest path in the CFG described in the example of figure \ref{fig:bpf_tcpdump_example} that a packet needs to follow to be accepted by the BPF filter set with \textit{tcpdump}.} - \label{fig:tcpdump_ex_sol} -\end{figure} - -\section{Analysis of modern eBPF} \label{section:modern_ebpf} -This section discusses the current state of modern eBPF in the Linux kernel. By building on the previous architecture described in classic BPF, we will be able to provide a comprehensive picture of the underlying infrastructure in which eBPF relies today. - -The addition of classic BPF in the Linux kernel set the foundations of eBPF, but nowadays it has already extended its presence to many other components other than traffic filtering. Similarly to how BPF filters were included in the networking module of the Linux kernel, we will now study the necessary changes made in the kernel to support these new program types. Table \ref{table:ebpf_history} shows the main updates that were incorporated and shaped modern eBPF of today. - -\begin{table}[H] -\begin{tabular}{|c|c|c|} -\hline -Description & Kernel version & Year\\ -\hline -\hline -\textit{BPF}: First addition in the kernel & 2.1.75 & 1997\\ -\textit{BPF+}: New JIT assembler & 3.0 & 2011\\ -\textit{eBPF}: Added eBPF support & 3.15 & 2014\\ -\textit New bpf() syscall & 3.18 & 2014\\ -\textit Introduction of eBPF maps & 3.19 & 2015\\ -\textit eBPF attached to kprobes & 4.1 & 2015\\ -\textit Introduction of Traffic Control & 4.5 & 2016\\ -\textit eBPF attached to tracepoints & 4.7 & 2016\\ -\textit Introduction of XDP & 4.8 & 2016\\ - - -\hline -\end{tabular} -\caption{Table showing relevant eBPF updates. Note that only those relevant for our research objectives are shown. This is a selection of the official complete table at \cite{ebpf_funcs_by_ver}.} -\label{table:ebpf_history} -\end{table} - -As it can be observed in the table above, the main breakthrough happened in the 3.15 version, where Alexei Starovoitov, along with Daniel Borkmann, decided to expand the capabilities of BPF by remodelling the BPF instruction set and overall architecture\cite{brendan_gregg_bpf_book}. - -Figure \ref{fig:ebpf_architecture} offers an overview of the current eBPF architecture. During the subsequent subsections, we will proceed to explain its components in detail. - -\begin{figure}[H] - \centering - \includegraphics[width=15cm]{ebpf_arch.jpg} - \caption{Figure showing overall eBPF architecture in the Linux kernel and the process of loading an eBPF program. Based on\cite{brendan_gregg_bpf_book} and \cite{ebpf_io_arch}.} - \label{fig:ebpf_architecture} -\end{figure} - -\subsection{eBPF instruction set} \label{subsection:ebpf_inst_set} -The eBPF update included a complete remodel of the instruction set architecture (ISA) of the BPF VM. Therefore, eBPF programs will need to follow the new architecture in order to be interpreted as valid and executed. - -\begin{table}[H] -\begin{tabular}{|c|c|c|c|c|c|} -\hline -& IMM & OFF & SRC & DST & OPCODE \\ -\hline -BITS & 32 & 16 & 4 & 4 & 8\\ -\hline -\end{tabular} -\caption{Table showing eBPF instruction format. It is a fixed-length 64 bit instruction, the number of bits used by each field are indicated.} -\label{table:ebpf_inst_format} -\end{table} - - -Table \ref{table:ebpf_inst_format} shows the new instruction format for eBPF programs\cite{ebpf_inst_set}. The new fields are similar to x86\_64 assembly, incorporating the typically found immediate and offset fields, and source and destination registers\cite{8664_inst_set_specs}. Similarly, the instruction set is extended to be similar to the one typically found on x86\_64 systems, the complete list can be consulted in the official documentation\cite{ebpf_inst_set}. -%Should I talk about assembly or this more in detail? - -With respect to the BPF VM registers, they get extended from 32 to 64 bits of length, and the number of registers is incremented to 10, instead of the original accumulator and index registers. These registers are also adapted to be similar to those in assembly, as it is shown in table \ref{table:ebpf_regs}. - -\begin{table}[H] -\begin{tabular}{|c|c|m{21em}|} -\hline -eBPF register & x86\_64 register & Purpose\\ -\hline -r0 & rax & Return value from functions and exit value of eBPF programs\\ -r1 & rdi & Function call argument 1\\ -r2 & rsi & Function call argument 2\\ -r3 & rdx & Function call argument 3\\ -r4 & rcx & Function call argument 4\\ -r5 & r8 & Function call argument 5\\ -r6 & rbx & Callee saved register, value preserved between calls\\ -r7 & r13 & Callee saved register, value preserved between calls\\ -r8 & r14 & Callee saved register, value preserved between calls\\ -r9 & r15 & Callee saved register, value preserved between calls\\ -r10 & rbp & Frame pointer for stack, read only\\ -\hline -\end{tabular} -\caption{Table showing eBPF registers and their purpose in the BPF VM.\cite{ebpf_inst_set}\cite{ebpf_starovo_slides}.} -\label{table:ebpf_regs} -\end{table} - -\subsection{JIT compilation} -We mentioned in subsection \ref{subsection:ebpf_inst_set} that eBPF registers and instructions describe an almost one-to-one correspondence to those in x86 assembly. This is in fact not a coincidence, but rather it is with the purpose of improving a functionality that was included in Linux kernel 3.0, called Just-in-Time (JIT) compilation\cite{ebpf_JIT}\cite{ebpf_JIT_demystify_page13}. - -JIT compiling is an extra step that optimizes the execution speed of eBPF programs. It consists of translating BPF bytecode into machine-specific instructions, so that they run as fast as native code in the kernel. Machine instructions are generated during runtime, written directly into executable memory and executed there\cite{ebpf_JIT_demystify_page14}. - -Therefore, when using JIT compiling (a setting defined by the variable \textit{bpf\_jit\_enable}\cite{jit_enable_setting}, BPF registers are translated into machine-specific registers following their one-to-one mapping and bytecode instructions are translated into machine-specific instructions\cite{ebpf_starovo_slides_page23}. There no longer exists an interpretation step by the BPF VM, since we can execute the code directly\cite{brendan_gregg_bpf_book_bpf_vm}. - -The programs developed during this project will always have JIT compiling active. - - -\subsection{The eBPF verifier} \label{subsection:ebpf_verifier} -We introduced in figure \ref{fig:ebpf_architecture} the presence of the so-called eBPF verifier. Provided that we will be loading programs in the kernel from user space, these programs need to be checked for safety before being valid to be executed. - -The verifier performs a series of tests which every eBPF program must pass in order to be accepted. Otherwise, user programs could leak privileged data, result in kernel memory corruption, or hang the kernel in an infinite loop, between others. Therefore, the verifier limits multiple aspects of eBPF programs so that they are restricted to the intended functionality, whilst at the same time offering a reasonable amount of freedom to the developer. - -The following are the most relevant checks that the verifier performs in eBPF programs\cite{ebpf_verifier_kerneldocs}\cite{ebpf_JIT_demystify_page17-22}: -\begin{itemize} -\item Tests for ensuring overall control flow safety: - \subitem No loops allowed (bounded loops accepted since kernel version 5.3\cite{ebpf_bounded_loops}. - \subitem Function call and jumps safety to known, reachable functions. - \subitem Sleep and blocking operations not allowed (to prevent hanging the kernel). -\item Tests for individual instructions: - \subitem Divisions by zero and invalid shift operations. - \subitem Invalid stack access and invalid out-of-bound access to data structures. - \subitem Reads from uninitialized registers and corruption of pointers. -\end{itemize} - -These checks are performed by two main algorithms: -\begin{itemize} -\item Build a graph representing the eBPF instructions (similar to the one shown in section \ref{subsection:analysis_bpf_filter_prog}. Check that it is in fact a direct acyclic graph (DAG), meaning that the verifier prevents loops and unreachable instructions. -\item Simulate execution flow by starting on the first instruction and following each possible path, observing at each instruction the state of every register and of the stack. -\end{itemize} - -\subsection{eBPF maps} \label{subsection:ebpf_maps} -An eBPF map is a generic storage for eBPF programs used to share data between user and kernel space, to maintain persistent data between eBPF calls and to share information between multiple eBPF programs\cite{ebpf_maps_kernel}. - -A map consists of a key + value tuple. Both fields can have an arbitrary data type, the map only needs to know the length of the key and the value field at its creation\cite{bpf_syscall}. Programs can open maps by specifying their ID, and lookup or delete elements in the map by specifying its key, also insert new ones by supplying the element value and they key to store it with. - -Therefore, creating a map requires a struct with the following fields: - -\begin{table}[H] -\begin{tabular}{|c|c|} -\hline -FIELD & VALUE\\ -\hline -type & Type of eBPF map. Described in table \ref{table:ebpf_map_types}\\ -key\_size & Size of the data structure to use as a key\\ -value\_size & Size of the data structure to use as value field\\ -max\_entries & Maximum number of elements in the map\\ -\hline -\end{tabular} -\caption{Table showing common fields for creating an eBPF map.} -\label{table:ebpf_map_struct} -\end{table} - -\begin{table}[H] -\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} -\hline -TYPE & DESCRIPTION\\ -\hline -BPF\_MAP\_TYPE\_HASH & A hast table-like storage, elements are stored in tuples.\\ -BPF\_MAP\_TYPE\_ARRAY & Elements are stored in an array.\\ -BPF\_MAP\_TYPE\_RINGBUF & Map providing alerts from kernel to user space, covered in subsection \ref{subsection:bpf_ring_buf}\\ -BPF\_MAP\_TYPE\_PROG\_ARRAY & Stores descriptors of eBPF programs\\ -\hline -\hline -\end{tabular} -\caption{Table showing types of eBPF maps. Only those used in our rootkit are displayed, the full list can be consulted in the man page \cite{bpf_syscall}} -\label{table:ebpf_map_types} -\end{table} - -Table \ref{table:ebpf_maps} describes the main types of eBPF maps that are available for use. During the development of our rootkit, we will mainly focus on hash maps (BPF\_MAP\_TYPE\_HASH), provided that they are simple to use and we do not require of any special storage for our research purposes. - -\subsection{The eBPF ring buffer} \label{subsection:bpf_ring_buf} -eBPF ring buffers are a special kind of eBPF maps, providing a one-way directional communication system, going from an eBPF program in the kernel to an user space program that subscribes to its events. - -%TODO DIAGRAM OF A TYPICAL RING BUFFER - -\subsection{The bpf() syscall} \label{subsection:bpf_syscall} -The bpf() syscall is used to issue commands from user space to kernel space in eBPF programs. This syscall is multiplexor, meaning that it can perform a great range of actions, changing its behaviour depending on the parameters. - -The main operations that can be issued are described in table \ref{table:bpf_syscall}: - -\begin{table}[H] -\begin{tabular}{|c|>{\centering\arraybackslash}p{5cm}|>{\centering\arraybackslash}p{5cm}|} -\hline -COMMAND & ATTRIBUTES & DESCRIPTION\\ -\hline -\hline -BPF\_MAP\_CREATE & Struct with map info as defined in table \ref{table:ebpf_map_struct} & Create a new map\\ -\hline -BPF\_MAP\_LOOKUP\_ELEM & Map ID, and struct with key to search in the map & Get the element on the map with an specific key\\ -\hline -BPF\_MAP\_UPDATE\_ELEM & Map ID, and struct with key and new value & Update the element of an specific key with a new value\\ -\hline -BPF\_MAP\_DELETE\_ELEM & Map ID and struct with key to search in the map & Delete the element on the map with an specific key\\ -\hline -BPF\_PROG\_LOAD & Struct describing the type of eBPF program to load & Load an eBPF program in the kernel\\ -\hline -\end{tabular} -\caption{Table showing types of syscall actions. Only those relevant to our research are shown the full list and attribute details can be consulted in the man page \cite{bpf_syscall}} -\label{table:ebpf_syscall} -\end{table} - -With respect to the program type indicated with BPF\_PROG\_LOAD, this parameter indicates the type of eBPF program, setting the context in the kernel in which it will run, and to which modules it will have access to. The types of programs relevant for our research are described in table \ref{table:ebpf_prog_types}. - -\begin{table}[H] -\begin{tabular}{|c|>{\centering\arraybackslash}p{5cm}|} -\hline -PROGRAM TYPE & DESCRIPTION\\ -\hline -\hline -BPF\_PROG\_TYPE\_KPROBE & Program to instrument code to an attached kprobe\\ -\hline -BPF\_PROG\_TYPE\_UPROBE & Program to instrument code to an attached uprobe\\ -\hline -BPF\_PROG\_TYPE\_TRACEPOINT & Program to instrument code to a syscall tracepoint\\ -\hline -BPF\_PROG\_TYPE\_XDP & Program to filter, redirect and monitor network events from the Xpress Data Path\\ -\hline -BPF\_PROG\_TYPE\_SCHED\_CLS & Program to filter, redirect and monitor events using the Traffic Control classifier\\ -\hline -\end{tabular} -\caption{Table showing types of eBPF programs. Only those relevant to our research are shown. The full list and attribute details can be consulted in the man page \cite{bpf_syscall}.} -\label{table:ebpf_prog_types} -\end{table} - -In section \ref{section:TODO}, we will proceed to analyse in detail the different program types and what capabilities` they offer. - -\subsection{eBPF helpers} \label{subsection:ebpf_helpers} -Our last component to cover of the eBPF architecture are the eBPF helpers. Since eBPF programs have limited accessibility to kernel functions (which kernel modules commonly have free access to), the eBPF system offers a set of limited functions called helpers\cite{ebpf_helpers}, which are used by eBPF programs to perform certain actions and interact with the context on which they are run. The list of helpers a program can call varies between eBPF program types, since different programs run in different contexts. - -It is important to highlight that, just like commands issued via the bpf() syscall can only be issued from the user space, eBPF helpers correspond to the kernel-side of eBPF program exclusively. Note that we will also find a symmetric correspondence to those functions of the bpf() syscall related to map operations (since these are accessible both from user and kernel space). - -Table \ref{table:ebpf_helpers} lists the most relevant general-purpose eBPF helpers we will use during the development of our project. We will later detail those helpers exclusive to an specific eBPF program type in the sections on which they are studied. - -\begin{table}[H] -\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} -\hline -eBPF helper & DESCRIPTION\\ -\hline -\hline -bpf\_map\_lookup\_elem() & Query an element with a certain key in a map\\ -\hline -bpf\_map\_delete\_elem() & Delete an element with a certain key in a map\\ -\hline -bpf\_map\_update\_elem() & Update the value of the element with a certain key in a map\\ -\hline -bpf\_probe\_read\_user() & Attempt to safely read data at an specific user address into a buffer\\ -\hline -bpf\_probe\_read\_kernel() & Attempt to safely read data at an specific kernel address into a buffer\\ -\hline -bpf\_trace\_printk() & Similarly to printk() in kernel modules, writes buffer in \/sys\/kernel\/debug\/tracing\/trace\_pipe\\ -\hline -bpf\_get\_current\_pid\_tgid() & Get the process process id (PID) and thread group id (TGID)\\ -\hline -bpf\_get\_current\_comm() & Get the name of the executable\\ -\hline -bpf\_probe\_write\_user() & Attempt to write data at a user memory address\\ -\hline -bpf\_override\_return() & Override return value of a probed function\\ -\hline -bpf\_ringbuf\_submit() & Submit data to an specific eBPF ring buffer, and notify to subscribers\\ -\hline -bpf\_tail\_call() & Jump to another eBPF program preserving the current stack\\ -\hline -\end{tabular} -\caption{Table showing common eBPF helpers. Only those relevant to our research are shown. Those helpers exclusive to an specific program type are not listed. The full list and attribute details can be consulted in the man page \cite{ebpf_helpers}.} -\label{table:ebpf_helpers} -\end{table} - - -% Is this the best title? -\section{eBPF program types} \label{section:ebpf_prog_types} -In the previous subsection \ref{subsection:bpf_syscall} we introduced the new types of eBPF programs that are supported and that we will be developing for our offensive analysis. In this section, we will analyse in greater detail how eBPF is integrated in the Linux kernel in order to support these new functionalities. - -\subsection{XDP} \label{subsection:xdp} -eXpress Data Path (XDP) programs are a novel type of eBPF program that allows for the lowest-latency traffic filtering and monitoring in the whole Linux kernel. In order to load an XDP program, a bpf() syscall with the command BPF\_PROG\_LOAD and the program type BPF\_PROG\_TYPE\_XDP must be issued. - -These programs are directly attached to the Network Interface Controller (NIC) driver, and thus they can process the packet before any other module\cite{xdp_gentle_intro}. - -\begin{figure}[H] - \centering - \includegraphics[width=15cm]{xdp_diag.jpg} - % Either this caption, or change the text afterwards. I still need to know whether to put the long explanation here or on the paragraph, it gets repetitive. - \caption{Figure showing how the eBPF XDP and TC modules are integrated in the network processing in the Linux kernel.} - \label{fig:xdp_diag} -\end{figure} - -Figure \ref{fig:xdp_diag} shows how XDP is integrated in the network processing of the Linux kernel. After receiving a raw packet (in the figure, \textit{xdp\_md}, which consists on the raw bytes plus some very basic metadata about the packet) from the incoming traffic, XDP program can perform the following actions\cite{xdp_manual}: -\begin{itemize} -\item Analyse the data between the packet buffer bounds. -\item Modify the packet contents, and modify the packet length. -\item Decide between one of the actions displayed in table \ref{table:xdp_actions_av}. -\end{itemize} - -\begin{table}[H] -\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} -\hline -ACTION & DESCRIPTION\\ -\hline -\hline -XDP\_PASS & Let packet proceed with operated modifications on it.\\ -\hline -XDP\_TX & Return the packet at the same NIC it was received from. Packet modifications are kept.\\ -\hline -XDP\_DROP & Drops the packet completely, kernel networking will not be notified.\\ -\hline -\end{tabular} -\caption{Table showing XDP relevant return values.} -\label{table:xdp_actions_av} -\end{table} - -Some of the XDP-exclusive eBPF helpers we will be discussing in later sections are shown in table \ref{table:xdp_helpers}. -\begin{table}[H] -\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} -\hline -eBPF helper & DESCRIPTION\\ -\hline -\hline -bpf\_xdp\_adjust\_head() & Enlarges or reduces the extension of a packet, by moving the address of its first byte.\\ -\hline -bpf\_xdp\_adjust\_tail() & Enlarges or reduces the extension of a packet, by moving the address of its last byte.\\ -\hline -\end{tabular} -\caption{Table showing relevant XDP-exclusive eBPF helpers.} -\label{table:xdp_helpers} -\end{table} - - -\subsection{Traffic Control} \label{subsection:tc} -Traffic Control (TC) programs are also indicated for networking instrumentation. Similarly to XDP, their module is positioned before entering the overall network processing of the kernel. However, as it can be observed in figure \ref{fig:xdp_diag}, they differ in some aspects: -\begin{itemize} -\item TC programs receive a network buffer with metadata (in the figure, \textit{sk\_buff}) about the packet in it. This renders TC programs less ideal than XDP for performing large packet modifications (like new headers), but at the same time the additional metadata fields make it easier to locate and modify specific packet fields\cite{tc_differences}. -\item TC programs can be attached to the \textit{ingress} or \textit{egress} points, meaning that an eBPF program can operate not only over incoming traffic, but also over the outgoing packets. -\end{itemize} - -With respect to how TC programs operate, the Traffic Control system in Linux is greatly complex and would require a complete section by itself. In fact, it was already a complete system before the appearance of eBPF. Full documentation can be found at \cite{tc_docs_complete}. For this document, we will explain the overall process needed to load a TC program\cite{tc_direct_action}: -\begin{enumerate} -\item The TC program defines a so-called queuing discipline (qdisc), a packet scheduler that issues packets in a First-In-First-Out (FIFO) order as soon as they are received. This qdisc will be attached to an specific network interface (e.g.: wlan0). -\item Our TC eBPF program is attached to the qdisc. It will work as a filter, being run for every of the packets dispatched by the qdisc. -\end{enumerate} - -Similarly to XDP, the TC eBPF programs can decide an action to be executed on a packet by specifying a return value. These actions are almost analogous to the ones in XDP, as it can be observed in table \ref{table:tc_actions}. - -\begin{table}[H] -\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} -\hline -ACTION & DESCRIPTION\\ -\hline -\hline -TC\_ACT\_OK & Let packet proceed with operated modifications on it.\\ -\hline -TC\_ACT\_RECLASSIFY & Return the packet to the back of the qdisc scheduling queue.\\ -\hline -TC\_ACT\_SHOT & Drops the packet completely, kernel networking will not be notified.\\ -\hline -\end{tabular} -\caption{Table showing TC relevant return values. Full list can be consulted at \cite{tc_ret_list_complete}.} -\label{table:tc_actions} -\end{table} - -Finally, as in XDP, there exists a list of useful BPF helpers that will be relevant for the creation of our rootkit. They are shown in table \ref{table:tc_helpers}. -\begin{table}[H] -\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} -\hline -eBPF helper & DESCRIPTION\\ -\hline -\hline -bpf\_l3\_csum\_replace() & Recomputes the network layer 3 (e.g.: IP) checksum of the packet.\\ -\hline -bpf\_l4\_csum\_replace() & Recomputes the network layer 4 (e.g: TCP) checksum of the packet.\\ -\hline -bpf\_skb\_store\_bytes() & Write a data buffer into the packet.\\ -\hline -bpf\_skb\_pull\_data() & Reads a sequence of packet bytes into a buffer.\\ -\hline -bpf\_skb\_change\_head() & (Only) enlarges the extension of a packet, by moving the address of its first byte.\\ -\hline -bpf\_skb\_change\_tail() & Enlarges or reduces the extension of a packet, by moving the address of its last byte.\\ -\hline -\hline -\end{tabular} -\caption{Table showing relevant TC-exclusive eBPF helpers.} -\label{table:tc_helpers} -\end{table} - - -%TODO This section might benefit from some diagrams, maybe. It was a bit to extense already, so skipping it from now -\subsection{Tracepoints} \label{subsection:tracepoints} -Tracepoints are a technology in the Linux kernel that allows to hook functions in the kernel, connecting a 'probe': a function that is executed every time the hooked function is called\cite{tp_kernel}. These tracepoints are set statically during kernel development, meaning that for a function to be hooked, it needs to have been previously marked with a tracepoint statement indicating its traceability. At the same time, this limits the number of tracepoints available. - -The list of tracepoint events available depends on the kernel version and can be visited under the directory \textit{/sys/kernel/debug/tracing/events}. - -It is particularly relevant for our later research that most of the system calls incorporate a tracepoint, both when they are called (\textit{enter} tracepoint) and when they are exited (\textit{exit} tracepoints). This means that, for a system call sys\_open, both the tracepoint sys\_enter\_open and sys\_exit\_open are available. - -Also, note that the probe functions that are called when hitting a tracepoint receive some parameters related to the context on which the tracepoint is located. In the case of syscalls, these include the parameters with which the syscall was called (only for \textit{enter} syscalls, \textit{exit} ones will only have access to the return value). The exact parameters and their format which a probe function receives can be visited in the file \textit{/sys/kernel/debug/tracing/events///format}. In the previous example with sys\_enter\_open, this is \textit{/sys/kernel/debug/tracing/events/syscalls/sys\_enter\_open/format}. - -In eBPF, a program can issue a bpf() syscall with the command BPF\_PROG\_LOAD and the program type BPF\_PROG\_TYPE\_TRACEPOINT, specifying which is the function with the tracepoint to attach to and an arbitrary function probe to call when it is hit. This function probe is defined by the user in the eBPF program submitted to the kernel. - -\subsection{Kprobes} -Kprobes are another tracing technology of the Linux kernel whose functionality has been become available to eBPF programs. Similarly to tracepoints, kprobes enable to hook functions in the kernel, with the only difference that it is dynamically attached to any arbitrary function, rather than to a set of predefined positions\cite{kprobe_manual}. It does not require that kernel developers specifically mark a function to be probed, but rather kprobes can be attached to any instruction, with a short list of blacklisted exceptions. - -As it happened with tracepoints, the probe functions have access to the parameters of the original hooked function. Also, the kernel maintains a list of kernel symbols (addresses) which are relevant for tracing and that offer us insight into which functions we can probe. It can be visited under the file \textit{/proc/kallsyms}, which exports symbols of kernel functions and loaded kernel modules\cite{kallsyms_kernel}. - -Also similarly, since tracepoints could be found in their \textit{enter} and \textit{exit} variations, kprobes have their counterpart, name kretprobes, which call the hooked probe once a return instruction is reached after the hooked symbol. This means that a kretprobe hooked to a kernel function will call the probe function once it exits. - -In eBPF, a program can issue a bpf() syscall with the command BPF\_PROG\_LOAD and the program type BPF\_PROG\_TYPE\_KPROBE, specifying which is the function with the kprobe to attach to and an arbitrary function probe to call when it is hit. This function probe is defined by the user in the eBPF program submitted to the kernel. - -\subsection{Uprobes} -Uprobes is the last of the main tracing technologies which has been become accessible to eBPF programs. They are the counterparts of Kprobes, allowing for tracing the execution of an specific instruction in the user space, instead of in the kernel. When the exeuction flow reaches a hooked instruction, a probe function is run. - -For setting an uprobe on an specific instruction of a program, we need to know three components: -\begin{itemize} -\item The name of the program. -\item The address of the function where the instruction is contained. -\item The offset at which the specific instruction is placed from the start of the function. -\end{itemize} - -Similarly to kprobes, uprobes have access to the parameters received by the hooked function. Also, the complementary uretprobes also exist, running the probe function once the hooked function returns. - -In eBPF, programs can issue a bpf() syscall with the command BPF\_PROG\_LOAD and the program type BPF\_PROG\_TYPE\_UPROBE, specifying the function with the uprobe to attach to and an arbitrary function probe to call when it is hit. This function probe is also defined by the user in the eBPF program submitted to the kernel. - -% Is this the best title? -\section{Developing eBPF programs} -In section \ref{section:modern_ebpf}, we discussed the overall architecture of the eBPF system which is now an integral part of the Linux kernel. We also studied the process which a piece of eBPF bytecode follows in order to be accepted in the kernel. However, for an eBPF developer, programming bytecode and working with bpf() calls natively is not an easy task, therefore an additional layer of abstraction was needed. - -Nowadays, there exist multiple popular alternatives for writing and running eBPF programs. We will overview which they are and proceed to analyse in further detail the option that we will use for the development of our rootkit. - -\subsection{BCC} -BPF Compiler Collection (BCC) is one of the first and well-known toolkits for eBPF programming available\cite{bcc_github}. It allows to include eBPF code into user programs. These programs are developed in python, and the eBPF code is embedded as a plain string. An example of a BCC program is included in %TODO ANNEX??? - -Although BCC offers a wide range of tools to easy the development of eBPF programs, we found it not to be the most appropriate for our large-scale eBPF project. This was in particular due to the feature of eBPF programs being stored as a python string, which leads to difficult scalability, poor development experience given that programming errors are detected at runtime (once the python program issues the compilation of the string), and simply better features from competing libraries. - -\subsection{Bpftool} -bpftool is not a development framework like BCC, but one of the most relevant tools for eBPF program development. Some of its functionalities include: -\begin{itemize} -\item Loading eBPF programs. -\item List running eBPF programs. -\item Dumping bytecode from live eBPF programs. -\item Extract program statistics and data from programs. -\item List and operate over eBPF maps. -\end{itemize} - -Although we will not be covering bpftool during our overview on the constructed eBPF rootkit, it was used extensively during the development and became a key tool for debugging eBPF programs, particularly to peek data at eBPF maps during runtime. - -\subsection{Libbpf} -libbpf\cite{libbpf_github} is a library for loading and interacting with eBPF programs, which is currently maintained in the Linux kernel source tree\cite{libbpf_upstream}. It is one of the most popular frameworks to develop eBPF applications, both because it makes eBPF programming similar to common kernel development and because it aims at reducing kernel-version dependencies, thus increasing programs portability between systems\cite{libbpf_core}. During our research, however, we will not make use of this functionalities given that a portable program is not in our research goals. - -As we discussed in section \ref{section:modern_ebpf}, eBPF programs are composed of both the eBPF code in the kernel and a user space program that can interact with it. With libbpf, the eBPF kernel program is developed in C (a real program, not a string later compiled as with BCC), while user programs are usually developed in C, Rust or GO. For our project, we will use the C version of libbpf, so both the user and kernel side of our rootkit will be developed in this language. - -% Cites in the following paragraph? -When using libbpf with the C language, both the user-side and kernel eBPF program are compiled together using the Clang/LLVM compiler, translating C instructions into eBPF bytecode. As a clarification, Clang is the front-end of the compiler, translating C instructions into an intermediate form understandable by LLVM, whilst LLVM is the back-end compiling the intermediate code into eBPF bytecode. As it can be observed in figure \ref{fig:libbpf}, the result of the compilation is a single program, comprising the user-side which will launch a user process, the eBPF bytecode to be run in the kernel, and other structures libbpf generates about eBPF maps and other meta data. This program is encapsulated as an ELF file (a common executable format). - -\begin{figure}[H] - \centering - \includegraphics[width=12cm, keepaspectratio=true]{libbpf_prog.jpg} - \caption{Sketch of the compilation and loading process of a program developed with libbpf.} - \label{fig:libbpf} -\end{figure} - -Finally, we will overview one of the main functionalities of libbpf to simplify eBPF programming, namely the BPF skeleton. This is auto-generated code by libbpf whose aim is to simplify working with eBPF from the user-side program. As a summary, it parses the eBPF programs developed (which may be using different technologies such as XDP, kprobes, TC...) and the eBPF maps used, and as a result offers a simple set of functions for dealing with these programs from the user program. In particular, it allows for loading and unloading an specific eBPF program from user space at runtime. - -Table \ref{table:libbpf_skel} describes the API offered by the BPF skeleton. Note that is subtituted by the name of the program being compiled. - -\begin{table}[H] -\begin{tabular}{|c|>{\centering\arraybackslash}p{10cm}|} -\hline -Function name & Description\\ -\hline -\hline -\_\_open() & Parse the eBPF programs and maps.\\ -\hline -\_\_load() & Load the eBPF map in the kernel after its validation, create the maps. However the programs are not active yet.\\ -\hline -\_\_attach() & Activate the eBPF programs, attaching them to their corresponding parts in the kernel (e.g. kprobes to kernel functions).\\ -\hline -\_\_destroy() & Detach and unload the eBPF programs from the kernel.\\ -\hline -\end{tabular} -\caption{Table showing BPF skeleton functions.} -\label{table:libbpf_skel} -\end{table} - -Note that the BPF skeleton also offers further granularity at the time of dealing with programs, so that individual programs can be loaded or attached instead of all simultaneously. This is the approach we will generally use in the development of our rootkit, as it will be explained in section \ref{TODO}. - - - - -\chapter{Analysis of offensive capabilities} \label{chapter:analysis_offensive_capabilities} -In the previous chapter, we detailed which functionalities eBPF offers and studied its underlying architecture. As with every technology, a prior deep understanding is fundamental for discussing its security implications. - -Therefore, given the previous background, this chapter is dedicated to an analysis in detail of the security implications of a malicious use of eBPF. For this, we will firstly explore the security features incorporated in the eBPF system. Then, we will identify the fundamental pillars onto which malware can build their functionality. As we mentioned during the project goals, these main topics of research will be the following: -\begin{itemize} -\item Analysing eBPF's possibilities when hooking system calls and kernel functions. -\item Learning eBPF's potential to read/write arbitrary memory. -\item Exploring networking capabilities with eBPF packet filters. -\end{itemize} - - -%TODO if this is finally not included, change the intro -Finally, we will study in detail some of the malicious applications that previous researchers have proposed to take advantage of these capabilities of eBPF. In the next chapter, we will proceed to elaborate on these ideas, find new purposes and design our own rootkit. - -\section{Security features in eBPF} -As we shown in section \ref{section:modern_ebpf}, eBPF has been an active part of the Linux kernel from its 3.18 version. However, as with many other components of the kernel, its availability to the user depends on the parameters with which the kernel has been compiled. Specifically, eBPF is only available to kernels compiled with the flags specified in table \ref{table:ebpf_kernel_flags}. - -\begin{table}[H] -\begin{tabular}{|c|c|>{\centering\arraybackslash}p{8cm}|} -\hline -Flag & Value & Description\\ -\hline -\hline -\multicolumn{1}{|c|}{CONFIG\_BPF} & \multicolumn{1}{|c|}{y} & \multirow{2}{*}{Basic BPF compilation (mandatory)}\\ -\cline{1-2} -\multicolumn{1}{|c|}{CONFIG\_BPF\_SYSCALL} & \multicolumn{1}{|c|}{m} & \\ -\hline -\multicolumn{1}{|c|}{CONFIG\_NET\_ACT\_BPF} & \multicolumn{1}{|c|}{m} & \multirow{2}{*}{Traffic Control functionality}\\ -\cline{1-2} -\multicolumn{1}{|c|}{CONFIG\_NET\_CLS\_BPF} & \multicolumn{1}{|c|}{y} & \\ -\hline -\multicolumn{1}{|c|}{CONFIG\_BPF\_JIT} & \multicolumn{1}{|c|}{y} & \multirow{2}{*}{Enable JIT compliation}\\ -\cline{1-2} -\multicolumn{1}{|c|}{CONFIG\_HAVE\_BPF\_JIT} & \multicolumn{1}{|c|}{y} & \\ -\hline -\multicolumn{1}{|c|}{CONFIG\_BPF\_EVENTS} & \multicolumn{1}{|c|}{y} & \multirow{4}{*}{Enable kprobes, uprobes and tracepoints}\\ -\cline{1-2} -\multicolumn{1}{|c|}{CONFIG\_KPROBE\_EVENTS} & \multicolumn{1}{|c|}{y} & \\ -\cline{1-2} -\multicolumn{1}{|c|}{CONFIG\_UPROBE\_EVENTS} & \multicolumn{1}{|c|}{y} & \\ -\cline{1-2} -\multicolumn{1}{|c|}{CONFIG\_TRACING} & \multicolumn{1}{|c|}{y} & \\ -\hline -CONFIG\_XDP\_SOCKETS & y & Enable XDP\\ -\hline -\end{tabular} -\caption{Kernel compilation flags for eBPF.} -\label{table:ebpf_kernel_flags} -\end{table} - -The above table is based on BCC's documentation\ref{table:ebpf_kernel_flags}, but the full list of eBPF-related flags can be extracted in a live system via bpftool, as detailed in Annex \ref{annex:bpftool_flags_kernel}. Nowadays, all mainstream Linux distributions include kernels with full support for eBPF. - -\subsection{Access control} - -It must be noted that, similarly to kernel modules, loading an eBPF program requires privileged access in the system. In old kernel versions, this means either an user having full root permissions, or having the Linux capability\cite{ubuntu_caps} CAP\_SYS\_ADMIN. Therefore, there existed two main options: -%Should we explain what is a capability? -\begin{itemize} -\item \textbf{Privileged users} can load any kind of eBPF program and use any functionality. -\item \textbf{Unprivileged users} can only load and attach eBPF programs of type BPF\_PROG\_TYPE\_SOCKET\_FILTER\cite{evil_ebpf_p9}, offering the very limited functionality of filtering packets received on a socket. -\end{itemize} - -More recently, in an effort to further granulate the permissions needed for loading, attaching and running eBPF programs, CAP\_SYS\_ADMIN has been substituted by more specific capabilities\cite{ebpf_caps_intro}\cite{ebpf_caps_lwn}. The current system is therefore described in table \ref{table:ebpf_caps_current}. - -\begin{table}[H] -\begin{tabular}{|>{\centering\arraybackslash}p{4cm}|>{\centering\arraybackslash}p{10cm}|} -\hline -Capabilities & eBPF functionality\\ -\hline -\hline -No capabilities & Load and attach BPF\_PROG\_TYPE\_SOCKET\_FILTER, load BPF\_PROG\_TYPE\_CGROUP\_SKB programs.\\ -\hline -CAP\_BPF & Load (but not attach) any type of program, create most types of eBPF map and access them if their id is known\\ -\hline -CAP\_NET\_ADMIN & Attach networking programs (Traffic Control, XDP, ...)\\ -\hline -CAP\_PERFMON & Attaching kprobes, uprobes and tracepoints. Read access to kernel memory.\\ -\hline -CAP\_SYS\_ADMIN & Privileged eBPF. Includes iterating over eBPF maps, and CAP\_BPF, CAP\_NET\_ADMIN, CAP\_PERFMON functionalities.\\ -\hline -\end{tabular} -\caption{Capabilities needed for eBPF.} -\label{table:ebpf_caps_current} -\end{table} - -Therefore, eBPF network programs usually require both CAP\_BPF and CAP\_NET\_ADMIN, whilst tracing programs require CAP\_BPF and CAP\_PERFMON. CAP\_SYS\_ADMIN still remains as the (non-preferred) capability to assign to eBPF programs with complete access in the system. - -Although for a long time there have existed efforts towards enhancing unprivileged eBPF, it remains a worrying feature\cite{unprivileged_ebpf}. The main issue is that the verifier must be prepared to detect any attempt to extract kernel memory access or user memory modification by unprivileged eBPF programs, which is a complex task. In fact, there have existed numerous security vulnerabilities which allow for privilege escalation using eBPF, that is, execution of privileged eBPF programs by exploiting vulnerabilities in unprivileged eBPF\cite{cve_unpriv_ebpf}. - -This influx of security vulnerabilities leads to the recent inclusion of an attribute into the kernel which allows for setting whether unprivileged eBPF is allowed in the system or not. This parameter is named \textit{kernel.unprivileged\_bpf\_disabled}, its values can be seen in table \ref{table:unpriv_ebpf_values}. - -\begin{table}[H] -\begin{tabular}{|>{\centering\arraybackslash}p{4cm}|>{\centering\arraybackslash}p{10cm}|} -\hline -Value & Meaning\\ -\hline -\hline -0 & Unprivileged eBPF is enabled.\\ -\hline -1 & Unprivileged eBPF is disabled. A system reboot is needed to enable it after changing this value.\\ -\hline -2 & Unprivileged eBPF is disabled. A system reboot is not needed to enable it after changing this value.\\ -\hline -\end{tabular} -\caption{Values for unprivileged eBPF kernel parameter.} -\label{table:unpriv_ebpf_values} -\end{table} - -Nowadays, most Linux distributions have set value 1 to this parameter, therefore disallowing unprivileged eBPF completely. These include Ubuntu\cite{unpriv_ebpf_ubuntu}, Suse Linux\cite{unpriv_ebpf_suse} or Red Hat Linux\cite{unpriv_ebpf_redhat}, between others. - -\subsection{eBPF maps security} -In table \ref{table:ebpf_caps_current}, we observed that only programs with CAP\_SYS\_ADMIN are allowed to iterate over eBPF maps. The reason why this is restricted to privileged programs is because it is functionality that is a potential security vulnerability, which we will now proceed to analyse. - -In subsection \ref{subsection:ebpf_maps} we mentioned that eBPF maps are opened by specifying an ID (which works similarly to the typical file descriptors), while in table \ref{table:ebpf_map_types} we showed that, for performing operations over eBPF maps using the bpf() syscall, the map ID must be specified too. - -Map IDs are known by a program after creating the eBPF map, however, a program can also explore all the available maps in the system by using the BPF\_MAP\_GET\_NEXT\_ID operation in the bpf() syscall, which allows for iterating through a complete hidden list of all the maps created. This means that privileged programs can find and have read and write access to any eBPF map used by any program in the system. - -Therefore, a malicious privileged eBPF program can access and modify other programs' maps, which can lead to: -\begin{itemize} -\item Modify data used for the program operation. This is the case for maps which mainly store data structures, such as BPF\_MAP\_TYPE\_HASH. -\item Modify the program control flow, altering the instructions executed by an eBPF program. This can be achieved if a program is using the bpf\_tail\_call() helper (introduced in table \ref{table:ebpf_helpers}) which is taking data from a map storing eBPF programs (BPF\_MAP\_TYPE\_PROG\_ARRAY, introduced in table \ref{table:ebpf_map_types}). -\end{itemize} - - -\section{Abusing tracing programs} -eBPF tracing programs (kprobes, uprobes and tracepoints) are hooked to specific points in the kernel or in the user space, and call probe functions once the flow of execution reaches the instruction to which they are attached. This section details the main security concerns regarding this type of programs. - -\subsection{Access to function arguments} -As we saw in section \ref{section:ebpf_prog_types}, tracing programs receive as a parameter those arguments with which the hooked function originally was called. These parameters are read-only and thus, in principle, they cannot be modified inside the tracing program (we will show this is not entirely true in section \ref{section:mem_corruption}). The next code snippets show the format in which parameters are received when using libbpf (Note that libbpf also includes some macros that offer an alternative format, but the parameters are the same). - - -\begin{lstlisting}[language=C, caption={Probe function for a kprobe on the kernel function vfs\_write.}, label={code:format_kprobe}] -SEC("kprobe/vfs_write") -int kprobe_vfs_write(struct pt_regs* ctx){ -\end{lstlisting} - -\begin{lstlisting}[language=C, caption={Probe function for an uprobe, execute\_command is defined from user space.}, label={code:format_uprobe}] -SEC("uprobe/execute_command") -int uprobe_execute_command(struct pt_regs *ctx){ -\end{lstlisting} - -\begin{lstlisting}[language=C, caption={Probe function for a tracepoint on the start of the syscall sys\_read.}, label={code:format_tracepoint}] -SEC("tp/syscalls/sys_enter_read") -int tp_sys_enter_read(struct sys_read_enter_ctx *ctx) { -\end{lstlisting} - -In code snippets \ref{code:format_kprobe} and \ref{code:format_uprobe} we can identify that the parameters are passed to kprobe and uprobe programs as a pointer to a \textit{struct pt\_regs*}. This struct contains as many attributes as registers exist in the system architecture, in our case x86\_64. Therefore, on each probe function, we will receive the state of the registers at the original hooked function. This explains the format of the \textit{struct pt\_regs}, shown in code snippet \ref{code:format_ptregs}: - -\begin{lstlisting}[language=C, caption={Format of struct pt\_regs.}, label={code:format_ptregs}] -struct pt_regs { - long unsigned int r15; - long unsigned int r14; - long unsigned int r13; - long unsigned int r12; - long unsigned int bp; - long unsigned int bx; - long unsigned int r11; - long unsigned int r10; - long unsigned int r9; - long unsigned int r8; - long unsigned int ax; - long unsigned int cx; - long unsigned int dx; - long unsigned int si; - long unsigned int di; - long unsigned int orig_ax; - long unsigned int ip; - long unsigned int cs; - long unsigned int flags; - long unsigned int sp; - long unsigned int ss; -}; -\end{lstlisting} - -By observing the value of the registers, we are able to extract the parameters of the original hooked function. This can be done by using the System V AMD64 ABI\cite{8664_params_abi}, the calling convention used in Linux. Depending on whether we are in the kernel or in user space, the registers used to store the values of the function arguments are different. Table \ref{table:systemv_abi} summarizes these two interfaces. - -\begin{table}[H] -\begin{tabular}{|>{\centering\arraybackslash}p{2cm}|>{\centering\arraybackslash}p{3cm}|} -\hline -\multicolumn{2}{|c|}{User interface}\\ -\hline -Register & Purpose\\ -\hline -\hline -rdi & 1st argument\\ -\hline -rsi & 2nd argument\\ -\hline -rdx & 3rd argument\\ -\hline -rcx & 4th argument\\ -\hline -r8 & 5th argument\\ -\hline -r9 & 6th argument\\ -\hline -rax & Return value\\ -\hline -\end{tabular} -\quad -\begin{tabular}{|>{\centering\arraybackslash}p{2cm}|>{\centering\arraybackslash}p{3cm}|} -\hline -\multicolumn{2}{|c|}{Kernel interface}\\ -\hline -Register & Purpose\\ -\hline -\hline -rdi & 1st argument\\ -\hline -rsi & 2nd argument\\ -\hline -rdx & 3rd argument\\ -\hline -r10 & 4th argument\\ -\hline -r8 & 5th argument\\ -\hline -r9 & 6th argument\\ -\hline -rax & Return value\\ -\hline -\end{tabular} -\caption{Argument passing convention of registers for function calls in user and kernel space respectively.} -\label{table:systemv_abi} -\end{table} - -In the case of tracepoints, we can see in code snippet \ref{code:format_tracepoint} that it receives a \textit{struct sys\_read\_enter\_ctx*}. This struct must be manually defined, as explained in \ref{subsection:tracepoints}, by looking at the file \textit{/sys/kernel/debug/tracing/events/syscalls/sys\_enter\_read/format}. Code snippet \ref{code:sys_enter_read_tp} shows the format of the struct. - -\begin{lstlisting}[language=C, caption={Format for parameters in sys\_enter\_read specified at the format file.}, label={code:sys_enter_read_tp_format}] -field:unsigned short common_type; offset:0; size:2; signed:0; -field:unsigned char common_flags; offset:2; size:1; signed:0; -field:unsigned char common_preempt_count; offset:3; size:1; signed:0; -field:int common_pid; offset:4; size:4; signed:1; -field:int __syscall_nr; offset:8; size:4; signed:1; -field:unsigned int fd; offset:16; size:8; signed:0; -field:char * buf; offset:24; size:8; signed:0; -field:size_t count; offset:32; size:8; signed:0; -\end{lstlisting} - -\begin{lstlisting}[language=C, caption={Format of custom struct sys\_read\_enter\_ctx.}, label={code:sys_enter_read_tp}] -struct sys_read_enter_ctx { - unsigned long long pt_regs; - int __syscall_nr; - unsigned int padding; - unsigned long fd; - char* buf; - size_t count; -}; -\end{lstlisting} - -As we can observe, we are given a set of attributes which include the parameters with which the syscall was called. Moreover, we can still obtain an address pointing to another \textit{struct pt\_regs}, as in kprobes and uprobes, by combining the first four fields and considering it as a 32-bit long address. This means we will still be able to extract the value of the rest of the registers too. - -It must be noted that, in syscalls, in addition to use the kernel parameter passing convention specified in table \ref{table:systemv_abi}, the number specifying the syscall must be passed in register rax too. - -On a final note, as we mentioned in section \ref{section:ebpf_prog_types}, there exist differences in the parameters received in probe functions depending on the two variations of tracing programs. Therefore: -\begin{itemize} -\item kprobe, uprobe and \textit{enter} tracepoints will receive the full parameters as we specified before, but not the return value of the function (since it is not executed yet). -\item kretprobes, uretprobes and \textit{exit} tracepoints will still receive the \textit{struct pt\_regs}, but without any of the parameters and with only the return value of the function. -\end{itemize} - -Taking into account all the previous, the fact that tracing programs have read-only access to function arguments can be considered an useful and needed feature for tracing applications, but malicious eBPF can use this for purposes such as: -\begin{itemize} -\item Gather kernel and user data passed to a function as a parameter. In many cases this information can be potentially interesting for an attacker, such as passwords. -\item Store in eBPF maps information about system activities, to be used by other malicious eBPF programs. -\end{itemize} - -Usually, since many function arguments are pointers to user or kernel addresses (such as buffers where a string or a struct with data is located), eBPF tracing programs can use two eBPF helpers that enable to read large byte arrays from both kernel and user space: -\begin{itemize} -\item bpf\_probe\_read\_user() -\item bpf\_probe\_read\_kernel() -\end{itemize} - -These helpers, previously introduced in table \ref{table:ebpf_helpers}, enable to read an arbitrary number of bytes from an user or kernel address respectively, allowing us to extract the information pointed by the parameters received by eBPF programs. - -\subsection{Reading memory out of bounds} \label{subsection:out_read_bounds} -As we introduced in the previous subsection, the bpf\_probe\_read\_user() and bpf\_probe\_read\_kernel() helpers can be used to access memory of pointers received as parameters in the hooked functions. - -However, although in general the eBPF verifier attempts to reject illegal memory accesses, it does not prevent a malicious program from passing an arbitrary memory address (in kernel or user space) to the above helpers. This means that an eBPF program can potentially read any address in user or kernel space, (as long as it is marked as readable in the corresponding memory pages). Furthermore, an attacker can locate specific data structures and memory sections by taking the function parameter as a reference point in memory. - -A particularly relevant case (which we will later use for our rootkit) involves accessing user memory via the parameters of tracepoints attached at system calls. Provided the nature of syscalls, whose purpose is to communicate user and kernel space, all parameters received will belong to the user space, and therefore any pointer passed will be an address in user memory. This enables an eBPF program to get a foothold into the virtual address space of the process calling the syscall, which it can proceed to scan looking for data or specific instructions. This technique will be further elaborated in section \ref{subsection_bpf_probe_write_apps}. - -\subsection{Overriding function return values} -A potentially dangerous functionality in eBPF tracing programs is the ability to modify the return value of kernel functions\cite{ebpf_friends_p15}\cite{ebpf_override_return}. This can be done via the eBPF helper bpf\_override\_return, and it works exclusively from kretprobes. - -Apart from only working on kretprobes, additional restrictions are applied to this helper. It will only work if the kernel was compiled with the CONFIG\_BPF\_KPROBE\_OVERRIDE flag, and only if the kretprobe is attached to a function to which, during the kernel development, the macro ALLOW\_ERROR\_INJECTION() has been indicated. Currently, only a small selection of functions include this macro, but most system calls can be found to implement it. The following code snippets show how a system call like sys\_open is defined in kernel v5.11: - -\begin{lstlisting}[language=C, caption={Definition of the syscall sys\_open in the kernel \cite{code_kernel_open}}, label={code:override_return_1}] -SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) -{ - if (force_o_largefile()) - flags |= O_LARGEFILE; - return do_sys_open(AT_FDCWD, filename, flags, mode); -} -\end{lstlisting} - -\begin{lstlisting}[language=C, caption={Definition of the macro for creating syscalls, containing the error injection macro. Only relevant instructions included, complete macro can be found in the kernel \cite{code_kernel_syscall}}, label={code:override_return_2}] -#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) -#ifndef __SYSCALL_DEFINEx -#define __SYSCALL_DEFINEx(x, name, ...)\ - [...] - ALLOW_ERROR_INJECTION(sys##name, ERRNO);\ - [...] -\end{lstlisting} - - -By looking at snippets \ref{code:override_return_1} and \ref{code:override_return_2}, we can observe that the system call sys\_open involves the inclusion of the ALLOW\_ERROR\_INJECTION macro. Therefore, any kretprobe attached to a system call function will be able to modify its return value. - -In order to be able to modify the return value of functions, the aforementioned eBPF helper makes use of the fault injection framework of the Linux kernel\cite{fault_injection}, which was created before eBPF itself, and whose original purpose is to allow for generating errors in kernel programs for debugging purposes. - -Taking the previous information into account, we can find that a malicious eBPF program, by tampering with the kernel-user space interface which are system calls, can mislead user programs, which trust the output of kernel code. This can lead to: -\begin{itemize} -\item A program believes a system call exited with an error, while in reality the kernel completed the operation with success, or viceversa. For instance, the result of a call to sys\_open can mislead a user program into thinking that a file does not exist. -\item A program receives incorrect data on purpose. For instance, a buffer may look empty or of a reduced size upon a sys\_read call, while in reality more data is available to be read. -\end{itemize} - -\subsection{Sending signals to user programs} -Another eBPF helper that is subject to malicious purposes is bpf\_send\_signal. This helper enables to send an arbitrary signal to the thread of the process running a hooked function. - -Therefore, this helper can be used to forcefully terminate running user processes, by sending the SIGKILL signal. In this way, combined with the observability into the parameters received at a function call, malicious eBPF can kill and deactivate processes to favour its malicious purposes. - -\subsection{Conclusion} \label{subsection:tracing_attacks_conclusion} -As a summary, a malicious eBPF program loaded and attached as a tracing program undermines the existing trust between user programs and the kernel space. - -Its ability to access sensitive data in function parameters and reading arbitrary memory can lead to gathering extensive information on the running processes of a system, whilst the malicious use of eBPF helpers enables the modification of the data passed to the user space from the kernel, and the control over which programs are allowed to be running on the system. - -\section{Memory corruption} \label{section:mem_corruption} -In the previous section we described how tracing programs can read user memory out of the bounds of function parameters via the helpers bpf\_probe\_read\_user() and bpf\_probe\_read\_kernel(). In this section, we will analyse another eBPF helper can be found to be the heart of malicious programs. - -Privileged eBPF programs (or those with at least CAP\_BPF + CAP\_PERFMON capabilities) have the potential to use an experimental (it is labelled as so \cite{ebpf_helpers}) helper called bpf\_probe\_write\_user(). This helper enables to write into user memory from within an eBPF program. - -However, this helper has certain limitations that restrict its use. We will now proceed to review some background into how user memory works and, afterwards, we will analyse the restrictions and possible uses of this eBPF helper in the context of malicious applications. - -\subsection{Memory management in Linux} -Linux systems divide the available random access memory (RAM) into 'pages', subsections of an specific length, usually 4 KB. The collection of all pages is called physical memory. - -Likewise, individual memory sections need to be assigned to each running process in the system, but instead of assigning a set of pages from physical memory, a new address space is defined, named virtual memory, which is divided into pages as well. These virtual memory pages are related to physical memory pages via a page table, so that each virtual memory address of a process can be translated into a real, physical memory address in RAM\cite{mem_page_arch}. Figure \ref{fig:mem_arch_pages} shows a diagram of the described architecture. - -\begin{figure}[H] - \centering - \includegraphics[width=13cm]{mem_arch_pages.jpg} - \caption{Memory translation of virtual pages to physical pages.} - \label{fig:mem_arch_pages} -\end{figure} - -As we can observe in the figure, each virtual page is related to one physical page. However, RAM needs to maintain multiple processes and data simultaneously, and therefore sometimes the operating system (OS) will remove them from physical memory when it believes they are no longer being used. This leads to the occurrence of two type of memory events\cite{page_faults}: -\begin{itemize} -\item \textbf{Major page faults} occur when a process tries to access a virtual page, but the related physical page has been removed from RAM. In this case, the OS will need to request a secondary storage (such as a hard disk) for the data removed, and allocate a new physical page for the virtual page. Figure \ref{fig:mem_major_page_fault} illustrates a major page fault. -\begin{figure}[H] - \centering - \includegraphics[width=11cm]{mem_major_page_fault.jpg} - \caption{Major page fault after a page was removed from RAM.} - \label{fig:mem_major_page_fault} -\end{figure} -\item \textbf{Minor page faults} occur when a process tries to access a virtual page, and although the related physical page exists, the connection in the page table has not been completed. A common event when these fault happen is on fork() calls, since with the purpose of making the call more efficient, the page table of the parent is not always completely copied into the child, leading into multiple minor page faults once the child tries to access the data on them. Figure \ref{fig:mem_minor_page_fault} illustrates a minor page fault after a fork. -\end{itemize} -\begin{figure}[H] - \centering - \includegraphics[width=11cm]{mem_minor_page_fault.jpg} - \caption{Minor page fault after a fork() in which the page table was not copied completely.} - \label{fig:mem_minor_page_fault} -\end{figure} - -\subsection{Process virtual memory} -In the previous subsection we have studied that each process disposes of a virtual address space. We will now describe how this virtual memory is organized in a Linux system. - -%TODO Add the .data section here -\begin{figure}[H] - \centering - \includegraphics[width=6cm]{memory.jpg} - \caption{Virtual memory architecture of a process\cite{mem_arch_proc}.} - \label{fig:mem_proc_arch} -\end{figure} - -Figure \ref{fig:mem_proc_arch} describes how virtual memory is distributed within a process in the x86\_64 architecture. As we can observe, it is partitioned into multiple sections: -\begin{itemize} -\item Lower and upper memory addresses are reserved for the kernel. -\item A section where shared libraries code is stored. -\item A .text section, which contains the code of the program being run. -\item A .data section, containing initialized static and global variables. -\item A .bss section, which contains global and static variables which are unitialized or initialized to zero. -\item The heap, a section which grows from lower to higher memory addresses, and which contains memory dynamically allocated by the program. -\item The stack, a section which grows from higher to lower memory addresses, towards the heap. It is a Last In First Out (LIFO) structure used to store local variables, function parameters and return addresses. -\item Right at the start of the stack we can find the arguments with which the programs has been executed. -\end{itemize} - -\subsection{The process stack} \label{subsection:stack} -Between all the sections we identified in a process virtual memory, the stack will be particularly relevant during our research. We will therefore study it now in detail. - -Firstly, we will present how the stack is structured, and which operations can be executed on it. Figure \ref{fig:stack_pres} presents a stack during the execution of a program. Table \ref{table:systemv_abi_other} explains the purpose of the most relevant registers related to the stack and program execution: - -\begin{figure}[H] - \centering - \includegraphics[width=14cm]{stack_pres.jpg} - \caption{Simplified stack representation showing only stack frames.} - \label{fig:stack_pres} -\end{figure} - -\begin{table}[H] -\begin{tabular}{|>{\centering\arraybackslash}p{2cm}|>{\centering\arraybackslash}p{10cm}|} -\hline -Register & Purpose\\ -\hline -\hline -rip & Instruction Pointer - Memory address of the next instruction to execute\\ -\hline -rsp & Stack Pointer - Memory address where next stack operation takes place\\ -\hline -rbp & Base/Frame Pointer - Memory address of the start of the stack frame\\ -\hline -\end{tabular} -\caption{Relevant registers in x86\_64 for the stack and control flow and their purpose.} -\label{table:systemv_abi_other} -\end{table} - -As it can be observed in figure \ref{fig:stack_pres}, the stack grows towards lower memory addresses, and it is organized in stack frames, delimited by the registers rsp and rbp. An stack frame is a division of the stack which contains all the data (variables, call arguments...) belonging to a single function execution. When a function is exited, its stack frame is removed, and if a function calls a nested function, then its stack frame is preserved and a new stack frame is inserted into the stack. - -As table \ref{table:systemv_abi_other} explains, the rbp and rsp registers are used for keeping track of the starting and final position of the current stack frame respectively. We can see in figure \ref{fig:stack_pres} that their value is a memory address pointing to their stack positions. On the other hand, the rip register does not point to the stack, but rather to the .text section (see figure \ref{fig:mem_proc_arch}), where it points to the next instruction to be executed. However, as we will now see, its value must also be stored in the stack frame when a nested function is called, since after the nested function exits we need to restore the execution in the same instruction of the original function. - -As with any LIFO structure, the stack supports two main operations: \textit{push} and \textit{pop}. In the x86\_64 architecture, it operates with chunks of data of either 16, 32 or 64 bytes. -\begin{itemize} -\item A \textbf{push} operation writes data in the free memory pointed by register rsp. It then moves the value of rsp to point to the new end of the stack. -\item A \textbf{pop} operation moves the value of rsp by 16, 32 or 64 bytes, and reads the data previously saved in that position. -\end{itemize} - -\begin{figure}[H] - \centering - \includegraphics[width=10cm]{stack_ops.jpg} - \caption{Representation of push and pop operations in the stack.} - \label{fig:stack_ops} -\end{figure} - - - -As we mentioned, the stack stores function parameters, return addresses and local variables inside a stack frame. We will now study how the processor uses the stack in order to call, execute, and exit a function. To illustrate this process, we will simulate the execution of function \lstinline{func(char* a, char* b, char* c)} \lstinline{}: - -\begin{figure}[H] - \centering - \includegraphics[width=14cm]{stack_before.jpg} - \caption{Stack representation right before starting the function call process.} - \label{fig:stack_before} -\end{figure} - -\begin{figure}[H] - \centering - \includegraphics[width=14cm]{stack.jpg} - \caption{Stack representation right after the function preamble.} - \label{fig:stack} -\end{figure} - -\begin{enumerate} -\item The function arguments are pushed into the stack. We can see them in the stack in reverse order. -\item The function is called: -\begin{enumerate} - \item The value of register rip is pushed into the stack, so that it is saved for when the function exists. We can see it on the figure as 'ret'. - \item The value of rip changes to point to the first instruction of the called function. -\item We execute what is called as the \textit{function preamble}\cite{8664_params_abi_p18}, which prepares the stack frame for the called function: - \item The value of rbp is pushed into the stack, so that we can restore the previous stack frame when the function exits. We can see it on the figure as the 'saved frame pointer'. - \item The value of rsp is moved into rbp. Therefore, now rbp points to the end of the previous stack frame. - \item The value of rsp is usually decremented (since the stack needs to go to lower memory addresses) so that we allocate some space for function variables. -\end{enumerate} -\item The function instructions are executed. The stack may be further modified, but on its end rsp must point to the same address of the beginning. Register rbp always keeps pointing to the end of the stack. -\item We execute what is called as the \textit{function epilogue}, which removes the stack frame and restores the original function: -\begin{enumerate} - \item The value of rbp is moved into rsp, so that rsp points to the start of the previous stack frame. All data allocated in the previous stack frame is considered to be free. - \item The value of the saved frame pointer is popped and stored into rbp, so that rbp now points to the start of the previous stack frame. - \item The value of the saved rip value is popped into register rip, so that the next instruction to execute is the instruction right after the function call. -\end{enumerate} -\item Since the function arguments where pushed into the stack, they are popped now. -\end{enumerate} - -\subsection{Attacks and limitations of bpf\_probe\_write\_user()} \label{subsection:bpf_probe_write_apps} -Provided the background into memory architecture and the stack operation, we will now study the offensive capabilities of the bpf\_probe\_write\_user() helper and which restrictions are imposed into its use by eBPF programs. - -The bpf\_probe\_write\_user() helper, when used from a tracing eBPF program, can write into any memory address in the user space of the process responsible from calling the hooked function. However, the write operation fails has some restrictions: -\begin{itemize} -\item{The operation fails if the memory space pointed by the address is marked as non-writeable by the user space process. For instance, if we try to write into the .text section, the helpers fails because this section is only marked as readable and executable (for protection reasons).} Therefore, the process must indicate a writeable flag in the memory section for the helper to succeed. -\item{The operation fails if the memory page is served with a minor or major page fault. As we saw in section \ref{subsection:ebpf_verifier}, eBPF programs are restricted from executing any sleeping or blocking operations, to prevent hanging the kernel. Therefore, since during a page fault the operating system needs to block the execution and write into the page table or retrieve data from the secondary disk, bpf\_probe\_write\_user() is defined as a non-faulting helper\cite{write_helper_non_fault}, meaning that instead of issuing a page fault for accessing data, it will just return and fail.} -\item{Each time the helper is called, an alert message is written into the kernel logs, alerting that a potentially dangerous eBPF program is making use of the helper. Note that this message appears when the eBPF program is attached, and not each time the helper is called. This will be particularly relevant since we will be able to bypass this alert by taking advantage of this.} -\end{itemize} - -Although we will not be able to modify kernel memory or the instructions of a program, this eBPF helper opens a range of possible attacks: -\begin{itemize} -\item Modify any of the arguments with which a system call is called (either with a tracepoint or a kprobe). Therefore, a malicious program can hijack any call to the kernel with its own arguments. -\item Modify user-provided arguments in kernel functions. When reading kernel code, we can find that data provided by the user is marked with the keyword \textit{\_\_user}. For instance, an internal kernel function in a nested call of the system call sys\_read receives an user buffer: -\begin{lstlisting}[language=C, caption={Definition of kernel function vfs\_read. \cite{code_vfs_read}}, label={code:vfs_read}] -ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) -\end{lstlisting} -Then, if we attach a kprobe to vfs\_read, we would be able to modify the value of the buffer. -\item Modify process memory by taking function parameters as a reference and scanning the stack. This technique, first introduced in section \ref{subsection:out_read_bounds} when we mentioned that tracing programs can read any user memory location with the bpf\_probe\_read\_user() helper, and which was publicly first used by Jeff Dileo at his talk in DEFCON 27\cite{evil_ebpf_p6974}, consists of: -\begin{enumerate} -\item Take an user-passed parameter received on a tracing program. The parameter must be a pointer to a memory location (such as a pointer to a buffer), so that we can use that memory address as the reference point in user space. According to the x86\_64 documentation, this parameter will be stored in the stack\cite{8664_params_abi_p1922}, so we will receive an stack address. -\item Locate the target data which we aim to write. There are two main methods for this: -\begin{itemize} - \item Sequentially read the stack, using bpf\_probe\_read\_user(), until we locate the bytes we are looking for. This requires knowing which data we want to overwrite. - \item By previously reverse engineering the user program, we can calculate the offset at which an specific data section will be stored in virtual memory with respect to the reference address we received as a parameter. -\end{itemize} -\item Overwrite the memory buffer using bpf\_probe\_write\_user(). -\end{enumerate} -\end{itemize} - -Figure \ref{fig:stack_scan_write_tech} illustrates a high-level overview of the stack scanning technique previously described: -%TODO i just noticed I included SFP outside the current stack frame, correct it here and everywhere -\begin{figure}[H] - \centering - \includegraphics[width=16cm]{stack_scan_write_tech.jpg} - \caption{Overview of stack scanning and writing technique.} - \label{fig:stack_scan_write_tech} -\end{figure} - -The above figure shows process memory executing a program similar to the following: -\begin{lstlisting}[language=C, caption={Sample program being executed on figure \ref{fig:stack_scan_write_tech}.}, label={code:stack_scan_write_tech}] -void func(char* a, char* b, char* c){ - int fd = open("FILE", 0); - write(fd, a, 1); -} - -int main(){ - char a[] = "AAA"; - char b[] = "BBB"; - char c[] = "CCC"; - func(a, b, c); -} -\end{lstlisting} - -In the figure, we can clearly observe how the technique is used to overwrite an specific buffer. The attacker goal is to overwrite buffer \textit{c} with some other bytes, but the kprobe program only has direct access to buffer \textit{a}: -\begin{enumerate} -\item By reverse engineering the program (we will see how this process works in section \ref{TODO}) we notice that buffer \textit{c} is stored 8 bytes lower on the stack than buffer \textit{a}. -\item When register rip points to the write() instruction, the processor executes the instruction and a system call is issued to sys\_write(). -\item The kprobe eBPF program hooked to the syscall hijacks the program execution. Since it has access to the memory address of buffer \textit{a} and it knows the relative position of buffer \textit{c}, it writes to that location whatever it wants (e.g.: "DDD") with the bpf\_probe\_write\_user() helper. -\item The eBPF program ends and the control flow goes back to the system call. It ends its execution successfully, and returns a value to the user space. The result of the program is that 1 byte has been written into file "FILE", and that buffer \textit{c} now contains "DDD". -\end{enumerate} - -\subsection{Conclusion} -As a summary, the bpf\_probe\_write\_user() helper is one of the main attack vectors for malicious eBPF programs. Although it does contain some restrictions, its ability to overwrite any user parameter enables it to, in practice, execute arbitrary code by hijacking that of others. When it is combined with tracing programs' ability to read memory out of bounds, it unlocks a wide range of attacks, since any writeable section of the process memory is a possible target. - -Therefore, if on the conclusion of section \ref{subsection:tracing_attacks_conclusion} we discussed that the ability to change the return value of kernel functions and kill processes hinders the trust between the user and kernel space (since what the kernel returns may not be a correct result), then the ability to directly overwrite process data is a complete disrupt of trust in any of the data in the user space itself, since it is subject to the control of a malicious eBPF program. - -Moreover, in the next sections we will discuss how we can create advanced attacks on the basis of the background and techniques previously discussed. We will research further into which sections of a process memory are writeable and whether they can lead to new attack vectors. - - -\section{Abusing networking programs}\label{section:abusing_networking} -The final main piece of a malicious eBPF program comes from taking advantage of the networking capabilities of TC and XDP programs. As we mentioned during sections \ref{subsection:xdp} and \ref{subsection:tc}, these type of programs have access to network traffic: -\begin{itemize} -\item Traffic Control programs can be placed either on egress or ingress traffic, and receive a struct \textit{sk\_buff}, containing the packet bytes and meta data that helps operating on it. -\item External Data Path programs can only be attached to ingress traffic, but in turn they receive the packet before any kernel processing (as a struct \textit{xdp\_md}) being able to access the raw data directly. -\end{itemize} - -Networking eBPF programs not only have read access to the network packets, but also write access: -\begin{itemize} -\item XDP programs can directly modify the raw packet via memcpy() operations. They can also increment or reduce the size of the packet at any of its ends (adding bytes before the head or after the packet tail). This is done via the multiple helpers previously presented on table \ref{table:xdp_helpers}. -\item TC programs can also modify the packet via the helpers presented on table \ref{table:tc_helpers}. The packet can be expanded or reduced via these eBPF helpers too. -\end{itemize} - -Apart from write access to the packet, the other critical feature of networking programs is their ability to drop packets. As we presented in tables \ref{table:xdp_actions_av} and \ref{table:tc_actions}, this can be achieved by returning specific values. - -\subsection{An overview on the network layer} -In order to tackle multiple techniques we will be using in networking programs, we will offer an overview on the relevant aspects of the Ethernet, IP and TCP protocols, on which we will focus during the later development of our rootkit. - -Firstly, we will describe the data structure we will be dealing with in networking programs. This will be Ethernet frames containing TCP/IP packets. Figure \ref{fig:frame} shows the frame in its completeness: - -\begin{figure}[H] - \centering - \includegraphics[width=14cm]{frame.jpg} - \caption{Ethernet frame with TCP/IP packet.} - \label{fig:frame} -\end{figure} - -As we can observe, we can distinguish five different network layers in the frame. This division is made according to the OSI model\cite{network_layers}: -\begin{itemize} -\item Layer 1 corresponds to the physical layer, and it is processed by the NIC hardware, even before it reaches the XDP module (see figure \ref{fig:xdp_diag}). Therefore, this layer is discarded and completely invisible to the kernel. Note that it does not only include a header, but also a trailer (a Frame Check Sequence, a redundancy check included to check frame integrity). -\item Layer 2 is the data layer, it is in charge of transporting the frame via physical media, in our case an Ethernet connection. Most relevant fields are the MAC destination and source, used for performing physical addressing. -\item Layer 3 is the network layer, in charge of packet forwarding and routing. In our case, packets will be using the IP protocol. Most relevant fields are the source and destination IP, used to indicate the host that sent the packet and who is the receiver. -\item Layer 4 is the transport layer, in charge of providing end-to-end connection services to applications in a host. We will be focusing on TCP during our research. Relevant fields include the source and destination port, which indicate the ports involved in the communication on which the application on each host are listening and sending packets. -\item The last layer is the payload of the TCP packet, which contains, according to the OSI model, all layers belong to application data. -\end{itemize} - - -\subsection{Introduction to the TCP protocol} \label{subsection:tcp} -We will now focus our view on the transport layer, specifically on the TCP protocol, since it will be a major concern at the time of designing the network capabilities of our rootkit. - -Firstly, since TCP aims to offer a reliable and ordered packet transmission\cite{tcp_reliable}, it includes sequence numbers (see table \ref{fig:frame}) which mark the order in which they are transmitted. However, since the physical medium may corrupt or lose packets during the transmission, TCP must incorporate mechanisms for ensuring the order and delivery of all packets: -\begin{itemize} -\item Mechanism for opening and establishing a reliable connection between two parties. -\item Mechanism for ensuring that packets are retransmitted in case of an error during the connection. -\end{itemize} - -With respect to the establishment of a reliable connection, this is achieved via a 3-way handshake, in which certain TCP flags will be set in a series of interchanged packets (see in figure \ref{fig:frame} the field TCP flags). Most relevant TCP flags are described in table \ref{table:tcp_flags}. - -\begin{table}[H] -\begin{tabular}{|>{\centering\arraybackslash}p{4cm}|>{\centering\arraybackslash}p{10cm}|} -\hline -Flag & Purpose\\ -\hline -\hline -ACK & Acknowledges that a packet has been successfully received. In the acknowledgment number (see figure \ref{fig:frame}), it is stored the sequence number of the packet being acknowledged + 1. \\ -\hline -SYN & Used during the 3-way handshake, indicates request for establishing a connection.\\ -\hline -FIN & Used to request a connection termination.\\ -\hline -RST & Abruptly terminates the connection, usually sent when a host receives an unexpected or unrecognized packet.\\ -\hline -\end{tabular} -\caption{Relevant TCP flags and their purpose.} -\label{table:tcp_flags} -\end{table} - -Taking the above into account, figure \ref{fig:tcp_conn} shows a depiction of the 3-way handshake\cite{tcp_handshake}: -\begin{figure}[H] - \centering - \includegraphics[width=12cm]{tcp_conn.jpg} - \caption{TCP 3-way handshake.} - \label{fig:tcp_conn} -\end{figure} - -As we can observe in the figure, the hosts interchange a sequence of , , packets, after which the communication starts. During this communication, the sender transmits packets with data (and no flags set), to which it expects an packet acknowledging having received it. - -With respect to maintaining the integrity of the connection once it starts, TCP works using timers, as it is illustrated in figure \ref{fig:tcp_retransmission}: -\begin{enumerate} -\item A data packet with sequence number X is sent. The timer starts. -\item The destination host receives the packet and returns an ACK packet with acknowledgment number X+1. -\item The sender receives the ACK packet and stops the timer. If, for any reason, the ACK packet is not received before the timer ends, then the same packet is retransmitted. -\end{enumerate} - -\begin{figure}[H] - \centering - \includegraphics[width=12cm]{tcp_retransmission.jpg} - \caption{TCP packet retransmission on timeout.} - \label{fig:tcp_retransmission} -\end{figure} - - - -\subsection{Attacks and limitations of networking programs} -Based on the previous background, we will now proceed to explore which limitations exist on which actions a network eBPF program can perform: -\begin{itemize} -\item Read and write access to the packet is heavily controlled by the eBPF verifier. It is not possible to read or write data out of bounds. Extreme care must also be taken before attempting to read any data inside the packet, since the verifier first requires making lots of checks beforehand. For any access to take place, the program must first classify the packet according to the network protocol it belongs, and later check that every header of every layer is well defined (e.g: Ethernet, IP and TCP). Only after that, the headers can be modified. - -If the program also wants to modify the packet payload, then it must be checked to be between the bounds of the packet and well defined according to the packet headers(using fields IHL, packet length and data offset, in figure \ref{fig:frame}). Also, after using any of the helpers that enlarge or reduce the size of the packet, all check operations must be repeated again before any subsequent operation. - -Finally, note that after any modification in the packet, some network protocols (such as IP and TCP) require to recalculate their checksum fields. - -\item XDP and TC programs are not able to create packets, they can only operate over existing traffic. - -\item If an XDP program modifies an incoming packet, the kernel will not know about the original data, but if an egress TC program modifies a packet being sent, the kernel will be able to notice the modification. -\end{itemize} - -Having the previous restrictions in mind, we can find multiple possible malicious uses of an XDP/TC program: -\begin{itemize} -\item \textbf{Spy all network connections} in the system. An XDP or TC ingress program can read any packet from any interface, therefore achieving a comprehensive view on which are the running communications and opened ports (even if protocols with encryption are being used) and gathering transmitted data (if the connection is also in plaintext). -\item \textbf{Hide arbitrary traffic} from the host. If an XDP program drops a packet, the kernel will not be able to know any packet was received in the first place. This can be used to hide malicious incoming traffic. However, as we will mention in section{TODO}, malicious traffic may still be detected by other external devices, such as network-wide firewalls. -\item \textbf{Modify incoming traffic} with XDP programs. Every packet can be modified (as we mentioned at the beginning of section \ref{section:abusing_networking}), and any modification will be unnoticeable to the kernel, meaning that we will have complete, invisible control over the packets received by the kernel. -\item \textbf{Modify outgoing traffic} with TC egress programs. Since every packet can be modified at will, we will therefore have complete control over any packet sent by the host. This can be used to enable a malicious program to communicate over the network and exfiltrate data, since even if we cannot create a new connection from eBPF, we can still modify existing packets, writing any payload and headers on it (thus being able to, for instance, change the destination of the packet). - -Notice, however, that these modifications are not transparent to the kernel as with XDP, and thus an internal firewall may detect our malicious traffic. -\end{itemize} - -Although we mention the possibility of modifying outgoing traffic as an alternative to the impossibility of sending new packets from eBPF, there exists a major disadvantage by doing this, since the original packet of the application will be lost, and we will thus be disrupting the normal functioning of the system (which in a rootkit is unacceptable, as we mentioned in section \ref{section:motivation}, stealth is a priority). - -There exists, however, a simple way of duplicating a packet so that the original packet is not lost but we can still send our overwritten packet. This technique, first presented by Guillaume Fournier and Sylvain Afchainthe in their DEFCON talk, consists of taking advantage of TCP retransmissions we described on section \ref{subsection:tcp}. Figure \ref{fig:tcp_exfiltrate_retrans} shows this process: - -\begin{figure}[H] - \centering - \includegraphics[width=15cm]{tcp_exfiltrate_retrans.jpg} - \caption{Technique to duplicate a packet for exfiltrating data.} - \label{fig:tcp_exfiltrate_retrans} -\end{figure} - -In the figure, we can observe a host infected by a malicious TC egress program. An user space application at some point needs to send a packet (in this case a simple ping), and the TC program will overwrite it (in this case, it writes a password which it has been able to find, and substitutes the destination IP address with that of a listening attacker. -After the timer runs out, the TCP protocol itself will retransmit the same packet as previously and thus the original data is delivered too. - -Using this technique, we will be able to send our own packets every time an application sends outgoing traffic. And, unless the network is being monitored, this attack will go unnoticed, provided that the delay of the original packet is similar to that when a single packet lost. - -\subsection{Conclusion} -As a summary, networking eBPF programs offer complete control over incoming and outgoing traffic. If tracing programs and memory corruption techniques served to disrupt the trust in the execution of both any user or kernel program, then a malicious networking program has the potential to do the same with any communication, since any packet is under the control of eBPF. - -Ultimately, the capabilities discussed in this section unlock complete freedom for the design of malicious programs. As we will explain in the next chapter, one particularly relevant type of application can be built: -\begin{itemize} -\item A \textbf{backdoor}, a stealthy program which listens on the network interface and waits for secret instructions from a remote attacker-controlled client program. This backdoor can have \textbf{Command and Control (C2)} capabilities, meaning that it can process commands sent by the attacker and received at the backdoor, executing a series of actions corresponding to the request received, and (when needed) answering the attacker with the result of the command. -\end{itemize} - -%TODO maybe a conclusion for this section? - - -%Maybe not the best title. "Design of malicious eBPF applications" may be better fitted? -\chapter{Design of a malicious eBPF rootkit} -In the previous chapter, we discussed the functionality of eBPF programs from a security standpoint, detailing which helpers and program types are particularly useful for developing malicious programs, and analysing some techniques (stack scanning, overwriting packets together with TCP retransmissions) which helps us circumvent some of the restrictions of eBPF and find new attack vectors. - -Taking as a basis these capabilities, this chapter is now dedicated to a comprehensive description of the advanced techniques and functionalities implemented in our eBPF rootkit, which show how these capabilities can lead to the creation of a real malicious application. As we mentioned during the project objectives, our goals for our rootkit include the following: -\begin{itemize} -\item Hijacking the execution of user programs while they are running, injecting libraries and executing malicious code, without impacting their normal execution. -\item Featuring a command-and-control module powered by a network backdoor, which can be operated from a remote client. This backdoor should be controlled with stealth in mind, featuring similar mechanisms to those present in rootkits found in the wild. -\item Tampering with user data at system calls, resulting in running malware-like programs and for other malicious purposes. -\item Achieving stealth, hiding rootkit-related files from the user. -\item Achieving rootkit persistence, the rootkit should run after a complete system reboot. - -\end{itemize} -%TODO maybe this is the place to mention that, on top of those, explaining some of the DEFCON techniques will be done too. Im particular interested on the one of hiding the kernel log message of bpf_probe_write_user and on ROP. - -We will be exploring each functionality individually, presenting the necessary background on each of them, and offering a final comprehensive view on how each of the systems work. - -\section{Library injection via GOT hijacking} -In this section, we will discuss how to hijack an user process running in the system so that it executes arbitrary code instructed from an eBPF program. For this, we will be injecting a library which will be executed by taking advantage of the architecture of an executable program (the GOT section in ELFs) and using the stack scanning technique covered in section \ref{subsection:bpf_probe_write_apps}. This injection will be stealthy (it must not crash the process), and will be able to hijack privileged programs such as systemd, so that the code is executed as root. - -We will also research how to circumvent the protections which modern compilers have set in order to prevent similar attacks (when performed without eBPF). - -This technique has some advantages and disadvantages to the one described by Jeff Dileo at DEFCON 27\cite{evil_ebpf_p6974}, which we will briefly cover before presenting ours. A comparison between them will also be offered. - -\subsection{Attacks at the stack: buffer overflow} \label{subsection: buf_overflow} -In section \ref{subsection:stack}, we studied how the stack works and which is the process that a program follows in order to call a function. As we saw in figure \ref{fig:stack}, the processor pushes into the stack several data which is used to restore the context of the original function once the called function exits. These pushed arguments included: -\begin{itemize} -\item The arguments with which the function is being called (if they need to be passed in the stack, such as byte arrays). -\item The original value of the rip register (ret), to restore the execution on the original function. -\item The original value of the rbp register (sfp), to restore the frame pointer of the original stack frame. -\end{itemize} - -Although this process is simple enough, it opens the possibility for an attacker to easily hijack the flow of execution if it can modify the value of ret, as it is shown in figure \ref{fig:stack_ret_hij_simple}: -\begin{figure}[H] - \centering - \includegraphics[width=15cm]{stack_ret_hij_simple.jpg} - \caption{Execution hijack overwriting saved rip value.} - \label{fig:stack_ret_hij_simple} -\end{figure} - -In the figure, we can observe how, during the execution of the called function, the attacker overwrites the value of ret in the stack. Once the function exists, as we explained in section \ref{subsection:stack}, during the function epilogue the value of ret will be popped and moved into rip, so that the execution is directed to the original next instruction. However, because the value was modified, the attacker controls which instructions are executed next. - -Attackers have historically used multiple techniques to overwrite the ret value in the stack, being the stack buffer overflow one of the most popular. In this technique, an attacker takes advantage of a program receiving an user value stored in a buffer whose capacity is smaller of that of the supplied value. Code snippet \ref{code:vuln_overflow} shows an example of a vulnerable program: - -\begin{lstlisting}[language=C, caption={Program vulnerable to buffer overflow.}, label={code:vuln_overflow}] -void foo(char *bar){ // bar may be larger than 12 characters - char buffer[12]; - strcpy(buffer, bar); //no bounds checking -} - -int main(int argc, char *argv[]){ - foo(argv[1]); - return 0; -} -\end{lstlisting} - -During the execution of the above program, since the char array \textit{buffer} is a buffer of length 12 stored in the stack, then if the value of \textit{bar} is larger than 12 bytes it will overflow the allocated space in the stack. This is usually the case of using unsafe functions for processing user input such as strcpy(), which does not check whether the array fits in the buffer. Figure \ref{fig:buffer_overflow} shows how the overflow happens in the stack. - -\begin{figure}[H] - \centering - \includegraphics[width=15cm]{buffer_overflow.jpg} - \caption{Stack buffer overflow overwriting ret value.} - \label{fig:buffer_overflow} -\end{figure} - -As we can observe in the figure, the new data written into the buffer has also overwritten other fields which were pushed into the stack, such as sfp and ret, resulting in changing the flow of execution once the function exists. - -Usually, an attacker exploiting a program vulnerable to stack buffer overflow is interested in running arbitrary (malicious) code. For this, the attacker follows the process shown in figure \ref{fig:buffer_overflow_shellcode}: - -\begin{figure}[H] - \centering - \includegraphics[width=15cm]{buffer_overflow_shellcode.jpg} - \caption{Executing arbitrary code exploiting a buffer overflow vulnerability.} - \label{fig:buffer_overflow_shellcode} -\end{figure} - -As we can observe in the figure, the attacker will take advantage of the buffer overflow to overwrite not only ret, but also the rest of the current stack frame and sfp with malicious code. This code is known as shellcode, consisting on instruction opcodes (machine assembly instructions translated to their representation in hexadecimal values) which the processor will execute. We will briefly explain how to write shellcode in section \ref{TODO probably an Annex}. Therefore, in this technique the attacker will: -\begin{itemize} -\item Introduce a byte array that overflows the buffer, consisting on SHELLCODE + the address of the buffer. -\begin{itemize} - \item The shellcode overwrites the buffer and all data until ret. - \item ret is overwritten by the value of the address where the buffer starts. -\end{itemize} -\item When the function exits and ret is popped from the stack, the register rip will now point to the address of the buffer at the stack, processing the stack data as instructions part of a program. The malicious code will be executed. -\end{itemize} - -By using eBPF, we should in principle be able to overwrite the stack, inject shellcode, overwrite ret and then execute our malicious code. However, the classic buffer overflow is one of the oldest techniques in binary exploitation, and thus numerous protections have historically been incorporated and thus the attack presented here does not work work in modern systems any more. One of the protections is the prohibition of executing code from the stack. By marking the stack as non-executable, in the case of rip pointing to an address in the stack any malicious code will not be ran, even if an application was vulnerable to a buffer overflow. We will explain more in detail the main protections that nowadays are incorporated in modern systems in section \ref{TODO}. - -\subsection{Return oriented programming attacks} \label{subsection:rop} -After the stack was marked non-executable, a new refined technique was invented to circumvent this restriction and adapt the classic buffer overflow to modern systems. In the end, attackers still maintained the ability to overflow the buffer in the stack of vulnerable applications, writing shellcode and overwriting ret, the only issue was that the shellcode could not be executed. - -Return Oriented Programming (ROP) is an exploitation technique that takes advantage of the fact that, even if malicious code in the stack cannot be executed, the attacker can still redirect the flow of execution by modifying ret to any other piece of executable code. The challenge for the attacker is executing malicious code, since any available executable instructions are either at the .text section (which will correspond to the normal functioning of the program) or at shared libraries, but none are useful for malware. - -ROP tackles this challenge by designing a method of reconstructing malicious code from parts of already-existing code, as in a 'collage'. Assembly instructions are selected from multiple places, so that, when put together and executed sequentially, they recreate the shellcode which the attacker wants to execute. These pieces of code are called ROP gadgets, and consist of a set of arbitrary instructions followed by a final \textit{ret} instruction, which triggers the function exit and pops the value of ret. These gadgets may belong to any code in the process memory, usually selected between the code of the shared libraries (see figure \ref{fig:stack}) to which the process is linked. - -Finding ROP gadgets and writing ROP-compatible payloads manually is hard, thus multiple programs exist that automatically scan the system libraries and construct provide the gadgets given the shellcode to execute\cite{rop_prog_finder}. - -However, we will now illustrate how ROP works with an example. Suppose that an attacker has discovered a buffer overflow vulnerability, but the stack is marked as not executable. The attacker wants to execute the assembly code shown in snippet \ref{code:rop_ex}: - -\begin{lstlisting}[language=C, caption={Sample program to run using ROP.}, label={code:rop_ex}] -mov rdx, 10 -mov rax, [rsp] -\end{lstlisting} - -After finding the address of the ROP gadgets manually or using an automated tool, the attacker takes advantage of a buffer overflow (or, in our case, a direct write using eBPF's bpf\_probe\_write\_user()) to overwrite the vale of ret with the address of the first ROP gadget, and also additional data in the stack. Figure \ref{fig:rop_compund} shows how we can execute the original program using ROP: - -\begin{figure}[H] - \centering - \includegraphics[width=16cm]{ROPcompound.jpg} - \caption{Steps for executing code sample using ROP.} - \label{fig:rop_compund} -\end{figure} - -The steps described in the figure are the following: -\begin{enumerate} -\item First step shows the two gadgets located and their addresses, and the overwritten data in the stack. The function has already exited and, because ret was overwritten with the address of the first gadget, register rip now points to that location, and thus it is the next instruction to execute. Register rsp, in turn, now points to the bottom address of the current stack frame, which is right next to the old ret (see section \ref{subsection:stack} for stack frames functioning). -\item The first instruction of the gadget is executed, popping the value from the stack (which also moves register rsp, see stack push and pop operations in section \ref{subsection:stack}). As we can observe, the value "10" was specifically put in that position by the attacker, so that, according to the instruction to execute \lstinline{mov rdx, 10} \lstinline{}, we now have loaded that data into register rdx. -\item The return instruction is executed, which pops from the stack what is supposed to be the value of the saved rip, but in turn the attacker has placed the address of the next gadget there. Now, rip has jumped to the address of the second gadget. By continuing with this process, we can chain an infinite number of gadgets. -\item Finally, we repeated the same process as before, using a pop instruction to load a value from the stack. This illustrates that push and pop instructions, commonly used on most programs, are also possible to be using ROP. - -After this step, the return instruction will be executed. Note that, at this point, if the attacker wants to be stealthy and avoid crashing the program (since we overwrote the original data in the stack), the original stack must be restored, together with the value of the registers before the malicious code execution. We will see an example of a technique for reconstructing the original state during our explanation of the library injection in section \ref{TODO}. -\end{enumerate} - - -\subsection{ROP with eBPF} \label{subsection:rop_ebpf} -In 2019, Jeff Dileo presented in DEFCON 27 the first technique to achieve arbitrary code execution using eBPF\cite{evil_ebpf_p6974}. For this, he used the ROP technique we have described previously to inject malicious code into a process. We will present an overview on his technique, in order to later compare it to the one we will develop for our rootkit, and find advantages and disadvantages. Note that this is a summary and some aspects have been simplified, however we will present the whole process during the explanation of our own technique. - -\begin{figure}[H] - \centering - \includegraphics[width=15cm]{rop_evil_ebpf_1.jpg} - \caption{Initial setup for the ROP with eBPF technique.} - \label{fig:rop_evil_ebpf_1} -\end{figure} - -Figure \ref{fig:rop_evil_ebpf_1} shows an overview on the process memory and the eBPF programs loaded. For this injection, we will use the stack scanning technique (section \ref{subsection:bpf_probe_write_apps}) using the arguments of a system call whose arguments are passed using the stack (sys\_timerfd\_settime, which receives two structs utmr and otmr). Therefore, a kprobe is attached to the system call, so that it can start to scan for the return address of the system call, which we know is the original value of register rip which was pushed into the stack (ret). - -An additional aspect must be introduced now (we will cover it more in detail in section \ref{TODO}): system calls are not directly called by the instructions in the .text section, but rather user programs in C make use of the C Standard Library to delegate the actual syscall, which in this case is the GNU Standard Library (glibc)\cite{glibc}. Therefore, a program calls a function in glibc (in this case timerfd\_settime) in which the syscall is performed, and the kernel executes it. - -This means that, during the stack scanning technique, if we start from struct utmr and scan forward in the stack, what we will find in ret is the return address of the function of glibc, and not directly that of the syscall to the kernel. Therefore, our goal is, for every data in the stack while scanning forward, check whether it is the real return address of glibc. For an address to be the real return address, we will follow the next steps: -\begin{enumerate} -\item Take an address from the stack. If that is the return address (the old rip), then the instruction that called the function in glibc must be the previous instruction (rip - 1). -\item We now have a \textit{call} instruction, that directs us to the function at glibc. We check in the instruction to which address it moves the flow of execution, that is the address of timerfd\_settime in glibc. -\item We scan forward, inside timerfd\_settime of glibc, until we find a \textit{syscall} instruction. That is the point where the flow of execution moves to the kernel, so we have checked that the return address we found in the stack truly is the one we are looking for. -\end{enumerate} - -Now that we have found the return address, we save a backup of the stack (to recover the original data later) and we proceed to overwrite the stack using bpf\_probe\_write\_user(), setting it for the ROP technique. For this, some gadgets (G0, G1 ... GN) have been previously discovered in the glibc library. Figure \ref{fig:rop_evil_ebpf_2} shows process memory after this overwrite: - -\begin{figure}[H] - \centering - \includegraphics[width=15cm]{rop_evil_ebpf_2.jpg} - \caption{Process memory after syscall exits and ROP code overwrites the stack.} - \label{fig:rop_evil_ebpf_2} -\end{figure} - -As we can see in the figure, the function has already exited, and ret has been popped into register rip. As we explained in section \ref{subsection:rop}, the attacker places in that position the address of the first ROP gadget. After that, the attacker can execute arbitrary code. Jeff Dileo, for instance, loads a malicious library into the process (we will do the same and explain this process in the next sections). - -Once the attacker has finished executing the injected code, the stack must be restored to the original position so that the program can continue without crashing. A simplified view of this procedure consists of attaching a kprobe to a random system call (in this case, sys\_close()) so that, from the ROP code, we can alert the eBPF program when it is time to remove the ROP code and restore the original stack. Figure \ref{fig:rop_evil_ebpf_3} shows this final step: - -\begin{figure}[H] - \centering - \includegraphics[width=15cm]{rop_evil_ebpf_3.jpg} - \caption{Stack data is restored and program continues its execution.} - \label{fig:rop_evil_ebpf_3} -\end{figure} - -As we can see, eBPF writes back the original stack and thus the execution can continue. Note that, in practice, some final gadgets must also be executed in order to restore the state of rip and rsp, the stack data for this is written in the free memory zone, so that it does not need to be removed. - - -%ALL OR PARTS OF THIS SECTION MAY GO TO AN ANNEX, I'm leaving it here just for now -\subsection{The ELF format and Lazy Binding} \label{subsection:elf_lazy_binding} -This section details the Executable and Linkable Format (ELF)\cite{elf}, the format in which we find executable files in Linux systems (between other types). We will perform an analysis from a security standpoint, that is, mainly oriented to describe the most relevant sections and the permissions incorporated into them. We will also focus on several of these sections which will be relevant for designing our attack. - -Note that, during all examples shown in this section, we will be using a sample program that has been compiled using Clang/LLVM: TODO %TODO How do I explain which progrm it is? It is an example I developed, src/helpers/simple_timer.c. Shoud I write the code somewhere? Seems excesive - -Table \ref{table:elf_tools} shows the main tools we will use during this analysis: - -\begin{table}[H] -\begin{tabular}{|>{\centering\arraybackslash}p{3cm}|>{\centering\arraybackslash}p{10cm}|} -\hline -Tool & Purposes\\ -\hline -\hline -Readelf & Display information about ELF files\\ -\hline -Objdump & Display information about object files, mainly used for decompiling programs\\ -\hline -GDB & The GNU Project Debugger, allows for debugging programs during runtime\\ -\hline -GDB-peda & The Python Exploit Development Assistance for GDB, allows for multiple advanced operations that ease exploit development, such as showing register values, the stack state or memory information. It works as a plugin for GDB.\\ -\hline -\end{tabular} -\caption{Tools used for analysis of ELF programs.} -\label{table:elf_tools} -\end{table} - -Firstly, we will analyse the main sections we can find in an executable. The command and complete list of headers can be found in Annex \ref{annexsec:readelf_sec_headers}. The most relevant sections are described in table \ref{table:elf_sec_headers}: - -\begin{table}[H] -\begin{tabular}{|>{\centering\arraybackslash}p{1cm}|>{\centering\arraybackslash}p{9cm}|>{\centering\arraybackslash}p{2cm}|} -\hline -Tool & Purpose & Permissions\\ -\hline -\hline -.init & Contains instructions executed before the \textit{main} function of the program & Alloc, Executable\\ -\hline -.plt & Procedure Linkage Table (PLT), contains code stubs that use the addresses at .got.plt for jumping to position-independent code & Alloc, Executable\\ -\hline -.got & Global Offset Table (GOT), it contains addresses of global variables and functions once the linker resolves them at runtime & Alloc, Writable\\ -\hline -.got.plt & A subset of .got section separated from .got with some compilers, it contains only the target addresses of position-independent code once the linker loads them at runtime, used by .plt section. & Alloc, Writable\\ -\hline -.plt.got & Generated depending on compiler options, it is a PLT section which does not use lazy binding. & Alloc, Executable\\ -\hline -.text & Stores executable instructions. & Alloc, Executable\\ -\hline -.data & Contains initialized static and global variables. & Alloc, Writable\\ -\hline -.bss & Contains global and static variables which are unitialized or initialized to zero. & Alloc, Writable\\ -\hline -\end{tabular} -\caption{Tools used for analysis of ELF programs.} -\label{table:elf_sec_headers} -\end{table} - -As it can be observed in table \ref{table:elf_sec_headers}, we can find that all sections have the Alloc flag, meaning they will be loaded into process memory during runtime (see table \ref{TODO}, they have not been shown in previous diagrams for simpleness). - -Apart from those we already discussed, we can find the GOT and PLT sections, whose purpose is to support Position Independent Code (PIC), that is, instructions whose address in virtual memory is not hardcoded by the compiler into the executable, but rather they are not known until resolved at runtime. This is usually the case of shared libraries (such as glibc, which as we described in \ref{subsection:rop_ebpf}, it offers an standatd API for calling system calls), which can be loaded into virtual memory starting at any address\cite{plt_got_overlord}. - -Therefore, in order to call a function of a shared library, the dynamic linker follows a process called 'Lazy binding'\cite{plt_got_technovelty}: -\begin{enumerate} -\item From the .text section, instead of calling a direct absolute address as usual, a PLT stub (in the .plt section) is called. Snippet \ref{code:lazy_bind_1} shows a call to the function timerfd\_settime, implemented by the shared library glibc and thus using a PLT: -\begin{lstlisting}[language=C, caption={Call to PLT stub seen from objdump.}, label={code:lazy_bind_1}] -$ objdump -d simple_timer -4014cb: b9 00 00 00 00 mov $0x0,%ecx -4014d0: be 01 00 00 00 mov $0x1,%esi -4014d5: 89 c7 mov %eax,%edi -4014d7: e8 44 fc ff ff call 401120 -\end{lstlisting} - -\item In the PLT stub, the flow of execution jumps to an address which is stored in the GOT section, which is the absolute address of the function at glibc. This address must be written there by the dynamic linker but, according to lazy binding, the first time to call this function the linker has not calculated that address yet. - -\begin{figure}[H] - \centering - \includegraphics[width=15.5cm]{sch_gdb_plt.png} - \caption{PLT stub for timerfd\_settime, seen from gdb-peda.} - \label{fig:lazy_bind_2} -\end{figure} - -\begin{figure}[H] - \centering - \includegraphics[width=15.5cm]{sch_gdb_got_prev.png} - \caption{Inspecting address stored in GOT section before dynamic linking, seen from gdb-peda.} - \label{fig:lazy_bind_3} -\end{figure} - -\item As we can see in figures \ref{fig:lazy_bind_2} and \ref{fig:lazy_bind_3}, the PLT stub calls address 0x4010a0, which leads to a dynamic linking routine, which proceeds to write the address into the GOT section and jump back to the start of the PLT stub. This time, the memory address at GOT to which the PLT jumps is already loaded with the address to the function at the shared library, as shown by figure \ref{fig:lazy_bind_4}. - -\begin{figure}[H] - \centering - \includegraphics[width=15.5cm]{sch_gdb_got_after.png} - \caption{Inspecting address stored in GOT section after dynamic linking, seen from gdb-peda.} - \label{fig:lazy_bind_4} -\end{figure} - -\begin{figure}[H] - \centering - \includegraphics[width=15.5cm]{sch_glibc_func.png} - \caption{Glibc function to which PLT jumps using address stored at GOT, seen from gdb-peda.} - \label{fig:lazy_bind_5} -\end{figure} - -\end{enumerate} - - -Therefore, in essence, when using lazy binding the dynamic linker will individually load into GOT the addresses of the functions at the shared libraries, during the first time they are called in the program. After that, the address will remain in the GOT section and will be used by the PLT for all subsequent calls. - -The reason lazy binding matters to us is because, as we will explain section \ref{subsection:got_attack}, the GOT section is actually writable from an eBPF program using bpf\_probe\_write\_user(). This is because this section specifically must be writeable at runtime for the dynamic linker to store the address once they are resolved. Therefore, even if we cannot write into the .text section from this helper, we still can modify the GOT section from eBPF, redirecting the address at which the PLT jumps, and thus controlling the flow of execution in the program. - -\subsection{Hardening ELF binaries and possible bypasses} -During the previous section, we have discussed how lazy binding works and how introduced how it could be exploited, and presented multiple of the classic attacks at the stack such as buffer overflow and ROP. However, during the years multiple hardening measures have been introduced into modern compilers, which attempt to mitigate these and other techniques. We will now present them so that, during the design of our rootkit, we can adapt to all of these. - -Table \ref{table:compilers} shows the compilers that we will be considering during this study. We will be exclusively looking at those security features that are included by default. - -\begin{table}[H] -\begin{tabular}{|>{\centering\arraybackslash}p{5cm}|>{\centering\arraybackslash}p{8cm}|} -\hline -Compiler & Security features by default\\ -\hline -\hline -Clang/LLVM 12.0.0 (2021) & Stack canaries, DEP/NX\\ -\hline -GCC 10.3.0 (2021) & Stack canaries, DEP/NX, PIE, Full RELRO\\ -\hline -\end{tabular} -\caption{Security features in C compilers used in the study.} -\label{table:compilers} -\end{table} - -\textbf{Stack canaries} -Stack canaries are random data that is pushed into the stack before calling potentially dangerous functions (such as strcpy()) that attempts to prevent attacks at the stack by ensuring that their value is the same before and after the execution of the called function. - -If a stack canary is present and a buffer overflow happened, it would overwrite the value of the canary, therefore alerting of the attack, in which case the processor halts the execution of the program. - -In order to bypass a canary, an attacker must ensure that it is not overwritten, or that the value of the canary remains in the same position and with the same value once the function that was called returns. - -\textbf{DEP/NX}\\ -Data Execution Prevention, also known as No Execute, is the option of marking the stack as non executable. This prevents, as we explained in section \ref{subsection: buf_overflow}, the possibility of executing injected shellcode in the stack after modifying the value of the saved rip. - -The creation of advanced techniques like ROP is one reaction to this mitigation, that circumvents this protection. - -\textbf{ASLR}\\ -Address Space Layout Randomization is a technique that randomizes the addresses on the heap, stack and libraries, so that an attacker cannot rely on known addresses during exploitation (e.g: libraries are loaded at a different memory address each time the program is run, so ROP gadgets change their position)\cite{aslr_pie_intro}. - -In order to bypass ASLR, attackers must take into account that, although the address at which, for instance, a library is loaded is random, the internal structure of the library remains unchanged, with all symbols in the same relative position, as figure \ref{table:aslr_offset} shows. - -%TODO Add the .data section here -\begin{figure}[H] - \centering - \includegraphics[width=13cm]{aslr_offset.jpg} - \caption{Two runs of the same executable using ASLR, showing a library and two symbols.} - \label{fig:alsr_offset} -\end{figure} - -As we can observe in the figure, although glibc is loaded at a different base address each run, the offset between the functions it implements, malloc() and free(), remains constant. Therefore, a method for bypassing ASLR is to achieve information about the absolute address of any symbol, which can then easily lead to knowing any other if an attacker decompiles the executable and calculates the offset between a pair of addresses where one is known. - -\textbf{PIE}\\ -Position Independent Executable is a mitigation introduced to reduce the ability of an attacker to locate symbols in virtual memory by randomizing the base address at which the program itself (including the .text section) is loaded. This base address determines an offset which is added to all memory addresses in the code, so that each instruction is located at an address + this offset. Therefore, all jumps are made using relative addresses.\cite{aslr_pie_intro}\cite{pie_exploit}. - -Similarly to ASLR, the internal structure of each section is maintained, therefore if an attacker is able to leak the meaning of some section, it is possible to calculate the rest. - -\textbf{RELRO}\\ -Relocation Read-Only is a hardening technique that mitigates the possibility of an attacker overwriting the GOT section, as we explained at section \ref{subsection:elf_lazy_binding}. In order to achieve the lazy binding process is substituted by the linker resolving all entries in the GOT section right after the beginning of the execution, and then marking the .got section as read-only. Two settings for RELRO are the most widespread, either Partial RELRO (which only marks sections of the .got section not related to the PLT as read-only, leaving .got.plt writeable) or Full RELRO (which marks the .got section as read-only completely). Binaries with only Partial RELRO are still non-secure, as the address at which the PLT section jumps can still be overwriten (including from eBPF)\cite{relro_redhat}. - -Bypassing Full RELRO, however, stops any attempt of GOT hijacking, unless an attacker finds an alternative method for writting into the virtual memory of a process that bypassed the read-only flag. We will use one of these methods for our rootkit. - - -\textbf{Intel CET}\\ -Intel Control-flow Enforcement Technology is a hardening feature fully incorporated in Windows 10 systems \cite{cet_windows} and a work in progress in Linux\cite{cet_linux}. Its purpose is to defeat ROP attacks and other derivates (e.g: Jump-oriented programming, JOP), by adding a strict kernel-supported control of the return addresses and strong restrictions over jump and call instructions. - -In Linux, the kernel will support a hidden 'shadow stack' that will save the return addresses for each call. This prevents modifying the saved value of rip in the stack, since the kernel would realise that the flow of execution has been modified. We can also find that modern compilers (such as GCC 10.3.0) already generate Intel CET-related instructions such as \textit{endbr64}, whose purpose is to be placed at the start of functions, marking that as the only address to which an indirect jump can land (otherwise, jumps will be rejected if not landing at \textit{endbr64}). - -As mentioned, we will not consider this feature since it is not active in the Linux kernel. - -%TODO Not the best title -\subsection{Design of our attack} \label{subsection:got_attack} -Taking all the previous background into stack attacks, ELF's lazy binding and hardening features for binaries, we will now present the exploitation technique that our rootkit will use to inject a malicious library into a running process, using the GOT hijacking technique that we analysed. The rootkit will inject the library only after the second time that an specific syscall is called by a process (since the first time we will wait for GOT addresses to be loaded by the dynamic linker). - -This technique works both in compilers with low hardening fetaures by default (Clang) and also on a compiler with all of them active (GCC), see table \ref{table:compilers}. We will present it by steps and, on each one, detail the different existing methods depending on the compiler features. - -For this research work, we will be performing this attack on processes that make use either the system call sys\_openat or sys\_timerfd\_settime, which are called by the standard library glibc. - -\textbf{Stage 1: eBPF tracing and scan the stack}\\ -We load and attach a tracepoint eBPF program at the \textit{enter} position of syscall sys\_timerfd\_settime. Firstly we must ensure that the process calling the tracepoint is one of the processes to hijack. - -We will then proceed with the stack scanning technique, as we explained in section \ref{subsection:bpf_probe_write_apps}. In this case, the algorithm will go as follows: -\begin{enumerate} -\item Take one of the syscall parameters and scan forward in the scan. For each iteration, we must check if the data at the stack corresponds to the saved rip: -\begin{enumerate} -\item Check that the previous instruction is a call instruction, by checking the instruction length and opcodes (call instructions always start with e8, and the length is 5 bytes, see figure \ref{fig:firstcall}). -\begin{figure}[H] - \centering - \includegraphics[width=13cm]{sch_firstcall.png} - \caption{Call to the glibc function, using objdump} - \label{fig:firstcall} -\end{figure} -\item Now that we know we localized a call instruction, we take the address at which it jumps. That should be an address in a PLT stub. -\item We analyze the instruction at the PLT stub. If the program was compiled with GCC, it will be an \textit{endbr64} instruction followed by the PLT jump instruction using the address at GOT (since it generates Intel CET-compatible programs, see table \ref{table:compilers}). Otherwise, if using Clang, the first instruction is the PLT jump. -%TODO Continue -\end{enumerate} -\end{enumerate} - - - - - - - - - - - - - - - - - - - -\chapter{Results} - - -\chapter{Conclusion and future work} @@ -2101,149 +337,7 @@ We will then proceed with the stack scanning technique, as we explained in secti \printbibliography - -%---------- -% ANEX -%---------- - -%M-> Mentioned putting some demos and PoCs here... -% - -%Including bpftool commands here to be referenced. Is it a good idea? - - -\chapter* {Appendix A - Bpftool commands} \label{annex:bpftool_flags_kernel} -\pagenumbering{gobble} % Las páginas de los anexos no se numeran -\section*{eBPF-related kernel compilation flags} -\begin{lstlisting}[language=bash] -$ bpftool feature -\end{lstlisting} - -\begin{verbatim} -CONFIG_BPF is set to y -CONFIG_BPF_SYSCALL is set to y -CONFIG_HAVE_EBPF_JIT is set to y -CONFIG_BPF_JIT is set to y -CONFIG_BPF_JIT_ALWAYS_ON is set to y -CONFIG_CGROUPS is set to y -CONFIG_CGROUP_BPF is set to y -CONFIG_CGROUP_NET_CLASSID is set to y -CONFIG_SOCK_CGROUP_DATA is set to y -CONFIG_BPF_EVENTS is set to y -CONFIG_KPROBE_EVENTS is set to y -CONFIG_UPROBE_EVENTS is set to y -CONFIG_TRACING is set to y -CONFIG_FTRACE_SYSCALLS is set to y -CONFIG_FUNCTION_ERROR_INJECTION is set to y -CONFIG_BPF_KPROBE_OVERRIDE is set to y -CONFIG_NET is set to y -CONFIG_XDP_SOCKETS is set to y -CONFIG_LWTUNNEL_BPF is set to y -CONFIG_NET_ACT_BPF is set to m -CONFIG_NET_CLS_BPF is set to m -CONFIG_NET_CLS_ACT is set to y -CONFIG_NET_SCH_INGRESS is set to m -CONFIG_XFRM is set to y -CONFIG_IP_ROUTE_CLASSID is set to y -CONFIG_IPV6_SEG6_BPF is set to y -CONFIG_BPF_LIRC_MODE2 is not set -CONFIG_BPF_STREAM_PARSER is set to y -CONFIG_NETFILTER_XT_MATCH_BPF is set to m -CONFIG_BPFILTER is set to y -CONFIG_BPFILTER_UMH is set to m -CONFIG_TEST_BPF is set to m -CONFIG_HZ is set to 250 -\end{verbatim} - - -\chapter* {Appendix B - Readelf commands} \label{annex:readelf_commands} -\pagenumbering{gobble} % Las páginas de los anexos no se numeran -\section*{Section headers in ELF file} \label{annexsec:readelf_sec_headers} -\begin{lstlisting}[language=bash, caption={List of ELF section headers with readelf tool of a program compiled with GCC.}, label={code:elf_sections}] -$ readelf -S simple_timer -There are 36 section headers, starting at offset 0x4120: - -Section Headers: - [Nr] Name Type Address Offset - Size EntSize Flags Link Info Align - [ 0] NULL 0000000000000000 00000000 - 0000000000000000 0000000000000000 0 0 0 - [ 1] .interp PROGBITS 0000000000400318 00000318 - 000000000000001c 0000000000000000 A 0 0 1 - [ 2] .note.gnu.pr[...] NOTE 0000000000400338 00000338 - 0000000000000030 0000000000000000 A 0 0 8 - [ 3] .note.gnu.bu[...] NOTE 0000000000400368 00000368 - 0000000000000024 0000000000000000 A 0 0 4 - [ 4] .note.ABI-tag NOTE 000000000040038c 0000038c - 0000000000000020 0000000000000000 A 0 0 4 - [ 5] .gnu.hash GNU_HASH 00000000004003b0 000003b0 - 000000000000001c 0000000000000000 A 6 0 8 - [ 6] .dynsym DYNSYM 00000000004003d0 000003d0 - 0000000000000108 0000000000000018 A 7 1 8 - [ 7] .dynstr STRTAB 00000000004004d8 000004d8 - 00000000000000ad 0000000000000000 A 0 0 1 - [ 8] .gnu.version VERSYM 0000000000400586 00000586 - 0000000000000016 0000000000000002 A 6 0 2 - [ 9] .gnu.version_r VERNEED 00000000004005a0 000005a0 - 0000000000000050 0000000000000000 A 7 1 8 - [10] .rela.dyn RELA 00000000004005f0 000005f0 - 0000000000000030 0000000000000018 A 6 0 8 - [11] .rela.plt RELA 0000000000400620 00000620 - 00000000000000c0 0000000000000018 AI 6 24 8 - [12] .init PROGBITS 0000000000401000 00001000 - 000000000000001b 0000000000000000 AX 0 0 4 - [13] .plt PROGBITS 0000000000401020 00001020 - 0000000000000090 0000000000000010 AX 0 0 16 - [14] .plt.sec PROGBITS 00000000004010b0 000010b0 - 0000000000000080 0000000000000010 AX 0 0 16 - [15] .text PROGBITS 0000000000401130 00001130 - 00000000000004c5 0000000000000000 AX 0 0 16 - [16] .fini PROGBITS 00000000004015f8 000015f8 - 000000000000000d 0000000000000000 AX 0 0 4 - [17] .rodata PROGBITS 0000000000402000 00002000 - 00000000000000a5 0000000000000000 A 0 0 8 - [18] .eh_frame_hdr PROGBITS 00000000004020a8 000020a8 - 000000000000004c 0000000000000000 A 0 0 4 - [19] .eh_frame PROGBITS 00000000004020f8 000020f8 - 0000000000000120 0000000000000000 A 0 0 8 - [20] .init_array INIT_ARRAY 0000000000403e10 00002e10 - 0000000000000008 0000000000000008 WA 0 0 8 - [21] .fini_array FINI_ARRAY 0000000000403e18 00002e18 - 0000000000000008 0000000000000008 WA 0 0 8 - [22] .dynamic DYNAMIC 0000000000403e20 00002e20 - 00000000000001d0 0000000000000010 WA 7 0 8 - [23] .got PROGBITS 0000000000403ff0 00002ff0 - 0000000000000010 0000000000000008 WA 0 0 8 - [24] .got.plt PROGBITS 0000000000404000 00003000 - 0000000000000058 0000000000000008 WA 0 0 8 - [25] .data PROGBITS 0000000000404058 00003058 - 0000000000000014 0000000000000000 WA 0 0 8 - [26] .bss NOBITS 0000000000404070 0000306c - 0000000000000020 0000000000000000 WA 0 0 16 - [27] .comment PROGBITS 0000000000000000 0000306c - 0000000000000025 0000000000000001 MS 0 0 1 - [28] .debug_aranges PROGBITS 0000000000000000 00003091 - 0000000000000030 0000000000000000 0 0 1 - [29] .debug_info PROGBITS 0000000000000000 000030c1 - 0000000000000295 0000000000000000 0 0 1 - [30] .debug_abbrev PROGBITS 0000000000000000 00003356 - 00000000000000fd 0000000000000000 0 0 1 - [31] .debug_line PROGBITS 0000000000000000 00003453 - 000000000000024d 0000000000000000 0 0 1 - [32] .debug_str PROGBITS 0000000000000000 000036a0 - 00000000000001f5 0000000000000001 MS 0 0 1 - [33] .symtab SYMTAB 0000000000000000 00003898 - 0000000000000480 0000000000000018 34 22 8 - [34] .strtab STRTAB 0000000000000000 00003d18 - 00000000000002a2 0000000000000000 0 0 1 - [35] .shstrtab STRTAB 0000000000000000 00003fba - 000000000000015f 0000000000000000 0 0 1 -Key to Flags: - W (write), A (alloc), X (execute), M (merge), S (strings), I (info), - L (link order), O (extra OS processing required), G (group), T (TLS), - C (compressed), x (unknown), o (OS specific), E (exclude), - l (large), p (processor specific) -\end{lstlisting} +\input{chapters/annex} diff --git a/docs/document.toc b/docs/document.toc index e8590f5..2b17b47 100644 --- a/docs/document.toc +++ b/docs/document.toc @@ -15,9 +15,11 @@ \defcounter {refsection}{0}\relax \contentsline {section}{\numberline {1.4}Structure of the document}{4}{section.1.4}% \defcounter {refsection}{0}\relax -\contentsline {chapter}{\numberline {2}State of the art}{5}{chapter.2}% +\contentsline {section}{\numberline {1.5}Code availability}{4}{section.1.5}% \defcounter {refsection}{0}\relax -\contentsline {section}{\numberline {2.1}eBPF history - Classic BPF}{5}{section.2.1}% +\contentsline {chapter}{\numberline {2}Background}{5}{chapter.2}% +\defcounter {refsection}{0}\relax +\contentsline {section}{\numberline {2.1}BPF}{5}{section.2.1}% \defcounter {refsection}{0}\relax \contentsline {subsection}{\numberline {2.1.1}Introduction to the BPF system}{5}{subsection.2.1.1}% \defcounter {refsection}{0}\relax @@ -29,7 +31,7 @@ \defcounter {refsection}{0}\relax \contentsline {subsection}{\numberline {2.1.5}An example of BPF filter with tcpdump}{10}{subsection.2.1.5}% \defcounter {refsection}{0}\relax -\contentsline {section}{\numberline {2.2}Analysis of modern eBPF}{11}{section.2.2}% +\contentsline {section}{\numberline {2.2}Modern eBPF}{11}{section.2.2}% \defcounter {refsection}{0}\relax \contentsline {subsection}{\numberline {2.2.1}eBPF instruction set}{13}{subsection.2.2.1}% \defcounter {refsection}{0}\relax @@ -65,67 +67,77 @@ \defcounter {refsection}{0}\relax \contentsline {subsection}{\numberline {2.4.3}Libbpf}{24}{subsection.2.4.3}% \defcounter {refsection}{0}\relax -\contentsline {chapter}{\numberline {3}Analysis of offensive capabilities}{27}{chapter.3}% +\contentsline {section}{\numberline {2.5}Security features in eBPF}{26}{section.2.5}% \defcounter {refsection}{0}\relax -\contentsline {section}{\numberline {3.1}Security features in eBPF}{27}{section.3.1}% +\contentsline {subsection}{\numberline {2.5.1}Access control}{26}{subsection.2.5.1}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.1.1}Access control}{28}{subsection.3.1.1}% +\contentsline {section}{\numberline {2.6}Memory management in Linux}{28}{section.2.6}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.1.2}eBPF maps security}{30}{subsection.3.1.2}% +\contentsline {subsection}{\numberline {2.6.1}Memory pages and faults}{28}{subsection.2.6.1}% \defcounter {refsection}{0}\relax -\contentsline {section}{\numberline {3.2}Abusing tracing programs}{30}{section.3.2}% +\contentsline {subsection}{\numberline {2.6.2}Process virtual memory}{30}{subsection.2.6.2}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.2.1}Access to function arguments}{30}{subsection.3.2.1}% +\contentsline {subsection}{\numberline {2.6.3}The process stack}{32}{subsection.2.6.3}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.2.2}Reading memory out of bounds}{33}{subsection.3.2.2}% +\contentsline {section}{\numberline {2.7}Attacks at the stack}{35}{section.2.7}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.2.3}Overriding function return values}{34}{subsection.3.2.3}% +\contentsline {subsection}{\numberline {2.7.1}Buffer overflow}{36}{subsection.2.7.1}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.2.4}Sending signals to user programs}{35}{subsection.3.2.4}% +\contentsline {subsection}{\numberline {2.7.2}Return oriented programming attacks}{39}{subsection.2.7.2}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.2.5}Conclusion}{35}{subsection.3.2.5}% +\contentsline {section}{\numberline {2.8}Networking fundamentals in Linux}{41}{section.2.8}% \defcounter {refsection}{0}\relax -\contentsline {section}{\numberline {3.3}Memory corruption}{36}{section.3.3}% +\contentsline {subsection}{\numberline {2.8.1}An overview on the network layer}{41}{subsection.2.8.1}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.3.1}Memory management in Linux}{36}{subsection.3.3.1}% +\contentsline {subsection}{\numberline {2.8.2}Introduction to the TCP protocol}{43}{subsection.2.8.2}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.3.2}Process virtual memory}{39}{subsection.3.3.2}% +\contentsline {section}{\numberline {2.9}ELF binaries}{45}{section.2.9}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.3.3}The process stack}{40}{subsection.3.3.3}% +\contentsline {subsection}{\numberline {2.9.1}The ELF format and Lazy Binding}{45}{subsection.2.9.1}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.3.4}Attacks and limitations of bpf\_probe\_write\_user()}{44}{subsection.3.3.4}% +\contentsline {subsection}{\numberline {2.9.2}Hardening ELF binaries}{49}{subsection.2.9.2}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.3.5}Conclusion}{47}{subsection.3.3.5}% +\contentsline {chapter}{\numberline {3}Analysis of offensive capabilities}{52}{chapter.3}% \defcounter {refsection}{0}\relax -\contentsline {section}{\numberline {3.4}Abusing networking programs}{47}{section.3.4}% +\contentsline {section}{\numberline {3.1}eBPF maps security}{52}{section.3.1}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.4.1}An overview on the network layer}{48}{subsection.3.4.1}% +\contentsline {section}{\numberline {3.2}Abusing tracing programs}{53}{section.3.2}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.4.2}Introduction to the TCP protocol}{49}{subsection.3.4.2}% +\contentsline {subsection}{\numberline {3.2.1}Access to function arguments}{53}{subsection.3.2.1}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.4.3}Attacks and limitations of networking programs}{51}{subsection.3.4.3}% +\contentsline {subsection}{\numberline {3.2.2}Reading memory out of bounds}{56}{subsection.3.2.2}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {3.4.4}Conclusion}{54}{subsection.3.4.4}% +\contentsline {subsection}{\numberline {3.2.3}Overriding function return values}{57}{subsection.3.2.3}% \defcounter {refsection}{0}\relax -\contentsline {chapter}{\numberline {4}Design of a malicious eBPF rootkit}{55}{chapter.4}% +\contentsline {subsection}{\numberline {3.2.4}Sending signals to user programs}{58}{subsection.3.2.4}% \defcounter {refsection}{0}\relax -\contentsline {section}{\numberline {4.1}Library injection via GOT hijacking}{55}{section.4.1}% +\contentsline {subsection}{\numberline {3.2.5}Conclusion}{58}{subsection.3.2.5}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {4.1.1}Attacks at the stack: buffer overflow}{56}{subsection.4.1.1}% +\contentsline {section}{\numberline {3.3}Memory corruption}{58}{section.3.3}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {4.1.2}Return oriented programming attacks}{60}{subsection.4.1.2}% +\contentsline {subsection}{\numberline {3.3.1}Attacks and limitations of bpf\_probe\_write\_user()}{59}{subsection.3.3.1}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {4.1.3}ROP with eBPF}{62}{subsection.4.1.3}% +\contentsline {subsection}{\numberline {3.3.2}Conclusion}{61}{subsection.3.3.2}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {4.1.4}The ELF format and Lazy Binding}{64}{subsection.4.1.4}% +\contentsline {section}{\numberline {3.4}Abusing networking programs}{62}{section.3.4}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {4.1.5}Hardening ELF binaries and possible bypasses}{67}{subsection.4.1.5}% +\contentsline {subsection}{\numberline {3.4.1}Attacks and limitations of networking programs}{62}{subsection.3.4.1}% \defcounter {refsection}{0}\relax -\contentsline {subsection}{\numberline {4.1.6}Design of our attack}{70}{subsection.4.1.6}% +\contentsline {subsection}{\numberline {3.4.2}Conclusion}{65}{subsection.3.4.2}% \defcounter {refsection}{0}\relax -\contentsline {chapter}{\numberline {5}Results}{72}{chapter.5}% +\contentsline {chapter}{\numberline {4}Design of a malicious eBPF rootkit}{66}{chapter.4}% \defcounter {refsection}{0}\relax -\contentsline {chapter}{\numberline {6}Conclusion and future work}{73}{chapter.6}% +\contentsline {section}{\numberline {4.1}Library injection attacks}{66}{section.4.1}% \defcounter {refsection}{0}\relax -\contentsline {chapter}{Bibliography}{74}{chapter.6}% +\contentsline {subsection}{\numberline {4.1.1}ROP with eBPF}{67}{subsection.4.1.1}% +\defcounter {refsection}{0}\relax +\contentsline {subsection}{\numberline {4.1.2}Bypassing hardening features in ELFs}{69}{subsection.4.1.2}% +\defcounter {refsection}{0}\relax +\contentsline {subsection}{\numberline {4.1.3}Library injection via GOT hijacking}{71}{subsection.4.1.3}% +\defcounter {refsection}{0}\relax +\contentsline {chapter}{\numberline {5}Evaluation}{73}{chapter.5}% +\defcounter {refsection}{0}\relax +\contentsline {chapter}{\numberline {6}Related work}{74}{chapter.6}% +\defcounter {refsection}{0}\relax +\contentsline {chapter}{Bibliography}{75}{chapter.6}% \contentsfinish diff --git a/docs/pdfa.xmpi b/docs/pdfa.xmpi index 1f9f060..1a780de 100644 --- a/docs/pdfa.xmpi +++ b/docs/pdfa.xmpi @@ -73,15 +73,15 @@ LaTeX with hyperref - 2022-06-09T22:56:16-04:00 - 2022-06-09T22:56:16-04:00 - 2022-06-09T22:56:16-04:00 + 2022-06-11T12:59:35-04:00 + 2022-06-11T12:59:35-04:00 + 2022-06-11T12:59:35-04:00 uuid:467B87E0-A1EA-A037-7CB7-0477245DEBC3 - uuid:B0F4602A-0208-8815-2371-500CE5249122 + uuid:252C0EB8-B2F4-7FB8-D36F-54C42CCB7207