1

最近我遇到了一个名为GetAppContainerNamedObjectPath. 但我不知道如何使用它。

我找到了这个 api 的 msdn 页面(https://docs.microsoft.com/en-us/windows/win32/api/securityappcontainer/nf-securityappcontainer-getappcontainernamedobjectpath)。但是它没有正确的例子和备注,参数写得不好。

最后我得到了ERROR_INVALID_PARAMETER(87)错误,这告诉我我输入的参数有问题。这是我尝试过的。

#define TokenIsAppContainer 29
#define TokenAppContainerSid 31
#define TokenAppContainerNumber 32

typedef struct _TOKEN_APPCONTAINER_INFORMATION {
    PSID TokenAppContainer;
} TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION;

void GetAppContainerProcessInfo(CString & procName)
{
    DWORD dwSize = 0;
    DWORD dwResult;
    HANDLE hToken;
    PTOKEN_APPCONTAINER_INFORMATION pAppCoInfo; 
    WCHAR wcsDebug[1024] = {0,};
    WCHAR * pwSID = NULL;

    typedef BOOL (WINAPI *_LPGETAPPCONTAINERNAMEOBJECTPATH)(HANDLE, PSID, ULONG, LPWSTR, PULONG);

    static _LPGETAPPCONTAINERNAMEOBJECTPATH lpGetAppContainerNamedObjectPath = NULL;

    if (0 == lpGetAppContainerNamedObjectPath)
    {
        HMODULE hKernel32 = LoadLibraryExW(L"kernel32.dll", NULL, 0);
        if (hKernel32)
        {
            lpGetAppContainerNamedObjectPath = reinterpret_cast<_LPGETAPPCONTAINERNAMEOBJECTPATH>(GetProcAddress(hKernel32, "GetAppContainerNamedObjectPath"));
        }
    }

    if (lpGetAppContainerNamedObjectPath)
    {
        DWORD processId = (DWORD)_ttoi((LPCTSTR)procName);
        //HANDLE hProcess = GetProcessHandleByProcessName(procName);
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);

        if(!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
        {
            dwResult = GetLastError();
            swprintf_s( wcsDebug, _countof(wcsDebug), L"OpenProcessToken Error(%u) PID(%d)\n", dwResult, processId );
            AfxMessageBox(wcsDebug);
            return;
        }

        if (!GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS) TokenAppContainerSid, NULL, dwSize, &dwSize))
        {
            dwResult = GetLastError();
            if( dwResult != ERROR_INSUFFICIENT_BUFFER ) 
            {
                swprintf_s( wcsDebug, _countof(wcsDebug), L"GetTokenInformation Error %u\n", dwResult );
                AfxMessageBox(wcsDebug);
                return;
            }
        }

        pAppCoInfo = (PTOKEN_APPCONTAINER_INFORMATION) GlobalAlloc( GPTR, dwSize );

        if (!GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS) TokenAppContainerSid, pAppCoInfo, dwSize, &dwSize))
        {
            dwResult = GetLastError();
            swprintf_s( wcsDebug, _countof(wcsDebug), L"GetTokenInformation Error %u\n", dwResult );
            AfxMessageBox(wcsDebug);
            return;
        }

        WCHAR wcsNamedObjectPath[MAX_PATH];
        ULONG ulRetlen = 0;

        BOOL bRet = lpGetAppContainerNamedObjectPath(hToken, pAppCoInfo->TokenAppContainer, _countof(wcsNamedObjectPath), wcsNamedObjectPath, &ulRetlen );
        if (bRet)
        {
            swprintf_s( wcsDebug, _countof(wcsDebug), L"GetAppContainerNamedObjectPath Path(%s)\n", wcsNamedObjectPath );
            AfxMessageBox(wcsDebug);
        }
        else
        {
            dwResult = GetLastError();
            swprintf_s( wcsDebug, _countof(wcsDebug), L"GetAppContainerNamedObjectPath Error %u\n", dwResult );
            AfxMessageBox(wcsDebug);
        }

        if (pwSID)
            LocalFree(pwSID);

        CloseHandle(hToken)
        CloseHandle(hProcess);
    }
}

作为旁注,我尝试通过调用两次来使用wchar_t *和动态分配内存缓冲区。GetAppContainerNamedObjectPath但还是没有机会。返回长度不返回有意义的值。

4

1 回答 1

3

如果你RtlGetLastNtStatus();打电话GetLastError();GetAppContainerNamedObjectPath

STATUS_INVALID_PARAMETER_MIX-指定了无效的参数组合。

这给你更多信息比较简单的无效参数。

然后寻找函数签名

BOOL
WINAPI
GetAppContainerNamedObjectPath(
    _In_opt_ HANDLE Token,
    _In_opt_ PSID AppContainerSid,
    _In_ ULONG ObjectPathLength,
    _Out_writes_opt_(ObjectPathLength) LPWSTR ObjectPath,
    _Out_ PULONG ReturnLength
    );

使用In_opt声明的TokenAppContainerSid ——这意味着此参数是可选的,您可以传递 0 来代替其中之一。然后问你自己 - 你为TokenAppContainerSid查询令牌是什么?如果您将此令牌传递给 api,系统是否无法为您执行此操作?明显可以。所以你不需要自己做。真的你需要将Token传递给 api,在这种情况下 AppContainerSid必须为 0。或者你可以将AppContainerSid传递给 api,在这种情况下Token必须为 0。当AppContainerSidToken都不为零时 - 你得到了STATUS_INVALID_PARAMETER_MIX

也作为旁注 -PROCESS_ALL_ACCESS如果您需要获取令牌,则不需要打开进程。PROCESS_QUERY_LIMITED_INFORMATION就够了


真的 api 不做大魔术。它返回给你

AppContainerNamedObjects\<Sid>

路径,其中应用程序容器 sid 的字符串形式。(有些像S-1-15-2-...

于 2020-09-18T08:29:33.423 回答