首页
社区
课程
招聘
[求助]win7,64位,hook nsiproxy 更改用户获取的mac地址;源码在此,求好心人指导
发表于: 2015-10-29 15:11 13753

[求助]win7,64位,hook nsiproxy 更改用户获取的mac地址;源码在此,求好心人指导

2015-10-29 15:11
13753
小弟第一次发贴,大大们赏个脸呗。。。

我在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是更改不了的。。。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 581
活跃值: (215)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
2
我试着改了啊。HardWareSimulate.sys 这个驱动是做什么的,给个源码呗。
2015-10-29 16:02
0
雪    币: 4
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
HardWareSimulate.sys是别的软件的驱动,我也是托到ida里面才看到这样做的。不明白为什么我的hook就不成功
2015-10-29 16:21
0
雪    币: 121
活跃值: (121)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
情况很简单,Win7 X64上面,调用API:GetAdaptersInfo经过NsiProxy这个驱动,所以Hook是有效果的。但是PhyMac的时候,CreateFile是直接打开的另外的驱动,如果没有Attach到这个被打开的驱动,是不经过NsiProxy的。所以你的Hook在这里是无效的。不经过你,就改不了数据。测试代码:
驱动在NsiHook.c中的LgDeviceControlDispatch:

    UNICODE_STRING uniNtPath = { 0 };
    WCHAR wszNtPath[RC_MAX_PATH] = { 0 };

    RtlInitEmptyUnicodeString(&uniNtPath, wszNtPath, RC_MAX_LEN);
    status = RCGetProcessNtPath(PsGetCurrentProcessId(), &uniNtPath);
    if ( NT_SUCCESS(status) )
    {
        if ( RCUniEndWithString(&uniNtPath, L"\\GetMacInfo.exe", TRUE) )
        {
            KdPrint(("指定进程: %wZ\n", &uniNtPath));
        }
    }

应用层代码:
bool GetPhyMacAddress(char* svr_name, std::string& str_local_mac)
{
    bool bRet         = false;
    char pstrBuf[512] = { 0 };

    sprintf_s(pstrBuf, "//./%s", svr_name);

    HANDLE hDev = CreateFileA(pstrBuf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
    if ( hDev != INVALID_HANDLE_VALUE )
    {
        int    inBuf;
        BYTE  outBuf[256]  = { 0 };
        DWORD  BytesReturned;
        inBuf  = OID_802_3_CURRENT_ADDRESS;

        BOOL bRetValue = DeviceIoControl(hDev, IOCTL_NDIS_QUERY_GLOBAL_STATS, (LPVOID)&inBuf, 4, outBuf, 256, &BytesReturned, NULL);
        if ( bRetValue )
        {
            inBuf = OID_802_3_PERMANENT_ADDRESS;
            bRetValue = DeviceIoControl(hDev, IOCTL_NDIS_QUERY_GLOBAL_STATS, (LPVOID)&inBuf, 4, outBuf, 256, &BytesReturned, NULL);
            if ( bRetValue )
            {
                //                printf(pstrBuf);
                printf("%02X-%02X-%02X-%02X-%02X-%02X", outBuf[0], outBuf[1], outBuf[2], outBuf[3], outBuf[4], outBuf[5]);
            }
        }
        else
        {

        }

        bRet = (bRetValue == TRUE) ? true : false;
        CloseHandle(hDev);
    }

    return bRet;
}

参数传递,用GetAdaptersInfo返回的piai->AdapterName。

如果调用GetAdaptersInfo,会有进程打印;如果调用后面这个,是没有打印进程的。
2015-10-29 17:30
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
路过,围观一下
2015-10-29 17:37
0
雪    币: 4
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
谢谢4楼了,驱动没问题,还是和应用层获取mac的方式有关,thanks very much...
2015-10-30 09:19
0
雪    币: 220
活跃值: (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习了。
2018-3-26 00:58
0
雪    币: 228
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
改MAC是可以,但是改了后浏览器都打不开了,代码哪里还是有问题。
2021-12-30 21:14
0
游客
登录 | 注册 方可回帖
返回
//