WinDbg是Windows的用户和内核模式调试器。它可用于调试本机代码和托管代码。
如何使用远程 Linux 系统调试在 Windows 上运行的应用程序?
我正在为 Descent 3 做出贡献。我目前正在处理的拉取请求有一个仅限 Windows 的错误。我想使用调试器来帮助我追踪错误。 该错误...
我按照这里的说明编译了pyx, 为了可以在WinDbg中对其进行调试,我现在可以在代码中放置断点,但是Locals面板中的值没有太大帮助。 在...
我发现了一个驱动程序漏洞,允许任意修改 msr 寄存器。 一种常见的攻击场景是修改 msr[lstar] 以将其指向攻击者的恶意代码。然后,当...
在 Microsoft Azure 平台虚拟机上调试 Windows 内核
我想将WinDbg连接到在Microsoft Azure平台VM上运行的Windows Server内核来调试一些驱动程序。我尝试按照 msdn 上的说明通过网络连接调试器...
寻找从 C++ Windows 程序获取所有类/结构的列表的方法
我正在调试一些可疑的内存泄漏问题,我在 Windbg 堆统计信息中看到大量特定大小的分配。 传统上 - 为了找到分配的来源,我使用了 Gflags,
我正在尝试使用windbg来研究在x64机器上为我们的x86进程创建的挂起转储文件。这是一个 4.0 x86 应用程序,因此为了获得非托管堆栈,我必须执行以下操作: ....
哪些 GDI 对象可能会被泄漏,但不会被枚举为已知的 GDI 对象类型?
我有一个进程不断循环运行某些东西。它打开表单,处理其中的内容,然后关闭它们。一段时间后,该过程开始出现一些错误,最终
windbg 输出“64 位机器不使用 64 位 API”是什么意思?
我有一个 Linux .Net Core 内存转储,我在 WinDbg 中打开它。它显示以下消息 - 64 位机器不使用 64 位 API 我使用 Windows 11,并且刚刚从 l...
我正在尝试使用 Windows 11 的 ARM 版本来找出 ARM64 架构。我可以看到 KeGetCurrentIrql 函数转换为: ldrb w0,[xpr,#0x38] 雷特 如果我理解正确的话...
我遇到了一个问题,即在云上运行的一个使用.Net4.8编写的Web服务内存使用率过高的问题。监控工具警告内存峰值达到1.4GB。我转储了该进程的
我正在阅读有关 Windbg 基于断点的操作,它就像触发断点时在调试器中自动执行命令一样。 例如这个: 0:005> bp kernel32!写...
Windbg 需要不同版本的 mscordacwks.dll
我在尝试使用windbg 调试小型转储文件时遇到一个非常奇怪的问题。 我已经在我自己的机器上尝试过这个,并在小型转储所在的目标机器上运行windbg...
我正在使用第三方闭源API,它会抛出一个异常,指出“所有命名管道都忙”。 我想进一步调试(而不是单步调试),这样我实际上就可以
正在调试的目标进程的地址空间中存在以空结尾的 ASCII 字符串。我想编写一个WinDbg脚本来打印出这个字符串的长度。假设我知道...
跟踪 Windows Crypto API 中的 CSP 调用
我正在使用 Windows Server 2008 R2 证书颁发机构进行私钥存档。在客户端,我有兴趣知道 Windows 进程调用了哪些 Crypto API 函数...
我正在寻找 SOS 的 !SyncBlk 命令生成的输出的描述。 特别是我在“MonitorHeld”列中没有找到有用的解释。此列显示了系列中的高值...
我将核心文件加载到 winDBG 中并对其进行了所需的更改。问题是,我需要写回来。由于我正在测试调试器,因此我需要对核心进行更改。我知道如何使用 .
有两个文件。一个是LearnHanle.exe(拼写错误,应该是LearnHandle.exe),另一个是pop.exe。 这些文件的源代码在这里: // 学习Hanle.cpp #包括 有两个文件。一个是LearnHanle.exe(拼写错误,应该是LearnHandle.exe),另一个是pop.exe。 这些文件的源代码在这里: // LearnHanle.cpp #include <windows.h> #include <stdlib.h> #include <stdio.h> int main() { STARTUPINFOW startup = { 0 }; startup.cb = sizeof startup; PROCESS_INFORMATION pi = { 0 }; BOOL createProcResult = FALSE; if (!CreateProcessW(L"C:\\pop.exe", NULL, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &pi)) MessageBoxA(NULL, "Create Process Failed", "Alert", MB_OK); char handle[80] = { 0 }; sprintf_s(handle, "Process Handle: %llu ProcessId: %llu", pi.hProcess, pi.dwProcessId); MessageBoxA(NULL, handle, "Process", MB_OK); sprintf_s(handle, "Thread Handle: %llu ThreadId: %llu", pi.hThread, pi.dwThreadId); MessageBoxA(NULL, handle, "Thread", MB_OK); system("pause"); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } // pop.cpp #include <windows.h> #include <stdlib.h> #include <stdio.h> int main() { MessageBox(0, 0, 0, 0); // Just sleep Sleep(6000000); } LearnHanle.exe 只是创建 pop.exe 进程,然后自行挂起。 我用LearnHanle.exe查看了Process Explorer进程的详细信息,找到了与pop.exe进程关联的HANDLE,然后就得到了HANDLE地址,如下所示: Basic Information Name: pop.exe(9092) Type: Process Description: Contains threads, an address space, and handles. Address: 0xFFFFE786E04AF080 我用WinDbg调试了Windows 11内核,我使用!object命令查看HANDLE地址。输出在这里: 0: kd> !object 0xffffe786e04af080 Object: ffffe786e04af080 Type: (ffffe786da2cfd20) Process ObjectHeader: ffffe786e04af050 (new version) HandleCount: 9 PointerCount: 293899 ObjectHeader指针指向_EPROCESS进程的pop.exe的对象头: 0: kd> dt _OBJECT_HEADER ffffe786e04af050 nt!_OBJECT_HEADER +0x000 PointerCount : 0n293899 +0x008 HandleCount : 0n9 +0x008 NextToFree : 0x00000000`00000009 Void +0x010 Lock : _EX_PUSH_LOCK +0x018 TypeIndex : 0x47 'G' +0x019 TraceFlags : 0 '' +0x019 DbgRefTrace : 0y0 +0x019 DbgTracePermanent : 0y0 +0x01a InfoMask : 0x88 '' +0x01b Flags : 0 '' +0x01b NewObject : 0y0 +0x01b KernelObject : 0y0 +0x01b KernelOnlyAccess : 0y0 +0x01b ExclusiveObject : 0y0 +0x01b PermanentObject : 0y0 +0x01b DefaultSecurityQuota : 0y0 +0x01b SingleHandleEntry : 0y0 +0x01b DeletedInline : 0y0 +0x01c Reserved : 0 +0x020 ObjectCreateInfo : 0xffffe786`dca5ccc0 _OBJECT_CREATE_INFORMATION +0x020 QuotaBlockCharged : 0xffffe786`dca5ccc0 Void +0x028 SecurityDescriptor : 0xffffd705`63f2962f Void +0x030 Body : _QUAD 但是, 0: kd> dq 0xffffe786e04af080 ffffe786`e04af080 00000000`00000003 ffffe786`e04af088 ffffe786`e04af090 ffffe786`e04af088 ffffe786`e04af098 ffffe786`e04af0a0 ffffe786`e04af098 00000000`9e0b9000 ffffe786`e04af0b0 ffffe786`df8ec378 ffffe786`df8ec378 ffffe786`e04af0c0 00000000`00000000 00000000`00000000 ffffe786`e04af0d0 00000000`00200001 00000000`0000000f ffffe786`e04af0e0 00000000`00000000 00000000`00000000 ffffe786`e04af0f0 00000000`00000000 00000000`00000000 我不知道该地址存储什么,以及!object命令如何获取pop.exe进程的信息。 然后我使用!process命令查看主机进程LearnHanle.exe。 0: kd> !process 0 0 LearnHanle.exe PROCESS ffffe786e04020c0 SessionId: 1 Cid: 22a8 Peb: 0036b000 ParentCid: 1344 DirBase: 999c2000 ObjectTable: ffffd70567953400 HandleCount: 121. Image: LearnHanle.exe 我看了LearnHanle.exe_HANDLE_TABLE。 0: kd> dt _HANDLE_TABLE ffffd70567953400 nt!_HANDLE_TABLE +0x000 NextHandleNeedingPool : 0x400 +0x004 ExtraInfoPages : 0n0 +0x008 TableCode : 0xffffd705`6645a000 +0x010 QuotaProcess : 0xffffe786`e04020c0 _EPROCESS +0x018 HandleTableList : _LIST_ENTRY [ 0xffffd705`67953bd8 - 0xffffd705`67133918 ] +0x028 UniqueProcessId : 0x22a8 +0x02c Flags : 0 +0x02c StrictFIFO : 0y0 +0x02c EnableHandleExceptions : 0y0 +0x02c Rundown : 0y0 +0x02c Duplicated : 0y0 +0x02c RaiseUMExceptionOnInvalidHandleClose : 0y0 +0x030 HandleContentionEvent : _EX_PUSH_LOCK +0x038 HandleTableLock : _EX_PUSH_LOCK +0x040 FreeLists : [1] _HANDLE_TABLE_FREE_LIST +0x040 ActualEntry : [32] "" +0x060 DebugInfo : (null) 0: kd> dt _HANDLE_TABLE_ENTRY nt!_HANDLE_TABLE_ENTRY +0x000 VolatileLowValue : Int8B +0x000 LowValue : Int8B +0x000 InfoTable : Ptr64 _HANDLE_TABLE_ENTRY_INFO +0x008 HighValue : Int8B +0x008 NextFreeHandleEntry : Ptr64 _HANDLE_TABLE_ENTRY +0x008 LeafHandleValue : _EXHANDLE +0x000 RefCountField : Int8B +0x000 Unlocked : Pos 0, 1 Bit +0x000 RefCnt : Pos 1, 16 Bits +0x000 Attributes : Pos 17, 3 Bits +0x000 ObjectPointerBits : Pos 20, 44 Bits +0x008 GrantedAccessBits : Pos 0, 25 Bits +0x008 NoRightsUpgrade : Pos 25, 1 Bit +0x008 Spare1 : Pos 26, 6 Bits +0x00c Spare2 : Uint4B 我想知道进程句柄表中的句柄表项如何与相应的对象类型关联。 而且我也想知道这两位成员的目的:struct _HANDLE_TABLE_ENTRY::ObjectPointerBits、struct _OBJECT_HEADER::TypeIndex和struct _KPROCESS::Header(_DISPATCHER_HEADER)。 作为示例,我将从资源管理器进程 (6496) 获取文件句柄 (0x1c8): 1: kd> !handle 0x1c8 3 0n6496 PROCESS ffffe4856647a080 SessionId: 2 Cid: 1960 Peb: 00238000 ParentCid: 1904 DirBase: 1409e3002 ObjectTable: ffffd10029c47740 HandleCount: 2981. Image: explorer.exe Handle table at ffffd10029c47740 with 2981 entries in use 01c8: Object: ffffe48565dd7110 GrantedAccess: 00100001 (Inherit) (Audit) Entry: ffffd10029ff9720 Object: ffffe48565dd7110 Type: (ffffe485608f7220) File ObjectHeader: ffffe48565dd70e0 (new version) HandleCount: 1 PointerCount: 32783 Directory Object: 00000000 Name: \Windows\en-US\explorer.exe.mui {HarddiskVolume3} 从_EPROCESS的手柄表开始: 0: kd> dt nt!_eprocess ffffe4856647a080 -y ObjectTable nt!_EPROCESS +0x570 ObjectTable : 0xffffd100`29c47740 _HANDLE_TABLE 0: kd> dt nt!_handle_table 0xffffd100`29c47740 nt!_HANDLE_TABLE +0x000 NextHandleNeedingPool : 0x3800 +0x004 ExtraInfoPages : 0n0 +0x008 TableCode : 0xffffd100`29ef4001 +0x010 QuotaProcess : 0xffffe485`6647a080 _EPROCESS +0x018 HandleTableList : _LIST_ENTRY [ 0xffffd100`29c47418 - 0xffffd100`29c47d98 ] +0x028 UniqueProcessId : 0x1960 +0x02c Flags : 0 +0x02c StrictFIFO : 0y0 +0x02c EnableHandleExceptions : 0y0 +0x02c Rundown : 0y0 +0x02c Duplicated : 0y0 +0x02c RaiseUMExceptionOnInvalidHandleClose : 0y0 +0x030 HandleContentionEvent : _EX_PUSH_LOCK +0x038 HandleTableLock : _EX_PUSH_LOCK +0x040 FreeLists : [1] _HANDLE_TABLE_FREE_LIST +0x040 ActualEntry : [32] "" +0x060 DebugInfo : (null) TableCode字段指向一个表数组,较低位决定应使用哪个表: 0: kd> dq 0xffffd100`29ef4000 ffffd100`29ef4000 ffffd100`29ff9000 ffffd100`29ef5000 ffffd100`29ef4010 ffffd100`255fd000 ffffd100`29d96000 ffffd100`29ef4020 ffffd100`2a1fd000 ffffd100`2a0f7000 ffffd100`29ef4030 ffffd100`258bc000 ffffd100`25b5a000 ffffd100`29ef4040 ffffd100`25bff000 ffffd100`25cfc000 ffffd100`29ef4050 ffffd100`25b57000 ffffd100`25dfe000 ffffd100`29ef4060 ffffd100`258c6000 ffffd100`2802c000 ffffd100`29ef4070 00000000`00000000 00000000`00000000 nt!ExpLookupHandleTableEntry中的代码有助于确定如何使用表数组(第一个参数是RCX中的_HANDLE_TABLE*,第二个参数是RDX中的句柄): PAGE:00000001407427E0 ExpLookupHandleTableEntry proc near ; CODE XREF: ObDuplicateObject+180↑p PAGE:00000001407427E0 ; ExMapHandleToPointer+11↑p ... PAGE:00000001407427E0 PAGE:00000001407427E0 ; FUNCTION CHUNK AT PAGE:0000000140895396 SIZE 00000022 BYTES PAGE:00000001407427E0 PAGE:00000001407427E0 mov eax, [rcx+_HANDLE_TABLE.NextHandleNeedingPool] PAGE:00000001407427E2 and rdx, 0FFFFFFFFFFFFFFFCh PAGE:00000001407427E6 cmp rdx, rax PAGE:00000001407427E9 jnb short loc_140742820 PAGE:00000001407427EB mov r8, [rcx+_HANDLE_TABLE.TableCode] PAGE:00000001407427EF mov eax, r8d PAGE:00000001407427F2 and eax, 3 PAGE:00000001407427F5 cmp eax, 1 PAGE:00000001407427F8 jnz short loc_140742812 PAGE:00000001407427FA mov rax, rdx PAGE:00000001407427FD shr rax, 0Ah PAGE:0000000140742801 mov rax, [r8+rax*8-1] PAGE:0000000140742806 PAGE:0000000140742806 loc_140742806: ; CODE XREF: ExpLookupHandleTableEntry+152BD3↓j PAGE:0000000140742806 and edx, 3FFh PAGE:000000014074280C lea rax, [rax+rdx*4] PAGE:0000000140742810 retn PAGE:0000000140742810 ; --------------------------------------------------------------------------- PAGE:0000000140742811 align 2 PAGE:0000000140742812 PAGE:0000000140742812 loc_140742812: ; CODE XREF: ExpLookupHandleTableEntry+18↑j PAGE:0000000140742812 test eax, eax PAGE:0000000140742814 jnz loc_140895396 PAGE:000000014074281A lea rax, [r8+rdx*4] PAGE:000000014074281E retn PAGE:000000014074281E ; --------------------------------------------------------------------------- PAGE:000000014074281F align 20h PAGE:0000000140742820 PAGE:0000000140742820 loc_140742820: ; CODE XREF: ExpLookupHandleTableEntry+9↑j PAGE:0000000140742820 xor eax, eax PAGE:0000000140742822 retn PAGE:0000000140742822 ExpLookupHandleTableEntry endp 在我的例子中,它只是数组中的第一个表,因此句柄条目位于table_base + (handle * 4)。尽管每个表条目都是 _HANDLE_TABLE_ENTRY(大小为 0x10),但每个句柄都是 4 的倍数(因此 0x10 / 4 = 4): 1: kd> ? ffffd100`29ff9000 + (0x1c8 * 4) Evaluate expression: -51676341889248 = ffffd100`29ff9720 表格条目: 1: kd> dt _handle_table_entry ffffd100`29ff9720 nt!_HANDLE_TABLE_ENTRY +0x000 VolatileLowValue : 0n-1980064459403493377 +0x000 LowValue : 0n-1980064459403493377 +0x000 InfoTable : 0xe48565dd`70e0ffff _HANDLE_TABLE_ENTRY_INFO +0x008 HighValue : 0n1048577 +0x008 NextFreeHandleEntry : 0x00000000`00100001 _HANDLE_TABLE_ENTRY +0x008 LeafHandleValue : _EXHANDLE +0x000 RefCountField : 0n-1980064459403493377 +0x000 Unlocked : 0y1 +0x000 RefCnt : 0y0111111111111111 (0x7fff) +0x000 Attributes : 0y000 +0x000 ObjectPointerBits : 0y11100100100001010110010111011101011100001110 (0xe48565dd70e) +0x008 GrantedAccessBits : 0y0000100000000000000000001 (0x100001) +0x008 NoRightsUpgrade : 0y0 +0x008 Spare1 : 0y000000 (0) +0x00c Spare2 : 0 这里至少有两个有趣的东西: GrantedAccessBits:这是对象的授予访问掩码(这里有 0x100001,对于文件对象来说它只是 SYNCHRONIZE (0x10000) | FILE_READ_DATA (0x1) ObjectPointerBits:经过计算后将是指向对象_OBJECT_HEADER的指针。 根据 ObjectPointerBits 值,您需要执行以下操作来获取对象头地址:(ObjectPointerBits << 4) | 0xffff000000000000 1: kd> ? (0xe48565dd70e << 4) | 0xffff000000000000 Evaluate expression: -30213385916192 = ffffe485`65dd70e0 1: kd> dt _object_header ffffe485`65dd70e0 nt!_OBJECT_HEADER +0x000 PointerCount : 0n32783 +0x008 HandleCount : 0n1 +0x008 NextToFree : 0x00000000`00000001 Void +0x010 Lock : _EX_PUSH_LOCK +0x018 TypeIndex : 0x14 '' +0x019 TraceFlags : 0 '' +0x019 DbgRefTrace : 0y0 +0x019 DbgTracePermanent : 0y0 +0x01a InfoMask : 0x4c 'L' +0x01b Flags : 0 '' +0x01b NewObject : 0y0 +0x01b KernelObject : 0y0 +0x01b KernelOnlyAccess : 0y0 +0x01b ExclusiveObject : 0y0 +0x01b PermanentObject : 0y0 +0x01b DefaultSecurityQuota : 0y0 +0x01b SingleHandleEntry : 0y0 +0x01b DeletedInline : 0y0 +0x01c Reserved : 0 +0x020 ObjectCreateInfo : 0xffffe485`62c5ecc0 _OBJECT_CREATE_INFORMATION +0x020 QuotaBlockCharged : 0xffffe485`62c5ecc0 Void +0x028 SecurityDescriptor : (null) +0x030 Body : _QUAD 从对象头中,您可以通过执行以下计算来获取对象类型: *((BYTE*)nt!ObHeaderCookie) ^ second_byte_of_object_header_address ^ _OBJECT_HEADER.TypeIndex 1: kd> db nt!ObHeaderCookie L1 fffff800`7911ed74 4c 1: kd> ? (ffffe485`65dd70e0 >> 8) & 0xff Evaluate expression: 112 = 00000000`00000070 1: kd> dt _object_header ffffe485`65dd70e0 -y TypeIndex nt!_OBJECT_HEADER +0x018 TypeIndex : 0x14 '' 1: kd> ? 0x4c ^ 0x70 ^ 0x14 Evaluate expression: 40 = 00000000`00000028 上面的结果(在本例中为 0x28)是内核类型数组的索引,该数组是一个名为 nt!ObTypeIndexTable 的全局变量(_OBJECT_TYPE 的数组): 1: kd> dt _OBJECT_TYPE poi(nt!ObTypeIndexTable + (0x28 * 8)) nt!_OBJECT_TYPE +0x000 TypeList : _LIST_ENTRY [ 0xffffe485`608f7220 - 0xffffe485`608f7220 ] +0x010 Name : _UNICODE_STRING "File" +0x020 DefaultObject : 0x00000000`0000009b Void +0x028 Index : 0x28 '(' +0x02c TotalNumberOfObjects : 0x27cc +0x030 TotalNumberOfHandles : 0xaae +0x034 HighWaterNumberOfObjects : 0x2a42 +0x038 HighWaterNumberOfHandles : 0xd36 +0x040 TypeInfo : _OBJECT_TYPE_INITIALIZER +0x0b8 TypeLock : _EX_PUSH_LOCK +0x0c0 Key : 0x656c6946 +0x0c8 CallbackList : _LIST_ENTRY [ 0xffffe485`608f72e8 - 0xffffe485`608f72e8 ] 所以它是一个文件对象(由 nt!FILE_OBJECT 表示)。 _DISPATCHER_HEADER 如果一个对象是可等待的(即它的句柄可以传递给WaitForSingleObject或WaitForMutipleObjects),那么它有一个_DISPATCH_HEADER。
使用windbg内核态调试从模块地址找到driverObject
我有已加载驱动程序的模块地址。我想在内核模式调试中使用windbg从模块地址或名称中获取驱动程序对象。有没有命令可以找到它?