296 lines
11 KiB
Python
296 lines
11 KiB
Python
|
# This file is part of Scapy
|
||
|
# See http://www.secdev.org/projects/scapy for more information
|
||
|
# Copyright (C) Philippe Biondi <phil@secdev.org>
|
||
|
# This program is published under a GPLv2 license
|
||
|
|
||
|
"""
|
||
|
NetBIOS over TCP/IP
|
||
|
|
||
|
[RFC 1001/1002]
|
||
|
"""
|
||
|
|
||
|
import struct
|
||
|
|
||
|
from scapy.packet import Packet, bind_layers
|
||
|
from scapy.fields import BitEnumField, BitField, ByteEnumField, ByteField, \
|
||
|
IPField, IntField, NetBIOSNameField, ShortEnumField, ShortField, \
|
||
|
StrFixedLenField, XShortField
|
||
|
from scapy.layers.inet import UDP, TCP
|
||
|
from scapy.layers.l2 import SourceMACField
|
||
|
|
||
|
|
||
|
class NetBIOS_DS(Packet):
|
||
|
name = "NetBIOS datagram service"
|
||
|
fields_desc = [
|
||
|
ByteEnumField("type", 17, {17: "direct_group"}),
|
||
|
ByteField("flags", 0),
|
||
|
XShortField("id", 0),
|
||
|
IPField("src", "127.0.0.1"),
|
||
|
ShortField("sport", 138),
|
||
|
ShortField("len", None),
|
||
|
ShortField("ofs", 0),
|
||
|
NetBIOSNameField("srcname", ""),
|
||
|
NetBIOSNameField("dstname", ""),
|
||
|
]
|
||
|
|
||
|
def post_build(self, p, pay):
|
||
|
p += pay
|
||
|
if self.len is None:
|
||
|
tmp_len = len(p) - 14
|
||
|
p = p[:10] + struct.pack("!H", tmp_len) + p[12:]
|
||
|
return p
|
||
|
|
||
|
# ShortField("length",0),
|
||
|
# ShortField("Delimiter",0),
|
||
|
# ByteField("command",0),
|
||
|
# ByteField("data1",0),
|
||
|
# ShortField("data2",0),
|
||
|
# ShortField("XMIt",0),
|
||
|
# ShortField("RSPCor",0),
|
||
|
# StrFixedLenField("dest","",16),
|
||
|
# StrFixedLenField("source","",16),
|
||
|
#
|
||
|
# ]
|
||
|
#
|
||
|
|
||
|
# NetBIOS
|
||
|
|
||
|
|
||
|
_NETBIOS_SUFFIXES = {
|
||
|
0x4141: "workstation",
|
||
|
0x4141 + 0x03: "messenger service",
|
||
|
0x4141 + 0x200: "file server service",
|
||
|
0x4141 + 0x10b: "domain master browser",
|
||
|
0x4141 + 0x10c: "domain controller",
|
||
|
0x4141 + 0x10e: "browser election service"
|
||
|
}
|
||
|
|
||
|
_NETBIOS_QRTYPES = {
|
||
|
0x20: "NB",
|
||
|
0x21: "NBSTAT"
|
||
|
}
|
||
|
|
||
|
_NETBIOS_QRCLASS = {
|
||
|
1: "INTERNET"
|
||
|
}
|
||
|
|
||
|
_NETBIOS_RNAMES = {
|
||
|
0xC00C: "Label String Pointer to QUESTION_NAME"
|
||
|
}
|
||
|
|
||
|
_NETBIOS_OWNER_MODE_TYPES = {
|
||
|
0: "B node",
|
||
|
1: "P node",
|
||
|
2: "M node",
|
||
|
3: "H node"
|
||
|
}
|
||
|
|
||
|
_NETBIOS_GNAMES = {
|
||
|
0: "Unique name",
|
||
|
1: "Group name"
|
||
|
}
|
||
|
|
||
|
# Name Query Request
|
||
|
# Node Status Request
|
||
|
|
||
|
|
||
|
class NBNSQueryRequest(Packet):
|
||
|
name = "NBNS query request"
|
||
|
fields_desc = [ShortField("NAME_TRN_ID", 0),
|
||
|
ShortField("FLAGS", 0x0110),
|
||
|
ShortField("QDCOUNT", 1),
|
||
|
ShortField("ANCOUNT", 0),
|
||
|
ShortField("NSCOUNT", 0),
|
||
|
ShortField("ARCOUNT", 0),
|
||
|
NetBIOSNameField("QUESTION_NAME", "windows"),
|
||
|
ShortEnumField("SUFFIX", 0x4141, _NETBIOS_SUFFIXES),
|
||
|
ByteField("NULL", 0),
|
||
|
ShortEnumField("QUESTION_TYPE", 0x20, _NETBIOS_QRTYPES),
|
||
|
ShortEnumField("QUESTION_CLASS", 1, _NETBIOS_QRCLASS)]
|
||
|
|
||
|
# Name Registration Request
|
||
|
# Name Refresh Request
|
||
|
# Name Release Request or Demand
|
||
|
|
||
|
|
||
|
class NBNSRequest(Packet):
|
||
|
name = "NBNS request"
|
||
|
fields_desc = [ShortField("NAME_TRN_ID", 0),
|
||
|
ShortField("FLAGS", 0x2910),
|
||
|
ShortField("QDCOUNT", 1),
|
||
|
ShortField("ANCOUNT", 0),
|
||
|
ShortField("NSCOUNT", 0),
|
||
|
ShortField("ARCOUNT", 1),
|
||
|
NetBIOSNameField("QUESTION_NAME", "windows"),
|
||
|
ShortEnumField("SUFFIX", 0x4141, _NETBIOS_SUFFIXES),
|
||
|
ByteField("NULL", 0),
|
||
|
ShortEnumField("QUESTION_TYPE", 0x20, _NETBIOS_QRTYPES),
|
||
|
ShortEnumField("QUESTION_CLASS", 1, _NETBIOS_QRCLASS),
|
||
|
ShortEnumField("RR_NAME", 0xC00C, _NETBIOS_RNAMES),
|
||
|
ShortEnumField("RR_TYPE", 0x20, _NETBIOS_QRTYPES),
|
||
|
ShortEnumField("RR_CLASS", 1, _NETBIOS_QRCLASS),
|
||
|
IntField("TTL", 0),
|
||
|
ShortField("RDLENGTH", 6),
|
||
|
BitEnumField("G", 0, 1, _NETBIOS_GNAMES),
|
||
|
BitEnumField("OWNER_NODE_TYPE", 00, 2,
|
||
|
_NETBIOS_OWNER_MODE_TYPES),
|
||
|
BitEnumField("UNUSED", 0, 13, {0: "Unused"}),
|
||
|
IPField("NB_ADDRESS", "127.0.0.1")]
|
||
|
|
||
|
# Name Query Response
|
||
|
# Name Registration Response
|
||
|
|
||
|
|
||
|
class NBNSQueryResponse(Packet):
|
||
|
name = "NBNS query response"
|
||
|
fields_desc = [ShortField("NAME_TRN_ID", 0),
|
||
|
ShortField("FLAGS", 0x8500),
|
||
|
ShortField("QDCOUNT", 0),
|
||
|
ShortField("ANCOUNT", 1),
|
||
|
ShortField("NSCOUNT", 0),
|
||
|
ShortField("ARCOUNT", 0),
|
||
|
NetBIOSNameField("RR_NAME", "windows"),
|
||
|
ShortEnumField("SUFFIX", 0x4141, _NETBIOS_SUFFIXES),
|
||
|
ByteField("NULL", 0),
|
||
|
ShortEnumField("QUESTION_TYPE", 0x20, _NETBIOS_QRTYPES),
|
||
|
ShortEnumField("QUESTION_CLASS", 1, _NETBIOS_QRCLASS),
|
||
|
IntField("TTL", 0x493e0),
|
||
|
ShortField("RDLENGTH", 6),
|
||
|
ShortField("NB_FLAGS", 0),
|
||
|
IPField("NB_ADDRESS", "127.0.0.1")]
|
||
|
|
||
|
# Name Query Response (negative)
|
||
|
# Name Release Response
|
||
|
|
||
|
|
||
|
class NBNSQueryResponseNegative(Packet):
|
||
|
name = "NBNS query response (negative)"
|
||
|
fields_desc = [ShortField("NAME_TRN_ID", 0),
|
||
|
ShortField("FLAGS", 0x8506),
|
||
|
ShortField("QDCOUNT", 0),
|
||
|
ShortField("ANCOUNT", 1),
|
||
|
ShortField("NSCOUNT", 0),
|
||
|
ShortField("ARCOUNT", 0),
|
||
|
NetBIOSNameField("RR_NAME", "windows"),
|
||
|
ShortEnumField("SUFFIX", 0x4141, _NETBIOS_SUFFIXES),
|
||
|
ByteField("NULL", 0),
|
||
|
ShortEnumField("RR_TYPE", 0x20, _NETBIOS_QRTYPES),
|
||
|
ShortEnumField("RR_CLASS", 1, _NETBIOS_QRCLASS),
|
||
|
IntField("TTL", 0),
|
||
|
ShortField("RDLENGTH", 6),
|
||
|
BitEnumField("G", 0, 1, _NETBIOS_GNAMES),
|
||
|
BitEnumField("OWNER_NODE_TYPE", 00, 2,
|
||
|
_NETBIOS_OWNER_MODE_TYPES),
|
||
|
BitEnumField("UNUSED", 0, 13, {0: "Unused"}),
|
||
|
IPField("NB_ADDRESS", "127.0.0.1")]
|
||
|
|
||
|
# Node Status Response
|
||
|
|
||
|
|
||
|
class NBNSNodeStatusResponse(Packet):
|
||
|
name = "NBNS Node Status Response"
|
||
|
fields_desc = [ShortField("NAME_TRN_ID", 0),
|
||
|
ShortField("FLAGS", 0x8500),
|
||
|
ShortField("QDCOUNT", 0),
|
||
|
ShortField("ANCOUNT", 1),
|
||
|
ShortField("NSCOUNT", 0),
|
||
|
ShortField("ARCOUNT", 0),
|
||
|
NetBIOSNameField("RR_NAME", "windows"),
|
||
|
ShortEnumField("SUFFIX", 0x4141, _NETBIOS_SUFFIXES),
|
||
|
ByteField("NULL", 0),
|
||
|
ShortEnumField("RR_TYPE", 0x21, _NETBIOS_QRTYPES),
|
||
|
ShortEnumField("RR_CLASS", 1, _NETBIOS_QRCLASS),
|
||
|
IntField("TTL", 0),
|
||
|
ShortField("RDLENGTH", 83),
|
||
|
ByteField("NUM_NAMES", 1)]
|
||
|
|
||
|
# Service for Node Status Response
|
||
|
|
||
|
|
||
|
class NBNSNodeStatusResponseService(Packet):
|
||
|
name = "NBNS Node Status Response Service"
|
||
|
fields_desc = [StrFixedLenField("NETBIOS_NAME", "WINDOWS ", 15),
|
||
|
ByteEnumField("SUFFIX", 0, {0: "workstation",
|
||
|
0x03: "messenger service",
|
||
|
0x20: "file server service",
|
||
|
0x1b: "domain master browser",
|
||
|
0x1c: "domain controller",
|
||
|
0x1e: "browser election service"
|
||
|
}),
|
||
|
ByteField("NAME_FLAGS", 0x4),
|
||
|
ByteEnumField("UNUSED", 0, {0: "unused"})]
|
||
|
|
||
|
# End of Node Status Response packet
|
||
|
|
||
|
|
||
|
class NBNSNodeStatusResponseEnd(Packet):
|
||
|
name = "NBNS Node Status Response"
|
||
|
fields_desc = [SourceMACField("MAC_ADDRESS"),
|
||
|
BitField("STATISTICS", 0, 57 * 8)]
|
||
|
|
||
|
# Wait for Acknowledgement Response
|
||
|
|
||
|
|
||
|
class NBNSWackResponse(Packet):
|
||
|
name = "NBNS Wait for Acknowledgement Response"
|
||
|
fields_desc = [ShortField("NAME_TRN_ID", 0),
|
||
|
ShortField("FLAGS", 0xBC07),
|
||
|
ShortField("QDCOUNT", 0),
|
||
|
ShortField("ANCOUNT", 1),
|
||
|
ShortField("NSCOUNT", 0),
|
||
|
ShortField("ARCOUNT", 0),
|
||
|
NetBIOSNameField("RR_NAME", "windows"),
|
||
|
ShortEnumField("SUFFIX", 0x4141, _NETBIOS_SUFFIXES),
|
||
|
ByteField("NULL", 0),
|
||
|
ShortEnumField("RR_TYPE", 0x20, _NETBIOS_QRTYPES),
|
||
|
ShortEnumField("RR_CLASS", 1, _NETBIOS_QRCLASS),
|
||
|
IntField("TTL", 2),
|
||
|
ShortField("RDLENGTH", 2),
|
||
|
BitField("RDATA", 10512, 16)] # 10512=0010100100010000
|
||
|
|
||
|
|
||
|
class NBTDatagram(Packet):
|
||
|
name = "NBT Datagram Packet"
|
||
|
fields_desc = [ByteField("Type", 0x10),
|
||
|
ByteField("Flags", 0x02),
|
||
|
ShortField("ID", 0),
|
||
|
IPField("SourceIP", "127.0.0.1"),
|
||
|
ShortField("SourcePort", 138),
|
||
|
ShortField("Length", 272),
|
||
|
ShortField("Offset", 0),
|
||
|
NetBIOSNameField("SourceName", "windows"),
|
||
|
ShortEnumField("SUFFIX1", 0x4141, _NETBIOS_SUFFIXES),
|
||
|
ByteField("NULL", 0),
|
||
|
NetBIOSNameField("DestinationName", "windows"),
|
||
|
ShortEnumField("SUFFIX2", 0x4141, _NETBIOS_SUFFIXES),
|
||
|
ByteField("NULL", 0)]
|
||
|
|
||
|
|
||
|
class NBTSession(Packet):
|
||
|
name = "NBT Session Packet"
|
||
|
fields_desc = [ByteEnumField("TYPE", 0, {0x00: "Session Message",
|
||
|
0x81: "Session Request",
|
||
|
0x82: "Positive Session Response",
|
||
|
0x83: "Negative Session Response",
|
||
|
0x84: "Retarget Session Response",
|
||
|
0x85: "Session Keepalive"}),
|
||
|
BitField("RESERVED", 0x00, 7),
|
||
|
BitField("LENGTH", 0, 17)]
|
||
|
|
||
|
|
||
|
bind_layers(UDP, NBNSQueryRequest, dport=137)
|
||
|
bind_layers(UDP, NBNSRequest, dport=137)
|
||
|
bind_layers(UDP, NBNSQueryResponse, sport=137)
|
||
|
bind_layers(UDP, NBNSQueryResponseNegative, sport=137)
|
||
|
bind_layers(UDP, NBNSNodeStatusResponse, sport=137)
|
||
|
bind_layers(NBNSNodeStatusResponse, NBNSNodeStatusResponseService, )
|
||
|
bind_layers(NBNSNodeStatusResponse, NBNSNodeStatusResponseService, )
|
||
|
bind_layers(NBNSNodeStatusResponseService, NBNSNodeStatusResponseService, )
|
||
|
bind_layers(NBNSNodeStatusResponseService, NBNSNodeStatusResponseEnd, )
|
||
|
bind_layers(UDP, NBNSWackResponse, sport=137)
|
||
|
bind_layers(UDP, NBTDatagram, dport=138)
|
||
|
bind_layers(TCP, NBTSession, dport=445)
|
||
|
bind_layers(TCP, NBTSession, sport=445)
|
||
|
bind_layers(TCP, NBTSession, dport=139)
|
||
|
bind_layers(TCP, NBTSession, sport=139)
|