I'm trying to write a BHO for Internet Explorer 11 (Windows 8.1).
My BHO implements the AppContainer sandbox, but I can't seem to create a Named Pipe, CreateNamedPipe
fails with that message: Access is denied.
Here's the code I'm using to create the named pipe (which I found on a russian website, last comment:
LPCWSTR LOW_INTEGRITY_SDDL_SACL_W = L"S:(ML;;NW;;;LW)D:(A;;0x120083;;;WD)(A;;0x120083;;;AC)"; PSECURITY_DESCRIPTOR pSD = NULL; ConvertStringSecurityDescriptorToSecurityDescriptorW ( LOW_INTEGRITY_SDDL_SACL_W, SDDL_REVISION_1, &pSD, NULL ); if ( pSD != NULL) { SECURITY_ATTRIBUTES SecurityAttributes; SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); SecurityAttributes.bInheritHandle = TRUE; SecurityAttributes.lpSecurityDescriptor = pSD; HANDLE hPipe = CreateNamedPipe( L"\\\\.\\pipe\\testpipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, 4096, 4096, 1000, &SecurityAttributes); }
Unfortunately, it doesn't work. GetLastError() returns this Access is denied
as usual.
You cannot create Named Pipe in BHO. But you can create it in your broker process and connect to the pipe from BHO. I'm author of the pointed comment and I tested the code in the broker part of my IE addon.
The code snippets. Pipe creating in auto-started exe (Delphi)
function CreateAppContainerSecurityDescriptor(var SD: PSECURITY_DESCRIPTOR): boolean;
const
SDDL_REVISION_1 = 1;
var
pSD: PSECURITY_DESCRIPTOR;
ConvertStringSecurityDescriptorToSecurityDescriptor: TConvertStringSecurityDescriptorToSecurityDescriptorW;
begin
@ConvertStringSecurityDescriptorToSecurityDescriptor := GetProcAddress(AdvapiDll(),
'ConvertStringSecurityDescriptorToSecurityDescriptorW');
result := false;
if ConvertStringSecurityDescriptorToSecurityDescriptor('S:(ML;;NW;;;LW)D:(A;;0x120083;;;WD)(A;;0x120083;;;AC)',
SDDL_REVISION_1, pSD, nil) then begin
SD := pSD;
result := true;
end;
end;
function TPipeServer.Start: boolean;
var
SD: PSECURITY_DESCRIPTOR;
SecurityAttributes: SECURITY_ATTRIBUTES;
begin
result := false;
if Win32MajorVersion >= 6 then begin
if CreateAppContainerSecurityDescriptor(SD) then begin
SecurityAttributes.nLength := sizeof(SECURITY_ATTRIBUTES);
SecurityAttributes.bInheritHandle := true;
SecurityAttributes.lpSecurityDescriptor := SD;
PipeHandle := CreateNamedPipe('\\.\pipe\MyPipe', PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE or PIPE_READMODE_BYTE, 1, 0, 0, 1000, @SecurityAttributes);
result := PipeHandle <> INVALID_HANDLE_VALUE;
end;
end;
end;
procedure TPipeServer.Execute;
begin
if Start() then begin
while true do begin
if ConnectNamedPipe(PipeHandle, nil) then begin
...
end;
end;
end;
end;
Connecting to pipe in IE toolbar (C++)
#define PIPE_NAME "\\\\.\\pipe\\MYPipe"
LRESULT CMFToolbar::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
...
HANDLE PipeHandle;
if (WaitNamedPipe(PIPE_NAME, NMPWAIT_WAIT_FOREVER) != 0) {
PipeHandle = CreateFile(PIPE_NAME, FILE_READ_DATA | FILE_WRITE_DATA,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (PipeHandle != INVALID_HANDLE_VALUE) {
WriteFile(PipeHandle, ...
CloseHandle(PipeHandle);
}
}
you can add the ALL_APPLICATION_PACKAGE permission to the handle, but it's a backdoor solution,the broker solution is long term.
DWORD WindowsSecurity::AddDACLToObject(HANDLE hObj,SE_OBJECT_TYPE seObjectType) {
LPWSTR szAddSid = 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)pSIDAllAppPackage;
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;
}
I found this question very useful and wanted to add in my 2 cents based on my recent experience with retrofitting an EPM-compatible BHO in a complex product. Dropping some info here that will hopefully help the community. My original question was posted here, so some of it is a repeat of my comments there - Accessing named pipe servers from within IE EPM BHO
I needed some way to achieve 2-way communication -
From BHO to a Windows Service that held some relevant data : The security descriptor above will not work because cross-session IPC doesn't seem to work. I tried setting the named pipes to allow EVERYONE too.
- Solved it by adding a broker to relay the communication.
From external to BHO : This was to provide the BHO some data to perform actions - DOM manipulation etc. Standard IPC options - named pipes, Windows RPC etc. won't work because the BHO cannot host the named pipe servers for external access, looks like.
- Solved it by creating a HWND_MESSAGE window in the SetSite function and calling to it from the Broker process using SendMessage. Message type used needs to be WM_COPYDATA since this is cross-process.
来源:https://stackoverflow.com/questions/18982221/is-there-a-way-to-create-a-named-pipe-from-an-appcontainer-bho-on-ie11