我有一个应用程序需要在以管理员身份运行时注册控件,我希望应用程序在不再需要提升的权限时放弃这些权限。我读到这可以通过 AdjustTokenPrivileges ( Dropping privileges in C++ on Windows ) 完成,但我没有找到任何示例代码可以让我从 SECURITY_MANDATORY_HIGH_RID 转到 SECURITY_MANDATORY_MEDIUM_RID。我的代码是使用 Visual Studio 编写的 C++。
最佳答案
如果你愿意
sample code that will allow me to go from SECURITY_MANDATORY_HIGH_RID to SECURITY_MANDATORY_MEDIUM_RID.
您需要使用 TOKEN_ADJUST_DEFAULT(用于更改完整性级别 - 这是强制性的)和 WRITE_OWNER(用于更改 token 安全描述符中的强制性标签 - 否则您无法通过更多的写访问权限打开自己的 token - 但这是可选的)
调用SetTokenInformation与 TokenIntegrityLevel让当前的完整性级别降级。在此之后它已经无法提升。
当我们将完整性级别设置为低于 SECURITY_MANDATORY_HIGH_RID 时,系统内部也会禁用 token 中的某些权限。我怀疑这是否已记录在案,但根据我的测试,下一个权限已被禁用并且无法再启用:
SeTakeOwnershipPrivilege
SeLoadDriverPrivilege
SeBackupPrivilege
SeRestorePrivilege
SeDebugPrivilege
SeImpersonatePrivilege
SeDelegateSessionUserImpersonatePrivilege
但您仍然是管理员组的成员(S-1-5-32-544 Administrators)并且此组不能被 AdjustTokenGroups 禁用因为函数无法禁用具有 SE_GROUP_MANDATORY 属性的组 - 但 S-1-5-32-544 具有此属性。并且更改主进程 token 也是不可能的(如果我们有 SeAssignPrimaryTokenPrivilege ,则只有在进程创建之后(处于暂停状态)并且在它开始执行(恢复)之前才有可能)
所以在将完整性级别降级到中之后,您的应用程序实际上将处于中间状态 - 从一方面您失去了最重要的特权,但访问对象(文件,注册表项)主要不是基于特权但组成员资格和强制性标签 - 与完整性级别相比。因为 Administrators 组仍将在您的 token 中启用,并且大多数对象没有明确的强制标签(默认情况下为中等)-您的应用程序仍然能够打开/创建限制应用程序的文件/ key (在 uac 下为管理员) ) 不能。但是,如果您将完整性级别降级到 SECURITY_MANDATORY_LOW_RID - 您的应用程序确实有限,但大多数遗留代码在低级别完整性下不正确
降级完整性级别的最少代码:
ULONG SetMediumLevel()
{
HANDLE hToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT, &hToken))
{
ULONG cbSid = GetSidLengthRequired(1);
TOKEN_MANDATORY_LABEL tml = { { alloca(cbSid)} };
ULONG dwError = NOERROR;
if (!CreateWellKnownSid(WinMediumLabelSid, 0, tml.Label.Sid, &cbSid) ||
!SetTokenInformation(hToken, TokenIntegrityLevel, &tml, sizeof(tml)))
{
dwError = GetLastError();
}
CloseHandle(hToken);
return dwError;
}
return GetLastError();
}
但这里存在薄弱点—— token 本身具有带有显式标签的安全描述符。和高完整性进程具有 High Mandatory Label 和 SYSTEM_MANDATORY_LABEL_NO_WRITE_UP 访问策略。这意味着我们不能再打开具有写入访问权限的进程 token (TOKEN_ADJUST_* )(具有读取访问权限的可以)。如果应用程序在某个地方尝试使用此访问权限打开自进程 token ,这可能会产生问题(一些糟糕的设计代码可以在需要查询自己的进程 token 属性时而不是 TOKEN_QUERY 访问询问 TOKEN_ALL_ACCESS 和在这一点上失败了)。为了防止这个潜在的问题,我们可以在降低完整性之前更改 token 安全描述符的强制标签:
ULONG SetMediumLevel()
{
HANDLE hToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT|WRITE_OWNER, &hToken))
{
ULONG cbSid = GetSidLengthRequired(1);
TOKEN_MANDATORY_LABEL tml = { { alloca(cbSid)} };
ULONG dwError = NOERROR;
if (CreateWellKnownSid(WinMediumLabelSid, 0, tml.Label.Sid, &cbSid))
{
SECURITY_DESCRIPTOR sd;
ULONG cbAcl = sizeof(ACL) + FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + cbSid;
PACL Sacl = (PACL)alloca(cbAcl);
if (!InitializeAcl(Sacl, cbAcl, ACL_REVISION) ||
!AddMandatoryAce(Sacl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, tml.Label.Sid) ||
!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ||
!SetSecurityDescriptorSacl(&sd, TRUE, Sacl, FALSE) ||
!SetKernelObjectSecurity(hToken, LABEL_SECURITY_INFORMATION, &sd) ||
!SetTokenInformation(hToken, TokenIntegrityLevel, &tml, sizeof(tml)))
{
dwError = GetLastError();
}
}
CloseHandle(hToken);
return dwError;
}
return GetLastError();
}
关于c++ - 当我不再需要它们时如何放弃提升的特权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44633587/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/