首页 > 编程语言 >python版nbtscan

python版nbtscan

时间:2022-11-20 21:25:06浏览次数:39  
标签:name ips python ip nbtscan start print x00

python版nbtscan

# -*- coding:utf-8 -*-
import socket
import sys
from datetime import datetime
# import threading
import time
import ipaddress    # 识别ip段模块
from multiprocessing.pool import ThreadPool
import argparse


# lock = threading.Lock()

##################################################ip转换######################################################
class IP_Conversion():

    def __init__(self):
        self.ip_nms = []
        self.base = [str(x) for x in range(10)] + [ chr(x) for x in range(ord('A'),ord('A')+6)]

    #十进制0~255转化为二进制,补0到8位
    def dec2bin80(self, string_num):
        num = int(string_num)
        mid = []
        while True:
            if num == 0: break
            num,rem = divmod(num, 2)
            mid.append(self.base[rem])

        result = ''.join([str(x) for x in mid[::-1]])
        length = len(result)
        if length < 8:
            result = '0' * (8 - length) + result
        return result


    #十进制0~255转化为二进制,补0到32位
    def dec2bin320(self, string_num):
        num = int(string_num)
        mid = []
        while True:
            if num == 0: break
            num,rem = divmod(num, 2)
            mid.append(self.base[rem])

        result = ''.join([str(x) for x in mid[::-1]])
        length = len(result)
        if length < 32:
            result = '0' * (32 - length) + result
        return result


    #十进制0~255转化为二进制,不补零
    def dec2bin(self, string_num):
        num = int(string_num)
        mid = []
        while True:
            if num == 0: break
            num,rem = divmod(num, 2)
            mid.append(self.base[rem])

        return ''.join([str(x) for x in mid[::-1]])


    #二进制转换为十进制
    def bin2dec(self, string_num):
        return str(int(string_num, 2))

    #ip列表生成
    def iplist(self, string_startip,string_endip):

        #分割IP,然后将其转化为8位的二进制代码
        start = string_startip.split('.')
        start_a = self.dec2bin80(start[0])
        start_b = self.dec2bin80(start[1])
        start_c = self.dec2bin80(start[2])
        start_d = self.dec2bin80(start[3])
        start_bin = start_a + start_b + start_c + start_d
        #将二进制代码转化为十进制
        start_dec = self.bin2dec(start_bin)

        end = string_endip.split('.')
        end_a = self.dec2bin80(end[0])
        end_b = self.dec2bin80(end[1])
        end_c = self.dec2bin80(end[2])
        end_d = self.dec2bin80(end[3])
        end_bin = end_a + end_b + end_c + end_d
        #将二进制代码转化为十进制
        end_dec = self.bin2dec(end_bin)

        #十进制相减,获取两个IP之间有多少个IP
        count = int(end_dec) - int(start_dec)

        #生成IP列表
        for i in range(0,count + 1):
            #将十进制IP加一,再转化为二进制(32位补齐)
            plusone_dec = int(start_dec) + i
            plusone_dec = str(plusone_dec)
            address_bin = self.dec2bin320(plusone_dec)
            #分割IP,转化为十进制
            address_a = self.bin2dec(address_bin[0:8])
            address_b = self.bin2dec(address_bin[8:16])
            address_c = self.bin2dec(address_bin[16:24])
            address_d = self.bin2dec(address_bin[24:32])
            address = address_a + '.'+ address_b +'.'+ address_c +'.'+ address_d
            self.ip_nms.append(address)
        return self.ip_nms

# ip = IP_Conversion()
# ips = ip.iplist('2.168.255.254','2.169.1.10')
# print(ips)
##############################################以上是ip转换#####################################################

# from https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc940063(v%3dtechnet.10)
UNIQUE_NAMES = {
    b'\x00': 'Workstation Service',
    b'\x03': 'Messenger Service',
    b'\x06': 'RAS Server Service',
    b'\x1F': 'NetDDE Service',
    b'\x20': 'Server Service',
    b'\x21': 'RAS Client Service',
    b'\xBE': 'Network Monitor Agent',
    b'\xBF': 'Network Monitor Application',
    b'\x03': 'Messenger Service',
    b'\x1D': 'Master Browser',
    b'\x1B': 'Domain Master Browser',
}
GROUP_NAMES = {
    b'\x00': 'Domain Name',
    b'\x1C': 'Domain Controllers',
    b'\x1E': 'Browser Service Elections',
    # Master Browser
}


NetBIOS_ITEM_TYPE = {
    b'\x01\x00':'NetBIOS computer name',
    b'\x02\x00':'NetBIOS domain name',
    b'\x03\x00':'DNS computer name',
    b'\x04\x00':'DNS domain name',
    b'\x05\x00':'DNS tree name',
    # b'\x06\x00':'',
    b'\x07\x00':'Time stamp',
}


def to_ips(raw):
    # if '/' in raw:
    #     addr, mask = raw.split('/')
    #     mask = int(mask)

    #     bin_addr = ''.join([ (8 - len(bin(int(i))[2:])) * '0' + bin(int(i))[2:] for i in  addr.split('.')])
    #     start = bin_addr[:mask] + (32 - mask) * '0'
    #     end = bin_addr[:mask] + (32 - mask) * '1'
    #     bin_addrs = [ (32 - len(bin(int(i))[2:])) * '0' + bin(i)[2:] for i in range(int(start, 2), int(end, 2) + 1)]

    #     dec_addrs = ['.'.join([str(int(bin_addr[8*i:8*(i+1)], 2)) for i in range(0, 4)]) for bin_addr in bin_addrs]                
    #     # print(dec_addrs)
    #     return dec_addrs
    # elif '-' in raw:
    #     addr, end = raw.split('-')
    #     end = int(end)
    #     start = int(addr.split('.')[3])
    #     prefix = '.'.join(addr.split('.')[:-1])
    #     addrs = [ prefix + '.' + str(i) for i in range(start, end + 1) ]
    #     # print(addrs)
    #     return addrs
    # else:
    #     return [raw]
        # 预处理,先处理干扰
        ips = raw
        ips_list = []
        ips = ips.strip()
        
        # (1)单ip
        if r"/" not in ips and r"-" not in ips and r"," not in ips:   # 单ip
            ips_list.append(ips)
            return ips_list

        # (2)几个ip  192.168.1.4,5,66,222
        elif r"/" not in ips and r"-" not in ips and r"," in ips:
            ip_base = ips.rsplit(".", 1)[0]             # 提取 192.168.1
            ip_other = ips.rsplit(".", 1)[1].split(",") # 提取 4,5,66,222 成list
            for other in ip_other:
                new_ip = ip_base + "." + other
                ips_list.append(new_ip)
            return ips_list

        # (3)定ip区间      192.168.1.9 - 192.160.1.10,172.0.0.1-172.8.1.1
        elif r"/" not in ips and r"-" in ips or r"," in ips:
            if r"," in ips:
                a_list = []
                for x in ips.split(","):
                    ip_start = x.split("-")[0].strip()
                    ip_end = x.split("-")[1].strip()
                    a_list.extend(IP_Conversion().iplist(ip_start, ip_end))
                return a_list
            elif r"," not in ips:
                ip_start = ips.split("-")[0].strip()
                ip_end = ips.split("-")[1].strip()
                return IP_Conversion().iplist(ip_start, ip_end)

        # (4)c段,b段,    192.168.1.0/24
        elif r"/" in ips and r"-" not in ips and r"," not in ips:
            # ip_base = ips.rsplit(".", 1)[0]             # 提取 192.168.1
            # ip_qujian = ips.rsplit(".", 1)[1]           # 提取 0/24
            # min_ip = ip_base + "." + ip_qujian.split("/")[0]
            # max_ip = ip_base + "." + ip_qujian.split("/")[1]
            
            return [str(ip) for ip in ipaddress.ip_network(ips)]



def nbns_name(addr):
    msg = ''
    data = b'ff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00 CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00!\x00\x01'
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.settimeout(2)
        s.sendto(data, (addr, 137))
        rep = s.recv(2000)
        if isinstance(rep, str):
            rep = bytes(rep)

        num = ord(rep[56:57].decode()) #  num of the answer
        data = rep[57:]  # start of the answer

        group, unique = '', ''
        # print('--------------------------')
        msg += '--------------------------' + '\n'
        for i in range(num):
            name = data[18 * i:18 *i + 15].decode()
            flag_bit = bytes(data[18 * i + 15:18 *i + 16])
            # print(type(flag_bit))
            if flag_bit in GROUP_NAMES and flag_bit != b'\x00':  # G TODO
                # print('%s\t%s\t%s' % (name, 'G', GROUP_NAMES[flag_bit]))
                msg += '%s\t%s\t%s' % (name, 'G', GROUP_NAMES[flag_bit]) + '\n'
                pass
            elif flag_bit in UNIQUE_NAMES and flag_bit != b'\x00':  # U 
                # print('%s\t%s\t%s' % (name, 'U', UNIQUE_NAMES[flag_bit]))
                msg += '%s\t%s\t%s' % (name, 'U', UNIQUE_NAMES[flag_bit]) + '\n'
                pass
            elif flag_bit in b'\x00':
                name_flags = data[18 * i + 16:18 *i + 18]
                if ord(name_flags[0:1])>=128:
                    group = name.strip()
                    # print('%s\t%s\t%s' % (name, 'G', GROUP_NAMES[flag_bit]))
                    msg += '%s\t%s\t%s' % (name, 'G', GROUP_NAMES[flag_bit]) + '\n'
                else:
                    unique = name
                    # print('%s\t%s\t%s' % (name, 'U', UNIQUE_NAMES[flag_bit]))
                    msg += '%s\t%s\t%s' % (name, 'U', UNIQUE_NAMES[flag_bit]) + '\n'
            else:
                # print('%s\t-\t-' % name)
                msg += '%s\t-\t-' % name + '\n'
                pass
        # print('--------------------------')
        msg += '--------------------------' + '\n'
        # print('%s\\%s' % (group, unique))
        msg = '%s\\%s' % (group, unique) + '\n' + msg

        return { 'group':group, 'unique':unique, 'msg':msg }
    
    except socket.error as e:
        # print(e)
        # print('Fail to Connect to UDP 137')
        return False


def netbios_encode(src):  
    # from http://weaponx.site/2017/06/07/NETBIOS%E4%B8%BB%E6%9C%BA%E5%90%8D%E7%BC%96%E7%A0%81%E7%AE%97%E6%B3%95/
    src = src.ljust(16,"\x20")
    names = []
    for c in src:
        char_ord = ord(c)
        high_4_bits = char_ord >> 4
        low_4_bits = char_ord & 0x0f
        names.append(high_4_bits)
        names.append(low_4_bits)
    
    res = b''
    for name in names:
        # print(name)
        res += chr(0x41 + name).encode()

    return res


def smb_detect(addr, port=139):
    msg = ''

    if port ==139:
        nbns_result = nbns_name(addr)
        if not nbns_result:
            return
        elif not nbns_result['unique']:
            # print('nbns_result_error')
            msg += 'nbns_result_error'
            lock.acquire()
            print(addr + '    ' + msg)
            lock.release()
            return
        # print('%s\\%s' % (nbns_result['group'],nbns_result['unique']))
        msg += nbns_result['msg']

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(2)
    try:
        s.connect((addr, port))
    except Exception as e:
        # print('%s:%d %s' % (addr, port, e))
        lock.acquire()
        print(addr + '    ' + msg)
        lock.release()
        return

    if port == 139:
        name = netbios_encode(nbns_result['unique'])
        # print(name)
        payload0 = b'\x81\x00\x00D ' + name  + b'\x00 EOENEBFACACACACACACACACACACACACA\x00'
        
        s.send(payload0)
        s.recv(1024)
    
    payload1 = b'\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x18\x53\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00\x00\x62\x00\x02\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00'
    payload2 = b'\x00\x00\x01\x0a\xff\x53\x4d\x42\x73\x00\x00\x00\x00\x18\x07\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x40\x00\x0c\xff\x00\x0a\x01\x04\x41\x32\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x00\x00\x00\x00\xd4\x00\x00\xa0\xcf\x00\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x02\xce\x0e\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x33\x00\x37\x00\x39\x00\x30\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x32\x00\x00\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x35\x00\x2e\x00\x32\x00\x00\x00\x00\x00'
    
    s.send(payload1)
    s.recv(1024)

    s.send(payload2)

    # TODO handle to rep
    ret = s.recv(1024)
    length = ord(ret[43:44]) + ord(ret[44:45]) * 256
    os_version = ret[47 + length:]
    # print(os_version.replace(b'\x00\x00', b'|').replace(b'\x00', b'').decode('UTF-8', errors='ignore'))
    msg += os_version.replace(b'\x00\x00', b'|').replace(b'\x00', b'').decode('UTF-8', errors='ignore') + '\n'

    start = ret.find(b'NTLMSSP')
    # print(ret[start:].replace(b'\x00', b''))

    length = ord(ret[start + 40:start + 41]) + ord(ret[start + 41:start + 42]) * 256 
    # print('length', length)
    # print('max_length', ret[start + 40:start + 44])
    # print('offset', ret[start + 44:start + 48])
    offset = ord(ret[start + 44:start + 45])

    # 中间有 8 位
    # print('Major Version: %d' % ord(ret[start + 48:start + 49]))
    msg += 'Major Version: %d' % ord(ret[start + 48:start + 49]) + '\n'
    # print('Minor Version: %d' % ord(ret[start + 49:start + 50]))
    msg += 'Minor Version: %d' % ord(ret[start + 49:start + 50]) + '\n'
    # print('Bulid Number: %d' %  (ord(ret[start + 50:start + 51]) + 256 * ord(ret[start + 51:start + 52])))
    msg += 'Bulid Number: %d' %  (ord(ret[start + 50:start + 51]) + 256 * ord(ret[start + 51:start + 52])) + '\n'
    # 有 3 字节是空的
    # print('NTLM Current Revision: %d' % (ord(ret[start + 55:start + 56]) ) )
    msg += 'NTLM Current Revision: %d' % (ord(ret[start + 55:start + 56]) ) + '\n' 


    index = start + offset

    while index < start + offset + length:
        item_type = ret[index:index + 2]
        # print('item type', item_type)
        item_length = ord(ret[index + 2:index +3]) + ord(ret[index + 3:index +4]) * 256  
        # print('item length', item_length)
        item_content = ret[index + 4: index + 4 + item_length].replace(b'\x00', b'')
        if item_type == b'\x07\x00':
            
            if sys.version_info[0] == 3:
                timestamp = int.from_bytes(item_content, byteorder='little')  # only py > 3.2
            elif sys.version_info[0] == 2:  # for py2 from https://www.aliyun.com/jiaocheng/445198.html 
                timestamp = int(''.join(reversed(item_content)).encode('hex'), 16) 

            # from https://www.e-learn.cn/content/wangluowenzhang/211641
            EPOCH_AS_FILETIME = 116444736000000000;  HUNDREDS_OF_NANOSECONDS = 10000000
            timestamp = datetime.fromtimestamp((timestamp - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS)

            # print('%s: %s' % (NetBIOS_ITEM_TYPE[item_type], timestamp))
            msg += '%s: %s' % (NetBIOS_ITEM_TYPE[item_type], timestamp) + '\n'
        elif item_type in NetBIOS_ITEM_TYPE:
            # print('%s: %s' % (NetBIOS_ITEM_TYPE[item_type], item_content.decode(errors='ignore')))
            msg += '%s: %s' % (NetBIOS_ITEM_TYPE[item_type], item_content.decode(errors='ignore')) + '\n'
        elif item_type == b'\x00\x00':  #  end
            break
        else:
            # print('Unknown: %s' % (item_content))
            msg += 'Unknown: %s' % (item_content) + '\n'
        # print(ret[index + 4 + item_length:])
        index +=  4 + item_length
    
    # lock.acquire()
    print(addr + '    ' +  msg)
    # lock.release()
 #################################################################################


if __name__ == '__main__':

    parser = argparse.ArgumentParser(description="[*] python NetBIOS scan [*]")
    parser.add_argument("--ip", type=str, help=" ips: --ip 192.168.0/24 or 192.168.0.1-192.168.0.254 or 192.168.0.1-192.168.0.10,192.168.1.1-192.168.1.100")
    parser.add_argument("--port", type=str, help=" port: --port 445 [default 139]")
    parser.add_argument("-t", type=str, help=" threads: -t 20")

    # 指定扫描的线程数,默认10个线程
    args = parser.parse_args()
    # pool = ThreadPool(10)
    if args.t:
        pool = ThreadPool(int(args.t))
    else:
        pool = ThreadPool(10)



    if not args.port:
        addrs = to_ips(args.ip)
        #########################################
        for addr in addrs:
            # print(addr, type(addr))
            pool.apply_async(smb_detect, (addr, 139))
        pool.close()
        pool.join()
        
    else:
        addrs = to_ips(args.ip)
        #########################################
        for addr in addrs:
            pool.apply_async(smb_detect, (addr, int(args.port)))
        pool.close()
        pool.join()



标签:name,ips,python,ip,nbtscan,start,print,x00
From: https://www.cnblogs.com/startstart/p/16909564.html

相关文章

  • Python学习笔记:删除多级索引
    在Python中使用stack/unstack/melt/pivot_talbe等函数进行聚合之后,计算得到的结果具有多层索引。一般情况下可以通过额外指定columns或者通过reset_index()可重置......
  • PYTHON_numpy
    C数组中数据类型一致;python列表可不一致,但numpy数组array中数据类型需一致如传进来的包含不同类型,则自动统一为同一类型,优先级:str>float>int1. array():importnum......
  • python算法题1:给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标
    题目:给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数。 函数应该返回这两个下标值index1和index2,其中index1必须小于index2。 说明: ......
  • python中循环值的处理
    以python3为例关于循环中经常出现赋值问题的几个形式(要赋值的变量a,循环变量b)就比如foriinrange(n):相对于b来说 1:a+=b......
  • python-解析式
     列表解析式(ListComprehension) 列表解析式的优势比循环更节省时间和空间。需要更少的代码行。可将迭代语句转换为公式。 公式#不加条件[返回值for元素......
  • python 打包 exe程序 ——注意事项以及运行exe报错【ModuleNotFoundError: No module
    只说打包成单文件——【仅针对win系统】步骤:1、写脚本2、在当前环境下安装pyinstaller3、打开终端界面【terminal】(1)切换到当前程序所在路径(2)运行打包命令: ......
  • 二进制安装docker的shell脚本和python脚本
    1.python脚本点击查看代码#!/bin/pythonimportosfrompathlibimportPathimporttarfileimportshutilimportgrpdefAddGroup():group_name="docker"......
  • PYTHON_pandas
    1.读写文件importpandasaspddata=pd.read_excel('C:/.../stock.xlsx')data2=pd.read_csv('C:/.../stock.csv')2.展示前n行data.head(5)3.基本信息data......
  • python进程
    今日内容概要同步与异步阻塞与非阻塞创建进程的多种方式进程join方法进程间数据隔离进程间通信之IPC机制进程对象诸多方法生产者消费者模型互斥锁今日内容......
  • Python单行代码
    1一行For循环#For循环在一行mylist=[200,300,400,500]#正常方式result=[]forxinmylist:ifx>250:result.append(x)prin......