问题描述
我正在尝试使用C#启动一个应用程序容器,并调用pinvoke,并试图通过UpdateProcThreadAttribute()将安全功能设置为属性列表。
GetLastError()返回
87-无效参数
本文类似的c ++代码(底部https://scorpiosoftware.net/2019/01/15/fun-with-appcontainers/的github链接)效果很好。
代码:(下面是pinvoke结构/枚举/外部元素)
public bool testAppContainer()
{
const uint SE_GROUP_ENABLED = 0x00000004;
const int ProcThreadAttributeSecurityCapabilities = 0x00020009;
STARTUPINFOEX startupInfoEx = new STARTUPINFOEX();
PROCESSINFO pInfo = new PROCESSINFO();
Security_CAPABILITIES sc = new Security_CAPABILITIES();
IntPtr pSidInternetClientServer = IntPtr.Zero;
startupInfoEx.StartupInfo.cb = Marshal.SizeOf(startupInfoEx);
string appContainerName = "Test.AppContainer";
try
{
//get the size,then the sid
IntPtr clientServerSid = IntPtr.Zero; uint cbSid = 0;
SecurityNative.CreateWellKNownSid(SecurityNative.WELL_KNowN_SID_TYPE.WinCapabilityInternetClientServerSid,clientServerSid,pSidInternetClientServer,ref cbSid);
pSidInternetClientServer = Marshal.AllocCoTaskMem(Convert.ToInt32(cbSid));
if (!CreateWellKNownSid(WELL_KNowN_SID_TYPE.WinCapabilityInternetClientServerSid,ref cbSid))
{
throw new ApplicationException($"Unable to create well kNown Client Server capability sid!");
}
//create an array of one capability
SID_AND_ATTRIBUTES[] sidAndAttributes = new SID_AND_ATTRIBUTES[1];
sidAndAttributes[0].Sid = pSidInternetClientServer;
sidAndAttributes[0].Attributes = SE_GROUP_ENABLED;
sc.Capabilities = sidAndAttributes;
sc.CapabilityCount = 1;
IntPtr appConSid = IntPtr.Zero;
int hResult = AppContainerNative.DeriveAppContainerSidFromAppContainerName(appContainerName,out appConSid);
if (hResult < 0)
{
throw new ApplicationException($"Application container {appContainerName} was not found on the machine (err code {hResult})");
}
//security capabilities for existing app container
sc.AppContainerSid = appConSid;
const int reserved = 0; var size = IntPtr.Zero; int attributeCount = 1;
bool alreadyInit = ProcessNative.InitializeProcThreadAttributeList(IntPtr.Zero,attributeCount,reserved,ref size);
if (alreadyInit || size == IntPtr.Zero)
{
throw new Exception(string.Format("Couldn't get the size of the attribute list for {0} attributes",attributeCount));
}
startupInfoEx.lpAttributeList = Marshal.AllocHGlobal(size);
if (startupInfoEx.lpAttributeList == IntPtr.Zero)
{
throw new Exception("Couldn't reserve space for a new attribute list");
}
bool initAttributeList = ProcessNative.InitializeProcThreadAttributeList(startupInfoEx.lpAttributeList,ref size);
if (!initAttributeList )
{
throw new Exception("Couldn't create new attribute list");
}
//also tried this (pass in unmanagedAddr instead of ref sc)
// IntPtr unmanagedAddr = Marshal.AllocHGlobal(Marshal.SizeOf(sc));
// Marshal.StructuretoPtr(sc,unmanagedAddr,true);
bool success = UpdateProcThreadAttribute(startupInfoEx.lpAttributeList,(IntPtr)ProcThreadAttributeSecurityCapabilities,ref sc,(IntPtr)Marshal.SizeOf(sc),IntPtr.Zero,IntPtr.Zero);
// Marshal.FreeHGlobal(unmanagedAddr);
// unmanagedAddr = IntPtr.Zero;
if (!success)
{
throw new Exception($"Error adding security capabilities to process launch. Error Code: {Marshal.GetLastWin32Error()}");
}
var pSec = new Security_ATTRIBUTES(); pSec.nLength = Marshal.SizeOf(pSec);
var tSec = new Security_ATTRIBUTES(); tSec.nLength = Marshal.SizeOf(tSec);
success = CreateProcess(null,@"c:\windows\notepad.exe",ref pSec,ref tSec,false,(uint)ProcessNative.CreateProcessFlags.EXTENDED_STARTUPINFO_PRESENT,null,ref startupInfoEx,out pInfo);
if (success)
{
System.Diagnostics.Debug.WriteLine($"Created new app container process {pInfo.dwProcessId}!");
return true;
}
}
finally
{
// Free the attribute list
if (startupInfoEx.lpAttributeList != IntPtr.Zero)
{
ProcessNative.DeleteProcThreadAttributeList(startupInfoEx.lpAttributeList);
Marshal.FreeHGlobal(startupInfoEx.lpAttributeList);
}
// Close process and thread handles
if (pInfo.hProcess != IntPtr.Zero)
{
ProcessNative.CloseHandle(pInfo.hProcess);
}
if (pInfo.hThread != IntPtr.Zero)
{
ProcessNative.CloseHandle(pInfo.hThread);
}
Marshal.FreeHGlobal(startupInfoEx.lpAttributeList);
if (pSidInternetClientServer != IntPtr.Zero)
Marshal.FreeCoTaskMem(pSidInternetClientServer);
}
return true;
}
[StructLayout(LayoutKind.Sequential)]
public struct Security_CAPABILITIES
{
public IntPtr AppContainerSid;
[MarshalAs(UnmanagedType.ByValArray)]
public SID_AND_ATTRIBUTES[] Capabilities;
public uint CapabilityCount;
public uint Reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]
internal struct PROCESSINFO
{
public IntPtr hProcess;
public IntPtr hThread;
public Int32 dwProcessId;
public Int32 dwThreadId;
}
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]
internal struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct Security_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
public enum WELL_KNowN_SID_TYPE
{
WinNullSid,WinWorldSid,WinLocalSid,WinCreatorOwnerSid,WinCreatorGroupSid,WinCreatorOwnerServerSid,WinCreatorGroupServerSid,WinNtAuthoritySid,WinDialupSid,WinNetworkSid,WinBatchSid,WinInteractiveSid,WinServiceSid,WinAnonymousSid,WinProxySid,WinEnterpriseControlleRSSid,WinSelfSid,WinAuthenticatedUserSid,WinRestrictedCodeSid,WinTerminalServerSid,WinRemotelogonIdSid,WinlogonIdsSid,WinLocalSystemSid,WinLocalServiceSid,WinNetworkServiceSid,WinBuiltinDomainSid,WinBuiltinAdministratoRSSid,WinBuiltinUseRSSid,WinBuiltinGuestsSid,WinBuiltinPowerUseRSSid,WinBuiltinAccountOperatoRSSid,WinBuiltinSystemOperatoRSSid,WinBuiltinPrintOperatoRSSid,WinBuiltinBackupOperatoRSSid,WinBuiltinReplicatorSid,WinBuiltinPreWindows2000CompatibleAccessSid,WinBuiltinRemoteDesktopUseRSSid,WinBuiltinNetworkConfigurationoperatoRSSid,WinAccountAdministratorSid,WinAccountGuestSid,WinAccountKrbtgtSid,WinAccountDomainAdminsSid,WinAccountDomainUseRSSid,WinAccountDomainGuestsSid,WinAccountComputeRSSid,WinAccountControlleRSSid,WinAccountCertAdminsSid,WinAccountSchemaAdminsSid,WinAccountEnterpriseAdminsSid,WinAccountPolicyAdminsSid,WinAccountRasAndIasServeRSSid,WinNTLMAuthenticationSid,WinDigestAuthenticationSid,WinSChannelAuthenticationSid,WinThisOrganizationSid,WinOtherOrganizationSid,WinBuiltinincomingForestTrustBuildeRSSid,WinBuiltinPerfMonitoringUseRSSid,WinBuiltinPerfLoggingUseRSSid,WinBuiltinAuthorizationAccessSid,WinBuiltinTerminalServerLicenseServeRSSid,WinBuiltinDCOMUseRSSid,WinBuiltiniUseRSSid,WinIUserSid,WinBuiltinCryptoOperatoRSSid,WinUntrustedLabelSid,WinLowLabelSid,WinMediumLabelSid,WinHighLabelSid,WinSystemLabelSid,WinWriteRestrictedCodeSid,WinCreatorOwnerRightsSid,WinCacheablePrincipalsGroupSid,WinNonCacheablePrincipalsGroupSid,WinEnterpriseReadonlyControlleRSSid,WinAccountReadonlyControlleRSSid,WinBuiltinEventLogReadersGroup,WinNewEnterpriseReadonlyControlleRSSid,WinBuiltinCertSvcDComAccessGroup,WinMediumPlusLabelSid,WinLocallogonSid,WinConsolelogonSid,WinThisOrganizationCertificateSid,WinApplicationPackageAuthoritySid,WinBuiltinAnyPackageSid,WinCapabilityInternetClientSid,WinCapabilityInternetClientServerSid,WinCapabilityPrivateNetworkClientServerSid,WinCapabilityPicturesLibrarySid,WinCapabilityVideosLibrarySid,WinCapabilityMusicLibrarySid,WinCapabilityDocumentsLibrarySid,WinCapabilitySharedUserCertificatesSid,WinCapabilityEnterpriseAuthenticationSid,WinCapabilityRemovableStorageSid,WinBuiltinRDSRemoteAccessServeRSSid,WinBuiltinRDSEndpointServeRSSid,WinBuiltinRDSManagementServeRSSid,WinusermodeDriveRSSid,WinBuiltinHyperVAdminsSid,WinAccountCloneableControlleRSSid,WinBuiltinAccessControlAssistanceOperatoRSSid,WinBuiltinRemoteManagementUseRSSid,WinAuthenticationAuthorityAssertedSid,WinAuthenticationServiceAssertedSid,WinLocalAccountSid,WinLocalAccountAndAdministratorSid,WinAccountProtectedUseRSSid,WinCapabilityAppointmentsSid,WinCapabilityContactsSid,WinAccountDefaultSystemManagedSid,WinBuiltinDefaultSystemManagedGroupSid,WinBuiltinStorageReplicaAdminsSid,WinAccountKeyAdminsSid,WinAccountEnterpriseKeyAdminsSid,WinAuthenticationKeyTrustSid,WinAuthenticationKeyPropertyMFASid,WinAuthenticationKeyPropertyAttestationSid,WinAuthenticationFreshKeyAuthSid,WinBuiltinDeviceOwneRSSid
}
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]
internal struct STARTUPINFOEX
{
public STARTUPINFO StartupInfo;
public IntPtr lpAttributeList;
}
[DllImport("advapi32.dll",SetLastError = true)]
internal static extern bool CreateWellKNownSid(WELL_KNowN_SID_TYPE WellKNownSidType,IntPtr DomainSid,IntPtr pSid,ref uint cbSid);
[DllImport("kernel32.dll",SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CreateProcess(string lpApplicationName,string lpCommandLine,ref Security_ATTRIBUTES lpProcessAttributes,ref Security_ATTRIBUTES lpThreadAttributes,bool bInheritHandles,uint dwCreationFlags,IntPtr lpEnvironment,string lpCurrentDirectory,[In] ref STARTUPINFOEX lpStartupInfo,out PROCESSINFO lpProcessinformation);
[DllImport("kernel32.dll",SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool InitializeProcThreadAttributeList(IntPtr lpAttributeList,int dwAttributeCount,int dwFlags,ref IntPtr lpSize);
[DllImport("kernel32.dll",SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateProcThreadAttribute(IntPtr lpAttributeList,uint dwFlags,IntPtr Attribute,[MarshalAs(UnmanagedType.Struct),In] ref Security_CAPABILITIES caps,IntPtr cbSize,IntPtr lpPrevIoUsValue,IntPtr lpReturnSize);
[DllImport("kernel32.dll",SetLastError = true)]
public static extern void DeleteProcThreadAttributeList(IntPtr lpAttributeList);
解决方法
哇,首先,这是一项很棒的工作,我很好奇您是如何利用它的(CICD?安全性?)。作为一个挑战,我试用了代码,并注意到您对SECURITY_CAPABILITIES
结构的声明与Microsoft文档不匹配。他们将Capabilities
成员列出为指向SID_AND_ATTRIBUTES
结构的指针,而不是结构本身的指针。因此,我将其更改为IntPtr
,以使其成为……
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_CAPABILITIES
{
public IntPtr AppContainerSid;
public IntPtr Capabilities;
public uint CapabilityCount;
public uint Reserved;
}
我不确定如何将结构数组编组为IntPtr,因此现在我下面的示例是您列出的单个功能。
//create one capability
SID_AND_ATTRIBUTES sidAndAttributes = new SID_AND_ATTRIBUTES();
sidAndAttributes.Sid = pSidInternetClientServer;
sidAndAttributes.Attributes = SE_GROUP_ENABLED;
IntPtr sidAndAttributesPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sidAndAttributes));
Marshal.StructureToPtr(sidAndAttributes,sidAndAttributesPtr,false);
sc.Capabilities = sidAndAttributesPtr;
sc.CapabilityCount = 1;
这允许notepad.exe以AppContainer的完整性启动并包含您指定的功能标志。
,感谢您的回复!我确实得到了这个工作。您的建议确实有帮助。实际上,这确实在具有两个功能的应用程序容器中启动了notepad.exe。这是所有想要尝试的元帅的代码。我的目标是将我们用来保护服务器的某些程序尽可能地容器化。
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_CAPABILITIES
{
public IntPtr AppContainerSid;
public IntPtr Capabilities;
public int CapabilityCount;
public int Reserved;
}
private void AddDefaultCapabilitiesSid(ref SECURITY_CAPABILITIES sc)
{
//get the size,then the sid
IntPtr mem = IntPtr.Zero;
IntPtr clientServerSid = IntPtr.Zero;
IntPtr privateNetworkSid = IntPtr.Zero;
IntPtr pSid = IntPtr.Zero;
uint cbSid = 0;
//get the size,then the sid
SecurityNative.CreateWellKnownSid(SecurityNative.WELL_KNOWN_SID_TYPE.WinCapabilityInternetClientServerSid,pSid,clientServerSid,ref cbSid);
clientServerSid = Marshal.AllocCoTaskMem(Convert.ToInt32(cbSid));
if (!SecurityNative.CreateWellKnownSid(SecurityNative.WELL_KNOWN_SID_TYPE.WinCapabilityInternetClientServerSid,ref cbSid))
{
throw new ApplicationException($"Unable to create well known Client Server capability sid!");
}
//get the size,then the sid
SecurityNative.CreateWellKnownSid(SecurityNative.WELL_KNOWN_SID_TYPE.WinCapabilityPrivateNetworkClientServerSid,privateNetworkSid,ref cbSid);
privateNetworkSid = Marshal.AllocCoTaskMem(Convert.ToInt32(cbSid));
if (!SecurityNative.CreateWellKnownSid(SecurityNative.WELL_KNOWN_SID_TYPE.WinCapabilityPrivateNetworkClientServerSid,ref cbSid))
{
throw new ApplicationException($"Unable to create well known Client Server capability sid!");
}
SecurityNative.SID_AND_ATTRIBUTES[] sidAndAttributes = new SecurityNative.SID_AND_ATTRIBUTES[2];
sidAndAttributes[0].Sid = clientServerSid;
sidAndAttributes[0].Attributes = SE_GROUP_ENABLED;
sidAndAttributes[1].Sid = privateNetworkSid;
sidAndAttributes[1].Attributes = SE_GROUP_ENABLED;
int arraySize = sidAndAttributes.Length;
int elemSize = Marshal.SizeOf(typeof(SecurityNative.SID_AND_ATTRIBUTES));
IntPtr result = Marshal.AllocHGlobal(elemSize * arraySize);
mem = new IntPtr(result.ToInt64());
for (int i = 0; i < arraySize; i++)
{
IntPtr ptr = new IntPtr(result.ToInt64() + elemSize * i);
Marshal.StructureToPtr(sidAndAttributes[i],ptr,false);
MemToFree.Add(ptr); //free this mem later
}
sc.Capabilities = mem;
sc.CapabilityCount = arraySize;
}