SMB12 Information Gathering

SMB12 Information Gathering is a data gathering python script that inspects SMB1 and SMB2 endpoints. It will extract various attributes from the remote server such as OS version (only supported by SMB1 as per protocol definition), DNS computer name, DNS domain name, NetBIOS computer name and NetBIOS domain name (SMB1 and SMB2).


MD5 | ddda39cbd4570cf2fc5b7af60557808c

######################################################################################################################
# Exploit Title: SMB12 information gathering
# SMB12 means it's capable of inspecting both SMB1 and SMB2 versions
# the utility will extract varios attributes from SMB protocol of the remote server such as
# OS version (only supported by SMB1 as per protocol definition)
# DNS computername, DNS domainname, NEtBIOS computername and NetBIOS domain name (SMB1 and SMB2)
# boot time and current time on the remote server (SMB1 and SMB2)
# Server's GUID (SMB1 and SMB2)
# Additional : NEtBIOS probe against UDP 137 (netbios session) to determine server roles such as
# -domain master browser
# -domain controller
# -server service
# Date: 11-July-2020
# Exploit Author: Ivica Stipovic
# Vendor Homepage: www.microsoft.com
# Software Link: intergrated as part of Windows OS
# Version: SMB1 and SMB2
# Tested on: Windows 7, Windows 10, Windows 2012 R2, Windows 2016, Windows 2019
# Domain setup: Some OS-es were setup as WORKGROUP members and some as DOMAIN
# Objective: enhance system info returned by SMB protocol in comparison to :
# nmap smb-system-info.nse and metasploit smb_version and smb2 modules
# Known Limitation: not designed for SAMBA implementations (Linux etc) - no reliable detection/exception possible
# Download link: https://github.com/adenosine-phosphatase/smb12info
###########################################################################################################

import socket
import sys
import time
from datetime import datetime, timedelta
from struct import *

TCP_PORT=445

netbios_check=(
"\x91\xe2" # Transaction ID
"\x00\x00" # Flags
"\x00\x01" # Questions=1
"\x00\x00" # Answer RRs
"\x00\x00" # Authority RRs
"\x00\x00" # Additional RRs
"\x20\x43\x4b\x41\x41\x41\x41\x41" # Queries MSHOME/Type NB, Class IN
"\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x00"
"\x00\x21" # NBSTAT (33)
"\x00\x01") # Class IN(1)

smb_helper_message=(
"\x00" # NEtbios header - Message type 00
"\x00\x00\x54" # Length
"\xff\x53\x4d\x42" # SMB header-Server component
"\x72" # SMB command - negotiate protocol
"\x00" # NT Status - status_success
"\x00" # NT Status
"\x00\x00" # NT Status
"\x18" # Flags: 0x18
"\x01\x28" # Flags2
"\x00\x00" # Process ID High
"\x00\x00\x00\x00\x00\x00\x00\x00" # Signature
"\x00\x00" # Reserved
"\x00\x00" # Tree ID
"\x2e\x6f" # Process ID
"\x00\x00" # User ID
"\x7f\xe6" # Multiplex ID
"\x00" # Word Count
"\x31\x00" # Byte count
"\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00" # Requested Dialects
"\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00" # PC NETWORK PROGRAM 1.0
"\x02\x4e\x54\x20\x4c\x41\x4e\x4d\x41\x4e\x20" # MICROSOFT NETWORKS 1.03
"\x31\x2e\x30\x00"
"\x02\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00")

smb_enahanced_helper_message=(
"\x00" # NetBIOS header - message type
"\x00\x00\x45" # Length
"\xff\x53\x4d\x42" # Server Component -SMB2
"\x72" # Header Length
"\x00\x00\x00\x00" # NT STATUS - status success
"\x18" # Flags
"\x53\xc8" # Flags2
"\x00\x00" # Process ID High
"\x00\x00\x00\x00\x00\x00\x00\x00" # Signature=00000
"\x00\x00" # Reserved=0000
"\xff\xff" # Tree ID
"\xff\xfe" # Process ID
"\x00\x00" # User ID
"\x00\x00" # Multiplex ID
"\x00" # Word Count
"\x22\x00" # Byte count
"\x02\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00" # Requested dialects - this is
"\x02\x53\x4d\x42\x20\x32\x2e\x30\x30\x32\x00" # the main difference to initial SMB1
"\x02\x53\x4d\x42\x20\x32\x2e\x3f\x3f\x3f\x00") # request

smb2_helper_message=(
"\x00" # NetBIOS message type
"\x00\x00\xae" # Length
"\xfe\x53\x4d\x42" # SMB2 -Protocol ID
"\x40\x00" # Header Length
"\x00\x00" # Credit Charge
"\x00\x00" # Channel sequence
"\x00\x00" # Reserved
"\x00\x00" # Negotiate Protocol
"\x00\x00" # Credits requested
"\x00\x00\x00\x00" # Flags
"\x00\x00\x00\x00" # Chain offset
"\x01\x00\x00\x00\x00\x00\x00\x00" # Message ID - unknown=1
"\xff\xfe\x00\x00" # PRocess ID
"\x00\x00\x00\x00" # Tree ID
"\x00\x00\x00\x00\x00\x00\x00\x00" # Session ID
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # Signature
"\x24\x00" # Structure size
"\x05\x00" # Dialect count
"\x01\x00" # Security mode / signing enabled
"\x00\x00" # Reserved
"\x7f\x00\x00\x00" # Capabilities
"\x86\xcc\xaa\x67\xca\xb6\xea\x11\x91\xb1\xfd\x77\x48\xa7\x6a\x3c" # Client GUID
"\x70\x00\x00\x00" # NegotiateContextOffset
"\x02\x00" # NEgotiateContextCount
"\x00\x00" # Reserved
"\x02\x02" # Dialect 1
"\x10\x02" # Dialect 2
"\x00\x03" # Dialect 3
"\x02\x03" # Dialect 4
"\x11\x03" # Dialect 5
"\x00\x00" # unknonw
"\x01\x00" # DataType SMB_PREAUTH
"\x26\x00" # Datalength
"\x00\x00\x00\x00" # Reserved
"\x01\x00" # Hash Algorithm
"\x20\x00" # salt length
"\x01\x00" # Hash algorithm SHA-512
"\xd3\x2f\xfe\xad\x6b\xc5\x32\xbb" # Salt (32 bytes)
"\x44\x29\x7d\x56\x33\x69\xcd\xe7"
"\x42\x1c\x20\x53\x85\x16\x97\xc5"
"\x01\xec\x80\x12\x6a\x9b\xbe\x2d"
"\x00\x00" # unknown
"\x02\x00" # SMB2_encryption_capabilities
"\x06\x00" # Datalength
"\x00\x00\x00\x00" # Reserved
"\x02\x00" # Cipher count
"\x02\x00" # Cipher ID
"\x01\x00") # Cipher ID

smb_helper_message_security_blob=(
"\x00" # NetBIOS message type
"\x00\x00\x8f" # Length
"\xff\x53\x4d\x42" # SMB1 Server Component
"\x73" # Session Setup AndX (0x73)
"\x00" # Error class=success
"\x00" # Reserved
"\x00\x00" # Error Code=no error
"\x18" # Flags
"\x01\x28" # Flags2
"\x00\x00" # Process ID High
"\x00\x00\x00\x00\x00\x00\x00\x00" # Signature
"\x00\x00" # Reserved
"\x00\x00" # Tree ID
"\x2e\x6f" # Process ID
"\x00\x00" # User ID
"\x7f\xe6" # Multiplex ID
"\x0c" # Word Count
"\xff" # AndX Command=no further commands
"\x00" # Reserved
"\x00\x00" # AndXOffset=0
"\xdf\xff" # Max Buffer
"\x02\x00" # Max Mpx Count
"\x01\x00" # VC Number
"\x00\x00\x00\x00" # Session Key
"\x31\x00" # Security Blob Length
"\x00\x00\x00\x00" # Reserved
"\xd4\x00\x00\x80" # Capabilities
"\x54\x00" # Byte Count
"\x4e\x54\x4c\x4d\x53\x53\x50\x00" # NTLMSSP identifier
"\x01\x00\x00\x00" # NTLM Message Type = NTLMSSP_NEGOTIATE
"\x05\x02\x88\xa2" # Negotiate flags
"\x01\x00\x01\x00\x20\x00\x00\x00\x10\x00\x10\x00\x21\x00\x00\x00" #Calling Wkst domain
"\x2e"
"\x32\x54\x64\x44\x36\x30\x77\x62\x4e\50\x36\47\x39\x61\x66\x76" # Calling wkst name
"\x57\x69\x6e\x64\x6f\x77\x73\x20\x32" # Native OS Win2000
"\x30\x30\x30\x20\x32\x31\x39\x35\x00" # Native LAN Manager
"\x57\x69\x6e\x64\x6f\x77\x73\x20\x32"
"\x30\x30\x30\x20\x35\x2e\x30\x00")

smb2_helper_ntlmssp_message= (
"\x00" # Netbios Message Type
"\x00\x00\xa2" # Length
"\xfe\x53\x4d\x42" # Server Component, ex: SMB2
"\x40\x00" # Header Length
"\x01\x00" # Credit Charge
"\x00\x00" # Channel sequence
"\x00\x00" # Reserved
"\x01\x00" # Session Setup
"\x21\x00" # Credits requested
"\x10\x00\x00\x00" # Flags
"\x00\x00\x00\x00" # Chain Offset
"\x02\x00\x00\x00\x00\x00\x00\x00" # Message ID
"\xff\xfe\x00\x00" # Process ID
"\x00\x00\x00\x00" # Tree ID
"\x00\x00\x00\x00\x00\x00\x00\x00" # Session ID
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # Signature
"\x19\x00" # Structure size
"\x00" # Flags
"\x02" # Security mode
"\x01\x00\x00\x00" # Capabilities
"\x00\x00\x00\x00" # Channel
"\x58\x00" # Previous session ID
"\x4a\x00" # Blob length
"\x00\x00\x00\x00\x00\x00\x00\x00" # Previos Session ID
"\x60\x48\x06\x06\x2b\x06\x01\x05" # GSS-API Generic Security Service
"\x05\x02\xa0\x3e\x30\x3c\xa0\x0e" # Simple Protected NEgotiation
"\x30\x0c\x06\x0a\x2b\x06\x01\x04" # mechtypes + NTLM Secure Service Provider
"\x01\x82\x37\x02\x02\x0a\xa2\x2a"
"\x04\x28\x4e\x54\x4c\x4d\x53\x53"
"\x50\x00\x01\x00\x00\x00\x97\x82"
"\x08\xe2\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x0a\x00\xee\x42\x00\x00"
"\x00\x0f")


def print_smb12_system_info (smb_type,data2):

netbios_header=4

if smb_type==1:
smb_header=32
else:
smb_header=64

blob_offset=netbios_header+smb_header
offset=0
index=0
size=len (data2)

pattern=0
security_blob="4e544c4d535350"
control=""

for t in data2[blob_offset:size-blob_offset]:

for x in data2[blob_offset+offset:blob_offset+offset+7]:
control=control+"{:02x}".format(ord(x),"x")


if security_blob==control:

index=blob_offset+offset
index=index+12

targetnamelen=int(ord(data2[index:index+1][::-1]))

index=index+28
index=index+16


targetname=data2[index:index+targetnamelen]
targetinfoitemlen=int(ord(data2[index+targetnamelen+2]))

netbiosname=data2[index+targetnamelen+4:index+targetnamelen+4+targetinfoitemlen]

netbioscomputernamelen=int(ord(data2[index+targetnamelen+4+targetinfoitemlen+2]))
index=index+targetnamelen+4+targetinfoitemlen+2

netbioscomputername=data2[index+2:index+2+netbioscomputernamelen]

dnsdomainnamelen=int(ord(data2[index+2+netbioscomputernamelen+2]))
index=index+2+netbioscomputernamelen+2

dnsdomainname=data2[index+2:index+2+dnsdomainnamelen]

dnscomputernamelen=int(ord(data2[index+2+dnsdomainnamelen+2]))
index=index+2+dnsdomainnamelen+2

dnscomputername=data2[index+2:index+2+dnscomputernamelen]

print "[+] Target Name:", targetname
print "[+] Netbios Domainname:",netbiosname
print "[+] Netbios Computername:", netbioscomputername
print "[+] DNS Domain Name:", dnsdomainname
print "[+] DNS Computer Name:", dnscomputername

index=index+2+dnscomputernamelen

# Check for DNS tree info item type - must be 5, anything else means not a domain member

if int(ord(data2[index]))==5:
dnstreelen=int(ord(data2[index+2]))

print "[+] DNS Tree Name:", data2[index+2:index+2+dnstreelen+1]
index=index+2+dnstreelen+2

# Skip over 16 bytes (timestamp=12 bytes + end-of-list=4 bytes

index=index+16

if size-index>0:

print "[+] OS info:",data2[index-2:size]

offset+=1
control=""

def netbios_fingerprint():

sockUDP=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
try:
sockUDP.sendto(netbios_check,(TCP_IP,137))
sockUDP.settimeout(3)
dataUDP,addrUDP=sockUDP.recvfrom(1024)

number_of_names=int(ord(dataUDP[56]))

delta=0
names_offset=57
role=0

for x in range(number_of_names):

role=int(ord(dataUDP[names_offset+(x+1)*16-1+delta]))
if role==0:
print ("[+] NetBIOS Role: Workstation/Redirector")
elif role==32:
print ("[+] NetBIOS Role: Server Service")
elif role==28:
print ("[+] NetBIOS Role: Domain Controller")
elif role==27:
print ("[+] NetBIOS Role: Domain Master Browser")
delta+=2

except socket.timeout:
print "[-] No response from NetBIOS"
sockUDP.close()

def send_smb_request(message_type,sock_type):

sock_type.sendall(message_type)
resp,addr=sock_type.recvfrom(1024)
return resp

def print_smb1_guid(smb1_guid_data):

guidA_id=""
guidB_id=""
guidC_id=""
guidD_id=""
guidE_id=""
for x in temp_data[73:77]:
guidA_id=guidA_id+"{:02x}".format(ord(x),"x")

for x in temp_data[77:79]:
guidB_id=guidB_id+"{:02x}".format(ord(x),"x")

for x in temp_data[79:81]:
guidC_id=guidC_id+"{:02x}".format(ord(x),"x")

for x in temp_data[81:83]:
guidD_id=guidD_id+"{:02x}".format(ord(x),"x")

for x in temp_data[83:89]:
guidE_id=guidE_id+"{:02x}".format(ord(x),"x")

print "[+] Server GUID:" ,guidA_id+'-'+guidB_id+'-'+guidC_id+'-'+guidD_id+'-'+guidE_id

def print_system_time(start_time,end_time,time_type):

# time_type=0 then boot time
# time_type=1 then current time

dx=""
for y in temp_data[start_time:end_time][::-1]:
dx=dx+"{:02x}".format(ord(y),"x")

if dx!="0000000000000000":
us=int(dx,16) / 10.
if time_type==0:
print "[+] Boot time:",datetime(1601,1,1) + timedelta(microseconds=us)
else:
print "[+] Current time:", datetime(1601,1,1) + timedelta(microseconds=us)
else:
if time_type==0:
print "[-] Boot time not specified"
else:
print "[+] Current time not specified"
dx=""


if len(sys.argv)!=2:
print ("usage: python smbinject.py <ip address>")
sys.exit()
else:
TCP_IP=sys.argv[1]

#====================================
# Negotiate Protocol Request sequence
#=====================================

print ("[+] Trying NetBIOS fingerprint...")

netbios_fingerprint()

sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((TCP_IP,TCP_PORT))

try:
print ("[+] Starting SMB1 check")
temp_data=send_smb_request(smb_helper_message,sock)
smb_dialect=temp_data[72:74]

current_time_start=60
current_time_stop=68

print_system_time(current_time_start,current_time_stop,1)
print_smb1_guid(temp_data)

print ("[+] SMB1 dialect detected")
time.sleep(1)

data=send_smb_request(smb_helper_message_security_blob,sock)
print ("[+] SMB response")

smb=1
print_smb12_system_info (smb,data)

except socket.error,ex:
print ("[-] Server reset SMB1 negotiation. Trying SMB2 ...")
sock2=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock2.connect((TCP_IP,TCP_PORT))

temp_data=send_smb_request(smb_enahanced_helper_message,sock2)

guid1_id=""
guid2_id=""
guid3_id=""
guid4_id=""
guid5_id=""

for x in temp_data[76:80][::-1]:
guid1_id=guid1_id+"{:02x}".format(ord(x),"x")

for x in temp_data[80:82][::-1]:
guid2_id=guid2_id+"{:02x}".format(ord(x),"x")

for x in temp_data[82:84][::-1]:
guid3_id=guid3_id+"{:02x}".format(ord(x),"x")

for x in temp_data[84:86]:
guid4_id=guid4_id+"{:02x}".format(ord(x),"x")

for x in temp_data[86:92]:
guid5_id=guid5_id+"{:02x}".format(ord(x),"x")

print "[+] Server GUID:" ,guid1_id+'-'+guid2_id+'-'+guid3_id+'-'+guid4_id+'-'+guid5_id

dt=""

current_time_start=108
current_time_stop=116
boot_time_start=116
boot_time_stop=124

print_system_time(current_time_start,current_time_stop,1)
print_system_time(boot_time_start,boot_time_stop,0)

time.sleep(2)

send_smb_request(smb2_helper_message,sock2)
time.sleep(1)

data2=send_smb_request(smb2_helper_ntlmssp_message,sock2)

smb=2
print_smb12_system_info (smb,data2)

sock2.close()

sock.close()


Related Posts