首页
论坛
课程
招聘
[求助]Hook ZwSetSystemInformation时遇到奇怪的问题
2008-3-7 21:33 4368

[求助]Hook ZwSetSystemInformation时遇到奇怪的问题

2008-3-7 21:33
4368
上次看到一个帖子说用ZwSetSystemInformation可以加载驱动,于是我想写个程序把这条路给封住,而且要让我可以知道是哪一个进程在加载哪一个驱动,我的方法是用SSDT Hook,Hook ZwSetSystemInformation函数,同时我还Hook了ZwLoadDriver函数,但是,我却碰到了一个奇怪的问题,具体表现是当我写的替代函数MySetSystemInformation完成了与用户层交换数据的工作然后去调用原ZwSetSystemInformation时,竟然会又一次跑到我的MySetSystemInformation中去,然后再次与用户层交换数据后再次调用原ZwSetSystemInformation时就会出现“Access violation - code c0000005”错误,我反复测试了多次,发现只要第二次与用户层交换数据时选择了否(“选择否”的含义见注释),就不会出问题,而如果选择了“是”就会出错,然后我试着修改了一下代码,去掉KeWaitForSingleObject那一行就不会出错,我Hook的其他的函数都是用的和这类似的代码,但只有这一个出了问题,实在不知道原因何在,请高手指点
NTSTATUS
    __stdcall
    MySetSystemInformation(
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
    IN OUT PSYSTEM_LOAD_AND_CALL_IMAGE SysInfo,
    IN ULONG SystemInformationLength
    )
  {
    NTSTATUS Result = STATUS_SUCCESS;
    //PHANDLELIST是一个指向HANDLELIST的指针,HANDLELIST是我自己定义的一个结构体
    //用来保存一些数据,这些数据将会传给用户层控制程序
    PHANDLELIST pOldStart = pStartHandle,pNewStartHandle;

    __try
    {
      KeClearEvent(pCanUnload_ZwSetInfo);

      if (SystemInformationClass == SystemLoadAndCallImage)
      {
        pNewStartHandle = (PHANDLELIST)ExAllocatePoolWithTag(NonPagedPool,
          sizeof(HANDLELIST),
          'kooh');
        KdPrint(("pNewStartHandle=%p\n",pNewStartHandle));
        if (pNewStartHandle)
        {
          pNewStartHandle->bCanLoad = TRUE;
          pNewStartHandle->bNeedToBeQueryed = TRUE;
          pNewStartHandle->hFileHandle = NULL;
          pNewStartHandle->PID = (ULONG)PsGetCurrentProcessId();
          pNewStartHandle->TID = (ULONG)PsGetCurrentThreadId();
          pNewStartHandle->pNext = pOldStart;
          pNewStartHandle->pPrevious = NULL;
          if (pOldStart)
          {
            pOldStart->pPrevious = pNewStartHandle;
          }
          KeInitializeEvent(&pNewStartHandle->CanContinue,
            NotificationEvent,
            FALSE);
          RtlZeroMemory(pNewStartHandle->FileName,
            min(FILENAMESIZE,SysInfo->ModuleName.Length + 2));
          RtlCopyMemory(pNewStartHandle->FileName,
            SysInfo->ModuleName.Buffer,
            min(FILENAMESIZE,SysInfo->ModuleName.Length + 2));
          KdPrint(("ZwSet:%ws\n",pNewStartHandle->FileName));
          pStartHandle = pNewStartHandle;
          //通知用户层
          KeSetEvent(pEventApp,
            IO_NO_INCREMENT,
            FALSE);
          KeClearEvent(pEventApp);

          //等待用户做出选择
          //问题就出在这里了,只要有这句代码,而且用户层选择了允许
          //即设置了pNewStartHandle->bCanLoad = TRUE,就会出错
          //但如果用户层选择了拒绝,即设置pNewStartHandle->bCanLoad = FALSE就没问题,如果去掉这句代码则也不会出现问题,pOldZwSetSysInfo确认是正确的

          KeWaitForSingleObject(&pNewStartHandle->CanContinue,
            Executive,
            KernelMode,
            FALSE,
            NULL);
          KeClearEvent(&pNewStartHandle->CanContinue);
         
          if (pNewStartHandle->bCanLoad)
          {
            KdPrint(("ZwSet CanContinue\npOldZwSetSysInfo=%p\n",pOldZwSetSysInfo));
            //执行完下面这句代码后竟然又跳回到了本函数的入口
            Result = pOldZwSetSysInfo(SystemInformationClass,
              SysInfo,
              SystemInformationLength);
            KdPrint(("Called Old ZwSet\n"));
          }
          else
            Result = STATUS_UNSUCCESSFUL;

          if (pNewStartHandle == pStartHandle)
          {
            pStartHandle = pNewStartHandle->pNext;
          }
          if (pNewStartHandle->pNext)
          {
            pNewStartHandle->pNext->pPrevious = pNewStartHandle->pPrevious;
          }
          if (pNewStartHandle->pPrevious)
          {
            pNewStartHandle->pPrevious->pNext = pNewStartHandle->pNext;
          }
          KdPrint(("ZwSet Free:%p\n",pNewStartHandle));
          ExFreePoolWithTag(pNewStartHandle,
            'kooh');
        }
        else
        {
          KdPrint(("Can't get mem"));
          Result = pOldZwSetSysInfo(SystemInformationClass,
            SysInfo,
            SystemInformationLength);
        }
      }
      else
      {
        Result = pOldZwSetSysInfo(SystemInformationClass,
          SysInfo,
          SystemInformationLength);
      }
    }

    __finally
    {
      KeSetEvent(pCanUnload_ZwSetInfo,
        IO_NO_INCREMENT,
        FALSE);
    }

    return Result;
  }

2021 KCTF 秋季赛 防守篇-征题倒计时(11月14日截止)!

收藏
点赞0
打赏
分享
最新回复 (6)
雪    币: 109
活跃值: 活跃值 (134)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
combojiang 活跃值 26 2008-3-7 21:47
2
0
为了方便别人帮你调试,麻烦把你的代码附件附上吧
雪    币: 479
活跃值: 活跃值 (659)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2008-3-7 22:30
3
0
Event设置的好像有问题。
无code不好调试啊~~
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
syzhaoyu 活跃值 2008-3-7 23:16
4
0
我正在整理代码,弄好了就发上来
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
syzhaoyu 活跃值 2008-3-7 23:56
5
0
我的编译环境是VC2005+WDK 6001.18000,主要代码在TestHook.rar\TestHook\TestHook\Testhook.cpp中, 编译好的TestHook.sys放在C盘根目录下,然后运行LoadTestHook.exe即可,然后运行一个使用了ZwLoadDriver的程序如IceSword,就可以看见效果了,但是运行使用了ZwSetSystemInformation的程序时就会出问题,附件中的ZwSetSysInfo.exe即是一个调用了ZwSetSystemInformation来加载驱动的小程序,它所调用的Driver1.sys也要放到C盘根目录

先谢谢各位啦
上传的附件:
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
syzhaoyu 活跃值 2008-3-7 23:58
6
0
ZwSetInfo.exe忘记发了
上传的附件:
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
syzhaoyu 活跃值 2008-3-8 18:04
7
0
自己顶上
我还是没找到解决办法
游客
登录 | 注册 方可回帖
返回