为什么 WinDBG 可以在 nt!NtCreateFile 而不是 nt!NtAccessCheck 或 nt!SeAccessCheckByType 上中断?

Why can WinDBG break on nt!NtCreateFile but not nt!NtAccessCheck or nt!SeAccessCheckByType?

我正在尝试检查访问检查中的令牌和安全描述符。出于学习目的,我编写了以下可用于测试的程序:

#include <iostream>
#include <windows.h>

int wmain( int argc, wchar_t *argv[], wchar_t *envp[] )
{
    if (argc < 3)
    {
        std::cerr << "Usage: OpenWithAccess <file> <read/write> [ -d ]" << std::endl;
        return ERROR_INVALID_PARAMETER;
    }

    if (argc == 4 && !_wcsicmp(argv[3], L"-d"))
    {
        __debugbreak();
    }

    HANDLE hFile = ::CreateFile(argv[1], !_wcsicmp(argv[2], L"write") ? FILE_ALL_ACCESS : GENERIC_READ, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        std::wcout << L"Successfully opened " << argv[1] << L" with " << argv[2] << L" access" << std::endl;
    }
    else
    {
        std::wcout << L"Failed to open " << argv[1] << L" with " << argv[2] << L" access, error = " << ::GetLastError() << std::endl;
    }
    
    return ERROR_SUCCESS;
}

当我 运行 作为标准用户使用 OpenWithAccess.exe c:\Windows\system32\drivers\etc\hosts write -d 这个程序时,我知道调用通过了 NtAccessCheck(由于访问被拒绝而失败)。

在内核调试器中,我可以像这样在 nt!NtCreateFile 中设置断点:

bp /p <myprocessaddress> nt!NtCreateFile

这很好。然而:

bp /p <myprocessaddress> nt!NtAccessCheck

不破。但是,如果我进入 nt!NtCreateFile 然后简单地保持 运行 宁 t 来追踪 API 我最终会进入 nt!NtAccessCheck。那么为什么一个断点起作用而另一个断点不起作用?

我应该注意,如果我 运行 这没有我当前的流程,例如:

bp nt!NtAccessCheck

它确实中断了,但不是在我当前的线程上,即使我知道它也会被跳过 运行 并且捕获了一些其他访问检查。我期望的那个永远不会被抓住。我错过了什么?

尝试在 nt!SeAccessCheck 上设置断点并检查它是否为您提供了足够的信息

我刚刚编译了代码并通过它运行它,点击了 nt!SeAccessCheck

0: kd> !process @$proc 3f
PROCESS ffffd10fc1503080
    SessionId: 1  Cid: 17b8    Peb: 55e8cf000  ParentCid: 0bd4
    DirBase: 0ef40002  ObjectTable: ffffaa883bdb1240  HandleCount:  32.
    Image: fufu.exe

命中 bp3

0: kd> bp /p ffffd10fc1503080 nt!NtCreateFile
0: kd> bp /p ffffd10fc1503080 nt!IopCreateFile
0: kd> bp /p ffffd10fc1503080 nt!NtAccessCheck
0: kd> bp /p ffffd10fc1503080 nt!SeAccessCheck
0: kd> g
Breakpoint 0 hit
nt!NtCreateFile:
fffff802`4c8974e0 4881ec88000000  sub     rsp,88h
1: kd> g
Breakpoint 1 hit
nt!IopCreateFile:
fffff802`4c897570 4c894c2420      mov     qword ptr [rsp+20h],r9
1: kd> g
Breakpoint 3 hit
nt!SeAccessCheck:
fffff802`4c3bd730 48895c2410      mov     qword ptr [rsp+10h],rbx
1: kd> kb
 # RetAddr            Call Site
00 fffff802`4c942c28  nt!SeAccessCheck
01 fffff802`4c9417bf  nt!ObpLookupObjectName+0x188
02 fffff802`4c897974  nt!ObOpenObjectByNameEx+0x1df
03 fffff802`4c897559  nt!IopCreateFile+0x404
04 fffff802`4c46d785  nt!NtCreateFile+0x79
05 00007fff`2c6e0114  nt!KiSystemServiceCopyEnd+0x25
06 00007fff`295ee5d6  ntdll!NtCreateFile+0x14
07 00007fff`295ee2c6  KERNELBASE!CreateFileInternal+0x2f6
08 00007ff7`afaa12ed  KERNELBASE!CreateFileW+0x66
09 ffffffff`fffffffe  fufu!wmain+0xed [c:\users\xxx\desktop\fufu\fufu.cpp @ 17] 
0a 00007ff7`00000002  0xffffffff`fffffffe
0b 00007ff7`afb39358  0x00007ff7`00000002
0c 00007ff7`afaa1032  fufu!std::classic_locale$initializer$
0d 00007ff7`00000004  fufu!`dynamic initializer for 'std::numpunct<wchar_t>::id''+0x12 
0e 00000000`00000080  0x00007ff7`00000004
0f 00000000`00000000  0x80
1: kd> dt nt!_SECURITY_DESCRIPTOR @rcx
   +0x000 Revision         : 0x1 ''
   +0x001 Sbz1             : 0 ''
   +0x002 Control          : 0x10
   +0x008 Owner            : 0xffffd10f`bb148fb0 Void
   +0x010 Group            : 0xffffd10f`bb148fb0 Void
   +0x018 Sacl             : 0xffffaa88`36e05c10 _ACL
   +0x020 Dacl             : (null)