Library netbios

Creates and parses NetBIOS traffic. The primary use for this is to send NetBIOS name requests.

Author:

  • Ron Bowes <ron@skullsecurity.net>

Copyright © Same as Nmap--See https://nmap.org/book/man-legal.html

Source: https://svn.nmap.org/nmap/nselib/netbios.lua

Functions

do_nbstat (host)

This is the function that actually handles the UDP query to retrieve the NBSTAT information.

flags_to_string (flags)

Convert the 16-bit flags field to a string.

get_names (host, prefix)

Sends out a UDP probe on port 137 to get a human-readable list of names the the system is using.

get_server_name (host, names)

Sends out a UDP probe on port 137 to get the server's name (that is, the entry in its NBSTAT table with a 0x20 suffix).

get_user_name (host, names)

Sends out a UDP probe on port 137 to get the user's name

get_workstation_name (host, names)

Sends out a UDP probe on port 137 to get the workstation's name (that is, the unique entry in its NBSTAT table with a 0x00 suffix).

name_decode (encoded_name)

Converts an encoded name to the string representation.

name_encode (name, scope)

Encode a NetBIOS name for transport.

Functions

do_nbstat (host)

This is the function that actually handles the UDP query to retrieve the NBSTAT information.

We make use of the Nmap registry here, so if another script has already performed a nbstat query, the result can be re-used.

The NetBIOS request's header looks like this:

 --------------------------------------------------
 |  15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0 |
 |                  NAME_TRN_ID                    |
 | R |   OPCODE  |      NM_FLAGS      |   RCODE    | (FLAGS)
 |                    QDCOUNT                      |
 |                    ANCOUNT                      |
 |                    NSCOUNT                      |
 |                    ARCOUNT                      |
 --------------------------------------------------

In this case, the TRN_ID is a constant (0x1337, what else?), the flags are 0, and we have one question. All fields are network byte order.

The body of the packet is a list of names to check for in the following format:

  • (ntstring) encoded name
  • (2 bytes) query type (0x0021 = NBSTAT)
  • (2 bytes) query class (0x0001 = IN)

The response header is the exact same, except it'll have some flags set (0x8000 for sure, since it's a response), and ANCOUNT will be 1. The format of the answer is:

  • (ntstring) requested name
  • (2 bytes) query type
  • (2 bytes) query class
  • (2 bytes) time to live
  • (2 bytes) record length
  • (1 byte) number of names
  • [for each name]
  • (16 bytes) padded name, with a 1-byte suffix
  • (2 bytes) flags
  • (variable) statistics (usually mac address)

Parameters

host
The IP or hostname of the system.

Return value:

(status, names, statistics) If status is true, then the servers names are returned as a table containing 'name', 'suffix', and 'flags'. Otherwise, names is an error message and statistics is undefined.
flags_to_string (flags)

Convert the 16-bit flags field to a string.

Parameters

flags
The 16-bit flags field

Return value:

A string representing the flags
get_names (host, prefix)

Sends out a UDP probe on port 137 to get a human-readable list of names the the system is using.

Parameters

host
The IP or hostname to check.
prefix
[optional] The prefix to put on each line when it's returned.

Return value:

(status, result) If status is true, the result is a human-readable list of names. Otherwise, result is an error message.
get_server_name (host, names)

Sends out a UDP probe on port 137 to get the server's name (that is, the entry in its NBSTAT table with a 0x20 suffix).

Parameters

host
The IP or hostname of the server.
names
[optional] The names to use, from do_nbstat.

Return value:

(status, result) If status is true, the result is the NetBIOS name. otherwise, result is an error message.
get_user_name (host, names)

Sends out a UDP probe on port 137 to get the user's name

User name is the entry in its NBSTAT table with a 0x03 suffix, that isn't the same as the server's name. If the username can't be determined, which is frequently the case, nil is returned.

Parameters

host
The IP or hostname of the server.
names
[optional] The names to use, from do_nbstat.

Return value:

(status, result) If status is true, the result is the NetBIOS name or nil. otherwise, result is an error message.
get_workstation_name (host, names)

Sends out a UDP probe on port 137 to get the workstation's name (that is, the unique entry in its NBSTAT table with a 0x00 suffix).

Parameters

host
The IP or hostname of the server.
names
[optional] The names to use, from do_nbstat.

Return value:

(status, result) If status is true, the result is the NetBIOS name. otherwise, result is an error message.
name_decode (encoded_name)

Converts an encoded name to the string representation.

If the encoding is invalid, it will still attempt to decode the string as best as possible.

Parameters

encoded_name
The L2-encoded name

Return value:

the decoded name and the scope. The name will still be padded, and the scope will never be nil (empty string is returned if no scope is present)
name_encode (name, scope)

Encode a NetBIOS name for transport.

Most packets that use the NetBIOS name require this encoding to happen first. It takes a name containing any possible character, and converted it to all uppercase characters (so it can, for example, pass case-sensitive data in a case-insensitive way)

There are two levels of encoding performed:

  • L1: Pad the string to 16 characters withs spaces (or NULLs if it's the wildcard "*") and replace each byte with two bytes representing each of its nibbles, plus 0x41.
  • L2: Prepend the length to the string, and to each substring in the scope (separated by periods).

Parameters

name
The name that will be encoded (eg. "TEST1").
scope
[optional] The scope to encode it with. I've never seen scopes used in the real world (eg, "insecure.org").

Return value:

The L2-encoded name and scope (eg. "\x20FEEFFDFEDBCACACACACACACACACAAA\x08insecure\x03org")