wenmo8 发布的文章

桌面堆可能不是你花很多时间考虑的事情,这是件好事。但是,有时您可能会遇到由于桌面堆耗尽而导致的问题,然后了解此资源会有所帮助。让我先说一下,在Vista中,内核地址空间的情况发生了显著的变化,而我今天所说的大部分内容并不适用于Vista。

我想提供一些关于桌面堆的后续信息。在第一篇文章中,我没有讨论64位Windows、3GB或Vista上与桌面堆相关的内存范围的大小。所以,不用再多说了,下面是各种平台上的相关大小。

Windows XP (32-bit)

· 48 MB = SessionViewSize (default registry value, set for XP Professional, x86)

· 20 MB = SessionViewSize (if no registry value is defined)

· 3072 KB = Interactive desktop heap size (defined in the registry, SharedSection 2nd value)

· 512 KB = Non-interactive desktop heap size (defined in the registry, SharedSection 3nd value)

· 128 KB = Winlogon desktop heap size

· 64 KB = Disconnect desktop heap size

Windows Server 2003 (32-bit)

· 48 MB = SessionViewSize (default registry value)

· 20 MB = SessionViewSize (if no registry value is defined; this is the default for Terminal Servers)

· 3072 KB = Interactive desktop heap size (defined in the registry, SharedSection 2nd value)

· 512 KB = Non-interactive desktop heap size (defined in the registry, SharedSection 3nd value)

· 128 KB = Winlogon desktop heap size

· 64 KB = Disconnect desktop heap size

Windows Server 2003 booted with 3GB (32-bit)

· 20 MB = SessionViewSize (registry value has no effect)

· 3072 KB = Interactive desktop heap size (defined in the registry, SharedSection 2nd value)

· 512 KB = Non-interactive desktop heap size (defined in the registry, SharedSection 3nd value)

· 128 KB = Winlogon desktop heap size

· 64 KB = Disconnect desktop heap size

在运行3GB时,您还可能看到堆大小减小。在初始化窗口管理器期间,尝试保留足够的会话视图空间,以容纳给定会话的预期桌面堆数。如果在SharedSection注册表值中指定的堆大小已增大,则保留会话视图空间的尝试可能会失败。当这种情况发生时,窗口管理器会回到桌面堆的一对“安全”大小(交互式为512KB,非交互式为128KB),并再次尝试保留会话空间,使用这些较小的数字。这可以确保即使注册表值对于20MB会话视图空间来说太大,系统仍然能够引导。

Windows Server 2003 (64-bit)

· 104 MB = SessionViewSize (if no registry value is defined; which is the default)

· 20 MB = Interactive desktop heap size (defined in the registry, SharedSection 2nd value)

· 768 KB = Non-interactive desktop heap size (defined in the registry, SharedSection 3nd value)

· 192 KB = Winlogon desktop heap size

· 96 KB = Disconnect desktop heap size

Windows Vista RTM (32-bit)

· Session View space is now a dynamic kernel address range. The SessionViewSize registry value is no longer used.

· 3072 KB = Interactive desktop heap size (defined in the registry, SharedSection 2nd value)

· 512 KB = Non-interactive desktop heap size (defined in the registry, SharedSection 3nd value)

· 128 KB = Winlogon desktop heap size

· 64 KB = Disconnect desktop heap size

Windows Vista (64-bit) and Windows Server 2008 (64-bit)

· Session View space is now a dynamic kernel address range. The SessionViewSize registry value is no longer used.

· 20 MB = Interactive desktop heap size (defined in the registry, SharedSection 2nd value)

· 768 KB = Non-interactive desktop heap size (defined in the registry, SharedSection 3nd value)

· 192 KB = Winlogon desktop heap size

· 96 KB = Disconnect desktop heap size

 

Windows Vista SP1 (32-bit) and Windows Server 2008 (32-bit)

· Session View space is now a dynamic kernel address range. The SessionViewSize registry value is no longer used.

· 12288 KB = Interactive desktop heap size (defined in the registry, SharedSection 2nd value)

· 512 KB = Non-interactive desktop heap size (defined in the registry, SharedSection 3nd value)

· 128 KB = Winlogon desktop heap size

· 64 KB = Disconnect desktop heap size

windowsvista引入了一个新的公共API函数:CreateDesktopEx,它允许调用者指定桌面堆的大小。
此外,GetUserObjectInformation现在包含一个新的标志,用于检索桌面堆大小(UOI_HEAPSIZE)。

 

什么是LPC

LPC(Local-Process-communicationandnotlocalprocedure-Calls)是一种在NT内核中实现的基于消息的高速通信机制。LPC可用于两个用户模式进程之间、用户模式进程与内核模式驱动程序之间或两个内核模式驱动程序之间的通信。一个例子是通过LPC通信的两个用户模式进程。像CSRSS.exe与SMSS.exe通信,在创建登录会话或任何与LSASS.exe。出于安全原因,通过lsa认证端口。用户模式进程与内核模式驱动程序通信的另一个例子是 KSecDD.sys司与LSASS.exe通信用于在读/写加密文件期间对EFS密钥进行加密和解密。
LPC使用两种不同的机制在客户端和服务器进程之间传递数据。它使用LPC消息缓冲区(对于小于304字节的数据),或者使用映射到客户机和服务器地址空间的共享内存部分(对于大于304字节的数据)。
除了用作在同一系统上运行的进程之间选择远程过程调用的协议外,LPC还用于整个系统,例如用于Win32应用程序与CSRSS.exe文件,安全参考监视器与LSASS的通信,WinLogon与LSASS的通信等。
LPC强制客户机进程和服务器进程之间的同步通信模型。Vista反对使用一种称为异步本地进程间通信(ALPC)的新机制来使用LPC。与LPC相比,ALPC有一个固有的优势,即从客户端到服务器的所有调用都是异步的,即客户端不需要阻塞/等待服务器响应消息。在Vista中,对lpcapis的旧应用程序调用会自动重定向到更新的alpcapi。

LPC APIs

LPC api是本机api,即它们在用户模式下通过NTDLL.dll在内核模式下NTOSKRNL.exe文件. lpcapis没有在Win32级别公开,因此Win32应用程序不能直接使用LPC工具。然而,在使用RPC时,Win32应用程序可以通过协议序列“ncalrpc”将LPC指定为其底层传输,从而间接地使用LPC。所有lpcapis都以单词“Port”结尾,这意味着LPC通信端点。

API

Description

NtCreatePort

Used by server to create a connection port

NtConnectPort

Used by client to connect to a connection port

NtListenPort

Used by server to listen for connection requests on the connection port.

NtAcceptConnectPort

Used by server to accept connection requests on the connection port

NtCompleteConnectPort

Used by server to complete the acceptance of a connection request

NtRequestPort

Used to send a datagram message that does not have a reply

NtRequestWaitReplyPort

Used to send a message and wait for a reply

NtReplyPort

Used to send a reply to a particular message

NtReplyWaitReplyPort

Used to send a reply to a particular message and wait for a reply to a previous message

NtReplyWaitReceivePort

Used by server to send a reply to the client and wait to receive a message from the client

NtImpersonateClientOfPort

Used by server thread to temporarily borrow the security context of a client thread

下图说明了LPC服务器进程侦听来自潜在客户端的连接请求所采取的步骤,以及客户端连接到侦听服务器所采取的步骤。

 

 

                              LPC客户机-服务器连接建立顺序

注意:许多服务器进程使用NtReplyWaitReceivePort()API而不是NtListenPort()。NtListenPort()除去连接请求之外的所有LPC消息。因此NtListenPort()只能用于第一个连接。对于以后的连接请求,使用NtReplyWaitReceivePort()。

下图说明了LPC客户机向已建立连接的LPC服务器发送请求所采取的步骤,以及服务器响应消息所采取的步骤。

 

 

                            客户端-服务器数据传输序列

 

LPC Data Structures

LPC Port Data Structure

LPC Port被称为端口。LPC实现使用相同的端口结构来表示各种类型的端口。LPC使用的端口是服务器连接端口,这些端口是由服务器进程创建的用于接受来自客户端的传入连接的命名端口。客户机通信端口由客户机进程创建以连接到服务器进程和服务器进程创建的服务器通信端口。

 

 

                   LPC端口类型及其关系

LPCP_PORT_OBJECT是LPC用来表示LPC端口的内部数据结构。LPCP_PORT_对象是从带有标记“PORT”的分页池中分配的。

kd> dt nt!_LPCP_PORT_OBJECT+0x000ConnectionPort : Ptr32 _LPCP_PORT_OBJECT+0x004ConnectedPort : Ptr32 _LPCP_PORT_OBJECT+0x008MsgQueue : _LPCP_PORT_QUEUE+0x018Creator : _CLIENT_ID+0x020ClientSectionBase : Ptr32 Void+0x024ServerSectionBase : Ptr32 Void+0x028PortContext : Ptr32 Void+0x02cClientThread : Ptr32 _ETHREAD+0x030SecurityQos : _SECURITY_QUALITY_OF_SERVICE+0x03cStaticSecurity : _SECURITY_CLIENT_CONTEXT+0x078LpcReplyChainHead : _LIST_ENTRY+0x080LpcDataInfoChainHead : _LIST_ENTRY+0x088ServerProcess : Ptr32 _EPROCESS+0x088MappingProcess : Ptr32 _EPROCESS+0x08cMaxMessageLength : Uint2B+0x08eMaxConnectionInfoLength : Uint2B+0x090Flags : Uint4B+0x094 WaitEvent : _KEVENT

我们将讨论调试器扩展,这些扩展允许您查看与LPC相关的问题。

LPC Kernel Debugger Extensions

Command

Description

!lpc

Display the list and description of all the !lpc commands

!lpc message [MessageId]

Display the message with a given ID and all related information by attempting to match the given Message ID to the EHTREAD->LpcReceivedMessageId and to the ETHREAD->LpcReplyMessageId of all threads in the system.

If the MessageId parameter is omitted then it attempts to display all the outstanding messages in the system by searching for the tag ‘LpcM’ in the pools.

!lpc port [PortAddress]

Displays port information. If a server connection port address is specified then only information about that port is displayed. If either a client or server communication port is specified it prints information about the specified communication port, the peer communication port and the server connection port.

If the PortAddress parameter is omitted then it attempts to walk the list of all objects of type “Port” and “WaitablePort” and display them. Note that for this feature to work the GFlags option “+otl” i.e. “Maintain a list of objects for each type” must be enabled.

!lpc scan PortAddress

Displays port information. It attempts to walk the list of all objects of type “Port” and “WaitablePort” and display the one matching the specified port address. Note that for this feature to work the GFlags option “+otl” i.e. “Maintain a list of objects for each type” must be enabled.

!lpc thread [ThreadAddr]

If ThreadAddr is specified it walks the list of threads in the ETHREAD-> LpcReplyChain to locate the list head i.e. a “Port” or “WaitablePort” object on which the thread is waiting for a reply.

If the ThreadAddr parameter is omitted then it attempts to find all LPC server threads by looking for threads with a non-NULL EHTREAD->LpcReceivedMessageId and all client threads by looking for threads with a non-NULL ETHREAD->LpcReplyMessageId and displays them.

!lpc PoolSearch

Toggles a setting that controls whether the “lpc message” command will search for LPC message tag (‘LpcM’) in the kernel pools or not.

LPC Kernel Debugger Extension Usage

来自调用堆栈的LPC连接端口信息
在LPC数据传输或LPC连接上阻塞的任何客户端或服务器线程的调用堆栈上,将有一个包含函数NtRequestWaitReplyPort()或NtReplyWaitReceivePortEx()之一的帧。其中任何一个函数的第一个参数是它们被阻塞的端口的句柄。

kd> !thread 810de2a8

THREAD 810de2a8 Cid 01dc.01f4 Teb: 7ffde000 Win32Thread:
00000000 WAIT: (WrLpcReceive) UserMode Non-Alertable81131188 Semaphore Limit 0x7fffffff810de398 NotificationTimer

Not impersonating

DeviceMap e196c460

Owning Process 810ddda0 Image: rpclpcs.exe

Wait Start TickCount
64666666 Ticks: 402 (0:00:00:04.025)

Context Switch Count
2UserTime00:00:00.000KernelTime00:00:00.000Win32 Start Address0x77e76bf0Start Address0x7c810856Stack Init f8e28000 Current f8e27c4c Base f8e28000 Limit f8e25000 Call0Priority8 BasePriority 8 PriorityDecrement 0 DecrementCount 0ChildEBP RetAddr Args to Child

f8e27c64 804dc6a6 810de318 810de2a8 804dc6f2 nt
!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])

f8e27c70 804dc6f2 e1084108 8055a540 e1084108 nt
!KiSwapThread+0x46 (FPO: [0,0,0])

f8e27c98 8056a50a
00000001 00000010 00000001 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])

f8e27d48 804df06b 000007c4 002bff70
00000000 nt!NtReplyWaitReceivePortEx+0x3dc (FPO: [Non-Fpo])

f8e27d48 7c90eb94 000007c4 002bff70
00000000 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f8e27d64)

002bff80
00000000 00000000 00000000 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])

kd
> !handle 7c4 3810ddda0

processor number
0, process 810ddda0

PROCESS 810ddda0 SessionId:
0Cid: 01dc Peb: 7ffd9000 ParentCid: 01b4

DirBase: 058cd000 ObjectTable: e1a13278 HandleCount:
18.

Image: rpclpcs.exe

Handle table at e107d000 with
18 Entries inuse

07c4: Object: e1084108 GrantedAccess: 001f0001 Entry: e107df88

Object: e1084108 Type: (812b5c80) Port

ObjectHeader: e10840f0 (old version)

HandleCount:
1 PointerCount: 4Directory Object: e14c72c8 Name: rpclpc

kd
> !lpc port e1084108

Server connection port e1084108 Name: rpclpc

Handles:
1 References: 4Server process : 810ddda0 (rpclpcs.exe)

Queue semaphore :
81131188Semaphore state0 (0x0)

The message queue is empty

The LpcDataInfoChainHead queue is empty

LPC Messages that are waiting to be picked up by the server thread

关于MBR的反汇编,我想花点时间向您展示一下快速而肮脏的方法。
首先,使用低级扇区编辑器(如Microsoft资源工具包实用程序DiskProbe)将MBR转储到文件中。保存文件后,启动一个程序(如记事本)并使用Windbg(Windows调试器)附加到它。
接下来,找到一个有效但未占用的内存范围(默认堆是一个很好的候选者)。内存范围至少需要512(0x200)字节。例如,我在这里找到了我的:

000120a0 00000000 00000000 00000000 00000000000120b000000000 00000000 00000000 00000000000120c000000000 00000000 00000000 00000000000120d000000000 00000000 00000000 00000000000120e000000000 00000000 00000000 00000000000120f000000000 00000000 00000000 00000000

00012100 00000000 00000000 00000000 00000000

00012110 00000000 00000000 00000000 00000000

00012120 00000000 00000000 00000000 00000000...