栈分析:
0: kd> kv
00 98803784 99d60f41 88e0fe00 98803814 98803810 DoubleCBFilter!PfpGetFullPathPreCreate (FPO: [Non-Fpo]) (CONV: stdcall)
01 98803890 99d61303 00000000 86f1d020 88e0fe00 DoubleCBFilter!PfpCommonCreate+0x301 (FPO: [Non-Fpo]) (CONV: stdcall)
02 988038b0 83e50593 86f1d020 88e0fe00 8889937c DoubleCBFilter!PfpCreate+0xb3 (FPO: [Non-Fpo]) (CONV: stdcall)
03 988038c8 840602a9 9ab230df 98803a70 00000000 nt!IofCallDriver+0x63
.....
第一部分:
.frame 02 <----切换到PfpCreate的栈上下文中
然后命令: uf DoubleCBFilter!PfpCreate+0xb3 <-----反汇编pfpCreate代码
可以看到:
DoubleCBFilter!PfpCreate+0xa4 [filespycreate.c @ 676]:
676 99d612f4 8b550c mov edx,dword ptr [ebp+0Ch] <---获取参数3,是一个入参
676 99d612f7 52 push edx
<---参数3入栈
676 99d612f8 8b4508 mov eax,dword ptr [ebp+8]
<---计算参数2,也是一个入参,所以也用ebp来计算
676 99d612fb 50 push eax
676 99d612fc 6a00 push 0
<---这个是参数1,是个NULL
676 99d612fe e83df9ffff call DoubleCBFilter!PfpCommonCreate (99d60c40) <----开始调用PfpCommonCreate
对应的代码: return PfpCommonCreate(NULL, DeviceObject, Irp);
(注: NTSTATUS PfpCreate(
__in PDEVICE_OBJECT DeviceObject, <----这个是入参1, 放在bp+8位置
__in PIRP Irp
<----这个是入参2, 放在bp+0C位置,栈中的参数存放从(栈顶向下:参数N...参数1)
) <-----这个是PfpCreate的参数
}
第二部分:
.frame 01 <-----切换到01的栈上下文中
.open -a DoubleCBFilter!PfpCommonCreate <----可以直接打开源码
然后命令: uf DoubleCBFilter!PfpCommonCreate
太多找不到就.cls清理屏幕
温习上次的调试说明:
DoubleCBFilter!PfpCommonCreate
354 99d60c40 55 push ebp
<-----先保存上次的ebp
354 99d60c41 8bec mov ebp,esp
<-----然后保存当前的esp到ebp上,此时的ebp就是新的栈顶,最后还可以用这个ebp来直接恢复esp
354 99d60c43 81ecf4000000 sub esp,0F4h
<-----给当前的函数创建局部变量空间
...............
//这里都是call函数PfpGetFullPathPreCreate()之前的参数入栈的操作,看后面的马上要调用的函数原型
484 99d60f2c 8b4d0c mov ecx,dword ptr [ebp+0Ch]
<--------因为是入参,直接用ebp来获取计算
484 99d60f2f 51 push ecx
<--------参数4,入栈
484 99d60f30 8d5580 lea edx,[ebp-80h]
<--------这个是局部变量,所以是ebp减去80的位置了,前面说了,ebp下面是局部变量空间
484 99d60f33 52 push edx
<--------参数3,入栈
484 99d60f34 8d4584 lea eax,[ebp-7Ch]
484 99d60f37 50 push eax
484 99d60f38 8b4d10 mov ecx,dword ptr [ebp+10h]
<--------这个也是之前的入参
484 99d60f3b 51 push ecx
484 99d60f3c e81f040000 call DoubleCBFilter!PfpGetFullPathPreCreate (99d61360) <----又开始进行新函数调用了!!
(注: 调用的函数原型
NTSTATUS PfpGetFullPathPreCreate(
PIRP pIrp,
WCHAR** pszFullPathWithOutDeviceName,
ULONG*
szLenReturnedInBytes,
PDEVICE_OBJECT pDevice)
)
-----------------
从上面这个简单的栈分析,就可以看到函数的每次的在栈中的调用运行关系
dt _tagstruct addr <-----这样就可以直接看当前栈的变量了
dv 所有变量