windbg 分析pchunter导致的蓝屏

转载自:https://bbs.pediy.com/thread-227076.htm

环境

被调试机:7600.16385.x86fre.win7_rtm.090713-1255

调试机:win10,

调试工具:windbg proview

导致蓝屏的软件:pchunter

视频:https://www.youtube.com/watch?v=8tBRtlvapWU

描述

运行pchunter,点击“网络”卡片页时,系统就会蓝屏。

对第一次蓝屏捕捉到的信息进行分析。这里只列出了一些重点信息及描述。

BUG的概述

1

2

3

4

5

6

7

8

9

PAGE_FAULT_IN_NONPAGED_AREA (50)

Invalid system memory was referenced.  This cannot be protected by try-except.

Typically the address is just plain bad or it is pointing at freed memory.

Arguments:

Arg1: fffffff5, memory referenced. 

Arg2: 00000000, value 0 = read operation, 1 = write operation.

Arg3: 840bf2ee, If non-zero, the instruction address which referenced the bad memory

    address.

Arg4: 00000000, (reserved)

 

  1. BugCheckCode:PAGE_FAULT_IN_NONPAGED_AREA 是微软定义的Bug编码,其值为0x00000050.下面英文说的是,系统使用了无效的系统内存导致触发异常,且该异常没能被处理。可能是内存地址被破坏了或被释放了。
  2. Arguments,为参数错误检查。这里检测到的信息是,参数1:指出当前系统访问当地址是0xfffffff5;参数2:是说当前的操作是读;参数3:是说当前指令的地址是0x840bf2ee;参数4:保留。

BUG的详情

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

Debugging Details:

------------------

KEY_VALUES_STRING: 1

TIMELINE_ANALYSIS: 1

DUMP_CLASS: 1

DUMP_QUALIFIER: 0

BUILD_VERSION_STRING:  7600.16385.x86fre.win7_rtm.090713-1255

DUMP_TYPE:  0

BUGCHECK_P1: fffffffffffffff5

BUGCHECK_P2: 0

BUGCHECK_P3: ffffffff840bf2ee

BUGCHECK_P4: 0

READ_ADDRESS:  fffffff5 

FAULTING_IP: 

nt!ObpQueryNameString+2b

840bf2ee 0fb6460c        movzx   eax,byte ptr [esi+0Ch]

......

DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT

PROCESS_NAME:  PCHunter32.exe

  1. BUILD_VERSION_STRING:指出了运行的系统版本信息。
  2. BUGCHECK_P1~4:和BUG概述中的基本一致。
  3. READ_ADDRESS:读地址为0xfffffff5的内存。
  4. FAULTING_IP:导致Bug的地址。即该bug发生在nt!ObpQueryNameString+2b处,该地址的需要执行的指令是
    movzx   eax,byte ptr [esi+0Ch]
  5. DEFAULT_BUCKET_ID:故障类型。这里指出是win7驱动发生故障。
  6. PROCESS_NAME:与该BUG相关的进程。

陷阱帧

 

1

2

3

4

5

6

7

8

9

10

11

12

TRAP_FRAME:  98926954 -- (.trap 0xffffffff98926954)

.trap 0xffffffff98926954

ErrCode = 00000000

eax=98926a1c ebx=00000000 ecx=98926abc edx=98926a6c esi=ffffffe9 edi=00000001

eip=840bf2ee esp=989269c8 ebp=98926a2c iopl=0         nv up ei pl zr na pe nc

cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010246

nt!ObpQueryNameString+0x2b:

840bf2ee 0fb6460c        movzx   eax,byte ptr [esi+0Ch]     ds:0023:fffffff5=??

.trap

Resetting default scope

 

LAST_CONTROL_TRANSFER:  from 83f1ee71 to 83ead394

  1. TRAP_FRAME :陷阱帧,是一个nt!_KTRAP_FRAME结构体。 KTRAP_FRAME 用于在系统处理异常或中断期间,保存CPU的寄存器的内容。 KTRAP_FRAME结构通常分配在线程的内核模式堆栈中。陷阱帧的一小部分由CPU填充,作为其自身中断和异常处理的一部分,陷阱帧的其余部分由Windows提供的软件异常和中断处理程序 创建 (例如KiTrap0E()、KiPageFault KiInterruptDispatch 等函数)。
  2. LAST_CONTROL_TRANSFER:最后的控制权转让,也就是调用栈中的最后一个CALL。这里,在地址0x83f1ee71调用了0x83ead394

调用堆栈

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

STACK_TEXT:  

9892649c 83f1ee71 00000003 21db833f 00000065 nt!RtlpBreakWithStatusInstruction

989264ec 83f1f96d 00000003 88621d48 00000000 nt!KiBugCheckDebugBreak+0x1c

989268b0 83ec78e3 00000050 fffffff5 00000000 nt!KeBugCheck2+0x68b

9892693c 83e885f8 00000000 fffffff5 00000000 nt!MmAccessFault+0x106

9892693c 840bf2ee 00000000 fffffff5 00000000 nt!KiTrap0E+0xdc

98926a2c 840bfa7a 00000001 98926a6c 00000050 nt!ObpQueryNameString+0x2b

98926a48 8bc76887 00000001 98926a6c 00000050 nt!ObQueryNameString+0x18

98926af4 8bc77245 03fc016c 001ffeb4 00000000 PCHunter32aq+0x52887

98926b2c 8bc772d3 00000010 0000013c 98926bfc PCHunter32aq+0x53245

98926b3c 8bca740b 00000000 00000000 03fc0020 PCHunter32aq+0x532d3

98926bfc 83e7e4bc 886240d8 88722178 88722178 PCHunter32aq+0x8340b

98926c14 8407feee 8862cc68 88722178 887221e8 nt!IofCallDriver+0x63

98926c34 8409ccd1 886240d8 8862cc68 00000000 nt!IopSynchronousServiceTail+0x1f8

98926cd0 8409f4ac 886240d8 88722178 00000000 nt!IopXxxControlFile+0x6aa

98926d04 83e8542a 00000258 00000000 00000000 nt!NtDeviceIoControlFile+0x2a

98926d04 779464f4 00000258 00000000 00000000 nt!KiFastCallEntry+0x12a

001263e0 77944cac 75d0a08f 00000258 00000000 ntdll!KiFastSystemCallRet

001263e4 75d0a08f 00000258 00000000 00000000 ntdll!ZwDeviceIoControlFile+0xc

00126444 768eec25 00000258 04470140 00126538 KERNELBASE!DeviceIoControl+0xf6

00126470 008cf640 00000258 04470140 00126538 kernel32!DeviceIoControlImplementation+0x80

00126520 00409ffa 00000000 0012c400 00000000 PCHunter32+0x4cf640

...

  1. 前面5个函数是系统用来保存现场(寄存器)以及检测崩溃信息。
  2. 从BUG详情中已经知道,崩溃地址是nt!ObpQueryNameString+0x2b。是由于[esi+0Ch]=0xfffffff5导致的。

追踪崩溃源头

查看 nt!ObpQueryNameString ~ nt!ObpQueryNameString+0x2b的 反汇编:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

uf nt!ObpQueryNameString

nt!ObpQueryNameString:

840bf2c3 6a44            push    44h

840bf2c5 68f0c3e583      push    offset nt! ?? ::FNODOBFM::`string'+0x1790 (83e5c3f0)

840bf2ca e83932dfff      call    nt!_SEH_prolog4 (83e72508)

840bf2cf 8b7d08          mov     edi,dword ptr [ebp+8]

840bf2d2 c745d8010000c0  mov     dword ptr [ebp-28h],0C0000001h

840bf2d9 33db            xor     ebx,ebx

840bf2db 895dc4          mov     dword ptr [ebp-3Ch],ebx

840bf2de 895de0          mov     dword ptr [ebp-20h],ebx

840bf2e1 c645e701        mov     byte ptr [ebp-19h],1

840bf2e5 885de6          mov     byte ptr [ebp-1Ah],bl

840bf2e8 8d77e8          lea     esi,[edi-18h]

840bf2eb 8975d0          mov     dword ptr [ebp-30h],esi

840bf2ee 0fb6460c        movzx   eax,byte ptr [esi+0Ch]

上述代码有关esi的整理如下:

1

2

3

4

5

------------------------------------------------------------------------------------------

840bf2cf 8b7d08          mov     edi,dword ptr [ebp+8]      ;edi=arg1

840bf2e8 8d77e8          lea     esi,[edi-18h]              ;esi=[arg1-18h]

840bf2ee 0fb6460c        movzx   eax,byte ptr [esi+0Ch]     ;eax=*(byte*)(esi+0c) error

------------------------------------------------------------------------------------------

这说明,导致esi+0ch崩溃的是因为arg1=1 。通过查看调用栈可知:arg1 是 nt!ObQueryNameString 传递给   nt!ObpQueryNameString 的第一个参数。

1

2

98926a2c 840bfa7a 00000001 98926a6c 00000050 nt!ObpQueryNameString+0x2b

98926a48 8bc76887 00000001 98926a6c 00000050 nt!ObQueryNameString+0x18

 
查看 nt!ObQueryNameString~ nt!ObQueryNameString +0x18的反汇编:

1

2

3

4

5

6

7

8

9

10

11

12

13

uf nt!ObQueryNameString

nt!ObQueryNameString:

840bfa62 8bff            mov     edi,edi

840bfa64 55              push    ebp

840bfa65 8bec            mov     ebp,esp

840bfa67 6a00            push    0

840bfa69 ff7514          push    dword ptr [ebp+14h]    ;

840bfa6c ff7510          push    dword ptr [ebp+10h]    ;

840bfa6f ff750c          push    dword ptr [ebp+0Ch]    ;

840bfa72 ff7508          push    dword ptr [ebp+8]      ;arg1:

840bfa75 e849f8ffff      call    nt!ObpQueryNameString (840bf2c3)

840bfa7a 5d              pop     ebp

840bfa7b c21000          ret     10h

分析 nt!ObQueryNameString 传给 nt!ObpQueryNameString的第一个参数是从哪里来的?都做了什么操作?

从汇编代码中很容易看出,传递给 nt!ObpQueryNameString的第一个参数也是 nt!ObQueryNameString的第一个参数,而且 nt!ObQueryNameString 未修改参数1. 

 

补充:

ObQueryNameString 函数:返回指定内核对象的名称。

1

2

3

4

5

6

7

NTKERNELAPI NTSTATUS ObQueryNameString(

  PVOID                    Object,

  POBJECT_NAME_INFORMATION ObjectNameInfo,

  ULONG                    Length,

  PULONG                   ReturnLength

);<span style="color:rgb(0, 0, 0); font-family:none; font-size:15px;">

</span>

参数

Object:内核对象的指针,该值不能为NULL.

ObjectNameInfo:由用户提供的存放返回值得缓冲区,若不知大小则可以为NULL,由ReturnLength返回需要的缓冲区大小。

Length: 缓冲区的字节数.该值必须包括OBJECT_NAME_INFORMATION结构和对象名称的长度。根据DDK上推荐该值为1024 

ReturnLength: 返回的数据的大小。此值包括OBJECT_NAME_INFORMATION结构和对象名称的长度 

 

接下来分nt!ObQueryNameString 的参数1的来历。 

1

2

3

98926a48 8bc76887 00000001 98926a6c 00000050 nt!ObQueryNameString+0x18

98926af4 8bc77245 03fc016c 001ffeb4 00000000 PCHunter32aq+0x52887

98926b2c 8bc772d3 00000010 0000013c 98926bfc PCHunter32aq+0x53245

使用 ub 8bc77245 找到 nt!ObQueryNameString 的父函数的入口地址:

1

2

3

4

5

6

7

8

9

10

1: kd> ub 8bc77245

PCHunter32aq+0x53233:

8bc77233 7230            jb      PCHunter32aq+0x53265 (8bc77265)

8bc77235 03f0            add     esi,eax

8bc77237 2bf8            sub     edi,eax

8bc77239 83ff0c          cmp     edi,0Ch

8bc7723c 7227            jb      PCHunter32aq+0x53265 (8bc77265)

8bc7723e 57              push    edi

8bc7723f 56              push    esi

8bc77240 e84bf5ffff      call    PCHunter32aq+0x52790 (8bc76790)//8bc76790为nt!ObQueryNameString的父函数入口

把 PCHunter32aq+0x52790 (8bc76790)记作 function_1。用uf  PCHunter32aq+0x52790命令 查看function_1的汇编代码,这里主要关注 PCHunter32aq+0x52790 ~PCHunter32aq+0x52887之间的代码,分析 function_1 在调用nt!ObQueryNameString函数前对 nt!ObQueryNameString函数 的参数1做了哪些操作?

 

由于 PCHunter32aq+0x52790~PCHunter32aq+0x5282c之间的代码没有对 nt!ObQueryNameString函数的参数1做操作,所以下文的代码省略了该部分内容

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

PCHunter32aq+0x5282c:

8bc7682c 57              push    edi

8bc7682d 8d3c00          lea     edi,[eax+eax]

8bc76830 e8fb780200      call    PCHunter32aq+0x7a130 (a287e130)    ;Pchunter获取一些内核信息

8bc76835 8945ec          mov     dword ptr [ebp-14h],eax            ;ebp-14h=PCHunter32aq+0x7a130返回的缓冲区地址,是一个数组

8bc76838 85c0            test    eax,eax

8bc7683a 0f84c8000000    je      PCHunter32aq+0x52908 (8bc76908)  Branch

 

PCHunter32aq+0x52840:

8bc76840 8b08            mov     ecx,dword ptr [eax]

8bc76842 894df0          mov     dword ptr [ebp-10h],ecx

8bc76845 c745f400000000  mov     dword ptr [ebp-0Ch],0

8bc7684c 85c9            test    ecx,ecx

8bc7684e 0f849f000000    je      PCHunter32aq+0x528f3 (8bc768f3)  Branch

 

PCHunter32aq+0x52854:

8bc76854 56              push    esi

8bc76855 8d700c          lea     esi,[eax+0Ch]

8bc76858 eb06            jmp     PCHunter32aq+0x52860 (8bc76860)  Branch

;------------------------------

;分析1

;8bc76840 8b08            mov     ecx,dword ptr [eax]

;8bc76855 8d700c          lea     esi,[eax+0Ch]

;通过这两处推测 eax 为一个结构体

;------------------------------

PCHunter32aq+0x52860:

8bc76860 0fb656fc        movzx   edx,byte ptr [esi-4]

8bc76864 3b55f8          cmp     edx,dword ptr [ebp-8]

8bc76867 7576            jne     PCHunter32aq+0x528df (8bc768df)  Branch

 

PCHunter32aq+0x52869:

8bc76869 8b06            mov     eax,dword ptr [esi]

8bc7686b 85c0            test    eax,eax

8bc7686d 7470            je      PCHunter32aq+0x528df (8bc768df)  Branch

 

PCHunter32aq+0x5286f:

8bc7686f 8b4004          mov     eax,dword ptr [eax+4]

8bc76872 85c0            test    eax,eax        ;只判断了eax=0的情况,而当前情况是eax=1,所以导致崩溃

8bc76874 7469            je      PCHunter32aq+0x528df (8bc768df)  Branch

;------------------------------

;分析2

;EAX=[EBP-14H]

;ESI=&[EAX+0CH] ESI存放一个指针,这个指针指向一个结构体,这个结构体就是数组单个元素的结构体

;@$t4:arg1 LPVOID object

;r @$t0=EBP

;r @$t1=ESI

;r @$t2=EBP-8=00000007 //通过内存查看到该处的值为7

;.if( by(@$t1-4)==7 )

;{

;    r @$t3=poi(@$t1);

;    .if(@$t3!=0)

;    {

;       r @$t4=poi(@$t3+4);

;       dd @$t3 L4;

;        r @$t4;

;    }

;}

;------------------------------

PCHunter32aq+0x52876:

8bc76876 8d4dc8          lea     ecx,[ebp-38h]

8bc76879 51              push    ecx                    ; arg4:ReturnLength

8bc7687a 6a50            push    50h                    ; arg3:Length

8bc7687c 8d9578ffffff    lea     edx,[ebp-88h]

8bc76882 52              push    edx                    ; arg2:ObjectNameInfo

8bc76883 50              push    eax                    ; arg1:object

8bc76884 ff55e8          call    dword ptr [ebp-18h]    ; call nt!ObpQueryNameString

8bc76887 85c0            test    eax,eax

8bc76889 7554            jne     PCHunter32aq+0x528df (8bc768df)  Branch

------------------------------------------------------------------------------------------

....该处代码与nt!ObQueryNameString的参数1无关

------------------------------------------------------------------------------------------

PCHunter32aq+0x528df:

8bc768df 8b45f4          mov     eax,dword ptr [ebp-0Ch]

8bc768e2 40              inc     eax

8bc768e3 83c610          add     esi,10h

8bc768e6 8945f4          mov     dword ptr [ebp-0Ch],eax

8bc768e9 3b45f0          cmp     eax,dword ptr [ebp-10h]

8bc768ec 0f826effffff    jb      PCHunter32aq+0x52860 (8bc76860)  Branch

------------------------------

;分析3

;8bc76842 894DF0          MOV     DWORD PTR [EBP-10H],ECX

;8bc768E9 3B45F0          CMP     EAX,DWORD PTR [EBP-10H]

;通过这两处判断 EBP-10H 为一个 DWORD 值,

;8bc76860 与 8bc768E2 构成了一个循环

;而 EBP-0CH 为循环计数器

;而 EBP-10H 就是这个循环的最大次数 => 推测 EBP-14H 为一个数组类型 而 EBP-10H 为该数组的元素个数

;8bc768E3 83C610          ADD     ESI,10H => 推测 数组中的单个元素的大小为 10H

;@$t5=EAX=[ebp-0ch]=0 初始值为0; 此时为 61H

;查看数组中第61H个元素的内容

;数组的起始地址为 ESI= [EAX+0CH]

 

分析到这里function_1在调用 call    dword ptr [ebp-18h]; call nt!ObpQueryNameString时只检验了参数1是否为0,并没有校验是否为有效地址。

但我认为导致 nt!ObpQueryNameString的参数1位“1”的原因应该是在调用PCHunter32aq+0x7a130函数时造成的。有时间再研究吧,暂时到这里吧。

1

2

8bc76830 e8fb780200      call    PCHunter32aq+0x7a130 (a287e130)    ;获取一些内核信息

8bc76835 8945ec          mov     dword ptr [ebp-14h],eax            ;ebp-14h=获取的内核信息地址

dump文件下载:  050718-19328-01.dmp (148.47kb,18次下载)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值