- 积分
- 6709
- 最后登录
- 2024-4-23
- 精华
- 0
- 阅读权限
- 220
- 主题
- 145
- UID
- 3887572
- 帖子
- 2897
- PB币
- 3573
- 威望
- 925
- 贡献
- 0
- 技术
- 801
- 活跃
- 4722
14N.M.
- UID
- 3887572
- 帖子
- 2897
- PB币
- 3573
- 贡献
- 0
- 技术
- 801
- 活跃
- 4722
|
本帖最后由 Mouri_Naruto 于 2015-7-7 09:20 编辑
Tip:估计看完这篇文章的巨神们可能会认为这个帖子有些微不足道,既然这样,就当我来水经验好了
笔者好久没有写新的技术贴了(因为一直在取材);最近我在研究Metro App的沙盒AppContainer也探索出了一些成果,特地分享一下
吐槽:无论是Baidu还是Google;关于AppContainer可以参考的第三方资料太少了;搜索结果里充斥着《腾讯反病毒实验室:深度解析AppContainer工作机制》这类看似高大上实际却很水没有一点用的文章;真正有用的文章有但很少;我想把这些已有的不多的资料整理并加工;这就是我写这篇文章的原因
AppContainer 是 Windows 8 新增的一个基于系统权限的沙盒;防御力度十分给力(可以控制文件,注册表和网络的访问);但是鱼和熊掌不能兼得;防御足够给力也会带来不少问题(比如Metro App就是在AppContainer下运行的;权限十分少;导致很多开发者没办法开发大部分类型的Metro App于是对Metro App开发产生了厌恶之情(比如我的引路人,他曾经也是Metro App的狂热开发者;但是可用的权限太低;他变成了Metro App黑);Win10一堆Brokers和Hosts也是拜此所赐(在AppContainer下的Metro App;很多高权限操作都无法完成;为了一定在Metro App下实现;微软采用了Socket与Brokers和Hosts通信完成高权限操作))。但是对用户而言;AppContainer是不可多得的福利;至少不用看到国产软件的流氓行径(比如我就是:上了8.1后;由于Sandboxie对8.1 x64支持不佳;所以我只敢在虚拟机里用QQ(QQ向系统目录写的垃圾文件已经多到无法直视))。接下来,我将会介绍我所知道的AppContainer的各个方面
PS:也许有人看过我用Metro App静默读取其他位置的文件成功的截图;但是我可是动了手脚的(正常情况下是做不到的,笑)
一.如何在AppContainer运行Win32 App
AppContainer下可以运行Win32 App?笔者你在逗我吧,不是只能运行Metro App的吧?很抱歉,AppContainer的确可以运行Win32 App;IE 10以后的64位增强保护模式和Office 2013的阅读模式就是很好的例子
要在AppContainer下运行Win32 App;正经的做法是
1.获取你所需要的Capabilities SIDs和AppContainer SID
2.把Capabilities SIDs做成SID_AND_ATTRIBUTES结构数组
3.把SID_AND_ATTRIBUTES结构数组与AppContainer SID传入SECURITY_CAPABILITIES结构
4.调用InitializeProcThreadAttributeList把你所生成的SECURITY_CAPABILITIES结构传入STARTUPINFOEX结构的lpAttributeList成员
5.最后用CreateProcess或传入你所生成的STARTUPINFOEX结构即可(PS:不要忘记在dwflags参数里加入EXTENDED_STARTUPINFO_PRESENT)
接下来,你肯定会有疑惑;不要急;我会慢慢解答
首先我想解释一下什么是Capability;如果是Metro App开发者的话;以下截图应该会很熟悉
这些功能声明就是Capabilities,Capabilities SID系统判断你是否可以使用某个Capability或某些Capabilities的依据;如果你想知道Metro App可以声明哪些Capabilities;可以参考http://msdn.microsoft.com/en-us/library/windows/apps/hh464936.aspx
那什么又是AppContainer SID呢;AppContainer SID是系统识别一个AppContainer的依据(抱歉;我实在无法给出更好的措辞来解释;如果有更好的;可以在下面回帖;笔者感激不尽)
多说无用,我还是提供一些代码示例来说明如何使用AppContainer吧
(1)如何创建一个AppContainer- //创建一个AppContainer
- bool NSudoCreateAppContainer(PCWSTR pszAppContainerName, PCWSTR pszDisplayName, PCWSTR pszDescription, bool bReCreate)
- {
- bool bRet = false;
- PSID pSidAppContainerSid;
- if (bReCreate) DeleteAppContainerProfile(pszAppContainerName);
- if (S_OK == CreateAppContainerProfile(
- pszAppContainerName,
- pszDisplayName,
- pszDescription,
- NULL, NULL, &pSidAppContainerSid))
- {
- bRet = true;
- }
- if (pSidAppContainerSid) FreeSid(pSidAppContainerSid);
- return bRet;
- }
复制代码
(2)如何删除一个AppContainer
- //删除指定的AppContainer
- bool NSudoDeleteAppContainer(PCWSTR pszAppContainerName)
- {
- if (S_OK == DeleteAppContainerProfile(pszAppContainerName)) return true;
- return false;
- }
复制代码
(3)如何在指定的AppContainer下创建一个进程
- //在指定的AppContainer运行一个程序(不能在模拟令牌模式调用,也不能在System和TrustedInstaller权限下调用)
- bool NSudoCreateProcessInAppContainer(HANDLE hToken, PCWSTR pszAppContainerName, LPCWSTR lpApplicationName, LPWSTR lpCommandLine,LPCWSTR lpCurrentDirectory)
- {
- bool bRet = true;
- const WELL_KNOWN_SID_TYPE capabilitiyTypeList[] =
- {
- WinCapabilityInternetClientSid,
- WinCapabilityInternetClientServerSid,
- WinCapabilityPrivateNetworkClientServerSid,
- WinCapabilityPicturesLibrarySid,
- WinCapabilityVideosLibrarySid,
- WinCapabilityMusicLibrarySid,
- WinCapabilityDocumentsLibrarySid,
- WinCapabilitySharedUserCertificatesSid,
- WinCapabilityEnterpriseAuthenticationSid,
- WinCapabilityRemovableStorageSid,
- };
- SID_AND_ATTRIBUTES CapabilitiesList[10];
- for (int i = 0; i < 10; i++)
- {
- DWORD dwSIDSize = SECURITY_MAX_SID_SIZE;
- CapabilitiesList[i].Sid = new unsigned char[SECURITY_MAX_SID_SIZE];
- CapabilitiesList[i].Attributes = SE_GROUP_ENABLED;
- if (!CreateWellKnownSid(capabilitiyTypeList[i], NULL, CapabilitiesList[i].Sid, &dwSIDSize) ||
- !IsWellKnownSid(CapabilitiesList[i].Sid, capabilitiyTypeList[i]))
- {
- bRet = false;
- break;
- }
- }
- if (bRet)
- {
- bRet = false;
- PSID pAppContainerSID;
- if (S_OK == DeriveAppContainerSidFromAppContainerName(pszAppContainerName, &pAppContainerSID))
- {
- SECURITY_CAPABILITIES SecurityCapabilities = { pAppContainerSID, CapabilitiesList, 10, 0 };
- STARTUPINFOEX StartupInfoEx = { 0 };
- PROCESS_INFORMATION ProcessInfo = { 0 };
- StartupInfoEx.StartupInfo.cb = sizeof(STARTUPINFOEXW);
- SIZE_T cbAttributeListSize = 0;
- InitializeProcThreadAttributeList(NULL, 3, 0, &cbAttributeListSize);
- StartupInfoEx.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize);
- if (InitializeProcThreadAttributeList(StartupInfoEx.lpAttributeList, 3, 0, &cbAttributeListSize))
- {
- if (UpdateProcThreadAttribute(
- StartupInfoEx.lpAttributeList,
- 0,
- PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES,
- &SecurityCapabilities,
- sizeof(SecurityCapabilities),
- NULL,
- NULL))
- {
- if (CreateProcessAsUserW(
- hToken, lpApplicationName, lpCommandLine, nullptr, nullptr, FALSE,
- EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
- NULL, lpCurrentDirectory, (LPSTARTUPINFOW)&StartupInfoEx, &ProcessInfo))
- {
- bRet = true;
- }
- DeleteProcThreadAttributeList(StartupInfoEx.lpAttributeList);
- }
- }
- FreeSid(pAppContainerSID);
- }
- }
- return bRet;
- }
复制代码
(4)如何使指定的文件或文件夹指定的AppContainer下运行的进程能被读取(这个操作不能在AppContainer里面运行的进程使用)- //设定一个指定目录在指定的AppContainer下完全访问权限
- bool SetFileGrantAccessInAppContainer(PCWSTR pszAppContainerName, LPWSTR pObjectName)
- {
- bool bRet = false;
- PSID pAppContainerSID;
- if (S_OK == DeriveAppContainerSidFromAppContainerName(pszAppContainerName, &pAppContainerSID))
- {
- EXPLICIT_ACCESS ea;
- ea.grfAccessMode = GRANT_ACCESS;
- ea.grfAccessPermissions = FILE_ALL_ACCESS;
- ea.grfInheritance = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
- ea.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
- ea.Trustee.pMultipleTrustee = NULL;
- ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
- ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
- ea.Trustee.ptstrName = (LPTSTR)pAppContainerSID;
- PACL pNewDacl = NULL, pOldDacl = NULL;
- // 获取文件(夹)安全对象的DACL列表
- if (ERROR_SUCCESS == GetNamedSecurityInfoW(
- pObjectName,
- SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
- NULL, NULL, &pOldDacl, NULL, NULL))
- {
- // 创建新的ACL对象(合并已有的ACL对象和刚生成的用户帐户访问控制信息)
- if (ERROR_SUCCESS == SetEntriesInAclW(1, &ea, pOldDacl, &pNewDacl))
- {
- // 设置文件(夹)安全对象的DACL列表
- if (ERROR_SUCCESS == SetNamedSecurityInfoW(
- pObjectName,
- SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
- NULL, NULL, pNewDacl, NULL))
- {
- bRet = true;
- }
- LocalFree(pNewDacl);
- }
- LocalFree(pOldDacl);
- }
- FreeSid(pAppContainerSID);
- }
- return bRet;
- }
复制代码 |
-
12
查看全部评分
-
|