为什么win32k.sys在System进程空间无法访问
2012-07-27 21:57
363 查看
2010年01月02日 21:21
玩过Shadow SSDT Hook的都知道,在System进程中是无法访问win32k.sys的内存空间的,要想访问必须切换到csrss进程或者任意一个GUI进程。 问题一:为什么System进程里无法访问win32k.sys呢? 某同学的说法,"在System进程和非GUI进程里,win32k.sys被页换出了,所以无法访问" win32k.sys作为GUI服务例程的载体,NtGdiXxxx,NtUserXxxx等GUI服务例程调用极其频繁。 所以,不管使用何种页置换算法,win32k几乎都不可能被页换出,因为它的使用频率太高了 真正的原因是因为win32k所占用的地址范围在System进程的页目录中没有相应的描述,也就是对应的PTE是无效的 下面来观察之: 先取得win32k.sys的地址: 可以知道模块地址为bf800000 下面切换到System进程空间: kd> dt _EPROCESS 823a7660 ImageFileName ntdll!_EPROCESS +0x174 ImageFileName : [16] "System" kd> .process /i 823a7660 kd> g Break instruction exception - code 80000003 (first chance) nt!RtlpBreakWithStatusInstruction: 80527da8 cc int 3 kd> db bf800000 bf800000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800010 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800020 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800030 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800040 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800050 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800060 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800070 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? kd> !pte bf800000 VA bf800000 PDE at 00000000C0602FE0 PTE at 00000000C05FC000 contains 0000000000000000 可以看到win32k无法访问,而且PTE是无效的。 切换到csrss.exe看看: kd> dt _EPROCESS 8235ada0 ImageFileName ntdll!_EPROCESS +0x174 ImageFileName : [16] "csrss.exe" kd> .process /i 8235ada0 kd> g Break instruction exception - code 80000003 (first chance) nt!RtlpBreakWithStatusInstruction: 80527da8 cc int 3 kd> db bf800000 bf800000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ.............. bf800010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@....... bf800020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ bf800030 00 00 00 00 00 00 00 00-00 00 00 00 e0 00 00 00 ................ bf800040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th bf800050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno bf800060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS bf800070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$....... kd> !pte bf800000 VA bf800000 PDE at 00000000C0602FE0 PTE at 00000000C05FC000 contains 00000000047BB063 contains 0000000005AA8221 pfn 47bb ---DA--KWEV pfn 5aa8 C---A--KREV 清清楚楚,就是PTE的问题。由于System进程中该地址的PTE无效,使得我们明明知道这个地址,但就是无法访问。 问题二:为什么一定要切换到一个GUI进程空间? 我们可能都是这样认为的:GUI进程要调用GUI服务例程,而这些服务例程都在win32k.sys中,就必然会访问win32k.sys,所以win32k.sys的地址范围在GUI进程中必然是可以访问的。这个逻辑没有错误。按照这个逻辑来推断,一个没有任何GUI的进程空间里,是无法访问win32k.sys的。事实当真如此吗? 来切换到lsass.exe进程看看,这个进程负责本地安全认证,并没有任何GUI。 kd> dt _EPROCESS 821e6348 ImageFileName ntdll!_EPROCESS +0x174 ImageFileName : [16] "lsass.exe" kd> .process /i 821e6348 kd> g Break instruction exception - code 80000003 (first chance) nt!RtlpBreakWithStatusInstruction: 80527da8 cc int 3 kd> db bf800000 bf800000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ.............. bf800010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@....... bf800020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ bf800030 00 00 00 00 00 00 00 00-00 00 00 00 e0 00 00 00 ................ bf800040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th bf800050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno bf800060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS bf800070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$....... kd> !pte bf800000 VA bf800000 PDE at 00000000C0602FE0 PTE at 00000000C05FC000 contains 00000000047BB063 contains 0000000005AA8221 pfn 47bb ---DA--KWEV pfn 5aa8 C---A--KREV 可以清楚地看到,在一个非GUI进程中也可以访问! 又有同学说了,本来非GUI进程是无法访问win32k.sys的,可能是因为某个线程调用了GUI服务,导致产生了某种转换,使得win32k在一个非GUI进程里可以访问。 实际上,完成这个转换的函数就是PsConvertToGuiThread。 但是PsConvertToGuiThread实际上只做了两件事,一是给当前线程使用新的更大的内核栈空间,另外就是把KTHREAD->ServiceTable由KeServiceDescriptorTable切换为KeServiceDescriptorTableShadow。PsConvertToGuiThread完成这个切换之后,就可以正常调用Shadow SSDT中的GUI服务了,也就说,这当中并没有一个过程来完成向当前进程页目录中添加win32k.sys的地址对应的PTE这个过程,由此推断,当一个进程刚出生的时候,win32k.sys的地址就已经在页目录中有描述了,此时就已经可以访问。 空口无凭,实验观察之: 下一个PspCreateProcess断点,当此函数成功返回时,进程已经创建并插入PsActiveProcessLink中,来看一下 PROCESS 82161030 SessionId: 0 Cid: 0344 Peb: 7ffd5000 ParentCid: 02b0 DirBase: 044402a0 ObjectTable: e20ae7b8 HandleCount: 1. Image: ftp.exe 此时进程已经创建,但是还未创建第一个线程,我们在第一个线程运行时断下来。 可以看一下调用栈,此时这个线程刚刚出生,还未调用任何SSDT服务或Shadow SSDT服务. kd> kvn # ChildEBP RetAddr Args to Child 00 f8acbd20 80660017 00000007 8055b140 8055b1fc nt!RtlpBreakWithStatusInstruction (FPO: [1,0,0]) 01 f8acbd74 80534dd0 00000000 00000000 823a4030 nt!ExpDebuggerWorker+0x91 (FPO: [Non-Fpo]) 02 f8acbdac 805c5a28 00000000 00000000 00000000 nt!ExpWorkerThread+0x100 (FPO: [Non-Fpo]) 03 f8acbddc 80541fa2 80534cd0 00000001 00000000 nt!PspSystemThreadStartup+0x34 (FPO: [Non-Fpo]) 04 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16 来访问下win32k.sys看看: kd> db bf800000 bf800000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ.............. bf800010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@....... bf800020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ bf800030 00 00 00 00 00 00 00 00-00 00 00 00 e0 00 00 00 ................ bf800040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th bf800050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno bf800060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS bf800070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$....... kd> !pte bf800000 VA bf800000 PDE at 00000000C0602FE0 PTE at 00000000C05FC000 contains 00000000047BB063 contains 0000000005AA8221 pfn 47bb ---DA--KWEV pfn 5aa8 C---A--KREV 完全可以正常访问!也就是说,在进程刚创建完成的时候,win32k.sys的地址就已经可以访问了,并不存在某种切换。而这个进程是系统自带的ftp.exe,一个标准的CUI程序。 MJ说win32k.sys和Session有关,也就是说,win32k.sys在Session Leader(Csrss.exe)及属于该Session的任何一个进程空间中都可以访问。 WindowsXP下系统服务和第一个登录用户共享同一个Session,即Session 0,Vista/Win7中采用了Session隔离,系统服务使用Session 0,第一个用户使用Session 1,其它依次类推。 在这两种系统中,都是遵守这个规则的。但是有一个特殊的不属于任何Session的进程,就是Session Manager(Smss.exe)。 切换到Smss.exe进程空间看一看: kd> dt _EPROCESS 822474e0 ImageFileName ntdll!_EPROCESS +0x174 ImageFileName : [16] "smss.exe" kd> .process /i 822474e0 kd> g Break instruction exception - code 80000003 (first chance) nt!RtlpBreakWithStatusInstruction: 80527da8 cc int 3 kd> db bf800000 bf800000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800010 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800020 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800030 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800040 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800050 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800060 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? bf800070 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? kd> !pte bf800000 VA bf800000 PDE at 00000000C0602FE0 PTE at 00000000C05FC000 contains 0000000000000000 在Session Manager的进程空间中,win32k.sys也是无法访问的,因为它不属于任何一个Session. 观察一下进程可以看到了: 也就是说,除了System进程和Smss进程,在其它任何一个属于某个Session进程内都可以访问win32k.sys,并非只有GUI进程才能访问。 PS:感谢某同学打破砂锅问到底的精神,才使我没有继续错下去。 |
相关文章推荐
- 为什么win32k.sys在System进程空间无法访问
- 为什么win32k.sys在System进程空间无法访问
- 【WCF】HTTP 无法注册 URL 进程,不具有此命名空间的访问权限
- HTTP 无法注册 URL http://+:8731/HelloWcfService/。进程不具有此命名空间的访问权限
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- 异常详细信息: System.Data.SqlClient.SqlException: 无法打开物理文件 。。。 操作系统错误 32:"32(另一个程序正在使用此文件,进程无法访问。
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- HTTP 无法注册 URL http://+:xxxxx/ServicesName/。进程不具有此命名空间的访问权限
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- [0] WCF开发下,提示HTTP 无法注册 URL 进程不具有此命名空间的访问权限
- 具有system权限的进程无法访问sdcard
- C# System.IO.FileStream 文件正由另一进程使用,因此该进程无法访问该文件
- 【WCF】HTTP 无法注册 URL 进程,不具有此命名空间的访问权限
- WCF服务:HTTP 无法注册 URL http://+:8000 进程不具有此命名空间的访问权限
- HTTP 无法注册 URL http://127.0.0.1:9999/calculatorservice/metadata。进程不具有此命名空间的访问权限
- C# System.IO.FileStream 文件正由另一进程使用,因此该进程无法访问该文件
- HTTP 无法注册 URL http://+:12345/HelloWcfService/。进程不具有此命名空间的访问权限
- WCF 无法注册URL 进程不具有此命名空间的访问权限
- HTTP 无法注册 URL http://127.0.0.1:9999/calculatorservice/metadata。进程不具有此命名空间的访问权限
- Windows7下面exe寄宿WCF:Http无法注册URL{0} ,进程不具有此命名空间的访问权限问题