您的位置:首页 > 其它

the functionality of an "nbtstat -A" code

2007-09-13 23:43 405 查看
/* Blood and Sweat code
 * - Juggler of ChAoS -
 * Demonstrates use of an undocumented IOCTL call to get the
 * NETBIOS name given an IP.
 *
 * basically replaces the functionality of an "nbtstat -A <ip address>" command.
 *
 *
 *  Copyright (C) 1998 Greg Hoglund
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 1, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 */

#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);

void 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);
                }
        }
}

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐