是否有 Windbg 命令来查明进程是 32 位进程还是 64 位进程?

Is there a Windbg command to find out if a process is a 32-bit one or a 64-bit one?

是否有 Windbg/NTSD 命令告诉我在实时调试会话中附加的进程是 32 位进程还是 64 位进程?

你能告诉我两个吗:

  1. 非托管进程?

  1. 托管的?

对于托管的,我可以在 C# 中以编程方式找到它,但我仍然想知道是否有用于此的 Windbg 命令。

更新

我正在调试的目标进程是 Microsoft Word (winword.exe)。 Office 版本是 2016,但我不确定它是 32 位还是 64 位二进制文​​件。以下是一些观察结果:

  1. 目标位置是C:\Program Files (x86)\Microsoft Office\root\Office16\WinWord.exe

  2. pipe (|) 命令只告诉我 PID,进程是否附加到调试器以及加载图像的路径(如中所述#1 以上)。

  3. 我正在 64 位机器上调试它。所以,r 揭示了 64 位寄存器。

  4. 在附加到一个没有崩溃的实时、健康的进程后(我刚刚打开 MS Word 并说 "Attach to Process"),当前线程的调用堆栈 (k) 读取wow64cpu!CpupSyscallStub+0x9 用于最顶层的调用。这与#1 表明该进程是一个 32 位进程。

命令已经尝试过

  1. !peb(进程环境块):告诉我们处理器架构,而不是正在调试的进程的位数。
  2. |
  3. vertarget
  4. r(指示我的处理器的寄存器大小,但不告诉我有关过程)

但我想知道是否有办法找出答案。

32位/64位决定

为了快速测试我经常使用

lm m wow64

检查是否加载了 WOW64 层。如果是,则为 32 位进程。

这种方法在很多情况下都有效,因为 OS 今天可能是 64 位的。但是,您也可以有一个 32 位的 32 位转储 OS,在这种情况下,这种方法效果不佳。

比较权威的做法是

.load wow64exts
!info

不幸的是,它给出了很多输出,因此很难在脚本中使用。

32 位输出看起来像

0:000> !info

PEB32: 0xe4d000
PEB64: 0xe4c000

Wow64 information for current thread:

TEB32: 0xe50000
TEB64: 0xe4e000

[...]

如果是 64 位,则为

0:000> !info
Could not get the address of the 32bit PEB, error 0

PEB32: 0
PEB64: 0x6b33c50000

Wow64 information for current thread:

TEB32: 0
TEB64: 0x6b33c51000

[...]

我没有可用的 32 位 Windows OS 转储,但我认为这样说是安全的

  • 如果PEB32不为0,则为32位进程
  • 如果PEB64为0,则为32位OS

如果知道模块名称,还可以查看文件头:

0:000> .shell -ci "!dh -f notepad" findstr "machine"
    8664 machine (X64)
.shell: Process exited

不起作用的东西

评论中建议的

vertarget 对于 32 位应用程序的 64 位故障转储效果不佳。

$ptrsize 会很好,但这取决于调试器模式:

0:000> ? $ptrsize
Evaluate expression: 8 = 00000000`00000008
0:000> .effmach x86
Effective machine: x86 compatible (x86)
0:000:x86> ? $ptrsize
Evaluate expression: 4 = 00000004

.NET决定

类似于WOW64层,可以检查.NET:

lm m mscorwks
lm m clr
lm m coreclr

当然可以通过 LoadLibrary() 直接从本机代码加载这样的 DLL,而不是使用 .NET,但我认为这是一种很少有人想愚弄你的用法。