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

2

7

Is there a Windbg/NTSD command to tell me if a process I have attached to in a live debugging session is a 32-bit one or a 64-bit one?

Could you please tell me for both:

  1. An unmanaged process?

and

  1. A managed one?

For a managed one, I can find that out programmatically in C# but still I'd like to know if there's a Windbg command for this.

UPDATE

The target process I am debugging is Microsoft Word (winword.exe). The Office version is 2016 but I am not sure if it is a 32-bit or a 64-bit binary. Here are some observations:

  1. The target location is C:\Program Files (x86)\Microsoft Office\root\Office16\WinWord.exe

  2. The pipe (|) command tells me nothing more than PID, whether the process is attached to the debugger or not and the path from where the image is loaded (as noted in #1 above).

  3. I am debugging this on a 64-bit machine. So, r reveals 64-bit registers.

  4. Upon attaching to a live, healthy process with no crashes (I just opened MS Word and said "Attach to Process"), the callstack for the current thread (k) reads wow64cpu!CpupSyscallStub+0x9 for the top-most call. This, with #1 suggests that the process is a 32-bit process.

Commands already tried

  1. !peb (Process Environment Block): Tells us the PROCESSOR ARCHITECTURE, not the bitness of the process being debugged.
  2. |
  3. vertarget
  4. r (indicates register size for my processor and does not tell me about the process)

But I'm wondering if there's a way to find out.

Gable answered 9/4, 2017 at 15:55 Comment(4)
Anything related to k can show you the method addresses, which indicate the pointer size and clearly the process bitness.Lilli
Wouldn't that tell us about the bitness of the processor rather than of the process? Just asking. Not challenging.Gable
Vertarget should do itSordid
I'd already tried vertarget before posting this question. I could be wrong but vertarget tells us everything else like environment variables, process and system uptime, commandline arguments and their values. It does not tell us the process architecture for the current process. I'd like to be corrected if I am wrong.Gable
S
8

32 bit / 64 bit decision

For a quick test I often use

lm m wow64

which checks if the WOW64 layer was loaded. If so, it's a 32 bit process.

This approach works in many cases, because OS is likely 64 bit today. However, you could also have a 32 bit dump of a 32 bit OS, in which case this approach does not work well.

A more authorative approach is

.load wow64exts
!info

which gives a lot of output unfortunately, so it'll be hard to use in a script.

The 32 bit output looks like

0:000> !info

PEB32: 0xe4d000
PEB64: 0xe4c000

Wow64 information for current thread:

TEB32: 0xe50000
TEB64: 0xe4e000

[...]

In case of 64 bit it is

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

[...]

I don't have a 32 bit Windows OS dump available, but I assume it's safe to say that

  • if PEB32 is not 0, it's a 32 bit process.
  • if PEB64 is 0, it's a 32 bit OS

If you know the module name, you can also inspect the file headers:

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

Things that do not work

vertarget as suggested in the comments does not work well for 64 bit crash dumps of 32 bit applications.

$ptrsize would have been so nice, but it depends on the debugger mode:

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 decision

Similar to the WOW64 layer, you can check for .NET:

lm m mscorwks
lm m clr
lm m coreclr

Of course it might be possible to load such a DLL via LoadLibrary() from native code directly and not using .NET, but I think that's a rare usage of someone who wants to fool you.

Sadfaced answered 10/4, 2017 at 7:31 Comment(5)
Thank you. That is an ingenious guess and it should mostly suffice. I was wondering -- if there was a Windbg command to read a native image's PE header, that would be the most reliable way to get to this information. In your knowledge, is there a command that displays the PE header of a loaded native image?Gable
@WaterCoolerv2: depends on what you mean by "read". !dh notepad and db notepad+f0 L200 will give you some output, but those commands depend on the module nameSadfaced
@WaterCoolerv2: .shell -ci "!dh -f notepad" findstr "machine" is a long command but has quite nice outputSadfaced
why not just run the lm command and see from where the modules are loaded, if you do not find anything loaded from SysWOW64 then its a 64 bit processMegaron
@user2101801: the output of lm on its own can be very lengthy. I wanted to reduce the output that needs to be read to make the decision. Also, if you don't read that as a human and want to parse the output, shorter output is easier to parse.Sadfaced
N
0

This WinDbg command will tell you what "machine type" a given module is built for. For x64, the value is 0x8664. For x86, the value is 0x14c. The full list of machine type values is found here: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format

dx @$curprocess.Modules.Where(x => x.Name.ToLower().Contains("foo.dll")).Select(x => x.Contents.Headers.FileHeader.Machine),x
Noneffective answered 29/10, 2023 at 7:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.