标题: windbg中判断被调试进程的位数
创建: 2018-03-05 18:10 更新: 2018-03-06 15:45 链接: https://scz.617.cn/windows/201803051810.txt
Q:
windbg中如何判断被调试进程的位数?
D: scz 2018-03-05
"C:\Program Files\Windows Kits\10\Debuggers\x64\cdb.exe" -noinh -snul -hd -o -xe ld:ntdll "C:\Windows\SysWOW64\mspaint.exe"
.effmach Effective machine: x64 (AMD64) bp $exentry g Breakpoint 0 hit :x86> .effmach Effective machine: x86 compatible (x86)
上例中,刚开始还是x64,断在$exentry时已经是x86,提示符都变了,此时如果r, 看到的是32位寄存器。
但是,这个办法不适用于Attach情形。先启动32位mspaint,再用64位cdb附加, .effmach会报x64。
@$ptrsize与.effmach同步,不可信。
参看:
《shellcode自识别32/64位架构》 https://scz.617.cn/windows/201412260000.txt
某些段选择子可能存在差异,Win7上可以靠用户态CS区分32位、SysWOW64、64位。这 是经验结论,随OS不同而变化。Win10的SysWOW64、64位,其用户态CS都是0x33。
"dt ntdll!_TEB WOW32Reserved @$teb"这个办法有缺陷。对于SysWOW64,如果用32 位cdb附加,看到的确实是非空指针;如果用64位cdb附加,看到NULL。对于后者,此 时的@$teb是"Native TEB",而不是"Guest (WoW) TEB"。即使用"!wow64exts.info" 得到"Guest (WoW) TEB","dt ntdll!_TEB WOW32Reserved ..."仍然不是期望值,因 为"ntdll!_TEB"是64位版的,WOW32Reserved的偏移不是0xc0,用".effmach x86"不 能解决该问题。总之,此处存在鸡生蛋、蛋生鸡问题。
可以试"dd fs:0xc0 l 1"或"? dwo(fs:0xc0)",对于SysWOW64,可以取到指针;对于 x64,用户态FS:0并不指向ntdll!_TEB,操作结果表明访问无效内存。其本质是利用 x86、x64用户态FS:0的区别,理论上TEB中的其他成员也能用于区分,只不过非空指 针成员对比效果更明显。
D: bluerust 2018-03-06
下面分别是32、64位PE的IMAGE_OPTIONAL_HEADER(64)的Magic成员:
? wo(mspaint+dwo(mspaint+0x3c)+0x18) Evaluate expression: 267 = 00000000`0000010b
? wo(mspaint+dwo(mspaint+0x3c)+0x18) Evaluate expression: 523 = 00000000`0000020b
可以靠这个区分32、64位PE。
.shell -ci "!dh -f mspaint" findstr "magic" 10B magic #
.shell -ci "!dh -f mspaint" findstr "magic" 20B magic #
此处有坑,之前想过:
? wo(ntdll+dwo(ntdll+0x3c)+0x18)
这是假设ntdll已经是对应位数的版本,但这个假设不总是成立。先启动32位mspaint, 再用64位cdb附加,刚进去时,ntdll是64位的那个;此时只有EXE是可靠的32位PE, 其他DLL都不可靠。
通用方案如下:
? wo(@@c++(@$peb->ImageBaseAddress)+dwo(@@c++(@$peb->ImageBaseAddress)+0x3c)+0x18)
或
r @$t0=@@c++(@$peb->ImageBaseAddress);? wo(@$t0+dwo(@$t0+0x3c)+0x18)
缺点是依赖ntdll的PDB。
A: zyh@nsfocus 2018-03-05
dt ntdll!_TEB ProcessEnvironmentBlock +0x030 ProcessEnvironmentBlock : Ptr32 _PEB
对于32位TEB,偏移0x30处是指向PEB的指针。结合x86、x64用户态FS:0的区别,可以 用"dd fs:0x30 l 1"区分它们;对于SysWOW64,取到"Guest (WoW) PEB",对于x64, 访问无效内存。
A: Thomas Weller 2017-04-10
1)
lm m wow64
如果wow64.dll存在,目标进程32位。
如果目标进程恶搞,刻意显式加载该DLL,这个办法就失效了。
即使不考虑恶搞,这也是充分非必要条件,考虑32位OS的情形。即使是64位OS,先启 动32位mspaint,再用32位cdb附加,同样看不到wow64.dll;其实是有的,但32位cdb 看不到。
2)
.load wow64exts !wow64exts.info
Guest (WoW) PEB: 0x3cf000 Native PEB: 0x3ce000
Wow64 information for current thread:
Guest (WoW) TEB: 0x3d2000 Native TEB: 0x3d0000
Guest (WoW), StackBase : 0x480000 StackLimit : 0x476000 Deallocation: 0x440000 ...
如果目标进程是64位,将看到
!wow64exts.info Could not get the address of the guest (WoW) PEB, error 0
Guest (WoW) PEB: 0 Native PEB: 0x35a4b6e000
Wow64 information for current thread:
Guest (WoW) TEB: 0 Native TEB: 0x35a4b6f000
Could not get information for guest (WoW) stack, error 0xe8f0c7e0 ...
这个办法只能在64位cdb中使用,不能在32位cdb中使用:
.load wow64exts !wow64exts.info *** !wow64exts is only useful targeting architectures that support WoW ***
3)
.shell -ci "!dh -f mspaint" findstr "machine" 14C machine (i386) 32 bit word machine
.shell -ci "!lmi mspaint" findstr "Machine" Machine Type: 332 (I386)
如果目标进程是64位,将看到
.shell -ci "!dh -f mspaint" findstr "machine" 8664 machine (X64)
.shell -ci "!lmi mspaint" findstr "Machine" Machine Type: 34404 (X64)
A: Andy Luhrs 2017-04-13
dx @$curthread.GuestState Architecture : x86
如果目标进程是64位,将看到
dx @$curthread.GuestState Error: Unable to bind name 'GuestState'
这个办法有缺陷。在64位OS上先启动32位mspaint,再用32位cdb附加,同样没有 GuestState。
/ * .load jsprovider.dll;.scriptload CheckArch.js * dx @$curprocess.Arch / "use strict";
class __CheckArchitecture { / * Add a property called 'Arch' on process. / get Arch () { var isx86 = this.Threads.Any( t => (!(t.GuestState === undefined) && t.GuestState.Architecture === "x86") );
if ( isx86 )
{
return "x86";
}
else
{
return "x64";
}
}
}
function initializeScript () { return [ new host.namedModelParent( __CheckArchitecture, "Debugger.Models.Process" ) ]; }
推荐该方案,显然这是为自动化脚本准备的方案。别提Process Explorer这种玩意儿。