linux-rootkit

Feature-rich interactive rootkit that targets Linux kernel 4.19, accompanied by a dynamic kernel memory analysis GDB plugin for in vivo introspection (e.g. using QEMU)
git clone git://git.deurzen.net/linux-rootkit
Log | Files | Refs

presentation.tex (12995B)


      1 \documentclass{i20lecture}
      2 \usepackage{listings}
      3 
      4 \subtitle{LiveDM --- Proof of Concept}
      5 
      6 \begin{document}
      7 
      8 \frame{\titlepage}
      9 
     10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     11 \section{Agenda}
     12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     13 \begin{frame}{\insertsection}
     14   \begin{enumerate}
     15    \item Background
     16     \begin{itemize}
     17         \item Dynamic Kernel Memory
     18         \item LiveDM
     19     \end{itemize}
     20     \item Approach
     21     \item Results
     22     \item Discussion / Questions
     23   \end{enumerate}
     24 \end{frame}
     25 
     26 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     27 \section{Background}
     28 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     29 \begin{frame}{\insertsection}
     30   \framesubtitle{Dynamic Kernel Memory}
     31 
     32   \begin{itemize}
     33     \item Dynamic kernel memory is...
     34     \begin{itemize}
     35 \pause
     36     \item ...hard to make sense of -- usually, no type information is available
     37 \pause
     38 	\item ...constantly changing -- it's dynamic, after all
     39 \pause
     40     \item ...difficult to analyze!
     41     \end{itemize}
     42 \pause
     43     \item How can we make analysis easier?
     44   \end{itemize}
     45 \end{frame}
     46 
     47 \begin{frame}{\insertsection}
     48   \framesubtitle{LiveDM --- Overview}
     49 
     50   \begin{itemize}
     51 	\item LiveDM seeks to overcome these issues through Virtual Machine Introspection (VMI)
     52 	\pause
     53 	\begin{itemize}
     54 		\item Monitor the runtime state of a VM
     55 		\pause
     56 		\item Without altering the guest OS
     57 	\end{itemize}
     58 \pause
     59     \item Memory allocation events can be intercepted
     60 \pause
     61     \item Going from there, LiveDM is able to create a memory map
     62 	\begin{itemize}
     63 		\pause
     64 		\item This map includes type information!
     65 	\end{itemize}
     66   \end{itemize}
     67 \end{frame}
     68 
     69 \begin{frame}{\insertsection}
     70   \framesubtitle{LiveDM --- Overview}
     71 
     72   \begin{itemize}
     73     \item Three distinct stages to create the mapping:
     74     \begin{enumerate}
     75 \pause
     76      \item Gathering of necessary values
     77 \pause
     78      \item Determining the scope of memory monitoring
     79 \pause
     80      \item Performing type interpretation
     81     \end{enumerate}
     82   \end{itemize}
     83 \end{frame}
     84 
     85 \begin{frame}{\insertsection}
     86   \framesubtitle{LiveDM --- Stage 1}
     87 
     88   \begin{itemize}
     89     \item Stage 1 is comprised of...
     90     \begin{itemize}
     91      \item ...intercepting a set of memory allocation/deallocation functions
     92 \pause
     93      \item ...retrieving the requested allocation size, as well as the return value
     94 \pause
     95 	 \item ...identifying the caller (call site) through the stack's return address
     96     \end{itemize}
     97   \end{itemize}
     98 \end{frame}
     99 
    100 \begin{frame}{\insertsection}
    101   \framesubtitle{LiveDM --- Stage 2}
    102 
    103   \begin{itemize}
    104     \item In stage 2, the scope of memory monitoring is chosen
    105     \begin{itemize}
    106 \pause
    107      \item Offer snapshots of the memory map (containing type and size for allocated memory)
    108      \begin{itemize}
    109 		 \item We offer this in our PoC (\lstinline|rk-print-mem| and \lstinline|rk-data <address>|)
    110      \end{itemize}
    111 \pause
    112 	 \item Trace every memory (write) access on known (vulnerable) memory blocks
    113      \begin{itemize}
    114       \item We are able to showcase this in a small demo
    115      \end{itemize}
    116     \end{itemize}
    117   \end{itemize}
    118 \end{frame}
    119 
    120 \begin{frame}{\insertsection}
    121   \framesubtitle{LiveDM --- Stage 3}
    122 
    123   \begin{itemize}
    124     \item In stage 3, the caller's address is translated into a type
    125 \pause
    126     \begin{itemize}
    127      \item Relies on instrumenting GCC to retrieve abstract syntax tree (AST)
    128     \end{itemize}
    129   \end{itemize}
    130 \end{frame}
    131 
    132 \begin{frame}{\insertsection}
    133   \framesubtitle{LiveDM --- Motivation}
    134 
    135   \begin{itemize}
    136     \item Why do we need this information? Possible answers include...
    137     \begin{enumerate}
    138 \pause
    139      \item To make dynamic memory less transparent
    140 \pause
    141      \item To utilize this information for debugging
    142 \pause
    143      \item \textcolor{yellow}{To utilize this information for rootkit detection}
    144     \end{enumerate}
    145   \end{itemize}
    146 \end{frame}
    147 
    148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    149 \section{Approach}
    150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    151 \begin{frame}{\insertsection}
    152   \begin{enumerate}
    153    \item Background
    154     \item Approach
    155     \begin{itemize}
    156         \item Tools
    157         \item Implementing stage 1 --- Gathering of necessary values
    158         \item Implementing stage 3 --- Performing type interpretation
    159         \item Implementing stage 2 --- Determining the scope of memory monitoring
    160     \end{itemize}
    161     \item Results
    162     \item Discussion / Questions
    163   \end{enumerate}
    164 \end{frame}
    165 
    166 \begin{frame}{\insertsection}
    167   \framesubtitle{Tools}
    168 
    169   \begin{itemize}
    170    \item Since introspection techniques are required, we need a VMM
    171 \pause
    172     \begin{itemize}
    173     \item Xen
    174     \item KVM
    175 	\item \textcolor{yellow}{QEMU} (in vivo introspection using GDB)
    176     \item ...
    177     \end{itemize}
    178   \end{itemize}
    179 \end{frame}
    180 
    181 \begin{frame}{\insertsection}
    182   \framesubtitle{Implementing stage 1 --- Gathering of necessary values}
    183 
    184     \begin{itemize}
    185 	\item Intercepting allocations is easy: non-blocking \textbf{breakpoints}
    186      \begin{itemize}
    187 \pause
    188       \item Break on function entry and exit
    189         \begin{itemize}
    190 \pause
    191 			\item At entry we extract allocation size
    192 			\item At exit we extract return value (base address of allocation)
    193         \end{itemize}
    194 \pause
    195       \item Has a significant performance overhead, but system is still usable
    196 \pause
    197       \item Possible improvement: hardware breakpoints
    198 \pause
    199         \begin{itemize}
    200 			\item Limited to a small amount
    201         \end{itemize}
    202      \end{itemize}
    203     \end{itemize}
    204 \end{frame}
    205 
    206 \begin{frame}[fragile]{\insertsection}
    207   \framesubtitle{Implementing stage 1 --- Gathering of necessary values}
    208 
    209     \begin{itemize}
    210      \item To retrieve the size and return value of each allocation, we can rely on the System V calling convention
    211 \pause
    212      \begin{itemize}
    213       \item As the size is not always the first argument, we build a dictionary:
    214      \end{itemize}
    215     \end{itemize}
    216     \begin{lstlisting}
    217     break_arg = {
    218         "kmem_cache_alloc_trace": "rdx",
    219         "kmalloc_order": "rdi"
    220         [...]
    221     }
    222     \end{lstlisting}
    223 \pause
    224 	\begin{itemize}
    225 	\item[]
    226 	\begin{itemize}
    227 		\item Return values are gathered by additionally breaking on return instructions
    228 		\pause
    229 		\begin{itemize}
    230 			\item Look for \lstinline|ret{,q}| instruction's offset from function entry in the disassembly
    231 			\pause
    232 			\item Break on \lstinline|<function entry> + <ret offset>|
    233 			\pause
    234 			\item Retrieve return value from \lstinline|$rax|
    235 		\end{itemize}
    236 	\end{itemize}
    237 	\end{itemize}
    238 \end{frame}
    239 
    240 \begin{frame}[fragile]{\insertsection}
    241   \framesubtitle{Implementing stage 3 --- Performing type interpretation}
    242     \begin{itemize}
    243      \item Translation of call sites to types
    244 	 \pause
    245      \item Possible approaches:
    246      \begin{itemize}
    247 \pause
    248       \item Instrumenting \lstinline|gcc| to extract AST (LiveDM)
    249 \pause
    250       \item Use \lstinline|clang| to generate an AST
    251 \pause
    252 	  \item \textcolor{yellow}{Utilize GDB's \lstinline|whatis| command to statically pre-compute type dictionary}
    253      \end{itemize}
    254     \end{itemize}
    255 \end{frame}
    256 
    257 \begin{frame}[fragile]{\insertsection}
    258   \framesubtitle{Implementing stage 3 --- Performing type interpretation}
    259     \begin{itemize}
    260      \item Process for statically generating the type dictionary: \footnote{Fully automated, since specific to kernel sources version, build options, and compiler optimizations}
    261 \pause
    262      \begin{enumerate}
    263       \item Find all occurences of function calls we are interested in using \lstinline|cscope|
    264 \pause
    265       \item Iterate over the generated occurences
    266 \pause
    267       \item Extract the assigned-to symbol name at call site
    268 \pause
    269       \item Execute \lstinline|whatis| on every assigned-to symbol
    270       \begin{itemize}
    271 \pause
    272        \item Assumption: debug symbols for current kernel sources are available
    273 \pause
    274        \item Compound type access chains (e.g., \lstinline|desc->inbuf|) have to be recursively resolved
    275 	\pause
    276 	   \item We only require the type of the last dereferenced field, as that is what's being assigned to
    277       \end{itemize}
    278 \pause
    279       \item Store the results in a dictionary
    280 \pause
    281       \item Use this precompiled type dictionary in our runtime script
    282 \pause
    283      \end{enumerate}
    284     \end{itemize}
    285     \begin{lstlisting}
    286      "./arch/x86/kernel/e820.c:675": "type = struct e820_table *",
    287      "./arch/x86/kernel/e820.c:681": "type = struct e820_table *",
    288 	 [...]
    289     \end{lstlisting}
    290 \end{frame}
    291 
    292 \begin{frame}[fragile]{\insertsection}
    293   \framesubtitle{Implementing stage 3 --- Performing type interpretation}
    294     \begin{itemize}
    295      \item Once a breakpoint is encountered, we can walk the stack with gdb...
    296     \end{itemize}
    297 \pause
    298     \begin{lstlisting}
    299     #0  __kmalloc (size=168, flags=6291456) at ./mm/slub.c:3784
    300     #1  0xffffffffa9384095 in kmalloc (flags=<optimized out>, size=<optimized out>) at ./include/linux/slab.h:520
    301     #2  bio_alloc_bioset (gfp_mask=6291456, nr_iovecs=<optimized out>, bs=0x0) at ./block/bio.c:452
    302     \end{lstlisting}
    303 \pause
    304     \begin{itemize}
    305      \item ...and match the \lstinline|file:line| descriptor to a type without expensive computations
    306     \end{itemize}
    307 \end{frame}
    308 
    309 \begin{frame}[fragile]{\insertsection}
    310   \framesubtitle{Implementing stage 2 --- Determining the scope of memory monitoring}
    311 
    312     \begin{enumerate}
    313      \item Snapshot-based approach
    314 \pause
    315      \begin{itemize}
    316       \item Since we already store everything gathered, this is readily available
    317 \pause
    318       \item Live allocations can be listed with \lstinline|rk-print-mem| and interpreted with \lstinline|rk-data <address>|:
    319      \end{itemize}
    320     \end{enumerate}
    321     \begin{lstlisting}
    322     > rk-print-mem
    323 	  type: struct task_struct *, size: 3776 B, address: 0xffff8e72b87ce740, call site: ./kernel/fork.c:807
    324 	  type: struct fdtable *, size: 56 B, address: 0xffff8e72b84104c0, call site: ./fs/file.c:111
    325     \end{lstlisting}
    326     \begin{lstlisting}
    327 	> rk-data 0xffff8e72b84104c0
    328 	  resolving 0xffff8e72b84104c0 to type = struct fdtable *
    329 
    330 	  $17 = {
    331 	    max_fds = 256,
    332 	    fd = 0xffff8e72b8ea4800,
    333 	    close_on_exec = 0xffff8e72b8411800,
    334 	    open_fds = 0xffff8e72b84117e0,
    335 	    full_fds_bits = 0xffff8e72b8411820,
    336 	    rcu = {
    337 	  	next = 0x0,
    338 	  	func = 0x0
    339 	    }
    340 	  }
    341     \end{lstlisting}
    342 \end{frame}
    343 
    344 \begin{frame}[fragile]{\insertsection}
    345   \framesubtitle{Implementing stage 2 --- Determining the scope of memory monitoring}
    346 
    347     \begin{enumerate}
    348      \setcounter{enumi}{1}
    349      \item Memory-access tracing
    350 \pause
    351     \begin{itemize}
    352      \item Would require some advanced techniques (e.g., page unmapping) for full coverage
    353 \pause
    354     \item Not feasible within the given time frame
    355 \pause
    356     \item Instead, we will demonstrate a small example based on \textit{hardware} watchpoints
    357 		\begin{itemize}
    358 		  \item Warn when critical values are written to traced blocks
    359 		\end{itemize}
    360     \end{itemize}
    361     \end{enumerate}
    362 \end{frame}
    363 
    364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    365 \section{Results}
    366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    367 
    368 \begin{frame}[fragile]{\insertsection}
    369   \framesubtitle{Demo 1 - Allocation \& Deallocation}
    370     \begin{itemize}
    371      \item We will demonstrate the output in a running system now:
    372      \end{itemize}
    373      \begin{lstlisting}
    374       Allocating ('type = struct elf64_phdr *', 616, './fs/binfmt_elf.c:441') at 0xffff8d96b8857000
    375       Allocating ('type = char *', 28, './fs/binfmt_elf.c:762') at 0xffff8d96ba5d98e0
    376       Allocating ('type = struct elf64_phdr *', 504, './fs/binfmt_elf.c:441') at 0xffff8d96bb4b1e00
    377       Allocating ('type = void *', 168, './block/bio.c:452') at 0xffff8d96ba14bcc0
    378 
    379      \end{lstlisting}
    380 
    381 \end{frame}
    382 
    383 \begin{frame}[fragile]{\insertsection}
    384   \framesubtitle{Demo 2 - Rootkit Detection}
    385     \begin{itemize}
    386      \item We will demonstrate the rootkit detection in a running system now:
    387      \end{itemize}
    388      \begin{lstlisting}
    389         //inside the vm, rootkit is loaded
    390         > make_me_root
    391      \end{lstlisting}
    392      \begin{lstlisting}
    393         ((((struct task_struct *)0xffff8d96bb6849c0)->real_cred)->uid) changed from val = 1000 to val = 0
    394         WARNING: critical value 0 set to ((((struct task_struct *)0xffff8d96bb6849c0)->real_cred)->uid)
    395 
    396      \end{lstlisting}
    397      
    398 
    399 \end{frame}
    400 
    401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    402 \section{Discussion / Questions}
    403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    404 \begin{frame}{\insertsection}
    405   \begin{center}
    406     \LARGE \dots
    407   \end{center}
    408 \end{frame}
    409 
    410 
    411 
    412 \end{document}