Почему WinDbg может сломаться на nt!NtCreateFile, но не nt!NtAccessCheck или nt!SeAccessCheckByType?

#windows #kernel #windbg

Вопрос:

Я пытаюсь изучить маркер и дескриптор безопасности при проверке доступа. В учебных целях я написал следующую программу, которую я мог бы использовать для тестирования:

 #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 amp;amp; !_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:Windowssystem32driversetchosts write -d как обычный пользователь, я знаю, что вызов проходит через проверку Ntaccess (которая завершается ошибкой с отказом в доступе).

В отладчике ядра я могу установить точку останова в nt!NtCreateFile выглядит так:

 bp /p <myprocessaddress> nt!NtCreateFile
 

Это прекрасно ломается. Однако:

 bp /p <myprocessaddress> nt!NtAccessCheck
 

Не ломается. Однако, если я ворвусь, nt!NtCreateFile а затем просто продолжу работать t , чтобы отслеживать через API, в котором я в конечном итоге окажусь nt!NtAccessCheck . Так почему же одна точка останова работает, а другая нет?

Я должен отметить, что если я запущу это без моего текущего процесса, как:

 bp nt!NtAccessCheck
 

Он действительно ломается, но не в моем текущем потоке, который пропускается, хотя я знаю, что он запущен, и перехватывается какая-то другая проверка доступа. Того, кого я ожидаю, никогда не поймают. Чего мне не хватает?

Комментарии:

1. Что произойдет, если вы это сделаете bu nt!NtAccessCheck ".if (@$proc != <yourproc>) { gc; }" ? Не обращайте внимания на производительность для целей этого упражнения.

Ответ №1:

попробуйте установить точку останова на nt!Проверьте и проверьте, предоставляет ли он вам достаточно информации

я просто скомпилировал код и прокрутил его, он попал в nt!Проверка наличия

 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:usersxxxdesktopfufufufu.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) 
 

Комментарии:

1. Могу я спросить, что это за ОС? Я пытался прерваться nt!SeAccessCheck изначально, так как это то, чего я ожидал, но это не сработало. Я только что разобрал nt!ObpLookupObjectName свой Win10 , и он на самом деле не звонит SeAccessCheck , а скорее звонит SeAccessCheckWithHint , что кажется недокументированным вариантом. К счастью, я могу сломаться на этом, и, похоже, у него очень похожие параметры, которые дают мне SD и токен. Спасибо, что подкрутили это, хотя очень интересно, что в вашей системе все по-другому.

2. это было на устаревшей виртуальной машине с ознакомительной версией w10 для предприятий. неудивительно, что все эти API безопасности меняются каждый третий день или, может быть, даже каждый день, если ваша машина сказала, пожалуйста, не выключайте, это означает, что была реализована некоторая безопасность с помощью somescurity