【总结】用户权限设置和进程权限提升
2017-09-08 16:10
316 查看
使用某些Windows API的时候需要提升进程的默认权限,例如RegRestoreKey需要SE_RESTORE_NAME 和SE_BACKUP_NAME 权限。在这种情况下,我们需要使用到一组Windows API提升进程权限。需要的函数有:
1.OpenProcessToken
2.LookupPrivilegeValue
3.AdjustTokenPrivileges
使用这组函数提升权限的前提是进程具备该权限,只是访问令牌中没有启用该权限。如果进程的访问令牌中本身就没有关联该权限,这AdjustTokenPrivileges函数调用将会返回ERROR_NOT_ALL_ASSIGNED(值为1300L)的错误码。如何让进程具有该权限?可以通过“控制面板”—“管理工具”—“本地安全策略”—“本地策略”—“用户权利指派”设置将该权限关联到指定的用户分组或用户上。具体设置如下图所示:
win7之本地安全策略启动:
1.单击“控制面板”--“系统和安全”--“管理工具”--“本地安全策略”,会进入“本地安全策略”界面。
2..win+R--secpol.msc,也可以。
利用AdjustTokenPrivileges提升权限,准确的说不是提升,而是将访问令牌中禁用的权限启用。
[cpp] view
plain copy
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
void main( )
{
HANDLE hToken;
BOOL bRet = OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken);
SetPrivilege(hToken,SE_DEBUG_NAME,TRUE);
}
这段代码在xp上没有问题,但如果在windows
7 或者vista上,如果程序以标准用户启动,AdjustTokenPrivileges将会调用失败,以管理员身份启动没有问题。
这是因为在Windows 7上,标准用户权限很少,没有Debug权限,更无从谈起启用Debug权限,用户可以以管理员和标准用户两种方式启用控制台,输入命令whoami /ALL来查看两种权限下权限的不同。
PS:即使提升调试权限,也不意味着对其它进程调用OpenProcess会成功(例如win7系统下的system和audiodg进程)
下面解释这三个函数:
首先需要获取进程的令牌句柄
OpenProcessToken的原型.
[cpp] view
plain copy
BOOL WINAPI OpenProcessToken(
__in HANDLE ProcessHandle,
__in DWORD DesiredAccess,
__out PHANDLE TokenHandle
);
第一个参数 进程句柄(当前进程为GetCurrentProcess()为参数)
第二个参数 访问令牌特权
第三个参数 返回的参数 就是AdjustTokenPrivileges的第一个参数
例子:
[cpp] view
plain copy
HANDLE hToken;
bool retn = OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
if(!retn)
{
return; //获取令牌失败。。
}
注:第二个参数 是令牌的权限,这个权限是要有修改权限的特权,意思就是要把你程序的权限修改得更高。
关于其他权限可以查MSDN.. 所有权限可以写TOKEN_ALL_ACCESS ,去查看一个令牌特权可以用TOKEN_QUERY
这个下面函数有写。
--------------------------------------------------------------
首先先说一下使用AdjustTokenPrivileges需要的。
在这个函数中的第3和第5个参数中需要用到一个TOKEN_PRIVILEGES的结构体,在这个结构体中还有个LUID_AND_ATTRIBUTES结构体
TOKEN_PRIVILEGES结构体
[cpp] view
plain copy
typedef struct _TOKEN_PRIVILEGES
{
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
}TOKEN_PRIVILEGES;
下面的参数是个特权数组。
上面的参数是要修改的特权数目
LUID_AND_ATTRIBUTES 结构体
[cpp] view
plain copy
typedef struct _LUID_AND_ATTRIBUTES
{
LUID Luid;
DWORD Attributes;
} LUID_AND_ATTRIBUTES;
第一个参数是Luid是一个标志,不同的Luid代表着各种不同的特权类型
第二个参数是要这个特权干嘛,如启用这个特权(SE_PRIVILEGE_ENABLED)
这里的Luid的值需要用LookupPrivilegeValue来获取。
------------------------------------------------------------------------------------------
LookupPrivilegeValue的原型
[cpp] view
plain copy
BOOL WINAPI LookupPrivilegeValue(
__in_opt LPCTSTR lpSystemName,
__in LPCTSTR lpName,
__out PLUID lpLuid
);
第一个参数是系统的名字,如果为NULL,就是本地名字(这里就填NULL)
第二个参数是特权的名字,要查看详细特权,看我的博客里翻译分类里的 包含特权 的文章。(在这里写SE_DEBUG_NAME)
第三个参数就可以通过指针返回一个LUID类型的Luid的标识了。 通过这个值就可以填入刚才的结构体里了。
----------------------------------------------------------------------------------------------------------------------------
最后就可以介绍AdjustTokenPrivilege就应该没什么问题了。
它的原型为:
[cpp] view
plain copy
BOOL WINAPI AdjustTokenPrivileges(
__in HANDLE TokenHandle,
__in BOOL DisableAllPrivileges,
__in_opt PTOKEN_PRIVILEGES NewState,
__in DWORD BufferLength,
__out_opt PTOKEN_PRIVILEGES PreviousState,
__out_opt PDWORD ReturnLength
);
第一个参数为OpenProcessToken第三个指针参数传出的句柄值
第二个参数为是否禁用所有所有的特权(这里填false)
第三个参数为新的TOKEN_PRIVILEGES的特权结构体指针
第四个参数是上面结构体的字节长度(sizeof)
第五个参数是 接受原先的特权的结构体
第六个参数也是这个结构体的字节长度的指针
在这里后两个参数不用管。
MSDN里说
如果第五个参数不是NULL,在OpenProcessToken加特权时除了需要指定TOKEN_ADJUST_PRIVILEGES还必须指定TOKEN_QUERY
如果第五个参数是NULL,你不接受原先的结构体(第六个当然也是NULL), 就不用再指定附加的TOKEN_QUERY的特权了。
还要注意:
就算这个函数返回为真,还要调用GetLastError()来检验是否完全成功。如果GetLastError()==ERROR_SUCCESS就代表修改非常成功
,这个非常重要!!
还有就是Vista和Window7 里 一定要开管理员模式 才能获取成功
----------------------------------------------------
完整的例子
可以直接复制运行
[cpp] view
plain copy
#include <windows.h>
#include <iostream>
using namespace std;
void main()
{
BOOL retn;
HANDLE hToken;
retn = OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
if(retn != TRUE)
{
cout<<"获取令牌句柄失败!"<<endl;
return;
}
TOKEN_PRIVILEGES tp; //新特权结构体
LUID Luid;
retn = LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&Luid);
if(retn != TRUE)
{
cout<<"获取Luid失败"<<endl;
return;
}
//给TP和TP里的LUID结构体赋值
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid = Luid;
AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL);
if(GetLastError() != ERROR_SUCCESS)
{
cout<<"修改特权不完全或失败!"<<endl;
}
else
{
cout<<"修改成功!"<<endl;
}
}
参考:
http://blog.csdn.net/xbgprogrammer/article/details/7276760 http://hi.baidu.com/honfei/item/c8f53302a60104c32f4c6b76
1.OpenProcessToken
2.LookupPrivilegeValue
3.AdjustTokenPrivileges
使用这组函数提升权限的前提是进程具备该权限,只是访问令牌中没有启用该权限。如果进程的访问令牌中本身就没有关联该权限,这AdjustTokenPrivileges函数调用将会返回ERROR_NOT_ALL_ASSIGNED(值为1300L)的错误码。如何让进程具有该权限?可以通过“控制面板”—“管理工具”—“本地安全策略”—“本地策略”—“用户权利指派”设置将该权限关联到指定的用户分组或用户上。具体设置如下图所示:
win7之本地安全策略启动:
1.单击“控制面板”--“系统和安全”--“管理工具”--“本地安全策略”,会进入“本地安全策略”界面。
2..win+R--secpol.msc,也可以。
利用AdjustTokenPrivileges提升权限,准确的说不是提升,而是将访问令牌中禁用的权限启用。
[cpp] view
plain copy
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
void main( )
{
HANDLE hToken;
BOOL bRet = OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken);
SetPrivilege(hToken,SE_DEBUG_NAME,TRUE);
}
这段代码在xp上没有问题,但如果在windows
7 或者vista上,如果程序以标准用户启动,AdjustTokenPrivileges将会调用失败,以管理员身份启动没有问题。
这是因为在Windows 7上,标准用户权限很少,没有Debug权限,更无从谈起启用Debug权限,用户可以以管理员和标准用户两种方式启用控制台,输入命令whoami /ALL来查看两种权限下权限的不同。
PS:即使提升调试权限,也不意味着对其它进程调用OpenProcess会成功(例如win7系统下的system和audiodg进程)
下面解释这三个函数:
首先需要获取进程的令牌句柄
OpenProcessToken的原型.
[cpp] view
plain copy
BOOL WINAPI OpenProcessToken(
__in HANDLE ProcessHandle,
__in DWORD DesiredAccess,
__out PHANDLE TokenHandle
);
第一个参数 进程句柄(当前进程为GetCurrentProcess()为参数)
第二个参数 访问令牌特权
第三个参数 返回的参数 就是AdjustTokenPrivileges的第一个参数
例子:
[cpp] view
plain copy
HANDLE hToken;
bool retn = OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
if(!retn)
{
return; //获取令牌失败。。
}
注:第二个参数 是令牌的权限,这个权限是要有修改权限的特权,意思就是要把你程序的权限修改得更高。
关于其他权限可以查MSDN.. 所有权限可以写TOKEN_ALL_ACCESS ,去查看一个令牌特权可以用TOKEN_QUERY
这个下面函数有写。
--------------------------------------------------------------
首先先说一下使用AdjustTokenPrivileges需要的。
在这个函数中的第3和第5个参数中需要用到一个TOKEN_PRIVILEGES的结构体,在这个结构体中还有个LUID_AND_ATTRIBUTES结构体
TOKEN_PRIVILEGES结构体
[cpp] view
plain copy
typedef struct _TOKEN_PRIVILEGES
{
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
}TOKEN_PRIVILEGES;
下面的参数是个特权数组。
上面的参数是要修改的特权数目
LUID_AND_ATTRIBUTES 结构体
[cpp] view
plain copy
typedef struct _LUID_AND_ATTRIBUTES
{
LUID Luid;
DWORD Attributes;
} LUID_AND_ATTRIBUTES;
第一个参数是Luid是一个标志,不同的Luid代表着各种不同的特权类型
第二个参数是要这个特权干嘛,如启用这个特权(SE_PRIVILEGE_ENABLED)
这里的Luid的值需要用LookupPrivilegeValue来获取。
------------------------------------------------------------------------------------------
LookupPrivilegeValue的原型
[cpp] view
plain copy
BOOL WINAPI LookupPrivilegeValue(
__in_opt LPCTSTR lpSystemName,
__in LPCTSTR lpName,
__out PLUID lpLuid
);
第一个参数是系统的名字,如果为NULL,就是本地名字(这里就填NULL)
第二个参数是特权的名字,要查看详细特权,看我的博客里翻译分类里的 包含特权 的文章。(在这里写SE_DEBUG_NAME)
第三个参数就可以通过指针返回一个LUID类型的Luid的标识了。 通过这个值就可以填入刚才的结构体里了。
----------------------------------------------------------------------------------------------------------------------------
最后就可以介绍AdjustTokenPrivilege就应该没什么问题了。
它的原型为:
[cpp] view
plain copy
BOOL WINAPI AdjustTokenPrivileges(
__in HANDLE TokenHandle,
__in BOOL DisableAllPrivileges,
__in_opt PTOKEN_PRIVILEGES NewState,
__in DWORD BufferLength,
__out_opt PTOKEN_PRIVILEGES PreviousState,
__out_opt PDWORD ReturnLength
);
第一个参数为OpenProcessToken第三个指针参数传出的句柄值
第二个参数为是否禁用所有所有的特权(这里填false)
第三个参数为新的TOKEN_PRIVILEGES的特权结构体指针
第四个参数是上面结构体的字节长度(sizeof)
第五个参数是 接受原先的特权的结构体
第六个参数也是这个结构体的字节长度的指针
在这里后两个参数不用管。
MSDN里说
如果第五个参数不是NULL,在OpenProcessToken加特权时除了需要指定TOKEN_ADJUST_PRIVILEGES还必须指定TOKEN_QUERY
如果第五个参数是NULL,你不接受原先的结构体(第六个当然也是NULL), 就不用再指定附加的TOKEN_QUERY的特权了。
还要注意:
就算这个函数返回为真,还要调用GetLastError()来检验是否完全成功。如果GetLastError()==ERROR_SUCCESS就代表修改非常成功
,这个非常重要!!
还有就是Vista和Window7 里 一定要开管理员模式 才能获取成功
----------------------------------------------------
完整的例子
可以直接复制运行
[cpp] view
plain copy
#include <windows.h>
#include <iostream>
using namespace std;
void main()
{
BOOL retn;
HANDLE hToken;
retn = OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
if(retn != TRUE)
{
cout<<"获取令牌句柄失败!"<<endl;
return;
}
TOKEN_PRIVILEGES tp; //新特权结构体
LUID Luid;
retn = LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&Luid);
if(retn != TRUE)
{
cout<<"获取Luid失败"<<endl;
return;
}
//给TP和TP里的LUID结构体赋值
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid = Luid;
AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL);
if(GetLastError() != ERROR_SUCCESS)
{
cout<<"修改特权不完全或失败!"<<endl;
}
else
{
cout<<"修改成功!"<<endl;
}
}
参考:
http://blog.csdn.net/xbgprogrammer/article/details/7276760 http://hi.baidu.com/honfei/item/c8f53302a60104c32f4c6b76
相关文章推荐
- 【总结】用户权限设置和进程权限提升
- 【总结】用户权限设置和进程权限提升
- 用户权限设置和进程权限提升
- 用户权限设置和进程权限提升
- 巧妙设置Sybase用户权限来处理进程
- 站在巨人肩膀上看世界:设置oracle用户的权限方法总结
- 通过权限设置禁止用户在任务管理器中杀掉我们的进程
- paip.提升用户体验与安全性----登录与权限流程总结
- 【总结】基于Spring LDAP和Spring Security的用户认证和权限控制Web实现
- mongodb权限设置之添加管理员、普通用户的方法
- php apache用户写文件夹权限设置
- linux的用户管理与权限学习总结
- MongoDB设置访问权限、设置用户
- EventHandler中如何提升用户权限(模拟管理员权限)
- mysql性能测试工具之tpcc-mysql 及 mysql 用户管理和权限设置
- 在linux中添加ftp用户,并设置相应的权限
- 在linux中添加ftp用户,并设置相应的权限
- SAP用户权限控制设置及开发
- git设置用户访问目录权限?
- Ubuntu下怎么将普通的用户的权限提升到root权限