Allowing connection to .NET COM server with mismat

2019-03-17 02:11发布

I'm having an issue with a COM based client-server setup. The COM server is written in C# (.NET 4.0) and runs as a (registered) local server.

Depending on which application connects to the server, other clients will receive a Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)

The underlying issue is explained here (in the section COM is integrity aware). The way I understand it, it is being caused by the fact that an elevated application creates the server with a higher integrity level. When another non-elevated application then connects, it is not allowed to connect to the same instance. The same happens when a non-elevated application creates the process, followed an elevated application connecting.

I've tried to implement the solution described on the page: modifying the registry to set a security descriptor that should allow all clients to connect. There is a code sample in C++, but this does effectively the same thing in .NET:

// Security Descriptor with NO_EXECUTE_UP
var sd = new RawSecurityDescriptor("O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)");
byte[] securityDescriptor = new Byte[sd.BinaryLength];
sd.GetBinaryForm(securityDescriptor, 0);

RegistryKey key = Registry.ClassesRoot.OpenSubKey("AppID\\{APP-ID-GUID}", true);
if (key == null)
{
    key = Registry.ClassesRoot.CreateSubKey("AppID\\{APP-ID-GUID}");
}

using (key)
{
    key.SetValue("LaunchPermission", securityDescriptor, RegistryValueKind.Binary);
}

However, this does not have the desired effect. When the second client tries to create an instance of the object in question, Windows tries to launch a separate instance of my COM Server, but the server prevents two instances from running as the same user. Given the permissions I've set, I would not expect a second instance to launch in the first place.

Since one of the client applications is running in Medium IL and the other in High IL, I also experimented with variants on the mandatory label, like:

O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;ME)
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)(ML;;NX;;;ME)(ML;;NX;;;HI)

I've also tried setting the ROTFlags registry key to 0x1 (ROTFLAGS_ALLOWANYCLIENT) as suggested on the page, still no change in behavior.

I've established that the LaunchPermission registry value is being used in some way. I cannot discover where it's being read using Process Monitor, but when I use the dcomcnfg.exe tool to set the same key, I can force the server to fail loading by denying launch permissions.

I would like to point out that my server process does not need elevation. How do I make both elevated and non-elevated processes capable of connecting to a single server instance?

标签: c# .net com uac
2条回答
▲ chillily
2楼-- · 2019-03-17 03:00

According to Windows Vista Security Model Analysis you will need to use shared objects such as a named pipe to go between the different IL. Also, the shared object should have an IL equivalent to your lowest IL being used.

查看更多
在下西门庆
3楼-- · 2019-03-17 03:09

you have to Set Debug option to Any cpu in VS.

查看更多
登录 后发表回答