API для получения AppContainerName из AppContainerSid

Скажем, если у меня есть DACL для процесса, который мне нужно показать конечному пользователю. Я могу преобразовать его в строковое представление с помощью ConvertSecurityDescriptorToStringSecurityDescriptor. Затем мне нужно сделать его немного более управляемым для пользователя, удалив из него «сумасшедшие» локальные SID. Вот пример:

D:(A;;0x1fffff;;;S-1-5-21-2301966995-2804055512-1978750589-1002)(A;;0x1fffff;;;SY)(A;;0x121411;;;S-1-5-5-0-1207601)(A;;0x1fffff;;;S-1-15-2-155514346-2573954481-755741238-1654018636-1233331829-3075935687-2861478708)

Например, результирующая строка может включать SID пользователя (или S-1-5-21-2301966995-2804055512-1978750589-1002 в приведенном выше случае), который я могу преобразовать в имя пользователя с помощью LookupAccountName, но я не могу найти способ конвертировать SID AppContainer в имя AppContainer.

В этом случае S-1-15-2-155514346-2573954481-755741238-1654018636-1233331829-3075935687-2861478708 означает Microsoft.Windows.ShellExperienceHost.

Существует API, который может преобразовать последнее в первое, которое называется DeriveAppContainerSidFromAppContainerName.

Но мне любопытно, как мне преобразовать AppContainerSid в AppContainerName?


person c00000fd    schedule 27.11.2017    source источник


Ответы (1)


для этой задачи существует недокументированная функция (см. app_container.cc из хрома)

LONG WINAPI AppContainerLookupMoniker(PSID Sid, PWSTR* packageFamilyName);

он экспортирован из api-ms-win-appmodel-identity-l1-2-0.dll

он принимает ваш sid в качестве входных данных и возвращает строку - packageFamilyName. для бесплатной этой строки нужно использовать другой недокументированный API

BOOLEAN WINAPI AppContainerFreeMemory(void* ptr);

возвращенное packageFamilyName мы уже можем использовать в документированном API GetPackagesByPackageFamily. возвращено packageFullName, которое мы уже можем использовать в API, например GetStagedPackagePathByFullName, OpenPackageInfoByFullName и т. д.

Например:

#include <appmodel.h>

void AppXtest(PSID Sid)
{
    LONG (WINAPI* AppContainerLookupMoniker)(PSID Sid, PWSTR* packageFamilyName);
    BOOLEAN (WINAPI* AppContainerFreeMemory)(void* ptr);

    if (HMODULE hmod = LoadLibraryW(L"api-ms-win-appmodel-identity-l1-2-0"))
    {
        if ((*(void**)&AppContainerLookupMoniker = GetProcAddress(hmod, "AppContainerLookupMoniker")) &&
            (*(void**)&AppContainerFreeMemory = GetProcAddress(hmod, "AppContainerFreeMemory")))
        {

            PWSTR packageFamilyName;
            LONG err = AppContainerLookupMoniker(Sid, &packageFamilyName);

            if (err == NOERROR)
            {
                DbgPrint("%S\n", packageFamilyName);

                UINT32 count = 0, bufferLength = 0;

                if (ERROR_INSUFFICIENT_BUFFER == GetPackagesByPackageFamily(packageFamilyName, &count, 0, &bufferLength, 0))
                {
                    PWSTR *packageFullNames = (PWSTR*)alloca(count * sizeof(PWSTR) + bufferLength*sizeof(WCHAR));
                    PWSTR buffer = (PWSTR)(packageFullNames+ count);

                    if (NOERROR == GetPackagesByPackageFamily(packageFamilyName, &count, packageFullNames, &bufferLength, buffer))
                    {
                        if (count)
                        {
                            do 
                            {
                                PCWSTR packageFullName = *packageFullNames++;
                                DbgPrint("%S\n", packageFullName);

                                WCHAR path[MAX_PATH];
                                UINT32 len = RTL_NUMBER_OF(path);

                                if (NOERROR == GetStagedPackagePathByFullName(packageFullName, &len, path))
                                {
                                    DbgPrint("%S\n", path);
                                }
                            } while (--count);
                        }
                    }
                }

                AppContainerFreeMemory(packageFamilyName);
            }
        }
    }
}

для Сид S-1-15-2-155514346-2573954481-755741238-1654018636-1233331829-3075935687-2861478708

я получил:

microsoft.windows.shellexperiencehost_cw5n1h2txyewy
Microsoft.Windows.ShellExperienceHost_10.0.14393.0_neutral_neutral_cw5n1h2txyewy
C:\Windows\SystemApps\ShellExperienceHost_cw5n1h2txyewy
person RbMm    schedule 28.11.2017
comment
О, чувак, ты опередил меня минут на 10. Я также нашел это, войдя в DeriveAppContainerSidFromAppContainerName с помощью отладчика. Просто любопытно, что это за cw5n1h2txyewy whatyamacallit в конце? Есть ли способ избавиться от него? В противном случае это выглядит как переполнение буфера. (Это то, что заняло у меня большую часть времени, чтобы понять. Сначала я подумал, что где-то нарушаю размер буфера.) - person c00000fd; 28.11.2017
comment
@ c00000fd нет, cw5n1h2txyewy буфер не переполнен. смотреть под ключом HKEY_CURRENT_USER\SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Mappings\S-1-15-2-155514346-2573954481-755741238-1654018636-1233331829-3075935687-2861478708 - person RbMm; 28.11.2017
comment
Это делается для того, чтобы сделать имя уникальным. Думаю, это объясняется в одном из блогов MSDN. Он привязан к вашей учетной записи разработчика магазина IIRC. - person Anders; 28.11.2017
comment
@Anders: Хм, интересно. Спасибо. Также, если я сделаю DeriveAppContainerSidFromAppContainerName(L"Microsoft.Windows.ShellExperienceHost", &sid);, это удастся. Но тогда, если я сделаю это с этим SID: AppContainerLookupMoniker(sid, &moniker);, произойдет сбой с кодом ошибки 0x80070002 или ERROR_FILE_NOT_FOUND - person c00000fd; 28.11.2017
comment
@c00000fd DeriveAppContainerSidFromAppContainerName всегда завершается успешно. для любого имени. потому что он просто преобразует имя в нижний регистр, а затем вычисляет для него хэш sha-256. и используйте первые 7 двойных слов из хеша для создания sid s-1-15-2-h[0]-h[1]-h[2]-h[3]-h[4]-h[5]-h[6]. последние 8 двойных слов из хеша просто игнорируются - person RbMm; 28.11.2017
comment
@RbMm: О, вот что это за штука. Мне было интересно, почему он вызывает некоторые криптографические функции внутри. Теперь это имеет смысл. (Ну, нет, на самом деле это не так. Например, почему бы ему сначала не проверить правильность pszAppContainerName.) В качестве примечания: чем больше я изучаю внутренности WinAPI, тем больше я вижу какие-то странные округления и -о реализации. - person c00000fd; 29.11.2017