内核调试 - 内核模式下的 Internet Explorer?

逆向工程 视窗 调试 风袋 内核模式 核心
2021-07-09 04:20:57

我的设置:Windows 10windbg和目标机器是 Windows 7 N SP1。我正在通过 com 调试(我知道它很慢;)。

所以我得到了进程列表!process,一个活动进程是 Internet Explorer:

kd>!process 0 0

>PROCESS fffffa8001a3db30
>SessionId: 2  Cid: 07e0    Peb: 7efdf000  ParentCid: 0a90
>DirBase: 2cc0a000  ObjectTable: fffff8a002007620  HandleCount: 561.
>
>Image: iexplore.exe

之后,我想查看进程在哪种模式下运行。所以我在美国/美国国旗上查看了 PDE 的内容。

kd> !pte FFFFF6FB7EA00068
                                       VA fffff6fd4000d000
>PXE at FFFFF6FB7DBEDFA8    PPE at FFFFF6FB7DBF5000    PDE at FFFFF6FB7EA00068    PTE at FFFFF6FD4000D4D0
>contains 0000000004000863  contains 0000000004001863  contains 000000007FC009E3  contains 0000000000000000
>pfn 4000      ---DA--KWEV  pfn 4001      ---DA--KWEV  **pfn 7fc00     -GLDA--*K*WEV**  LARGE PAGE pfn 7fc9a

usermode/kernelmode 标志设置为 K。也就是说,iexplorer.exe 正在内核模式下运行。为什么?我认为这些应用程序在用户模式下运行。

2个回答

在 pte 命令中,您使用的地址是从哪里获得的地址FFFFF6FB7EA00068 <<<<<

如果它是一个虚拟地址,它真的属于活动进程上下文吗?

你在 iexplore.exe 的进程上下文中吗??
(did you do .process /p /r EPROC_ADDR )

只是做 .process /p /r 只改变了windbg中的显示,实际的底层进程可能不等于当前的进程上下文

您是否检查了进程上下文DirectoryTableBase (DirBase) 和注册cr3 是否匹配?

如果它们不匹配,您可能正在查看一些属于其他进程上下文的虚假地址,这些地址可能具有相同的虚拟地址

如果不匹配,您可能需要执行.process /i并使用g 或 f5执行目标

这使得windbg 侵入性地调试底层进程,当它
在几秒钟后重新中断时,您感兴趣的进程(在您的情况下为iexplore.exe)
将被设置为活动进程上下文,并且页表条目相对于活动进程上下文进行解码
(注册 cr3 和 @$proc->Pcb.DirectoryTableBase 将匹配并显示相同的 DirBase)

只有当您真正确定您有一个活动的流程上下文时,您的问题才可能是可重现的查询

一个样品

目标和主机都是 win7 sp1 32 位(目标是 vm)
windbg 版本是发布当天的最新 rtm

Microsoft (R) Windows Debugger Version 10.0.16299.15 X86

使用 ctrl+break 将目标分解为 windbg

checking current cr3
kd> r cr3
cr3=00185000

检查 iexplore.exe 进程实例

kd> !process 0 0 iexplore.exe
PROCESS 841f3c08  SessionId: 1  Cid: 059c    Peb: 7ffdf000  ParentCid: 0774
    DirBase: 096de000  ObjectTable: 92aed4d0  HandleCount: 419.
    Image: iexplore.exe

PROCESS 841ce5d8  SessionId: 1  Cid: 0784    Peb: 7ffdf000  ParentCid: 059c
    DirBase: 0db73000  ObjectTable: 8b221ba0  HandleCount: 350.
    Image: iexplore.exe

查看 iexplore 模块是否可用的命令

kd> lm m iexp*
Browse full module list
start    end        module name

Unable to enumerate user-mode unloaded modules, Win32 error 0n30

没有windbg 不在正确的进程上下文中
让它进入正确的进程上下文
记住这是一个显示而不是目标状态
请参阅.cache(windbg 从其缓存
数据刷新显示

您会注意到模块 iexplore.exe 现在可供检查

kd> .process /p /r 841ce5d8
Implicit process is now 841ce5d8
.cache forcedecodeuser done
Loading User Symbols

kd> lm m iexp*
Browse full module list
start    end        module name
00af0000 00b96000   iexplore   (deferred)             
kd> x iexplore!wWinMain
00af12a3          iexplore!wWinMain (<no parameter info>)

但是这个
缓存进程上下文空间中虚拟地址的 !pte是无效的,因为我们不在
活动进程上下文中(寄存器 cr3 和 DirBase 不匹配)
进入活动进程上下文 windbg 应该
侵入性地调试目标进程
,这只是可能的如果我们做一个 .process /i

kd> !pte iexplore!wWinMain
                 VA 00af12a3
PDE at C0300008         PTE at C0002BC4
contains 00000000
not valid


kd> r cr3
cr3=00185000

kd> ?? @$proc->Pcb.DirectoryTableBase
unsigned long 0xdb73000

让 Windbg 侵入式调试 iexplore.exe 并
在进程上下文处于活动状态时中断

kd> .process /i /p /r /P 841ce5d8
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
8289dd00 cc              int     3

现在您可以看到注册上下文和 Dirbase 匹配

kd> r cr3
cr3=0db73000

kd> ?? @$proc->Pcb.DirectoryTableBase
unsigned long 0xdb73000

kd> !pte iexplore!wWinMain
                 VA 00af12a3
PDE at C0300008         PTE at C0002BC4
contains 0DD71867       contains 07B5F005
pfn dd71  ---DA--UWEV   pfn 7b5f  -------UREV

pte enties are valid now 

您可以进一步将 va 与物理页面内容进行匹配,如下所示

kd> !pte iexplore!wWinMain
                 VA 00af12a3
PDE at C0300008         PTE at C0002BC4
contains 0DD71867       contains 07B5F005
pfn dd71  ---DA--UWEV   pfn 7b5f  -------UREV

kd> db iexplore!wWinMain l 20
00af12a3  8b ff 55 8b ec 81 ec 30-01 00 00 a1 50 c0 af 00  ..U....0....P...
00af12b3  33 c5 89 45 fc 53 56 57-be 88 c5 af 00 56 e8 cb  3..E.SVW.....V..


kd> $$ from the !pte above we know pfn is at 7b5f 
kd> $$ we can confirm if this is the right physical page with either 
kd> $$ !vtop 0 va or simply adding the last 3 bytes of our va to the pfn 
kd> $$and dump the physical page 

物理地址内容的转储

kd> !db 7b5f2a3 l20
# 7b5f2a3 8b ff 55 8b ec 81 ec 30-01 00 00 a1 50 c0 af 00 ..U....0....P...
# 7b5f2b3 33 c5 89 45 fc 53 56 57-be 88 c5 af 00 56 e8 cb 3..E.SVW.....V..

如所见,虚拟地址内容和物理页面内容匹配,
但让我们查找可能唯一的字符串并重新确认

kd> s -a iexplore!wWinMain L?100000 "Internet Explorer_Server"
00bb7df8  49 6e 74 65 72 6e 65 74-20 45 78 70 6c 6f 72 65  Internet Explore
kd> da /c 100 bb7df8
00bb7df8  "Internet Explorer_Server"

kd> !pte bb7df8
                 VA 00bb7df8
PDE at C0300008         PTE at C0002EDC
contains 0DD71867       contains 0D7B1025
pfn dd71  ---DA--UWEV   pfn d7b1  ----A--UREV

kd> !db d7b1df8 l 20
# d7b1df8 49 6e 74 65 72 6e 65 74-20 45 78 70 6c 6f 72 65 Internet Explore
# d7b1e08 72 5f 53 65 72 76 65 72-00 00 00 00 00 00 00 00 r_Server........

kd> !vtop 0 bb7df8
X86VtoP: Virt 0000000000bb7df8, pagedir 000000000db73000
X86VtoP: PDE 000000000db73008 - 0dd71867
X86VtoP: PTE 000000000dd71edc - 0d7b1025
X86VtoP: Mapped phys 000000000d7b1df8
Virtual address bb7df8 translates to physical address d7b1df8.

您在问题中列出的内容不会告诉您流程正在以哪种模式执行,并且思维过程存在一些问题。

帮助文档!pte指定命令大约需要该地址的虚拟地址和显示PTE和PDE信息。这个命令的输出有点不直观,因为实际上 PTE/PDE 条目是物理地址,但 Windows 也将它们映射到内核虚拟内核地址。

在您的输出中,您正在分析的虚拟地址特别是VA fffff6fd4000d000. 输出显示的是,此虚拟地址的 PXE 条目位于物理地址 4000000(这是由pfn条目给出的,下部为标志等被屏蔽),并映射到虚拟地址FFFFF6FB7DBEDFA8

那么接下来的部分就是为什么输出显示页面是内核模式的。根据你在做什么,你从 !address 得到的地址是fffffa8001a3db30无需过多了解内核的内部结构,该地址是EPROCESS对象的虚拟地址,该对象是用于管理系统进程的内核数据结构。此外,内核分配的每个对象都有一个标头,系统用于引用计数和其他一些管理功能。

您可以使用 dt 命令在 windbg 中看到这个头结构:dt _OBJECT_HEADER在 x64 上,您会注意到这个结构是 0x30 字节大。所以实际 EPROCESS 的地址是fffffa8001a3db30但分配的基础包括头文件fffffa8001a3db00.

所以基本上你在运行该!pte命令时所做的是分析内核EPROCESS 对象的页表条目,但正如我在最后一段中所说的,这只是内核分配和用于管理系统资源的结构,所以该地址将始终是内核模式地址。

要执行您真正想做的事情,您需要使用以下命令:

  • .process /p /r <iexplore.exe address from !process> - 这会将您置于 Internet Explorer 的进程上下文中,这基本上意味着 windbg 访问的所有用户模式内容(虚拟内存和句柄)对该进程都有效
  • !dml_proc <iexplorer address from !process>!process <iexploer address from !process- 这为您提供有关在该进程中运行的线程的信息
  • 从那里,如果您使用 !dml_proc,您可以单击链接以获取线程堆栈,或者 !process 将为您转储所有线程

现在,如果您按照上述操作,您将获得每个线程的堆栈跟踪。从那里你可以根据它所在的模块看到它在哪里执行。特别是,如果你nt!KiSystemServiceCopyEnd在调用堆栈上看到这意味着线程已经转换到内核模式并且正在做一些事情。

然而,话虽如此,我仍然不确定您想要实现什么,因为您的帖子中的评论之一提到所有线程都会一直转换到内核模式,因为基本上系统上发生的所有事情都发生在内核模式下.