首页
社区
课程
招聘
[求助]驱动遍历eprocess链表,蓝屏
发表于: 2013-8-21 17:11 7253

[求助]驱动遍历eprocess链表,蓝屏

2013-8-21 17:11
7253
小弟测试一个入门的驱动程序:在ring3 通过DeviceIoControl 与驱动通信,驱动将一个进程的部分信息(ID、进程名等)写进缓冲区,通过双机调试在 win7 home basic 虚拟机上可以运行,但在外面主机(win7 旗舰版)中,运行蓝屏,所以求助各位大大,指点迷津。

这是 DispatchDeviceControl 例程,用windbg 看了dump文件,指出貌似是在最后一句,return 是出错。。。

NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
  NTSTATUS status = STATUS_SUCCESS;

  ULONG dwPIdOffset;
  ULONG dwPLinkOffset;
  ULONG dwPNameOffset;
  ULONG dwPCreateTimeOffset;

  ULONG ulEprocess;
  ULONG ulFirstProcess, ulNextProcess;
  LIST_ENTRY*        ActiveProcessLinks;
  
  PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(pIrp);

  PVOID    pInBuffer      = pIrp->AssociatedIrp.SystemBuffer;
  PCHAR    pOutBuffer    = pIrp->AssociatedIrp.SystemBuffer;
  ULONG   inBufLength    = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  ULONG  outBufLength  = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  ULONG  ioControlCode  = irpStack->Parameters.DeviceIoControl.IoControlCode;

  switch (ioControlCode)
  {
  case IOCTL_PROCESSLIST:
    {
      ulFirstProcess = (ULONG)IoGetCurrentProcess();
      ulNextProcess = ulFirstProcess;

      dwPCreateTimeOffset = GetPlantformDependentInfo(CREATE_TIME_OFFSET);
      dwPIdOffset = GetPlantformDependentInfo(PROCESS_ID_OFFSET);
      dwPNameOffset = GetPlantformDependentInfo(FILE_NAME_OFFSET);
      dwPLinkOffset = GetPlantformDependentInfo(PROCESS_LINK_OFFSET);

      do 
      {
        memcpy(pOutBuffer, (void*)(ulNextProcess+dwPIdOffset), sizeof(ULONG));
        pOutBuffer += sizeof(ULONG);

        memcpy(pOutBuffer, (void*)(ulNextProcess+dwPCreateTimeOffset), sizeof(ULONG));
        pOutBuffer += sizeof(ULONG);

        memcpy(pOutBuffer, (void*)(ulNextProcess+dwPNameOffset), 15);
        pOutBuffer += 15;

        ActiveProcessLinks = (LIST_ENTRY*)*(ULONG*)(ulNextProcess + dwPLinkOffset);
        ulEprocess = (ULONG)ActiveProcessLinks->Flink;
        ulEprocess -=dwPLinkOffset;
        ulNextProcess = ulEprocess;

      } while (ulNextProcess != ulFirstProcess);
    }
    break;
  default:
    break;
  }

  pIrp->IoStatus.Status = STATUS_SUCCESS;
  pIrp->IoStatus.Information = (ULONG)pOutBuffer-(ULONG)pInBuffer;
  IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  return pIrp->IoStatus.Status;
}
先谢过了!

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
2
您传上来dump文件,大家一起看看。
2013-8-21 17:51
0
雪    币: 11
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
有效性啊有效性……不过在没看到完整dump前不敢断定
2013-8-21 17:56
0
雪    币: 1
活跃值: (1174)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
直接 return STATUS_SUCCESS 试试, 也许IRP已经被释放了
2013-8-21 18:27
0
雪    币: 304
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
已经上传了,谢谢啦!
2013-8-21 19:17
0
雪    币: 304
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
也试过,不过还是蓝屏了~~
2013-8-21 19:19
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
7
最后一句出错在 nt!ExpReleasePoolQuota,拷贝缓冲区时,超出缓冲区大小了吧?

ULONG   inBufLength    = irpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG  outBufLength  = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

inBufLength 和 outBufLength 具体值是多少?

您R3往下送的时候,怎么写的?
请贴出来(缓冲区建立的代码, DEVICE_IO_CONTROL 发送时的代码)

您可以尝试少拷贝一些内容,应该就不报错了
/*
do
      {
        memcpy(pOutBuffer, (void*)(ulNextProcess+dwPIdOffset), sizeof(ULONG));
        pOutBuffer += sizeof(ULONG);

        memcpy(pOutBuffer, (void*)(ulNextProcess+dwPCreateTimeOffset), sizeof(ULONG));
        pOutBuffer += sizeof(ULONG);

        memcpy(pOutBuffer, (void*)(ulNextProcess+dwPNameOffset), 15);
        pOutBuffer += 15;

        ActiveProcessLinks = (LIST_ENTRY*)*(ULONG*)(ulNextProcess + dwPLinkOffset);
        ulEprocess = (ULONG)ActiveProcessLinks->Flink;
        ulEprocess -=dwPLinkOffset;
        ulNextProcess = ulEprocess;

      } while (ulNextProcess != ulFirstProcess);        ///< 这里记录一个数目,看看向缓冲区一共拷贝了多少内容?
*/

真机上的进程列表很多,虚拟机里面可能较少

      {
        memcpy(pOutBuffer, (void*)(ulNextProcess+dwPIdOffset), sizeof(ULONG));
        pOutBuffer += sizeof(ULONG);

        memcpy(pOutBuffer, (void*)(ulNextProcess+dwPCreateTimeOffset), sizeof(ULONG));
        pOutBuffer += sizeof(ULONG);

        memcpy(pOutBuffer, (void*)(ulNextProcess+dwPNameOffset), 15);
        pOutBuffer += 15;

        ActiveProcessLinks = (LIST_ENTRY*)*(ULONG*)(ulNextProcess + dwPLinkOffset);
        ulEprocess = (ULONG)ActiveProcessLinks->Flink;
        ulEprocess -=dwPLinkOffset;
        ulNextProcess = ulEprocess;

      }        ///< 改成这样, 就拷贝一次, 驱动应该不会报错

得进程列表之前,应先发一个 IO_CTRL_CODE 给驱动,驱动报出,当前有多少个进程.

R3根据(进程数 * sizeof(进程结构)) 开辟Buffer.
再发 IO_CTRL_CODE 给驱动, (下发的缓冲区中包含Buffer的数量(sizeof(进程结构) * N))让驱动上报进程具体信息.
有可能进程数量有变化,  当缓冲区不够时,就不再往里面拷贝进程信息了.
这样靠谱些.

看了您的代码实现, 我觉得主要问题,在于没有判断R3提供的缓冲区到底有多大,就一股脑的往里面写,所以引起报错。

STACK_TEXT:  
b0891ab8 8413b77f 00000000 877bd4c8 8b04b5e0 nt!ExpReleasePoolQuota+0x21
b0891b18 840bd555 8704abc8 00000000 9a1f90e1 nt!ExFreePoolWithTag+0x779
b0891b64 8408417f 017bd508 b0891bac b0891ba4 nt!IopCompleteRequest+0xe6
b0891bb4 aa9f14fe 00222000 000003e8 00000000 nt!IopfCompleteRequest+0x3b4
WARNING: Stack unwind information not available. Following frames may be wrong.
b0891bfc 8405779c 8a7c1a08 877bd4c8 877bd4c8 AthenyDriver+0x14fe


您看Dump文件的堆栈调用, IoCompleteRequest之后,就是返回,您说可能在返回那错了.

看调用链, 是 IoCompleteRequest 内部会释放一些空间, 应该和pIrp有关, 但是因为我们代码中拷贝多了,覆盖了pIrp的未知空间, 使IoCompleteRequest 内部释放空间的操作失败了,引起报错。
2013-8-21 19:58
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
8
忘了引用您的原文了, 您看看上面我对您驱动的怀疑点.
2013-8-21 20:01
0
雪    币: 182
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
处理IDLE这个进程
2013-8-21 20:58
0
雪    币: 304
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
犀利呀。
兄弟,多谢啦,试了下,正是由于缓冲区太小的原因了
多谢指点啦。
也谢过楼上其他帮忙的兄弟!
2013-8-21 21:03
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
11
thanks~
2013-8-21 21:06
0
游客
登录 | 注册 方可回帖
返回
//