小弟第一次发贴,大大们赏个脸呗。。。我在win7,64位下模仿一个驱动HardWareSimulate.sys中更改mac地址,hook nsiproxy的IRP_MJ_DEVICE_CONTROL分发函数,更改分发函数中pIrp->userBuffer中mac的值,我在windbg中,看到mac值已经更改成功了,但是应用层获取的mac地址还是未更改前的mac地址。搞了好几天了,怎么都没搞明白,求位好心人帮帮小弟一下,很急。。。。。。完整可编译源码如下:#include <Ntifs.h>
#include <ntddk.h>
#define MAC_SIZE 6
UCHAR g_mac[MAC_SIZE] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
PDRIVER_DISPATCH pOldDeviceControlDispatch = NULL;
#define IOCTL_NSI_GETALLPARAM 1179675
extern POBJECT_TYPE *IoDriverObjectType;
NTKERNELAPI
NTSTATUS
ObReferenceObjectByName(
__in PUNICODE_STRING ObjectName,
__in ULONG Attributes,
__in_opt PACCESS_STATE AccessState,
__in_opt ACCESS_MASK DesiredAccess,
__in POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__inout_opt PVOID ParseContext,
__out PVOID *Object
);
void WPOFFx64()
{
UINT64 cr0 = __readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
_disable();
}
void WPONx64()
{
UINT64 cr0 = __readcr0();
cr0 |= 0x10000;
_enable();
__writecr0(cr0);
}
typedef struct _LG_CONTEXT
{
PIO_COMPLETION_ROUTINE oldIocomplete;
PVOID oldCtx;
BOOLEAN bShouldInvolve;
PKEVENT pEvent;
}LG_CONTEXT, *PLG_CONTEXT;
NTSTATUS
LgCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION irpspNext = IoGetNextIrpStackLocation(Irp);
PLG_CONTEXT pCtx = Context;
if (NT_SUCCESS(Irp->IoStatus.Status))
{
if (pCtx->pEvent)
{
KeSetEvent(pCtx->pEvent, 0, 0);
}
}
irpspNext->Context = pCtx->oldCtx;
irpspNext->CompletionRoutine = pCtx->oldIocomplete;
ExFreePool(Context);
if (pCtx->bShouldInvolve)
{
return irpspNext->CompletionRoutine(DeviceObject, Irp, Context);
}
else
{
if (Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
return STATUS_SUCCESS;
}
}
NTSTATUS LgDeviceControlDispatch(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION irpStack;
ULONG uIoControlCode;
irpStack = IoGetCurrentIrpStackLocation(pIrp);
uIoControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
//KdPrint(("uIoControlCode :%d\n", uIoControlCode));
if (uIoControlCode == IOCTL_NSI_GETALLPARAM)
{
KAPC_STATE ApcState;
KEVENT Event;
PEPROCESS pEprocess = IoGetCurrentProcess();
PLG_CONTEXT pContext = (LG_CONTEXT*)ExAllocatePool(NonPagedPool, sizeof(LG_CONTEXT));
KeInitializeEvent(&Event, 0, 0);
pContext->oldIocomplete = irpStack->CompletionRoutine;
pContext->oldCtx = irpStack->Context;
irpStack->CompletionRoutine = LgCompletion;
irpStack->Context = pContext;
pContext->pEvent = &Event;
if ((irpStack->Control&SL_INVOKE_ON_SUCCESS) == SL_INVOKE_ON_SUCCESS)
{
pContext->bShouldInvolve = TRUE;
}
else
{
pContext->bShouldInvolve = FALSE;
}
irpStack->Control |= SL_INVOKE_ON_SUCCESS;
status = pOldDeviceControlDispatch(pDeviceObject, pIrp);
KeWaitForSingleObject(&Event, 0, 0, 0, 0);
if (status == STATUS_SUCCESS)
{
PVOID pUserBuffer = pIrp->UserBuffer;
if (MmIsAddressValid(pUserBuffer))
{
PVOID pBuffer2 = NULL;
KeStackAttachProcess(pEprocess, &ApcState);
{
pBuffer2 = *(ULONG*)((PUCHAR)pUserBuffer + 4 * 10);
if (pBuffer2 != NULL)
{
PUCHAR pMac = NULL;
//ULONG i = 0;
PMDL pMdl = IoAllocateMdl((PUCHAR)pBuffer2 + 0x1186/* + 1968 * i*/, MAC_SIZE, FALSE, FALSE, NULL);
__try
{
MmProbeAndLockPages(pMdl, UserMode, IoWriteAccess);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(pMdl);
goto label;
}
if (pMdl->MdlFlags & ((MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)))
{
pMac = pMdl->MappedSystemVa;
}
else
{
pMac = MmMapLockedPagesSpecifyCache(pMdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
}
KdPrint(("pBuffer2:original mac == %02X-%02X-%02X-%02X-%02X-%02X\n", *pMac, *(pMac + 1), *(pMac + 2), *(pMac + 3), *(pMac + 4), *(pMac + 5)));
RtlCopyMemory(pMac, g_mac, MAC_SIZE);
//此处,在windbg中看到pIrp->userBuffer中的mac地址已经被更改,但是应用层程序还是返回原来的mac,小弟怎么也想不明白?
KdPrint(("pBuffer2:modify mac == %02X-%02X-%02X-%02X-%02X-%02X\n", *pMac, *(pMac + 1), *(pMac + 2), *(pMac + 3), *(pMac + 4), *(pMac + 5)));
MmUnlockPages(pMdl);
IoFreeMdl(pMdl);
}
}
label1:
KeUnstackDetachProcess(&ApcState);
}
}
goto label;
}
status = pOldDeviceControlDispatch(pDeviceObject, pIrp);
label:
return status;
}
void hookNsi()
{
PDRIVER_OBJECT pDriverObject = NULL;
UNICODE_STRING uDeviceName;
NTSTATUS status = STATUS_UNSUCCESSFUL;
RtlInitUnicodeString(&uDeviceName, L"\\Driver\\nsiproxy");
status = ObReferenceObjectByName(&uDeviceName, OBJ_CASE_INSENSITIVE, NULL, FILE_ALL_ACCESS, *IoDriverObjectType, KernelMode, NULL, (PVOID*)&pDriverObject);
if (status == STATUS_SUCCESS)
{
pOldDeviceControlDispatch = pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
WPOFFx64();
InterlockedExchangePointer(&pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL], LgDeviceControlDispatch);
WPONx64();
ObDereferenceObject(pDriverObject);
}
}
void UnHookNsi()
{
PDRIVER_OBJECT pDriverObject = NULL;
UNICODE_STRING uDeviceName;
NTSTATUS status = STATUS_UNSUCCESSFUL;
if (pOldDeviceControlDispatch != NULL)
{
RtlInitUnicodeString(&uDeviceName, L"\\Driver\\nsiproxy");
status = ObReferenceObjectByName(&uDeviceName, OBJ_CASE_INSENSITIVE, NULL, FILE_ALL_ACCESS, *IoDriverObjectType, KernelMode, NULL, (PVOID*)&pDriverObject);
if (status == STATUS_SUCCESS)
{
WPOFFx64();
InterlockedExchangePointer(&pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL], pOldDeviceControlDispatch);
WPONx64();
ObDereferenceObject(pDriverObject);
}
}
}
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
UnHookNsi();
return;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
hookNsi();
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
下面附件为小弟写的驱动源码,另外还包括一个得到本机mac地址的应用层程序和可供分析的驱动HardWareSimulate.sys
第一次发帖,那个应用层的exe我上传错了,GetMacInfo2.exe是更改不了的。。。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!