C# 以编程方式实现dcomcnfg功能
我可以找到关于如何为DCOM编程的各种资料,但实际上没有任何关于如何以编程方式设置/检查安全性的资料 我不想重新创建dcomcnfg,但如果我知道如何在C#(首选,或VB.net)中复制dcomcnfg的所有功能,那么我的目标就在望了 我似乎找不到任何关于这方面的好资源,没有开源API,甚至没有关于如何执行每个步骤的快速示例。即使在这里,DCOM或dcomcnfg也很少返回关于如何设置/验证/列出安全性的结果C# 以编程方式实现dcomcnfg功能,c#,.net,security,permissions,dcom,C#,.net,Security,Permissions,Dcom,我可以找到关于如何为DCOM编程的各种资料,但实际上没有任何关于如何以编程方式设置/检查安全性的资料 我不想重新创建dcomcnfg,但如果我知道如何在C#(首选,或VB.net)中复制dcomcnfg的所有功能,那么我的目标就在望了 我似乎找不到任何关于这方面的好资源,没有开源API,甚至没有关于如何执行每个步骤的快速示例。即使在这里,DCOM或dcomcnfg也很少返回关于如何设置/验证/列出安全性的结果 如果任何人有一些指向开放API的指针或一些示例,我将不胜感激。我找不到任何.NET方法
如果任何人有一些指向开放API的指针或一些示例,我将不胜感激。我找不到任何.NET方法来实现这一点-您也可以使用MS命令行实用程序(也是SDK的一部分) 此信息存储在
HKCR\AppID\{Your AppID}\LaunchPermission
和AccessPermission
中。这些是包含序列化安全描述符的REG_二进制值。不知道是否有任何东西可以方便地从.NET访问这些内容
更多信息。面对类似的情况(从MSI配置DCOM安全性),我设法创建了一个解决方案,通过更改HKEY_CLASSES_ROOT\AppID{APP-GUID-GOES-HERE}中的注册表键值来实现我想要的功能。多亏阿诺的回答让我走上了正确的道路 具体来说,我创建了一个方法来编辑DCOM对象的安全权限,这些权限存储在LaunchPermission和AccessPermission注册表键值中。这些是序列化的安全描述符,您可以通过
RawSecurityDescriptor
传递二进制数据来访问它们。这个类以美味的.NET-y方式简化了许多细节,但您仍然必须关注有关Windows ACL的所有逻辑细节,并且必须确保使用RawSecurityDescriptor.GetBinaryForm
将安全描述符写回注册表
我创建的方法名为EditOrCreateACE
。此方法将编辑帐户的现有ACE,或插入新ACE,并确保访问掩码设置了已传递的标志。我在此附上它作为一个示例,这绝对不是关于如何处理它的任何权威,因为我对Windows ACL的内容仍然知之甚少:
// These are constants for the access mask on LaunchPermission.
// I'm unsure of the exact constants for AccessPermission
private const int COM_RIGHTS_EXECUTE = 1;
private const int COM_RIGHTS_EXECUTE_LOCAL = 2;
private const int COM_RIGHTS_EXECUTE_REMOTE = 4;
private const int COM_RIGHTS_ACTIVATE_LOCAL = 8;
private const int COM_RIGHTS_ACTIVATE_REMOTE = 16;
void EditOrCreateACE(string keyname, string valuename,
string accountname, int mask)
{
// Get security descriptor from registry
byte[] keyval = (byte[]) Registry.GetValue(keyname, valuename,
new byte[] { });
RawSecurityDescriptor sd;
if (keyval.Length > 0) {
sd = new RawSecurityDescriptor(keyval, 0);
} else {
sd = InitializeEmptySecurityDescriptor();
}
RawAcl acl = sd.DiscretionaryAcl;
CommonAce accountACE = null;
// Look for the account in the ACL
int i = 0;
foreach (GenericAce ace in acl) {
if (ace.AceType == AceType.AccessAllowed) {
CommonAce c_ace = ace as CommonAce;
NTAccount account =
c_ace.SecurityIdentifier.Translate(typeof(NTAccount))
as NTAccount;
if (account.Value.Contains(accountname)) {
accountACE = c_ace;
}
i++;
}
}
// If no ACE found for the given account, insert a new one at the end
// of the ACL, otherwise just set the mask
if (accountACE == null) {
SecurityIdentifier ns_account =
(new NTAccount(accountname)).Translate(typeof(SecurityIdentifier))
as SecurityIdentifier;
CommonAce ns = new CommonAce(AceFlags.None, AceQualifier.AccessAllowed,
mask, ns_account, false, null);
acl.InsertAce(acl.Count, ns);
} else {
accountACE.AccessMask |= mask;
}
// Write security descriptor back to registry
byte[] binarySd = new byte[sd.BinaryLength];
sd.GetBinaryForm(binarySd, 0);
Registry.SetValue(keyname, valuename, binarySd);
}
private static RawSecurityDescriptor InitializeEmptySecurityDescriptor()
{
var localSystem =
new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
var new_sd =
new RawSecurityDescriptor(ControlFlags.DiscretionaryAclPresent,
localSystem, localSystem, null,
new RawAcl(GenericAcl.AclRevision, 1));
return new_sd;
}
请注意,此代码绝不是完美的。如果注册表中缺少这些ACL的整个注册表项值,则合成的ACL将只授予对传递的帐户的访问权限,而不授予其他任何权限。我也确信有很多错误情况我没有正确处理,细节我已经掩盖了。同样,这是一个如何在.NET中处理DCOM ACL的示例。Daniel给出的答案非常有用。非常感谢你,丹尼尔 问题在于,它们表示注册表值包含二进制形式的ACL。因此,例如,如果您试图设置机器的默认访问权限(而不是每个进程),您将访问注册表项HKEY\U LOCAL\U machine\SOFTWARE\Microsoft\Ole\DefaultAccessPermission。但是,在我最初尝试使用System.Security.AccessControl.RawACL类访问此密钥时失败 正如Daniel的代码所指出的,该值实际上不是ACL,而是包含ACL的SecurityDescriptor 因此,尽管我知道这篇文章很旧,但我还是要发布我的解决方案,用于检查和设置安全设置,并为默认本地访问添加NetworkService。当然,我相信你可以把它做得更好,但要开始,你只需要更改密钥和访问掩码
static class ComACLRights{
public const int COM_RIGHTS_EXECUTE= 1;
public const int COM_RIGHTS_EXECUTE_LOCAL = 2;
public const int COM_RIGHTS_EXECUTE_REMOTE = 4;
public const int COM_RIGHTS_ACTIVATE_LOCAL = 8;
public const int COM_RIGHTS_ACTIVATE_REMOTE = 16;
}
class Program
{
static void Main(string[] args)
{
var value = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", "DefaultAccessPermission", null);
RawSecurityDescriptor sd;
RawAcl acl;
if (value == null)
{
System.Console.WriteLine("Default Access Permission key has not been created yet");
sd = new RawSecurityDescriptor("");
}else{
sd = new RawSecurityDescriptor(value as byte[], 0);
}
acl = sd.DiscretionaryAcl;
bool found = false;
foreach (CommonAce ca in acl)
{
if (ca.SecurityIdentifier.IsWellKnown(WellKnownSidType.NetworkServiceSid))
{
//ensure local access is set
ca.AccessMask |= ComACLRights.COM_RIGHTS_EXECUTE | ComACLRights.COM_RIGHTS_EXECUTE_LOCAL | ComACLRights.COM_RIGHTS_ACTIVATE_LOCAL; //set local access. Always set execute
found = true;
break;
}
}
if(!found){
//Network Service was not found. Add it to the ACL
SecurityIdentifier si = new SecurityIdentifier(
WellKnownSidType.NetworkServiceSid, null);
CommonAce ca = new CommonAce(
AceFlags.None,
AceQualifier.AccessAllowed,
ComACLRights.COM_RIGHTS_EXECUTE | ComACLRights.COM_RIGHTS_EXECUTE_LOCAL | ComACLRights.COM_RIGHTS_ACTIVATE_LOCAL,
si,
false,
null);
acl.InsertAce(acl.Count, ca);
}
//re-set the ACL
sd.DiscretionaryAcl = acl;
byte[] binaryform = new byte[sd.BinaryLength];
sd.GetBinaryForm(binaryform, 0);
Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", "DefaultAccessPermission", binaryform, RegistryValueKind.Binary);
}
}
我发现这个解决方案有效:
public static void SetUp()
{
SetCOMSercurityAccess("DefaultAccessPermission");
SetCOMSercurityAccess("DefaultLaunchPermission");
}
private static void SetCOMSercurityAccess(string regKey)
{
//This is the magic permission!
byte[] binaryform = new string[]
{
"01","00","04","80","80","00","00","00","90","00","00","00","00","00","00","00","14","00","00","00","02","00","6c","00","04",
"00","00","00","00","00","14","00","1f","00","00","00","01","01","00","00","00","00","00","05","12","00","00","00","00","00",
"24","00","0b","00","00","00","01","05","00","00","00","00","00","05","15","00","00","00","a3","53","d8","c8","94","bd","63",
"84","88","bf","fa","cf","a7","2b","00","00","00","00","18","00","1f","00","00","00","01","02","00","00","00","00","00","05",
"20","00","00","00","20","02","00","00","00","00","14","00","1f","00","00","00","01","01","00","00","00","00","00","05","04",
"00","00","00","01","02","00","00","00","00","00","05","20","00","00","00","20","02","00","00","01","02","00","00","00","00",
"00","05","20","00","00","00","20","02","00","00"
}.Select(o=> Convert.ToByte(o,16)).ToArray();
Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", regKey, binaryform, RegistryValueKind.Binary);
}
如果它能帮助别人…Yikes!刚刚注意到你的回答,很抱歉。我会尝试一下,希望很快,然后再给你回复。看来我们需要一个完整的图书馆。你和丹尼尔似乎都在正确的轨道上。这一切仍然很痛苦,但它起作用了。我对谁应该给予赞扬感到苦恼。但你看起来可以更多地利用这些要点。:)不客气。我通过跟踪DCOMPerm的源代码并分析它在做什么(在C++中)获得了大部分详细信息。这可能也会有所帮助:是否还有dcomper.exe存在?我在任何地方都找不到预编译的版本,链接似乎已经死了