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}