"""
Base exploit class
"""
import os
import subprocess
from constants import *

# hack for correcting input to raw_input when running python2 instead of python3
try:
	input = raw_input
except NameError:
	pass


class LinuxExploit:
	def __init__(self):
		self.name = "CVE-WHOOPS-LINUX-BASE-CLASS"
		self.e_type = "linux"
		self.brief_desc = "A base class for linux exploits"
		self.reliability = LOW_RELIABILITY
		self.vulnerable_base = None
		self.vulnerable_kernels = []
		self.exploit_kernels = []
		self.architecture = ARCHITECTURE_GENERIC
		self.exploit_source_file_name = "{}.c".format(self.name)
		self.source_c_path = os.path.join(PLAYGROUND_PATH, self.exploit_source_file_name)
		self.compilation_path = os.path.join(PLAYGROUND_PATH, self.name)
		self.compilation_command = "gcc -o {} {}".format(self.compilation_path, self.source_c_path)
		self.exploit_command = self.compilation_path
		self.exploit_source = """
#include <stdio.h>
int main()
{
	// printf() displays the string inside quotation
	printf("whoops, this is the linux base class!\\n");
	return 0;
}
"""

	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 False

	def shell_results(self, shell_command):
		p = subprocess.Popen(
			shell_command,
			stdin=subprocess.PIPE,
			stdout=subprocess.PIPE,
			stderr=subprocess.PIPE,
			shell=True
		)
		return p.communicate()

	def exploit_failure(self, failure_reason):
		color_print("\t[-] exploitation failed: {}".format(failure_reason), color="red")

	def compilation_successful(self):
		if os.path.isfile(self.compilation_path):
			return True
		else:
			return False

	def write_exploit_source(self):
		color_print("\t[*] writing the exploit source to disk ({})".format(self.source_c_path), color="blue")
		try:
			with open(self.source_c_path, 'w') as source_file:
				source_file.write(self.exploit_source)
		# we have to handle this nastily because python3 is PermissionError and python2 is IOError. PermissionError
		# doesn't exist on python2...
		except Exception as e:
			color_print("\t[!] cannot write exploit source code to destination, permission denied (does the path exist?)", color="red")
			color_print("\t[!] exiting", color="red")
			exit(0)

	def exploit_compile(self):
		color_print("\t[*] compiling exploit {} to {}".format(self.name, self.compilation_path), color="blue")
		color_print("\t[*] {}".format(self.compilation_command), color="blue")
		compilation_results = self.shell_results(self.compilation_command)
		if self.compilation_successful():
			color_print("\t[+] compilation successful!", color="green")
		else:
			self.exploit_failure("failed to compile exploit {}".format(self.name))

	def exploit(self):
		perform_exploitation = str(input("Would you like to run exploit {} on this system? (y/n): ".format(self.name)))
		if "y" in perform_exploitation.lower():
			self.write_exploit_source()
			self.exploit_compile()
			if self.compilation_successful():
				color_print("\t[*] performing exploitation of {}".format(self.name))
				try:
					subprocess.call(self.exploit_command)
				except KeyboardInterrupt:
					self.exploit_failure("exploitation interrupted")
		else:
			self.exploit_failure("canceled execution of exploit {}".format(self.name))

	def jsonify(self):
		vulnerable_base = 		self.vulnerable_base.jsonify()
		vulnerable_kernels = 	jsonify_kernel_window_list(self.vulnerable_kernels)
		exploit_kernels = 		jsonify_kernel_window_list(self.exploit_kernels)

		return {
			"name": 				self.name,
			"e_type": 				self.e_type,
			"brief_desc": 			self.brief_desc,
			"reliability": 			self.reliability,
			"vulnerable_base": 		vulnerable_base,
			"vulnerable_kernels": 	vulnerable_kernels,
			"exploit_kernels": 		exploit_kernels,
			"architecture": 		self.architecture,
			"source_c_path": 		self.source_c_path,
			"compilation_path": 	self.compilation_path,
			"compilation_command": 	self.compilation_command,
			"exploit_command": 		self.exploit_command
		}


class MacExploit:
	def __init__(self):
		self.name = "CVE-WHOOPS-MAC-BASE-CLASS"
		self.e_type = "mac"
		self.brief_desc = "A base class for mac exploits"
		self.reliability = LOW_RELIABILITY
		self.vulnerable_base = None
		self.vulnerable_kernels = []
		self.exploit_kernels = []
		self.architecture = ARCHITECTURE_GENERIC
		self.source_c_path = os.path.join(PLAYGROUND_PATH, "{}.c".format(self.name))
		self.compilation_path = os.path.join(PLAYGROUND_PATH, self.name)
		self.compilation_command = ["gcc", "-o", self.compilation_path, self.source_c_path]
		self.exploit_command = self.compilation_path
		self.exploit_source = """
#include <stdio.h>
int main()
{
	// printf() displays the string inside quotation
	printf("whoops, this is the mac base class!\\n");
	return 0;
}
"""

	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 False

	def shell_results(self, shell_command):
		p = subprocess.Popen(
			shell_command,
			stdin=subprocess.PIPE,
			stdout=subprocess.PIPE,
			stderr=subprocess.PIPE,
			shell=True
		)
		return p.communicate()

	def exploit_failure(self, failure_reason):
		color_print("\t[-] exploitation failed: {}".format(failure_reason), color="red")

	def compilation_successful(self):
		if os.path.isfile(self.compilation_path):
			return True
		else:
			return False

	def write_exploit_source(self):
		color_print("\t[*] writing the exploit source to disk ({})".format(self.source_c_path), color="blue")
		try:
			with open(self.source_c_path, 'w') as source_file:
				source_file.write(self.exploit_source)
		# we have to handle this nastily because python3 is PermissionError and python2 is IOError. PermissionError
		# doesn't exist on python2...
		except Exception as e:
			color_print("\t[!] cannot write exploit source code to destination, permission denied (does the path exist?)", color="red")
			color_print("\t[!] exiting", color="red")
			exit(0)

	def exploit_compile(self):
		color_print("\t[*] compiling exploit {} to {}".format(self.name, self.compilation_path), color="blue")
		color_print("\t[*] {}".format(self.compilation_command), color="blue")
		compilation_results = self.shell_results(self.compilation_command)
		if self.compilation_successful():
			color_print("\t[+] compilation successful!", color="green")
		else:
			self.exploit_failure("failed to compile exploit {}".format(self.name))

	def exploit(self):
		perform_exploitation = str(input("Would you like to run exploit {} on this system? (y/n): ".format(self.name)))
		if "y" in perform_exploitation.lower():
			self.exploit_compile()
			if self.compilation_successful():
				color_print("\t[*] performing exploitation of {}".format(self.name))
				try:
					subprocess.call(self.exploit_command)
				except KeyboardInterrupt:
					self.exploit_failure("exploitation interrupted")
		else:
			self.exploit_failure("canceled execution of exploit {}".format(self.name))

	def jsonify(self):
		vulnerable_base = 		self.vulnerable_base.jsonify()
		vulnerable_kernels = 	jsonify_kernel_window_list(self.vulnerable_kernels)
		exploit_kernels = 		jsonify_kernel_window_list(self.exploit_kernels)

		return {
			"name": 				self.name,
			"e_type": 				self.e_type,
			"brief_desc": 			self.brief_desc,
			"reliability": 			self.reliability,
			"vulnerable_base": 		vulnerable_base,
			"vulnerable_kernels": 	vulnerable_kernels,
			"exploit_kernels": 		exploit_kernels,
			"architecture": 		self.architecture,
			"source_c_path": 		self.source_c_path,
			"compilation_path": 	self.compilation_path,
			"compilation_command": 	self.compilation_command,
			"exploit_command": 		self.exploit_command
		}