《寒江独钓-WINDOWS内核安全编程》中 10.3 小节,描述了获取生成地址的办法:
1、绑定相应的NDIS协议驱动对象
"\Device\Tcp"
"\Device\Udp"
"\Device\RawIp"
2、过滤IRP_MJ_CREATE请求
2.1 判断irp->AssociatedIrp.SystemBuffer->EaName是否为TdiTransportAddress;
2.2 下发该请求,并在完成函数(这里为:IoCompletionCreate)中查询传输地址的信息。
2.3 在查询传输地址的完成例程中,打印信息。
3、相应的代码如下:
//tdifilter.c
#include <ntddk.h>
#include <tdi.h>
#include <TdiKrnl.h>
#define TDI_TCP_DEVICE L"\\Device\\Tcp"
#define TDI_UDP_DEVICE L"\\Device\\Udp"
#define TDI_RAWIP_DEVICE L"\\Device\\RawIp"
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING LowerDeviceName;
PDEVICE_OBJECT LowerDeviceObject;
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;
typedef struct _COMPLETION_CREATE_CONTEXT
{
PIRP Irp;
PMDL Mdl;
PVOID Buffer;
PRKEVENT Event;
}COMPLETION_CREATE_CONTEXT,*PCOMPLETION_CREATE_CONTEXT;
NTSTATUS
IoCompletionQuery(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PVOID Context
);
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_EXTENSION pdx = NULL;
PDEVICE_OBJECT fdo = DriverObject->DeviceObject;
while(fdo != NULL)
{
pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
fdo = fdo->NextDevice;
KdPrint(("tdifilter!DriverUnLoad:[%wZ] Detached.\n",&pdx->LowerDeviceName));
IoDetachDevice(pdx->LowerDeviceObject);
IoDeleteDevice(pdx->DeviceObject);
}
}
NTSTATUS
CreateAndAttachDevice(
IN PDRIVER_OBJECT DriverObject,
IN PCWSTR DeviceName
)
{
NTSTATUS status;
UNICODE_STRING devname;
PDEVICE_OBJECT fdo;
PDEVICE_EXTENSION pdx;
RtlInitUnicodeString(&devname,DeviceName);
status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&fdo);
if(!NT_SUCCESS(status))
{
return status;
}
//设置设备IO为直接IO
fdo->Flags |= DO_DIRECT_IO;
pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
pdx->LowerDeviceName = devname;
pdx->DeviceObject = fdo;
status = IoAttachDevice(fdo,&devname,&pdx->LowerDeviceObject);
if(!NT_SUCCESS(status))
{
IoDeleteDevice(fdo);
}
KdPrint(("tdifilter!CreateAndAttachDevice:[%wZ] Attached.\n",&pdx->LowerDeviceName));
return status;
}
NTSTATUS DispatchAny(PDEVICE_OBJECT fdo, PIRP Irp)
{
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
}
//IRP_MJ_CREATE的完成例程
NTSTATUS
IoCompletionCreate(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PVOID Context
)
{
//KEVENT event;
PCOMPLETION_CREATE_CONTEXT ctx = (PCOMPLETION_CREATE_CONTEXT)Context;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
if(Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
KdPrint(("tdifilter!IoCompletionCreate\n"));
//KeInitializeEvent(&event,NotificationEvent,FALSE);
//ctx->Event = &event;
TdiBuildQueryInformation(ctx->Irp,
pdx->LowerDeviceObject,
IrpSp->FileObject,
IoCompletionQuery,
ctx,
TDI_QUERY_ADDRESS_INFO,
ctx->Mdl
);
IoCallDriver(pdx->LowerDeviceObject,ctx->Irp);
//KeWaitForSingleObject(ctx->Event,Executive,KernelMode,TRUE,TRUE,TRUE);
return STATUS_SUCCESS;
}
//查询传输地址IRP的完成例程
NTSTATUS
IoCompletionQuery(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PVOID Context
)
{
PTDI_ADDRESS_INFO tdiAddress;
PTA_ADDRESS taAddress;
PTDI_ADDRESS_IP ip;
PCOMPLETION_CREATE_CONTEXT ctx = (PCOMPLETION_CREATE_CONTEXT)Context;
if(Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
KdPrint(("tdifilter!IoCompletionQuery: Start.\n"));
tdiAddress = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdlSafe(Irp->MdlAddress,NormalPagePriority);
taAddress = tdiAddress->Address.Address;
ip = (PTDI_ADDRESS_IP)(taAddress->Address);
KdPrint(("ip:%x,port:%u\n",ip->in_addr,ip->sin_port));
KdPrint(("tdifilter!IoCompletionQuery: End.\n"));
//释放内存
//IoFreeMdl(ctx->Mdl);
//ExFreePoolWithTag(ctx->Buffer,0x12345678);
KeSetEvent(ctx->Event,IO_NO_INCREMENT,FALSE);
return STATUS_SUCCESS;
}
NTSTATUS
TdiDispatchCreate(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
{
//NTSTATUS status;
KEVENT event;
PIRP QueryIrp;
PTDI_ADDRESS_INFO tdiAddress;
PMDL MdlAddress;
COMPLETION_CREATE_CONTEXT context;
PUCHAR Ep = (PUCHAR)PsGetCurrentProcess();
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_FULL_EA_INFORMATION ea = (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
KeInitializeEvent(&event,NotificationEvent,FALSE);
if((ea->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH)
&&(memcmp(ea->EaName,TdiTransportAddress,TDI_TRANSPORT_ADDRESS_LENGTH) == 0))
{
//生成查询的IRP,给IRP_MJ_CREATE完成例程下发查询
QueryIrp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION,
pdx->LowerDeviceObject,
IrpSp->FileObject,
NULL,NULL);
if(QueryIrp == NULL)
{
return DispatchAny(fdo,Irp);
}
//分配内存
tdiAddress = (PTDI_ADDRESS_INFO)ExAllocatePoolWithTag(NonPagedPool,
sizeof(TDI_ADDRESS_INFO)*16,0x12345678);
MdlAddress = IoAllocateMdl(tdiAddress,
sizeof(TDI_ADDRESS_INFO)*16,
FALSE,FALSE,NULL);
MmBuildMdlForNonPagedPool(MdlAddress);
context.Irp = QueryIrp;
context.Mdl = MdlAddress;
context.Buffer = tdiAddress;
context.Event = &event;
//在这里捕获传输层地址的生成
KdPrint(("%s:pname[%s].\n",TdiTransportAddress,(Ep + 0x174)));
IoCopyCurrentIrpStackLocationToNext(Irp);
//设置IRP_MJ_CREATE完成例程
IoSetCompletionRoutine(Irp,IoCompletionCreate,&context,TRUE,TRUE,TRUE);
IoCallDriver(pdx->LowerDeviceObject,Irp);
//等待查询完毕,释放内存
KeWaitForSingleObject(context.Event,Executive,KernelMode,FALSE,NULL);
//释放内存
IoFreeMdl(context.Mdl);
ExFreePoolWithTag(context.Buffer,0x12345678);
return Irp->IoStatus.Status;
}
else if((ea->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH)
&&(memcmp(ea->EaName,TdiConnectionContext,TDI_CONNECTION_CONTEXT_LENGTH) == 0))
{
KdPrint(("%s:pname[%s].\n",TdiConnectionContext,(Ep + 0x174)));
}
return DispatchAny(fdo,Irp);
}
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
ULONG i;
DriverObject->DriverUnload = DriverUnload;
for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i ++)
{
DriverObject->MajorFunction[i] = DispatchAny;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = TdiDispatchCreate;
//绑定TCP协议
status = CreateAndAttachDevice(DriverObject,
TDI_TCP_DEVICE);
if(!NT_SUCCESS(status))
{
DriverUnload(DriverObject);
return status;
}
//绑定UDP协议
status = CreateAndAttachDevice(DriverObject,
TDI_UDP_DEVICE);
if(!NT_SUCCESS(status))
{
DriverUnload(DriverObject);
return status;
}
//绑定IP协议
status = CreateAndAttachDevice(DriverObject,
TDI_RAWIP_DEVICE);
if(!NT_SUCCESS(status))
{
DriverUnload(DriverObject);
return status;
}
return STATUS_SUCCESS;
}
4、加载并测试,
输入:telnet 127.0.0.1 时,蓝屏重启。
5、windbg得到的信息是这样的,看不懂.
PFN_LIST_CORRUPT (4e)
Typically caused by drivers passing bad memory descriptor lists (ie: calling
MmUnlockPages twice with the same list, etc). If a kernel debugger is
available get the stack trace.
Arguments:
Arg1: 00000007, A driver has unlocked a page more times than it locked it
Arg2: 00002582, page frame number
Arg3: 00000001, current share count
Arg4: 00000000, 0
Debugging Details:
------------------
BUGCHECK_STR: 0x4E_7
DEFAULT_BUCKET_ID: INTEL_CPU_MICROCODE_ZERO
PROCESS_NAME: System
LAST_CONTROL_TRANSFER: from 805334a7 to 804e4592
SYMBOL_ON_RAW_STACK: 1
STACK_ADDR_RAW_STACK_SYMBOL: fffffffff7d9f360
STACK_COMMAND: dds F7D9F360-0x20 ; kb
STACK_TEXT:
f7d9f340 00000286
f7d9f344 f7d9f624
f7d9f348 00000010
f7d9f34c 8054c2b9 nt!ExAllocatePoolWithTag+0x7af
f7d9f350 804e30d2 nt!InterlockedPopEntrySList
f7d9f354 82a03120
f7d9f358 828e2ba8
f7d9f35c f7e6864a kdcom!CpReadLsr+0x8d
f7d9f360 000003fe
f7d9f364 00000000
f7d9f368 f7e68d20 kdcom!Port
f7d9f36c 00000000
f7d9f370 00000000
f7d9f374 00000000
f7d9f378 82add190
f7d9f37c 00000000
f7d9f380 00000000
f7d9f384 f76374bc
f7d9f388 00000000
f7d9f38c 00000001
f7d9f390 00000000
f7d9f394 00010010
f7d9f398 0000003b
f7d9f39c 0000000a
f7d9f3a0 00000000
f7d9f3a4 f76374cc
f7d9f3a8 0000bb40
f7d9f3ac 0000bb40
f7d9f3b0 0000bb40
f7d9f3b4 f7637134
f7d9f3b8 f7637718
f7d9f3bc f7637718
FOLLOWUP_IP:
kdcom!CpReadLsr+8d
f7e6864a 88450f mov byte ptr [ebp+0Fh],al
SYMBOL_NAME: kdcom!CpReadLsr+8d
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: kdcom
IMAGE_NAME: kdcom.dll
DEBUG_FLR_IMAGE_TIMESTAMP: 3b7d8346
FAILURE_BUCKET_ID: 0x4E_7_kdcom!CpReadLsr+8d
BUCKET_ID: 0x4E_7_kdcom!CpReadLsr+8d
6、问题:本人太菜,请大家帮帮忙,代码中哪里写错了?万分感谢!!
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)