EreTIk's Box » Cтатьи, исходники » Дескриптор безопасности объекта нити или почему при создании процесса игнорируется имперсонированность нити


Не так давно мы с коллегой задались вопросом: а по какому принципу формируется DACL дескриптора безопасности объекта нити? В частности стало интересно: а есть ли какое-то наследование между создающей нитью и создаваемой.


Ответ достаточно легко найти к коде WRK. И, начав смотреть ядра Windows, я сразу вспомнил, что уже изучал этот код, когда рассматривал особенность создания процессов. Не секрет, что если мы получим токен привилегированного процесса, имперсонируемся под этим токеном и запустим процесс, то новый процесс не будет привилегированным. Это же относится и к созданию нитей процессов. Функции создания процесса и нити используют расширенную функцию создания nt!_ACCESS_STATE’а: SeCreateAccessStateEx, которая явно парметризуется объектом нити и объектом процесса. Но при создании нити или процесса вызывающая функцию передает в SeCreateAccessStateEx NULL в качестве параметра нити, что обеспечивает игнорирование имперсонированности вызывающей нити, а в расчет берется только основной токен вызывающего процесса. Никаких действий по наследованию описателя безопасности между нитями не предпринимается.


Это достаточно легко проверить на практике: напишем некоторый тест, который будет содержать в себе обработчик нити, запускающий вторую нить. В конце каждого из обработчиков поставим бесконечный Sleep. И запустим нить с адресов входа первого обработчика из первой нити процесса и из внешнего процесса-сервиса. В качестве целевой системы возьмем WinXP SP2, а анализировать результаты будем следующим простеньким скриптом для pykd:

import sys
if len(sys.argv) != 2:
    print("Usage : " + sys.argv[0] + " <EPROCESS_ADDR>")
    exit()

import pykd
if not pykd.isKernelDebugging():
    print("This script is for kernel debugging only")

nt = pykd.module("nt")

# list the thread and collect the unique SDs
print("\t***\n")
lstSecDesc = []
prcObj = nt.typedVar("_EPROCESS", pykd.expr(sys.argv[1]))
for thrdObj in nt.typedVarList(prcObj.ThreadListHead.getAddress(), 
                               "_ETHREAD",
                               "ThreadListEntry"):
    thrdObjHeader = nt.containingRecord(thrdObj.getAddress(),
                                        "_OBJECT_HEADER",
                                        "Body")
    sdArrd = (thrdObjHeader.SecurityDescriptor & ~7)
    print("\tThread 0x%x, SD: 0x%x" % (thrdObj.getAddress(), sdArrd))
    if not(sdArrd in lstSecDesc):
        lstSecDesc.append(sdArrd)

# print the unique SDs
print("\n\t***\n")
for sdArrd in lstSecDesc:
    print("\tSD: 0x%x" % sdArrd)
    print(pykd.dbgCommand("!sd 0x%x" % sdArrd))
                

В результате исполнения скрипта мы получим пять нитей:

Thread 0xffffffff823dd868, SD: 0xffffffffe1d69680 Thread 0xffffffff82600420, SD: 0xffffffffe1d69680 Thread 0xffffffff8279cbf0, SD: 0xffffffffe1d69680 Thread 0xffffffff8275fb78, SD: 0xffffffffe1002c08 Thread 0xffffffff82765020, SD: 0xffffffffe1d69680

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

SD: 0xffffffffe1d69680 ->Revision: 0x1 ->Sbz1 : 0x0 ->Control : 0x8004 SE_DACL_PRESENT SE_SELF_RELATIVE ->Owner : S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxx ->Group : S-1-5-21-yyyyyyyyy-yyyyyyyyyy-yyyyyyyyy-yyy ->Dacl : ->Dacl : ->AclRevision: 0x2 ->Dacl : ->Sbz1 : 0x0 ->Dacl : ->AclSize : 0x40 ->Dacl : ->AceCount : 0x2 ->Dacl : ->Sbz2 : 0x0 ->Dacl : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE ->Dacl : ->Ace[0]: ->AceFlags: 0x0 ->Dacl : ->Ace[0]: ->AceSize: 0x24 ->Dacl : ->Ace[0]: ->Mask : 0x001f03ff ->Dacl : ->Ace[0]: ->SID: S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxx ->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE ->Dacl : ->Ace[1]: ->AceFlags: 0x0 ->Dacl : ->Ace[1]: ->AceSize: 0x14 ->Dacl : ->Ace[1]: ->Mask : 0x001f03ff ->Dacl : ->Ace[1]: ->SID: S-1-5-18 ->Sacl : is NULL SD: 0xffffffffe1002c08 ->Revision: 0x1 ->Sbz1 : 0x0 ->Control : 0x8004 SE_DACL_PRESENT SE_SELF_RELATIVE ->Owner : S-1-5-32-544 ->Group : S-1-5-18 ->Dacl : ->Dacl : ->AclRevision: 0x2 ->Dacl : ->Sbz1 : 0x0 ->Dacl : ->AclSize : 0x44 ->Dacl : ->AceCount : 0x2 ->Dacl : ->Sbz2 : 0x0 ->Dacl : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE ->Dacl : ->Ace[0]: ->AceFlags: 0x0 ->Dacl : ->Ace[0]: ->AceSize: 0x14 ->Dacl : ->Ace[0]: ->Mask : 0x001f03ff ->Dacl : ->Ace[0]: ->SID: S-1-5-18 ->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE ->Dacl : ->Ace[1]: ->AceFlags: 0x0 ->Dacl : ->Ace[1]: ->AceSize: 0x18 ->Dacl : ->Ace[1]: ->Mask : 0x00120048 ->Dacl : ->Ace[1]: ->SID: S-1-5-32-544 ->Sacl : is NULL

ΞρεΤΙκ