Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- '''
- This is a make-shift replacement for metasploit's auxiliary/scanner/smb_version for clients that have disabled/removed
- SMBv1. This grabs the hostname, domain name, and Windows version from the NTLMv2 challenge response
- @Quickbreach
- '''
- import argparse
- import struct
- from binascii import hexlify, unhexlify
- import socket
- import random
- import string
- from netaddr import IPNetwork
- from threading import Thread
- from multiprocessing import Queue
- from impacket.spnego import SPNEGO_NegTokenResp
- from impacket.ntlm import NTLMAuthChallenge, AV_PAIRS, NTLMSSP_AV_HOSTNAME
- from impacket.smb3structs import SMB2Packet, SMB2Negotiate, \
- SMB2SessionSetup_Response, SMB2_DIALECT_002, SMB2_DIALECT_21, \
- SMB2_DIALECT_30, SMB2_DIALECT_302
- import logging
- from impacket.examples import logger
- logger.init()
- logging.getLogger().setLevel(logging.INFO)
- class VChecker(Thread):
- def __init__(self, IPQueue, Timeout = 3):
- Thread.__init__(self)
- self.daemon = True
- self.IPQueue = IPQueue
- self.Timeout = 3
- self.suicide = False
- self.start()
- def join(self, timeout):
- if(timeout == -1):
- return
- else:
- self.suicide = True
- super(VChecker, self).join(timeout)
- def run(self):
- while True:
- if self.suicide: return
- nextIP = None # need this declared outside of the try/catch
- try:
- if not self.IPQueue.empty():
- nextIP = self.IPQueue.get()
- else:
- self.suicide = True
- return
- except Exception, e:
- return
- if nextIP == None: return
- s = None
- try:
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- s.settimeout(self.Timeout)
- s.connect((nextIP, 445))
- except Exception, e:
- continue
- if(s == None):
- continue
- try:
- # Negotiate
- negProto = SMB2Negotiate(unhexlify("24000500010000007f000000cb78cd146438e7119168000c291232a370000000020000000202100200030203110300000100260000000000010020000100c8c31f28d43563c829b9070423e96a98701ac3ec788a3ac01573ee03d07d942600000200060000000000020002000100"))
- negProto['Dialects'] = [SMB2_DIALECT_002, SMB2_DIALECT_21, SMB2_DIALECT_30, SMB2_DIALECT_302, 0, 0]
- negProto['ClientGuid'] = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8))
- rawData = str(SMB2Packet()) + str(negProto)
- netbios = struct.pack('>i', len(str(rawData)))
- rpkt = str(netbios) + str(rawData)
- s.sendall(rpkt)
- data = s.recv(4096)
- negResp = SMB2Packet(data[4:])
- # NTLMSSP Negotiate
- sessionSetup = unhexlify("000000a2fe534d42400001000000000001001f0000000000000000000200000000000000fffe00000000000000000000000000000000000000000000000000000000000019000001010000000000000058004a000000000000000000604806062b0601050502a03e303ca00e300c060a2b06010401823702020aa22a04284e544c4d5353500001000000978208e2000000000000000000000000000000000601b11d0000000f")
- test = SMB2Packet(sessionSetup[4:])
- test['Reserved'] = 0
- test['MessageID'] = 1
- netbios = str(struct.pack('>i', len(str(test))))
- s.sendall(netbios + str(test))
- # Get NTLMSSP challenge response
- data = s.recv(4096)
- s.close()
- packet = SMB2Packet(data[4:])
- resp = SMB2SessionSetup_Response(packet['Data'])
- securityBlob = SPNEGO_NegTokenResp(resp['Buffer'])
- authData = NTLMAuthChallenge(securityBlob['ResponseToken'])
- serverInfo = AV_PAIRS(authData['TargetInfoFields'])
- majorVersion = int(hexlify(struct.unpack('<c', str(authData['Version'])[0])[0]), 16)
- minorVersion = int(hexlify(struct.unpack('<c', str(authData['Version'])[1])[0]), 16)
- buildVersion = struct.unpack('<h', str(authData['Version'])[2:4])[0]
- hostname = serverInfo[NTLMSSP_AV_HOSTNAME][1].decode("utf-16-le").encode("utf-8")
- domain = authData['domain_name'].decode("utf-16-le").encode("utf-8")
- except Exception, e:
- logging.error("Failed to get data from " + nextIP + " (Does it support NTLM?)")
- logging.error(e)
- continue
- OS = "(Unknown OS version)"
- if majorVersion == 5:
- # Major 5, minor 1: Windows XP SP2
- if minorVersion == 1: OS = "Windows XP SP2"
- # Major 5, minor 2: Windows server 2003
- if minorVersion == 2: OS = "Windows Server 2003"
- if majorVersion == 6:
- if minorVersion == 0: OS = "Windows Vista or Server 2008"
- if minorVersion == 1: OS = "Windows 7 or Server 2008 R2"
- if minorVersion == 2: OS = "Windows 8 or Server 2012"
- if minorVersion == 3: OS = "Windows 8.1 or Server 2012 R2"
- if majorVersion == 10:
- if minorVersion == 0: OS = "Windows 10 or Server 2016"
- logging.info(nextIP + ":445\t" + OS + " (build:" + str(buildVersion) + ") (name:" + hostname + ") (Domain:" + domain + ")")
- if __name__ == "__main__":
- parser = argparse.ArgumentParser()
- parser._optionals.title = "Standard arguments"
- parser.add_argument('-t', type=str, help='Target IP or CIDR', required=True)
- parser.add_argument('--threads', default=1, type=int, help='Maximum number of concurrent threads (default: 1)', required=False)
- parser.add_argument('--timeout', default=1, type=int, help='Connection timeout in seconds (default: 1)', required=False)
- args = parser.parse_args()
- targetList = Queue()
- workers = []
- for ip in IPNetwork(args.t):
- targetList.put(str(ip))
- for x in range(0, args.threads):
- workers.append(VChecker(targetList, args.timeout))
- try:
- for worker in workers:
- while worker.isAlive():
- worker.join(-1)
- except KeyboardInterrupt:
- logging.error("Recieved interrupt - cleaning up...")
- for worker in workers:
- worker.join(0)
- exit(0)
Add Comment
Please, Sign In to add comment