NetBIOS,Network Basic Input/Output System的缩写,一般指用于局域网通信的一套API,相关RFC文档包括 RFC 1001, RFC 1002. RFC 1001主要对NetBIOS及相关协议和服务进行解释说明,RFC 1002给出了相关协议和服务的数据组包格式。
NetBIOS提供三种软件服务:
Service Name | Port | Protocol | Short Name |
---|---|---|---|
NetBIOS Name service | 137 | UDP/TCP | NBNS |
NetBIOS Datagram | 138 | UDP | NBND |
NetBIOS Session service | 139 | TCP | NBSS |
本文主要描述最常见的NBNS
.
NBNS是NetBIOS name service的缩写,是NetBIOS的命名服务,用于将NetBIOS名称映射到IP地址上,是NetBIOS-over-TCP(NBT)协议族的一份子。NBNS是动态DNS的一种,Microsoft的NBNS实现称为WINS
。路由器可以通过发送NBNS状态请求以获取设备名,windows PC 接收到后通过WINS或将本地缓存发送命名信息给路由器。
NBNS的数据报文格式在RFC 1002 Ch4.2中定义,包含以下信息
> 4.2.1 GENERAL FORMAT OF NAME SERVICE PACKETS
> 4.2.1.1 HEADER
> 4.2.1.2 QUESTION SECTION
> 4.2.1.3 RESOURCE RECORD
> 4.2.2 NAME REGISTRATION REQUEST
4.2.3 NAME OVERWRITE REQUEST & DEMAND
4.2.4 NAME REFRESH REQUEST
> 4.2.5 POSITIVE NAME REGISTRATION RESPONSE
4.2.6 NEGATIVE NAME REGISTRATION RESPONSE
4.2.7 END-NODE CHALLENGE REGISTRATION RESPONSE
4.2.8 NAME CONFLICT DEMAND
4.2.9 NAME RELEASE REQUEST & DEMAND
4.2.10 POSITIVE NAME RELEASE RESPONSE
4.2.11 NEGATIVE NAME RELEASE RESPONSE
4.2.12 NAME QUERY REQUEST
4.2.13 POSITIVE NAME QUERY RESPONSE
4.2.14 NEGATIVE NAME QUERY RESPONSE
4.2.15 REDIRECT NAME QUERY RESPONSE
4.2.16 WAIT FOR ACKNOWLEDGEMENT (WACK) RESPONSE
> 4.2.17 NODE STATUS REQUEST
> 4.2.18 NODE STATUS RESPONSE
本文主要介绍列表中>
开头的部分。
NetBIOS数据包的通用格式如下:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ ------ ------- +
| HEADER |
+ ------ ------- +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ QUESTION ENTRIES /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ ANSWER RESOURCE RECORDS /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ AUTHORITY RESOURCE RECORDS /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ ADDITIONAL RESOURCE RECORDS /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
下面先来看HEADER
信息。
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NAME_TRN_ID | OPCODE | NM_FLAGS | RCODE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| QDCOUNT | ANCOUNT |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NSCOUNT | ARCOUNT |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
关于OPCODE,如下表所示:
0 1 2 3 4
+---+---+---+---+---+
| R | OPCODE |
+---+---+---+---+---+
关于NM_FLAGS, 如下表所示:
0 1 2 3 4 5 6
+---+---+---+---+---+---+---+
|AA |TC |RD |RA | 0 | 0 | B |
+---+---+---+---+---+---+---+
RA
与RD
的原文解释如下:
RA
3 Recursion Available Flag.
Only valid in responses from a NetBIOS Name Server – must be zero in all other responses.
If one (1) then the NBNS supports recursive query, registration, and release.
If zero (0) then the end-node must iterate for query and challenge for registration.
RD
6 Recursion Desired Flag.
May only be set on a request to a NetBIOS Name Server.
The NBNS will copy its state into the response packet.
If one (1) the NBNS will iterate on the query, registration, or release.
大致意思是,对于请求、注册和释放,包含递归发送和迭代发送两种方式。RA
为1说明支持递归,为0说明只能迭代,表征的是一种能力;RD
则是说明具体以什么方式发送,如果为1则代表迭代,表征的是一个具体动作,这个值在响应包中会从请求包中复制得到。
NBNS的请求数据段格式如下:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ QUESTION_NAME /
/ /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| QUESTION_TYPE | QUESTION_CLASS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
NBNS的资源数据段可以存在于请求报文和应答报文中,数据格式如下:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ RR_NAME /
/ /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RR_TYPE | RR_CLASS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TTL |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RDLENGTH | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
/ /
/ RDATA /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
QUESTION_NAME
一致RR_TYPE
和RR_CLASS
的数据信息,包含具体的NetBIOS name.针对RR_TYPE为NB的情况,RDATA的NB_FLAGS
部分的数据格式如下:
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| G | ONT | RESERVED |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
以上便是HEADER, QUESTION SECTION以及RESOURCE RECORD 3个部分的主要内容,所有NBNS相关的请求包和响应包都依循以上格式,具体的信息细节则依情况而定。
名称注册请求格式如下:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NAME_TRN_ID |0| 0x5 |0|0|1|0|0 0|B| 0x0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0001 | 0x0000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0000 | 0x0001 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ QUESTION_NAME /
/ /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NB (0x0020) | IN (0x0001) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ RR_NAME /
/ /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NB (0x0020) | IN (0x0001) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TTL |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0006 | NB_FLAGS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NB_ADDRESS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
可以和上面介绍的进行一一核对,头部信息的OPCODE
为0|0x5
, R为0说明是请求包,0x5说明是registration,即注册信息请求;NM_FLAGSAA|TC|RD|RA|0|0|B
为0|0|1|0|0|0|B
, 因为是请求包,所以AA=0
;默认支持注册信息请求包含query和additional两部分信息,所以QDCOUNT
和ARCOUND
均为1,其余两个计数值为0。
HEADER往后是QUESTION_NAME,NB (0x0020)说明名称请求类型为NB
, 请求类别通常均为0x0001, 固定不变。
再往后是TTL,固定的0x0006表征NB_FLAGS和NB_ADDRESS的总长为6个字节。其中NB_ADDRESS就是要注册的地址,而NB_FLAGS标记了这个名称的唯一性和数据包的类型(广播还是单播)。
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| 0x0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0000 | 0x0001 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0000 | 0x0000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ RR_NAME /
/ /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NB (0x0020) | IN (0x0001) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TTL |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0006 | NB_FLAGS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NB_ADDRESS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
在Registration response中,HEADER的R
和AA
都变成了1,代表响应包;B
为0代表单播包形式发送;RA
与RD
均为1,说明终端支持递归请求、注册和释放,但是会以迭代的方式进行请求、注册或释放。后面部分与请求注册的信息一致。
Node status request也是路由器获取PC设备名称的常用方式,其请求格式如下:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NAME_TRN_ID |0| 0x0 |0|0|0|0|0 0|B| 0x0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0001 | 0x0000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0000 | 0x0000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ QUESTION_NAME /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NBSTAT (0x0021) | IN (0x0001) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
与registration相比,RR_TYPE由NB变味了NBSTAT,少了Additional部分,仅仅包含请求信息。
Node status response的数据包格式如下:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NAME_TRN_ID |1| 0x0 |1|0|0|0|0 0|0| 0x0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0000 | 0x0001 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0000 | 0x0000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ RR_NAME /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NBSTAT (0x0021) | IN (0x0001) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x00000000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RDLENGTH | NUM_NAMES | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| |
+ +
/ NODE_NAME ARRAY /
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
/ STATISTICS /
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
节点状态信息很多,其中NUM_NAMES
表示后面紧随的节点名称数组长度,每个数组元素包含18字节:16字节的名称和2个字节的NAME_FLAGS. NAME_FLAGS格式如下:
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| G | ONT |DRG|CNF|ACT|PRM| RESERVED |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
STATISTICS字段的格式如下:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UNIT_ID (Unique unit ID) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UNIT_ID,continued | JUMPERS | TEST_RESULT |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VERSION_NUMBER | PERIOD_OF_STATISTICS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NUMBER_OF_CRCs | NUMBER_ALIGNMENT_ERRORS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NUMBER_OF_COLLISIONS | NUMBER_SEND_ABORTS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NUMBER_GOOD_SENDS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NUMBER_GOOD_RECEIVES |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NUMBER_RETRANSMITS | NUMBER_NO_RESOURCE_CONDITIONS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NUMBER_FREE_COMMAND_BLOCKS | TOTAL_NUMBER_COMMAND_BLOCKS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|MAX_TOTAL_NUMBER_COMMAND_BLOCKS| NUMBER_PENDING_SESSIONS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAX_NUMBER_PENDING_SESSIONS | MAX_TOTAL_SESSIONS_POSSIBLE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SESSION_DATA_PACKET_SIZE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
上面所有提及的报文中都包含NetBIOS名称,这个名称是被经过编码处理的。参考以下RFC 1001 Ch14.1可知,最长16Byte的NetBIOS name被要求映射为32Byte的可逆的、半ASCII偏置编码。
The 16 byte NetBIOS name is mapped into a 32 byte wide field using a reversible, half-ASCII, biased encoding. Each half-octet of the NetBIOS name is encoded into one byte of the 32 byte field. The first half octet is encoded into the first byte, the second half- octet into the second byte, etc.
Each 4-bit, half-octet of the NetBIOS name is treated as an 8-bit, right-adjusted, zero-filled binary number. This number is added to value of the ASCII character ‘A’ (hexidecimal 41). The resulting 8- bit number is stored in the appropriate byte.
简单讲,就是将每个字符按ASCII拆成两部分,每部分再加上A
,从而由1个字符变成两个字符。比如字符L
,对应ASCII 0x4C
,拆成两部分为0x4
和0xC
,然后每部分都加上字符A
对应的ASCII 0x41
,得到0x45
和0x4D
,对应字符E
和M
,这样原始字符L
就变成了双字符EM
。下面是这个示例的详细说明图解。
注意原始名称不足16字节可以补空格0x20
或NULL0x00
,这里补的是空格;如果长度超过16则需要截取前16字节。
使用Python
可以快速完成编码↓
>>> orig_name = 'LITREILY'.ljust(16)
>>> encoded_name = ''.join([ chr((ord(c)>>4) + ord('A')) + chr((ord(c)&0x0F) + ord('A')) for c in orig_name ])
>>> encoded_name
'EMEJFEFCEFEJEMFJCACACACACACACACA'
在真实的数据包中,NetBIOS名称前面是0x20
,代表名称固定长度32字节,名称后面填补一个0x00
即\0
作为结束符。那么上面的LITREILY
对应的数据为:
20 45 4d 45 4a 46 45 46 43 45 46 45 4a 45 4d 46
4a 43 41 43 41 43 41 43 41 43 41 43 41 43 41 43
41 00
注意:
A label length count is actually a 6-bit field in the label length field. The most significant 2 bits of the field, bits 7 and 6, are flags allowing an escape from the above compressed representation. If bits 7 and 6 are both set (11), the following 14 bits are an offset pointer into the full message to the actual label string from another domain name that belongs in this name. This label pointer allows for a further compression of a domain name in a packet.
简单说,当长度设置不为
0x20
,而是将最高两位置1,即设为0xc0
时,代表当前名称使用指针,随后的字节指定名称所在的位置。
nbtstat.exe
是Windows中用于查看NBT status的工具,通过它可以查看当前局域网内的NetBIOS name.
C:\Users\Litre>nbtstat.exe -a
显示协议统计和当前使用 NBI 的 TCP/IP 连接
(在 TCP/IP 上的 NetBIOS)。
NBTSTAT [ [-a RemoteName] [-A IP address] [-c] [-n]
[-r] [-R] [-RR] [-s] [-S] [interval] ]
-a (适配器状态) 列出指定名称的远程机器的名称表
-A (适配器状态) 列出指定 IP 地址的远程机器的名称表。
-c (缓存) 列出远程[计算机]名称及其 IP 地址的 NBT 缓存
-n (名称) 列出本地 NetBIOS 名称。
-r (已解析) 列出通过广播和经由 WINS 解析的名称
-R (重新加载) 清除和重新加载远程缓存名称表
-S (会话) 列出具有目标 IP 地址的会话表
-s (会话) 列出将目标 IP 地址转换成计算机 NETBIOS 名称的会话表。
-RR (释放刷新) 将名称释放包发送到 WINS,然后启动刷新
RemoteName 远程主机计算机名。
IP address 用点分隔的十进制表示的 IP 地址。
interval 重新显示选定的统计、每次显示之间暂停的间隔秒数。
按 Ctrl+C 停止重新显示统计。
其中RemoteName
既可以是ASCII形式的名称,也可以是IP地址。
第一个例子,在加入域DELTA
的办公电脑上。3个网卡,第1个网卡连接路由器,第2个网卡连接公司网,第3个为虚拟网卡。
C:\WINDOWS\system32>nbtstat.exe -n
Router:
节点 IP 址址: [192.168.1.10] 范围 ID: []
NetBIOS 本地名称表
名称 类型 状态
---------------------------------------------
CNSHDNI2PC074 <00> 唯一 已注册
DELTA <00> 组 已注册
CNSHDNI2PC074 <20> 唯一 已注册
DELTA <1E> 组 已注册
DELTA <1D> 唯一 已注册
..__MSBROWSE__.<01> 组 已注册
Company:
节点 IP 址址: [172.17.144.33] 范围 ID: []
NetBIOS 本地名称表
名称 类型 状态
---------------------------------------------
CNSHDNI2PC074 <00> 唯一 已注册
DELTA <00> 组 已注册
CNSHDNI2PC074 <20> 唯一 已注册
DELTA <1E> 组 已注册
以太网:
节点 IP 址址: [0.0.0.0] 范围 ID: []
缓存中没有名称
需要注意的是,名称表中每个名称都是16字节,中间空白处是空格符,最后一个字节用<>
显示,里面使用16进制数表示。如CHSH2DNIPC074__<00>
,_
代表空格,最后一个字节<00>
是\0
. NetBIOS name可以唯一,也可以是多个设备共用一个组,唯一名称用于指定唯一一台设备,而组名如此处的DELTA
是域名称,局域网加入域对应的域名就是这种组名称,也称之为工作组。
第二个例子,我使用家用台式PC在局域网内进行了反复测试。下面是简要的抓包信息。
nbtstat -a RemoteName
用于请求指定名称所在设备的名称表。
C:\WINDOWS\system32>nbtstat -a DZ-DN-700
eth0:
节点 IP 址址: [192.168.1.14] 范围 ID: []
NetBIOS 远程计算机名称表
名称 类型 状态
---------------------------------------------
DZ-DN-700 <20> 唯一 已注册
DZ-DN-700 <00> 唯一 已注册
DIAS <00> 组 已注册
DIAS <1E> 组 已注册
MAC 地址 = E4-42-A6-18-AB-00
C:\WINDOWS\system32>nbtstat -a 192.168.1.12
eth0:
节点 IP 址址: [192.168.1.14] 范围 ID: []
NetBIOS 远程计算机名称表
名称 类型 状态
---------------------------------------------
DZ-DN-700 <20> 唯一 已注册
DZ-DN-700 <00> 唯一 已注册
DIAS <00> 组 已注册
DIAS <1E> 组 已注册
MAC 地址 = E4-42-A6-18-AB-00
nbtstat -A IP_Address
用于请求指定IP所在设备的名称表。
C:\WINDOWS\system32>nbtstat -A 192.168.1.12
eth0:
节点 IP 址址: [192.168.1.14] 范围 ID: []
NetBIOS 远程计算机名称表
名称 类型 状态
---------------------------------------------
DZ-DN-700 <20> 唯一 已注册
DZ-DN-700 <00> 唯一 已注册
DIAS <00> 组 已注册
DIAS <1E> 组 已注册
DIAS <1D> 唯一 已注册
..__MSBROWSE__.<01> 组 已注册
MAC 地址 = E4-42-A6-18-AB-00
nbtstat -c
用于查看当前设备缓存中的名称表,注意每个名称都是可以被修改的,所以需要定时刷新,同时每个名称都有其寿命,寿命耗尽后需要重新请求。
C:\WINDOWS\system32>nbtstat -c
eth0:
节点 IP 址址: [192.168.1.14] 范围 ID: []
NetBIOS 远程缓存名称表
名称 类型 主机地址 寿命[秒]
------------------------------------------------------------
DZ-DN-700 <20> 唯一 192.168.1.12 269
DZ-DN-700 <00> 唯一 192.168.1.12 269
nbtstat -n
用于查看当前设备的本地名称表,与第一个例子一样。
C:\WINDOWS\system32>nbtstat -n
eth0:
节点 IP 址址: [192.168.1.14] 范围 ID: []
NetBIOS 本地名称表
名称 类型 状态
---------------------------------------------
DT-LITREILY <20> 唯一 已注册
DT-LITREILY <00> 唯一 已注册
WORKGROUP <00> 组 已注册
nbtstat -r
用于查看通过广播和经由 WINS 解析的名称
C:\WINDOWS\system32>nbtstat -r
NetBIOS 名称解析和注册统计
----------------------------------------------------
通过广播解析的 = 5
通过名称服务器解析 = 0
通过广播注册的 = 3
通过名称服务器注册的 = 0
通过广播解析的 NetBIOS 名称
---------------------------------------------
DZ-DN-700 <00>
DZ-DN-700 <00>
DZ-DN-700 <00>
DIAS <00>
DZ-DN-700 <00>
nbtstat -s
与nbtstat -S
都用于会话服务信息查询,因为没有连接所以信息为空。
C:\WINDOWS\system32>nbtstat -s
eth0:
节点 IP 址址: [192.168.1.14] 范围 ID: []
无连接
C:\WINDOWS\system32>nbtstat -S
eth0:
节点 IP 址址: [192.168.1.14] 范围 ID: []
无连接
nbtstat -R
用于清除缓存,清除后再用-c
查看就会显示没有名称了。
C:\WINDOWS\system32>nbtstat -R
NBT 远程缓存名称表的成功清除和预加载。
C:\WINDOWS\system32>nbtstat -c
eth0:
节点 IP 址址: [192.168.1.14] 范围 ID: []
缓存中没有名称
nbtstat -RR
用于刷新经本机注册的NetBIOS名称,间隔一段时间方能刷新第二次。
C:\WINDOWS\system32>nbtstat -RR
已经刷新经过此计算机注册的 NetBIOS 名称。
在Windows操作系统中,可以打开某网卡的属性配置,然后选择IPv4配置的高级选项,WINS
选项卡即可配置NetBIOS
。默认情况是启用的,与下图所示一致。
最后来分析两个使用wireshark抓的NBNS数据包,以便更直观的理解和记忆。
使用指令nbtstat -A 192.168.1.12
向指定设备发送Node status query,使用wireshark抓包。
请求数据包如下:
从wireshark得到的解析数据如下:
0000 e4 42 a6 18 ab 00 00 e0 4c 5a 0a 78 08 00 45 00 äB¦.«..àLZ.x..E.
0010 00 4e 1e 82 00 00 80 11 98 b2 c0 a8 01 0e c0 a8 .N.......²À¨..À¨
0020 01 0c 00 89 00 89 00 3a 5a 12 e2 b1 00 00 00 01 .......:Z.â±....
0030 00 00 00 00 00 00 20 43 4b 41 41 41 41 41 41 41 ...... CKAAAAAAA
0040 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0050 41 41 41 41 41 41 41 00 00 21 00 01 AAAAAAA..!..
NetBIOS Name Service
Transaction ID: 0xe2b1
Flags: 0x0000, Opcode: Name query
0... .... .... .... = Response: Message is a query
.000 0... .... .... = Opcode: Name query (0)
.... ..0. .... .... = Truncated: Message is not truncated
.... ...0 .... .... = Recursion desired: Do not do query recursively
.... .... ...0 .... = Broadcast: Not a broadcast packet
Questions: 1
Answer RRs: 0
Authority RRs: 0
Additional RRs: 0
Queries
*<00><00><00><00><00><00><00><00><00><00><00><00><00><00><00>: type NBSTAT, class IN
Name: *<00><00><00><00><00><00><00><00><00><00><00><00><00><00><00> (Workstation/Redirector)
Type: NBSTAT (33)
Class: IN (1)
该数据报包含一个请求,所以Questions
为1,其余为0;请求包中的编码名称为*
的编码后数据CKAAAAAAAAAAAAAAA…; 由于使用的是指定IP,所以是单播包;因为是NODE STATUS REQUEST, 所以QUESTION_TYPE是NBSTAT(0x0021).
从指定设备获取到的响应数据如下:
从截图中已经可以清晰的看到数据格式及具体内容了,被折叠的名称信息中,DZ-DN-700<20>
与DIAS<1e>
如下:
0000 00 e0 4c 5a 0a 78 e4 42 a6 18 ab 00 08 00 45 00 ..LZ.x........E.
0010 00 cb 53 50 00 00 80 11 63 67 c0 a8 01 0c c0 a8 ..SP....cg......
0020 01 0e 00 89 00 89 00 b7 01 c0 .........
0020 e2 b1 84 00 00 00 .......
0030 00 01 00 00 00 00 20 43 4b 41 41 41 41 41 41 41 ...... CKAAAAAAA
0040 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0050 41 41 41 41 41 41 41 00 00 21 00 01 00 00 00 00 AAAAAAA..!......
0060 00 77 04 .w.
0060 44 5a 2d 44 4e 2d 37 30 30 20 20 20 20 DZ-DN-700
0070 20 20 20 04 00 ..
Name: DZ-DN-700<20> (Server service)
Name flags: 0x0400, ONT: B-node, Name is active
0... .... .... .... = Name type: Unique name
.00. .... .... .... = ONT: B-node (0)
...0 .... .... .... = Name is being deregistered: No
.... 0... .... .... = Name is in conflict: No
.... .1.. .... .... = Name is active: Yes
.... ..0. .... .... = Permanent node name: No
0070 44 5a 2d 44 4e 2d 37 30 30 20 20 DZ-DN-700
0080 20 20 20 20 00 04 00 ...
Name: DZ-DN-700<00> (Workstation/Redirector)
Name flags: 0x0400, ONT: B-node, Name is active
0... .... .... .... = Name type: Unique name
.00. .... .... .... = ONT: B-node (0)
...0 .... .... .... = Name is being deregistered: No
.... 0... .... .... = Name is in conflict: No
.... .1.. .... .... = Name is active: Yes
.... ..0. .... .... = Permanent node name: No
0080 44 49 41 53 20 20 20 20 20 DIAS
0090 20 20 20 20 20 20 00 84 00 ...
Name: DIAS<00> (Workstation/Redirector)
Name flags: 0x8400, Name type, ONT: B-node, Name is active
1... .... .... .... = Name type: Group name
.00. .... .... .... = ONT: B-node (0)
...0 .... .... .... = Name is being deregistered: No
.... 0... .... .... = Name is in conflict: No
.... .1.. .... .... = Name is active: Yes
.... ..0. .... .... = Permanent node name: No
0090 44 49 41 53 20 20 20 DIAS
00a0 20 20 20 20 20 20 20 20 1e 84 00 ...
Name: DIAS<1e> (Browser Election Service)
Name flags: 0x8400, Name type, ONT: B-node, Name is active
1... .... .... .... = Name type: Group name
.00. .... .... .... = ONT: B-node (0)
...0 .... .... .... = Name is being deregistered: No
.... 0... .... .... = Name is in conflict: No
.... .1.. .... .... = Name is active: Yes
.... ..0. .... .... = Permanent node name: No
00a0 e4 42 a6 18 ab .B...
00b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00d0 00 00 00 00 00 00 00 00 00 .........
NBNS名称注册请求包如下图所示:
请求包格式与NAME REGISTRATION REQUEST中的一致。使用广播包方式,OPCODE
为5,包含一条Questions记录和Additional记录,注册地址为发送方的IP地址192.168.1.12.
在局域网内的其它设备或路由器接收到该广播包后,即可将其名称和IP地址记录到本地缓存当中。
文章首发于: 网络协议详解1 - NBNS