
iis日志
-
2023年2月15日发(作者:)IIS日志文件分析器ReadLogs探秘(五)-电脑
资料
意外监控器所使用的CDB命令
(作者:青苹果工作室编译
意外监控器所使用的一些命令在调试的时候是有用的,
Kv命令
意外监控器运行的第一个命令是Kv。它显示的是在挑错时刻激
活的流的函数调用返回堆栈。读这个堆栈是从底部向顶部:最顶部
的函数是调用的最后一个函数,而最底部的函数则是这个流调用的
第一个函数。
输出样本(x86平台):
ChildEBPRetAddrArgstoChild
00f8fdf853d0f7f3003070ac6d480x1000113c[Stdca
ll:0]
00f8fe5c53d0ad4500306ee400f8ff0c00f8ff4cw3svc!AddFilterR
esponseHeaders+0x26
00f8ff2053d01ce600f8ff4c00f8ff68003154b0w3svc!HTTP_REQUE
ST__DoDirList+0x2f7
00f8ff5053d01f5600f8ff685460w3svc!&127;ole32
_NULL_THUNK_DATA+0x96e
00f8ff6c53d04adbw3svc!&127;ole32
_NULL_THUNK_DATA+0xbde
00f8ff88539895d0w3svc!HTTP_REQ_B
ASE__`vftable+0x1fd3
00f8ffb877f04f2cabcdef01776a225400000028infocomm!AtqPool
Thread+0x1c8
00f8ffec9408abcdefkernel32!BaseThr
eadStart+0x51
输出样本(alpha平台):
Callee-SPReturn-RACallSite
0815ffc077e6f5b8:ntdll!DbgBreakPoint+0x4
0815ffc077e6cc48:KERNEL32!DebugBreak+0x8
0815ffd000000000:KERNEL32!BaseThreadStart+0x60
函数的调用返回堆栈列出了在给定流中激活的所有函数。意思是
函数1调用了函数2,函数2最终又调用了函数3,等等。当最后一
个被调用的函数结束了其工作时,它就“展开”,或者说是返回了
调用它的那个函数;而那个函数结束后也返回调用它的函数,依次
类推。调用返回堆栈列出了什么调用了什么,以及函数正确运行后
代码如何返回。因为这个堆栈是故障堆栈,你就可以知道在堆栈顶
部列出的函数所发生的访问冲突。但是这不一定说明这个函数引发
了实际问题。问题也许是由于另一个函数向堆栈传递了错误的指针,
或者甚至于是由一个不同的流引起的。在堆和堆栈冲突中可以看到
有关详细内容。
请注意当确认文件没有装载符号,堆栈顶部的命令并不列出调用
命令。当堆栈装载到ReadLogs时,通过使用装载的模块的列表,它
试图将这个函数调用分解到一个友好的名字中。首先它获得进行调
用的内存地址(0x1000113c),然后寻找拥有这个内存地址的装载的
DLL。
!
IIS调试器增加到CDB的一个扩展是文件。如果这
个文件存在于WindowsNT目录中(或本地调试目录中),这样CDB
就可以使用这个命令了。如果在这个扩展命令之前增加一个!符号,
那么CDB就寻找这个DLL,然后将这个命令传递到扩展。这时,你
调用Inetdbg扩展,并在mod命令中传递。这个命令在Inetinfo内
存空间中堆积了所有当前装载的模块的列表,并返回下面的信息
(这是一个省略的列表):
输出样本:
StartEndEntryPath
6C:WINNTSystem32inetsrvinetinfo.e
xe
77f6000077fbcC:
78007800546dC:
77f0000077f5e00077f01000C:
77dc000077dfe00077dc1000C:
77e7000077ec100077e7a2a2C:
77ed000077efcC:
1C:
如果想要确定是什么代码正在Inetinfo内存空间运行,这些信
息是有用的。在前面的kv命令中,你的函数是未分解的。要分解它,
你要使用内存地址-—0x1000113c,看它是否在
的起始地址和结束地址范围内。
!
Inetdbg可以使用的另一个扩展是ver命令。这个命令列出了从
装载的DLL中提取出来的所有版本信息。大多数DLL的版本信息都
是在实际文件的头部。这个扩展就试图从这里获取这些信息:
输出样本:
Module@0x01000000=
dwFileFlags=0x00000000(FREE)
CompanyName=MicrosoftCorporation
FileDescription=InternetInformationServicesApplicationv1
.0
FileVersion=4.00
InternalName=
LegalCopyright=Copyright(C)MicrosoftCorp.1981-1996
riginalFilename=
ProductName=Microsoft(R)WindowsNT(TM)
OperatingSystemProductVersion=4.00
Module@0x77f60000=
dwFileFlags=0x00000000(FREE)
CompanyName=MicrosoftCorporation
FileDescription=NTLayerDLL
FileVersion=4.00
InternalName=
LegalCopyright=Copyright(C)MicrosoftCorp.1981-1996
riginalFilename=
ProductName=Microsoft(R)WindowsNT(TM)
OperatingSystemProductVersion=4.00
在这个例子中,没有列出存在问题的DLL(),
注意:在某些运行WindowsNTServicePace(SP)4的机器上,ver
命令运行是完全失败的。如果希望获取适当的版本信息,可以将这
个命令运行两次。这时ReadLogs就会特意寻找一个没有包含任何错
误的输出的版本,并用这个设置来显示版本信息。如果这两次运行
都失败了,ReadLogs就不能显示版本信息了。
~*kb
~*kb命令指示调试器为内存空间上的每个流保存一套堆栈的副
本(同kv)。(~命令说\"选择一个流\";*命令说\"所有的流\",然后
你可以加上你想要对所有流运行的任何命令,这里是kb)。你可以
用这个命令来看看在发生冲突的时候发生了一些别的什么。如果你
在排除100%CPU利用率和死锁的故障,也可以使用这个信息。每个
堆栈都同kv堆栈的分析方法相同。
运行调试器,你可以用这个信息排除100%CPU利用率的故障,在
你捕捉到流计数器的地方还可以运行一个性能监控器日志。对于一
个100%CPU利用率的问题,你可以手动给调试器挑错,然后停止
PerfMon日志。通过分析PerfMon日志,你就获取了正在使用CPU
的流的号码。你还可以在~*kb命令所列出的有同样号码的流上使用
ReadLogs(或手动检查调试日志文件)。这样就告诉你流在做什么
并指出“罪犯”是谁。
注意:要捕捉流的输出,你必须使用PerfMon的日志功能,要等
到100%利用率发生才能起动日志。仅仅在图表中看看流会得到错误
的流号码。
ueip-50eip+20(只在x86平台)
这个u命令指示调试器显示存在于提供的地址范围内的汇编代码。
这时你是在请求从扩展指令指针(EIP)寄存器所指向的50个字节
之前到EIP指向的20个字节之后的那些代码。EIP寄存器通常指向
要执行的代码的下一行。你可以看到在冲突发生时代码在做些什么。
输出样本(缩略):
ntdll!RtlpWaitForCriticalSection+0x45:
77f6cc160000add[eax],al
77f6cc18008b0d805afaadd[ebx+0xfa5a800d],cl
77f6cc1e7739jantdll!RtlpWaitForCriticalSection+0x88(77f6
cc59)
77f6cc2048deceax
77f6cc212475andal,0x75
77f6cc232333andesi,[ebx]
77f6cc25c8rorbyteptr[ecx+0x46890446],0x8
77f6cc2c89460cmov[esi+0xc],eax
77f6cc2f894610mov[esi+0x10],eax
!locks
这个!locks命令显示的信息是关于当前运行代码的哪个部分被
标记为关键部分(CS)。有关CS的详细讨论可以看理解锁那部分。
输出样本:
CritSecw3svc!MDIDMappingTable+100at68c2b1b0
LockCount0
RecursionCount1
OwningThread156
EntryCount0
ContentionCount0
!–g
这个atq命令显示的信息与IIS非同步流排队有关。流排队是
IIS特有的功能。当一个新的请求进入IIS时,它就需要处理一个
流。由于创建一个流从时间和CPU使用的方面来说是比较昂贵的,
因此IIS保持着一套随时处理引入的请求的工作流;IIS则管