#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
typedef UINT NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#define STATUS_ALREADY_COMMITTED ((NTSTATUS)0xC0000021L)
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010L)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L)
#define STATUS_OBJECT_NAME_INVALID ((NTSTATUS)0xC0000033L)
#define STATUS_ACCESS_VIOLATION ((NTSTATUS)0xC0000005L) // winnt ntsubauth
#define STATUS_PENDING ((NTSTATUS)0x00000103L) // winnt
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
#ifdef MIDL_PASS
[size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;
#else // MIDL_PASS
PWSTR Buffer;
#endif // MIDL_PASS
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
#define UNICODE_NULL ((WCHAR)0) // winnt
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR
PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
typedef struct _IO_STATUS_BLOCK {
NTSTATUS Status;
ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
NTSTATUS (__stdcall *fNtCreateFile)(
PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
PLARGE_INTEGER AllocationSize,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PVOID EaBuffer,
ULONG EaLength
);
NTSTATUS (__stdcall *fNtDeviceIoControlFile)(
HANDLE FileHandle,
DWORD a,
DWORD b,
DWORD c,
PVOID structA,
PVOID d,
PVOID e,
PVOID f,
PVOID outBuf,
DWORD size
);
//
// Macro definition for defining IOCTL and FSCTL function control codes. Note
// that function codes 0-2047 are reserved for Microsoft Corporation, and
// 2048-4095 are reserved for customers.
//
#define CTL_CODE( DeviceType, Function, Method, Access ) ( /
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) /
)
#define FILE_DEVICE_TRANSPORT 0x00000021
//
// Define the method codes for how buffers are passed for I/O and FS controls
//
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER 3
//
// Define the access check value for any access
//
//
// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
// constants *MUST* always be in sync.
//
#define FILE_ANY_ACCESS 0
#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
//
// NtDeviceIoControlFile IoControlCode values for this device.
//
// Warning: Remember that the low two bits of the code specify how the
// buffers are passed to the driver!
//
#define _TDI_CONTROL_CODE(request,method) /
CTL_CODE(FILE_DEVICE_TRANSPORT, request, method, FILE_ANY_ACCESS)
#define IOCTL_TDI_ACCEPT _TDI_CONTROL_CODE( 0, METHOD_BUFFERED )
#define IOCTL_TDI_CONNECT _TDI_CONTROL_CODE( 1, METHOD_BUFFERED )
#define IOCTL_TDI_DISCONNECT _TDI_CONTROL_CODE( 2, METHOD_BUFFERED )
#define IOCTL_TDI_LISTEN _TDI_CONTROL_CODE( 3, METHOD_BUFFERED )
#define IOCTL_TDI_QUERY_INFORMATION _TDI_CONTROL_CODE( 4, METHOD_OUT_DIRECT )
#define IOCTL_TDI_RECEIVE _TDI_CONTROL_CODE( 5, METHOD_OUT_DIRECT )
#define IOCTL_TDI_RECEIVE_DATAGRAM _TDI_CONTROL_CODE( 6, METHOD_OUT_DIRECT )
#define IOCTL_TDI_SEND _TDI_CONTROL_CODE( 7, METHOD_IN_DIRECT )
#define IOCTL_TDI_SEND_DATAGRAM _TDI_CONTROL_CODE( 8, METHOD_IN_DIRECT )
#define IOCTL_TDI_SET_EVENT_HANDLER _TDI_CONTROL_CODE( 9, METHOD_BUFFERED )
#define IOCTL_TDI_SET_INFORMATION _TDI_CONTROL_CODE( 10, METHOD_IN_DIRECT )
#define IOCTL_TDI_ASSOCIATE_ADDRESS _TDI_CONTROL_CODE( 11, METHOD_BUFFERED )
#define IOCTL_TDI_DISASSOCIATE_ADDRESS _TDI_CONTROL_CODE( 12, METHOD_BUFFERED )
#define IOCTL_TDI_ACTION _TDI_CONTROL_CODE( 13, METHOD_OUT_DIRECT )
/* These *UNDOCUMENTED* IOCTL codes are used in NBTSTAT.EXE */
#define IOCTL_TDI_UNKNOWN1 _TDI_CONTROL_CODE( 41, METHOD_OUT_DIRECT ) //gets dword from ip?
#define IOCTL_TDI_UNKNOWN2 _TDI_CONTROL_CODE( 43, METHOD_OUT_DIRECT ) //gets netbios name
#define IOCTL_TDI_UNKNOWN3 _TDI_CONTROL_CODE( 30, METHOD_BUFFERED )
#define IOCTL_TDI_UNKNOWN4 _TDI_CONTROL_CODE( 31, METHOD_OUT_DIRECT )
#define IOCTL_TDI_UNKNOWN5 _TDI_CONTROL_CODE( 32, METHOD_OUT_DIRECT )
#define IOCTL_TDI_UNKNOWN6 _TDI_CONTROL_CODE( 33, METHOD_OUT_DIRECT )
typedef LONG TDI_STATUS;
typedef PVOID CONNECTION_CONTEXT;
/* This structure is passed with every TDI_REQUEST_ to TDI. It describes that
* request and the parameters to it.
*/
typedef struct _TDI_REQUEST {
union {
HANDLE AddressHandle;
CONNECTION_CONTEXT ConnectionContext;
HANDLE ControlChannel;
} Handle;
PVOID RequestNotifyObject;
PVOID RequestContext;
TDI_STATUS TdiStatus;
} TDI_REQUEST, *PTDI_REQUEST;
/* EDIT the following structure as needed */
typedef struct _TDI_REQUEST_XXX {
TDI_REQUEST Request;
/* SOME ADDITIONAL DATA HERE */
} TDI_REQUEST_XXX, *PTDI_REQUEST_XXX;
/* test structure for TDI_UNKNOWN1 */
typedef struct _TDI_REQUEST_UNKNOWN1 {
TDI_REQUEST Request;
/* SOME ADDITIONAL DATA HERE */
} TDI_REQUEST_UNKNOWN1, *PTDI_REQUEST_UNKNOWN1;
/* test structure for TDI_UNKNOWN2 */
typedef struct _TDI_REQUEST_UNKNOWN2 {
TDI_REQUEST Request;
/* SOME ADDITIONAL DATA HERE */
DWORD a, b, c, d;
} TDI_REQUEST_UNKNOWN2, *PTDI_REQUEST_UNKNOWN2;
struct netbiosName {
char name[15];
char type;
char index;
char registered;
};
LPWSTR WINAPI Ascii2WideHelper(LPWSTR lpw, LPCSTR lpa, int nChars);
LPSTR WINAPI Wide2AsciiHelper(LPSTR lpa, LPCWSTR lpw, int nChars);
#ifndef A2WHELPER
#define A2WHELPER Ascii2WideHelper
#define W2AHELPER Wide2AsciiHelper
#endif
#ifndef _DEBUG
#define USES_UNICODE_CONVERSION int _Uconvert; _Uconvert
#else
#define USES_UNICODE_CONVERSION int _Uconvert = 0
#endif
#define ASCII2WIDE(lpa) (/
((LPCSTR)lpa == NULL) ? NULL : (/
_Uconvert = (lstrlenA(lpa)+1),/
A2WHELPER((LPWSTR) alloca(_Uconvert*2), lpa, _Uconvert)))
#define WIDE2ASCII(lpw) (/
((LPCWSTR)lpw == NULL) ? NULL : (/
_Uconvert = (lstrlenW(lpw)+1)*2,/
W2AHELPER((LPSTR) alloca(_Uconvert), lpw, _Uconvert)))
#define ASCII2CWIDE(lpa) ((LPCWSTR)ASCII2WIDE(lpa))
#define WIDE2CASCII(lpw) ((LPCSTR)WIDE2ASCII(lpw))
void dumpNames(char *outbuf);
char * getLinkage(char *theKey);
int main( int argc, char *argv[])
{
USES_UNICODE_CONVERSION;
if(argc != 2){
fprintf(stdout, "Usage: %s <ip address>/n", argv[0]);
exit(0);
}
if(!(fNtCreateFile =
(void *) GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtCreateFile"))){
fputs("Could not find entry point in NTDLL.DLL/n", stderr);
exit(1);
}
if(!(fNtDeviceIoControlFile =
(void *) GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtDeviceIoControlFile"))){
fputs("Could not find entry point in NTDLL.DLL/n", stderr);
exit(1);
}
if(fNtCreateFile){
HANDLE h;
OBJECT_ATTRIBUTES anObjAttrib;
IO_STATUS_BLOCK aReturnCode;
NTSTATUS ret;
char *aCs = 0;
WCHAR *aUs = 0;
UNICODE_STRING aSS;
aCs = getLinkage("system//currentcontrolset//services//netbt//linkage");
if(!aCs){
fputs("Could not get linkage for NetBT/n", stderr);
exit(1);
}
aUs = ASCII2WIDE(aCs);
aSS.Length = strlen(aCs) * sizeof(WCHAR);
aSS.MaximumLength = aSS.Length + sizeof(WCHAR);
aSS.Buffer = aUs;
/* InitializeObjectAttributes */
memset((void *)&anObjAttrib, 0, sizeof(OBJECT_ATTRIBUTES));
anObjAttrib.ObjectName = &aSS;
anObjAttrib.Length = sizeof(OBJECT_ATTRIBUTES);
anObjAttrib.Attributes = 0x40; /* sniffed this value */
ret = fNtCreateFile( &h,
0x00100003, /* snooped this too */
&anObjAttrib,
&aReturnCode,
0, /* optional */
0x80, /* file attrib, snooped this */
0x3,
0x3,
0,
NULL,
0
);
if(ret != STATUS_SUCCESS){
fprintf(stderr, "NtCreateFile error %d/n", GetLastError());
exit(1);
}
if(h){
if(fNtDeviceIoControlFile){
char outbuf2[600];
TDI_REQUEST_UNKNOWN2 aTdi2;
/* this is hax0red sushi */
aTdi2.Request.Handle.AddressHandle = (void *) htonl(inet_addr(argv[1]));
aTdi2.Request.RequestNotifyObject = (void *) 1;
aTdi2.Request.RequestContext = (void *) 0x110012;
aTdi2.Request.TdiStatus = 0x2a0000;
aTdi2.a = 0;
aTdi2.b = 0;
aTdi2.c = 0;
aTdi2.d = 0;
/* outbuf2 should be filled with the nbtstat data */
ret = fNtDeviceIoControlFile( h,
0,
0,
0,
&aTdi2, // ???
IOCTL_TDI_UNKNOWN2, //0x2100A6, // code
&aTdi2,
0x20,
outbuf2,
0x258
);
if(ret == STATUS_PENDING){
if(WaitForSingleObject(h, 5000) == WAIT_TIMEOUT){
fputs("Timed out waiting for response.../n", stderr);
exit(1);
}
}
dumpNames(outbuf2);
}
CloseHandle(h);
}
}
return 0;
}
char * getLinkage(char *theKey)
{
HKEY aKey;
if(RegOpenKey(HKEY_LOCAL_MACHINE, theKey, &aKey) == ERROR_SUCCESS){
char dt[255];
int dsz = 255;
int i = 0;
char *aDest;
if(RegQueryValueEx( aKey,
"Export",
NULL,
NULL,
dt,
&dsz ) == ERROR_SUCCESS){
aDest = malloc(dsz);
memcpy(aDest, dt, dsz);
return(aDest);
}
}
return(0);
}
void dumpNames(char *outbuf)
{
struct netbiosName *aNameP;
char numEntries;
outbuf += 0x3a; /* interesting data starts 58 bytes in */
numEntries = *outbuf;
outbuf += 2;
while(numEntries--){
char temp[16];
aNameP = (struct netbiosName *)outbuf;
strncpy(temp, aNameP->name, 15);
temp[15] = '/0';
if(aNameP->registered < 0)
fprintf(stdout, "%16s<%2x> %10s/n", temp, aNameP->type, "GROUP");
else
fprintf(stdout, "%16s<%2x> %10s/n", temp, aNameP->type, "UNIQUE");
outbuf += sizeof(struct netbiosName);
}
}
/* Global UNICODE<>ANSI translation helpers */
LPWSTR WINAPI Ascii2WideHelper(LPWSTR lpw, LPCSTR lpa, int nChars)
{
if(lpa == NULL){
__asm int 3
}
if(lpw == NULL){
__asm int 3
}
// verify that no illegal character present
// since lpw was allocated based on the size of lpa
// don't worry about the number of chars
lpw[0] = '/0';
MultiByteToWideChar(CP_ACP, 0, lpa, -1, lpw, nChars);
return lpw;
}
LPSTR WINAPI Wide2AsciiHelper(LPSTR lpa, LPCWSTR lpw, int nChars)
{
if(lpw == NULL){
__asm int 3
}
if(lpa == NULL){
__asm int 3
}
// verify that no illegal character present
// since lpa was allocated based on the size of lpw
// don't worry about the number of chars
lpa[0] = '/0';
WideCharToMultiByte(CP_ACP, 0, lpw, -1, lpa, nChars, NULL, NULL);
return lpa;
}