我正在尝试在 Windows 中的 appcontainer 进程和正常进程之间创建 ipc。
我在 Windows appcontainer 中做了一个进程,感谢这篇文章。但是,我不知道如何在 appcontainer 中的进程和正常进程之间进行通信。
我尝试使用命名管道进行通信,但在 appcontainer 进程“访问被拒绝”上出现错误。(GetLastError() 返回 5)。然后我尝试了一个套接字(localhost),但即使端口号相同,它们也没有连接。
我检查了很多文章来解决这个问题......但我确实失败了。这是我检查的文章。
- https://docs.microsoft.com/ko-kr/windows/win32/api/securityappcontainer/nf-securityappcontainer-getappcontainernamedobjectpath?redirectedfrom=MSDN
- 有没有办法从 IE11 上的 AppContainer BHO 创建命名管道?
- https://docs.microsoft.com/en-us/windows/win32/secauthz/modifying-the-acls-of-an-object-in-c--
- 以低完整性级别打开命名管道
- https://docs.microsoft.com/en-us/windows/win32/ipc/transactions-on-named-pipes
- https://social.msdn.microsoft.com/Forums/Windowsapps/en-US/e92502b1-0b9f-4e02-9d72-e4e47e924a8f/accessing-named-objects-from-an-appcontainer?forum=windowssecurity
- AppContainer 完整性等级
- http://recxltd.blogspot.com/2012/03/windows-8-app-container-security-notes.html
- https://www.malwaretech.com/2015/09/advanced-desktop-application-sandboxing.html
我想知道有一种方法可以在普通进程和 Windows 应用程序容器中的进程之间进行 ipc。
我正在以下环境中工作。
- 视窗 10
- 视觉工作室 2019
这是我的代码。
#include <iostream>
#include <Windows.h>
#include <strsafe.h>
#include <Sddl.h>
#include <AccCtrl.h>
#include <AclAPI.h>
#include <UserEnv.h>
#pragma comment(lib, "Userenv.lib")
//List of allowed capabilities for the application
extern WELL_KNOWN_SID_TYPE app_capabilities[] =
{
WinCapabilityInternetClientSid,
//WinCapabilityPrivateNetworkClientServerSid,
};
WCHAR container_name[] = L"SandboxTest";
WCHAR container_desc[] = L"Sandbox Test";
BOOL IsInAppContainer();
BOOL SetSecurityCapabilities(PSID container_sid, SECURITY_CAPABILITIES* capabilities, PDWORD num_capabilities);
BOOL GrantNamedObjectAccess(PSID appcontainer_sid, HANDLE object_handle, SE_OBJECT_TYPE object_type, DWORD access_mask);
DWORD AddDACLToObject(PSID appcontainer_sid, HANDLE hObj, SE_OBJECT_TYPE seObjectType);
BOOL CreateObjectSecurityDescriptor(PSID pLogonSid, PSECURITY_DESCRIPTOR* ppSD);
BOOL GetLogonSid(HANDLE hToken, PSID* ppsid);
int ConnectClient(HANDLE hNamePipe);
BOOL IsInAppContainer()
{
HANDLE process_token;
BOOL is_container = 0;
DWORD return_length;
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token);
if (!GetTokenInformation(process_token, TokenIsAppContainer, &is_container, sizeof is_container, &return_length))
return false;
return is_container;
}
HANDLE hNamePipe;
BOOL RunExecutableInContainer(CHAR* executable_path)
{
PSID sid = NULL;
HRESULT result;
SECURITY_CAPABILITIES SecurityCapabilities = { 0 };
DWORD num_capabilities = 0;
SIZE_T attribute_size = 0;
STARTUPINFOEXA startup_info = { 0 };
PROCESS_INFORMATION process_info = { 0 };
CHAR* string_sid = NULL;
BOOL success = FALSE;
HANDLE hToken = NULL;
HANDLE hNewToken = NULL;
PSID pIntegritySid = NULL;
TOKEN_MANDATORY_LABEL TIL = { 0 };
CHAR wszIntegritySid[20] = "S-1-16-4096";
//4096
//8192
// HANDLE hNamePipe;
CHAR pipe_name[] = "\\\\.\\pipe\\LOCAL";
do {
result = CreateAppContainerProfile(container_name, container_name, container_desc, NULL, 0, &sid);
if (!SUCCEEDED(result))
{
if (HRESULT_CODE(result) == ERROR_ALREADY_EXISTS)
{
result = DeriveAppContainerSidFromAppContainerName(container_name, &sid);
if (!SUCCEEDED(result))
{
printf("Failed to get existing AppContainer name, error code: %d", HRESULT_CODE(result));
break;
}
}
else {
printf("Failed to create AppContainer, last error: %d\n", HRESULT_CODE(result));
break;
}
}
printf("[Container Info]\nname: %ws\ndescription: %ws\n", container_name, container_desc);
if (ConvertSidToStringSidA(sid, &string_sid))
printf("Sid: %s\n\n", string_sid);
if (!SetSecurityCapabilities(sid, &SecurityCapabilities, &num_capabilities))
{
printf("Failed to set security capabilities, last error: %d\n", GetLastError());
break;
}
/*
// pipe
hNamePipe = CreateNamedPipe(
pipe_name,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0,
0,
20000,
NULL);
if (hNamePipe == INVALID_HANDLE_VALUE)
{
printf("CreateNamePipe error! \n");
break;
}
if (!GrantNamedObjectAccess(sid, hNamePipe, SE_KERNEL_OBJECT, FILE_ALL_ACCESS))
{
printf("Failed to grant explicit access to %s\n", pipe_name);
DisconnectNamedPipe(hNamePipe);
CloseHandle(hNamePipe);
break;
}
*/
/*
hNamePipe = CreateNamedPipe(
pipe_name,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0,
0,
20000,
NULL);
if (AddDACLToObject(sid, hNamePipe, SE_KERNEL_OBJECT))
{
printf("Failed to grant explicit access to %s\n", pipe_name);
break;
}*/
/*
PSID pLogonSid = NULL;
PSECURITY_DESCRIPTOR pSd = NULL;
SECURITY_ATTRIBUTES SecurityAttributes;
HANDLE hToken = NULL;
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
pLogonSid = (PSID)malloc(sizeof(PSID));
//Allowing LogonSid and all appcontainers.
if (GetLogonSid(hToken, &pLogonSid) && CreateObjectSecurityDescriptor(pLogonSid, &pSd))
{
SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
SecurityAttributes.bInheritHandle = TRUE;
SecurityAttributes.lpSecurityDescriptor = pSd;
hNamePipe = CreateNamedPipe(
pipe_name,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0,
0,
20000,
&SecurityAttributes);
printf("pipe created\n");
}
*/
InitializeProcThreadAttributeList(NULL, 1, NULL, &attribute_size);
startup_info.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)malloc(attribute_size);
if (!InitializeProcThreadAttributeList(startup_info.lpAttributeList, 1, NULL, &attribute_size))
{
printf("InitializeProcThreadAttributeList() failed, last error: %d", GetLastError());
break;
}
if (!UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES,
&SecurityCapabilities, sizeof(SecurityCapabilities), NULL, NULL))
{
printf("UpdateProcThreadAttribute() failed, last error: %d", GetLastError());
break;
}
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_DUPLICATE |
TOKEN_ADJUST_DEFAULT |
TOKEN_QUERY |
TOKEN_ASSIGN_PRIMARY,
&hToken))
{
break;
}
if (!DuplicateTokenEx(hToken,
0,
NULL,
SecurityImpersonation,
TokenPrimary,
&hNewToken))
{
break;
}
if (!ConvertStringSidToSid(wszIntegritySid, &pIntegritySid))
{
break;
}
TIL.Label.Attributes = SE_GROUP_INTEGRITY;
TIL.Label.Sid = pIntegritySid;
if (!SetTokenInformation(hNewToken,
TokenIntegrityLevel,
&TIL,
sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid)))
{
break;
}
if (!CreateProcessAsUser(hNewToken,
executable_path,
NULL,
NULL,
NULL,
FALSE,
EXTENDED_STARTUPINFO_PRESENT,
NULL,
NULL,
(LPSTARTUPINFOA)& startup_info,
&process_info))
{
printf("Failed to create process %s, last error: %d\n", executable_path, GetLastError());
break;
}
printf("Successfully executed %s in AppContainer\n", executable_path);
success = TRUE;
} while (FALSE);
if (startup_info.lpAttributeList)
DeleteProcThreadAttributeList(startup_info.lpAttributeList);
if (SecurityCapabilities.Capabilities)
free(SecurityCapabilities.Capabilities);
if (sid)
FreeSid(sid);
if (string_sid)
LocalFree(string_sid);
if (process_info.hProcess != NULL)
CloseHandle(process_info.hProcess);
if (process_info.hThread != NULL)
CloseHandle(process_info.hThread);
LocalFree(pIntegritySid);
if (hNewToken != NULL)
CloseHandle(hNewToken);
if (hToken != NULL)
CloseHandle(hToken);
return success;
}
/*
Set the security capabilities of the container to those listed in app_capabilities
*/
BOOL SetSecurityCapabilities(PSID container_sid, SECURITY_CAPABILITIES* capabilities, PDWORD num_capabilities)
{
DWORD sid_size = SECURITY_MAX_SID_SIZE;
DWORD num_capabilities_ = sizeof(app_capabilities) / sizeof(DWORD);
SID_AND_ATTRIBUTES* attributes;
BOOL success = TRUE;
attributes = (SID_AND_ATTRIBUTES*)malloc(sizeof(SID_AND_ATTRIBUTES) * num_capabilities_);
ZeroMemory(capabilities, sizeof(SECURITY_CAPABILITIES));
ZeroMemory(attributes, sizeof(SID_AND_ATTRIBUTES) * num_capabilities_);
for (unsigned int i = 0; i < num_capabilities_; i++)
{
attributes[i].Sid = malloc(SECURITY_MAX_SID_SIZE);
if (!CreateWellKnownSid(app_capabilities[i], NULL, attributes[i].Sid, &sid_size))
{
success = FALSE;
break;
}
attributes[i].Attributes = SE_GROUP_ENABLED;
}
if (success == FALSE)
{
for (unsigned int i = 0; i < num_capabilities_; i++)
{
if (attributes[i].Sid)
LocalFree(attributes[i].Sid);
}
free(attributes);
attributes = NULL;
num_capabilities_ = 0;
}
capabilities->Capabilities = attributes;
capabilities->CapabilityCount = num_capabilities_;
capabilities->AppContainerSid = container_sid;
*num_capabilities = num_capabilities_;
return success;
}
/*
Explicitly grants the container access to a named object (file, section, etc)
*/
BOOL GrantNamedObjectAccess(PSID appcontainer_sid, HANDLE object_handle, SE_OBJECT_TYPE object_type, DWORD access_mask)
{
EXPLICIT_ACCESS_A explicit_access;
PACL original_acl = NULL, new_acl = NULL;
DWORD status;
BOOL success = FALSE;
do
{
explicit_access.grfAccessMode = GRANT_ACCESS;
explicit_access.grfAccessPermissions = access_mask;
explicit_access.grfInheritance = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
explicit_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
explicit_access.Trustee.pMultipleTrustee = NULL;
explicit_access.Trustee.ptstrName = (CHAR*)appcontainer_sid;
explicit_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
explicit_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
status = GetSecurityInfo(object_handle, object_type, DACL_SECURITY_INFORMATION, NULL, NULL, &original_acl,
NULL, NULL);
if (status != ERROR_SUCCESS)
{
printf("GetSecurityInfo() failed, error: %d\n", status);
break;
}
status = SetEntriesInAclA(1, &explicit_access, original_acl, &new_acl);
if (status != ERROR_SUCCESS)
{
printf("SetEntriesInAclA() failed, error: %d\n", status);
break;
}
status = SetSecurityInfo(object_handle, object_type, DACL_SECURITY_INFORMATION, NULL, NULL, new_acl, NULL);
if (status != ERROR_SUCCESS)
{
printf("SetSecurityInfo() failed, error: %d\n", status);
break;
}
success = TRUE;
} while (FALSE);
if (original_acl)
LocalFree(original_acl);
if (new_acl)
LocalFree(new_acl);
return success;
}
DWORD AddDACLToObject(PSID appcontainer_sid, HANDLE hObj, SE_OBJECT_TYPE seObjectType)
{
LPSTR szAddSid = (LPSTR)"S-1-15-2-1";
// LPWSTR szAddSid = L"S-1-15-2-1";//SID_ALL_APP_PACKAGES;
PACL pACL = NULL;
DWORD dwRes;
PSID pSIDAllAppPackage = NULL;
PSECURITY_DESCRIPTOR pSDOld = NULL;
PACL pOldDACL = NULL;
dwRes = GetSecurityInfo(hObj, seObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldDACL, NULL, &pSDOld);
if (ERROR_SUCCESS != dwRes)
{
return dwRes;
}
if (ConvertStringSidToSid(szAddSid, &pSIDAllAppPackage) == FALSE)
{
dwRes = GetLastError();
return dwRes;
}
const int NUM_ACES = 1;
EXPLICIT_ACCESS ea[NUM_ACES];
ZeroMemory(&ea, NUM_ACES * sizeof(EXPLICIT_ACCESS));
ea[0].grfAccessPermissions = GENERIC_ALL;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR)appcontainer_sid;
dwRes = SetEntriesInAcl(NUM_ACES, ea, pOldDACL, &pACL);
if (ERROR_SUCCESS != dwRes)
{
return dwRes;
}
dwRes = SetSecurityInfo(
hObj, // name of the object
seObjectType, // type of object
DACL_SECURITY_INFORMATION, // change only the object's DACL
NULL, NULL, // do not change owner or group
pACL, // DACL specified
NULL); // do not change SACL
return dwRes;
}
BOOL GetLogonSid(HANDLE hToken, PSID* ppsid)
{
BOOL bSuccess = FALSE;
DWORD dwLength = 0;
PTOKEN_GROUPS ptg = NULL;
// Verify the parameter passed in is not NULL.
if (NULL == ppsid)
goto Cleanup;
// Get required buffer size and allocate the TOKEN_GROUPS buffer.
if (!GetTokenInformation(
hToken, // handle to the access token
TokenLogonSid, // get information about the token's groups
(LPVOID)ptg, // pointer to TOKEN_GROUPS buffer
0, // size of buffer
&dwLength // receives required buffer size
))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto Cleanup;
ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwLength);
if (ptg == NULL)
goto Cleanup;
}
// Get the token group information from the access token.
if (!GetTokenInformation(
hToken, // handle to the access token
TokenLogonSid, // get information about the token's groups
(LPVOID)ptg, // pointer to TOKEN_GROUPS buffer
dwLength, // size of buffer
&dwLength // receives required buffer size
) || ptg->GroupCount != 1)
{
goto Cleanup;
}
// Found the logon SID; make a copy of it.
dwLength = GetLengthSid(ptg->Groups[0].Sid);
*ppsid = (PSID)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwLength);
if (*ppsid == NULL)
goto Cleanup;
if (!CopySid(dwLength, *ppsid, ptg->Groups[0].Sid))
{
HeapFree(GetProcessHeap(), 0, (LPVOID)* ppsid);
goto Cleanup;
}
bSuccess = TRUE;
Cleanup:
// Free the buffer for the token groups.
if (ptg != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
return bSuccess;
}
BOOL
CreateObjectSecurityDescriptor(PSID pLogonSid, PSECURITY_DESCRIPTOR* ppSD)
{
BOOL bSuccess = FALSE;
DWORD dwRes;
PSID pAllAppsSID = NULL;
PACL pACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea[2];
SID_IDENTIFIER_AUTHORITY ApplicationAuthority = SECURITY_APP_PACKAGE_AUTHORITY;
// Create a well-known SID for the all appcontainers group.
if (!AllocateAndInitializeSid(&ApplicationAuthority,
SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT,
SECURITY_APP_PACKAGE_BASE_RID,
SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE,
0, 0, 0, 0, 0, 0,
&pAllAppsSID))
{
wprintf(L"AllocateAndInitializeSid Error %u\n", GetLastError());
goto Cleanup;
}
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow LogonSid generic all access
ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));
ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER;
ea[0].Trustee.ptstrName = (LPTSTR)pLogonSid;
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow the all appcontainers execute permission
ea[1].grfAccessPermissions = STANDARD_RIGHTS_READ | STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTEX_MODIFY_STATE;
ea[1].grfAccessMode = SET_ACCESS;
ea[1].grfInheritance = NO_INHERITANCE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[1].Trustee.ptstrName = (LPTSTR)pAllAppsSID;
// Create a new ACL that contains the new ACEs.
dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);
if (ERROR_SUCCESS != dwRes)
{
wprintf(L"SetEntriesInAcl Error %u\n", GetLastError());
goto Cleanup;
}
// Initialize a security descriptor.
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == pSD)
{
wprintf(L"LocalAlloc Error %u\n", GetLastError());
goto Cleanup;
}
if (!InitializeSecurityDescriptor(pSD,
SECURITY_DESCRIPTOR_REVISION))
{
wprintf(L"InitializeSecurityDescriptor Error %u\n",
GetLastError());
goto Cleanup;
}
// Add the ACL to the security descriptor.
if (!SetSecurityDescriptorDacl(pSD,
TRUE, // bDaclPresent flag
pACL,
FALSE)) // not a default DACL
{
wprintf(L"SetSecurityDescriptorDacl Error %u\n",
GetLastError());
goto Cleanup;
}
*ppSD = pSD;
pSD = NULL;
bSuccess = TRUE;
Cleanup:
if (pAllAppsSID)
FreeSid(pAllAppsSID);
if (pACL)
LocalFree(pACL);
if (pSD)
LocalFree(pSD);
return bSuccess;
}
int ConnectClient(HANDLE hNamePipe)
{
TCHAR recvMessage[100];
TCHAR sendMessage[100];
DWORD recvSize;
DWORD sendSize;
while (1)
{
printf("Input Send Message : ");
scanf("%s", sendMessage);
if (!(WriteFile(
hNamePipe,
sendMessage,
(strlen(sendMessage) + 1) * sizeof(TCHAR),
&sendSize,
NULL)))
{
printf("WriteFile error! \n");
return -1;
}
FlushFileBuffers(hNamePipe);
if (!(ReadFile(
hNamePipe,
recvMessage,
sizeof(recvMessage) - sizeof(TCHAR) * 1,
&recvSize,
NULL)))
{
printf("ReadFile error! \n");
return -1;
}
recvMessage[recvSize / sizeof(TCHAR) - 1] = '\x00';
printf("Recv Message : %s \n", recvMessage);
}
return 1;
}
int main()
{
CHAR path[] = "D:\\Projects\\Visual Studio Project\\SandboxTest\\socket.exe";
std::cout << IsInAppContainer();
RunExecutableInContainer(path);
getchar();
}