OpenProcessToken LookupPrivilegeValue 和AdjustTokenPrivilege[通俗易懂]

OpenProcessToken LookupPrivilegeValue 和AdjustTokenPrivilege[通俗易懂]OpenProcessToken函数功能用来打开与进程相关联的访问令牌函数申明WINADVAPIBOOLWINAPIOpenProcessToken(_In_HANDLEProcessHandle,_In_DWORDDesiredAccess,_Outptr_PHANDLETokenHandle);第一个参数ProcessHandle[in],输入参数,要打开的访问令牌所属的进程句柄,查询进程必须拥有PROCESS_QUERY_INF

大家好,又见面了,我是你们的朋友全栈君。

提升程序的特权,要用到三个函数:
OpenProcessToken
AdjustTokenPrivileges
LookupPrivilegeValue

OpenProcessToken

函数功能

用来打开与进程相关联的访问令牌

函数申明

WINADVAPI
BOOL
WINAPI
OpenProcessToken(
    _In_ HANDLE ProcessHandle,
    _In_ DWORD DesiredAccess,
    _Outptr_ PHANDLE TokenHandle
    );

第一个参数

ProcessHandle [in],输入参数,要打开的访问令牌所属的进程句柄,查询进程必须拥有PROCESS_QUERY_INFORMATION访问权限。

第二个参数

DesiredAccess [in] 输入参数, 提供一个访问掩码,该掩码用来指定将要从访问令牌中查询的访问请求类型。这个访问请求类型将会与Discretionary Access Control List(DACL) 中的令牌相比较,以确定哪些访问权将被允许或拒绝。

有关访问令牌的访问权限列表,请参见访问令牌对象的访问权限*。

第三个参数

TokenHandle [out] 输出参数, 一个指向句柄数据类型的指针。该指针标识出函数返回时最新打开的访问令牌

返回值

如果函数执行成功,返回非零值;

如果函数执行失败,返回值为零。如果要得到附加的错误信息,请调用GetLastError函数。

补充:

如果要关闭打开的访问令牌句柄(该句柄通过TokenHandle参数返回),请调用CloseHandle函数。

第一个参数 进程句柄(当前进程为GetCurrentProcess()为参数)
第二个参数 访问令牌特权
第三个参数 返回的参数 就是AdjustTokenPrivileges的第一个参数
注:第二个参数 是令牌的权限,这个权限是要有修改权限的特权,意思就是要把你程序的权限修改得更高。所有权限可以写TOKEN_ALL_ACCESS ,去查看一个令牌特权可以用TOKEN_QUERY

LookupPrivilegeValue

函数功能

函数查看系统权限的特权值,返回信息到一个LUID结构体里。

函数声明

WINADVAPI
BOOL
WINAPI
LookupPrivilegeValue(
    _In_opt_ LPCSTR lpSystemName,
    _In_     LPCSTR lpName,
    _Out_    PLUID   lpLuid
    );

第一个参数

输入参数,表示所要查看的系统,本地系统直接用NULL

第二个参数

输入参数,向一个以零结尾的字符串,指定特权的名称,如在WinNT h头文件定义。例如,此参数可指定常数,se_security_name,或其对应的字符串,“sesecurityprivilege “;。

第三个参数

输出参数,用来接收所返回的制定特权名称的信息,函数调用成功后,信息存入第三个类型为LUID的结构体中,并且函数返回非0。

返回值

函数调用成功后,信息存入第三个类型为LUID的结构体中,并且函数返回非0。

第一个参数是系统的名字,如果为NULL,就是本地名字(这里就填NULL)

第二个参数是特权的名字,要查看详细特权,看我的博客里翻译分类里的 包含特权 的文章。(在这里写SE_DEBUG_NAME)

第三个参数就可以通过指针返回一个LUID类型的Luid的标识了。 通过这个值就可以填入刚才的结构体里了。

AdjustTokenPrivilege

函数功能

这个函数启用或禁止 指定访问令牌的特权。启用或禁用特权一个有TOKEN_ADJUST_PRIVILEGES访问的访问令牌.

函数声明

BOOL AdjustTokenPrivileges(  
HANDLE TokenHandle, //包含特权的句柄 
BOOL DisableAllPrivileges,  //禁用所有权限标志  
PTOKEN_PRIVILEGES NewState,  //新特权信息的指针(结构体) 
DWORD BufferLength, //大小,以字节为单位的PreviousState的缓存区(sizeof)  
PTOKEN_PRIVILEGES PreviousState,  //接收被改变特权当前状态的Buffer  
PDWORD ReturnLength //接收PreviousState缓存区要求的大小  );

第一个参数

TokenHandle包含要修改特权的访问令牌的标识(句柄).这个句柄必须有TOKEN_ADJUST_PRIVILEGES访问令牌.如果PreviousState不是NULL,这个句柄还必须有TOKEN_QUERY访问特权.

第二个参数

DisableAllPrivileges  标志这个函数是否禁用该令牌的所有特权.如果为TRUE,这个函数禁用所有特权,NewState参数无效.如果为假,以NewState参数指针的信息为基础来修改特权.

第三个参数

NewState 一个TOKEN_PRIVILEGES结构体的指针指定了一组特权和他们的属性.  
如果参数DisableAllPrivileges为FALSE,AdjustTokenPrivileges 启用或禁用这些令牌的特权.  
如果你给一个特权设置了SE_PRIVILEGE_ENABLED的属性,这个函数将启动特权,否则禁用特权.  如果DisableAllPrivileges为TRUE,这个参数无效.

typedef struct _TOKEN_PRIVILEGES 
{ 
    
       DWORD PrivilegeCount;  
       LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; 
}TOKEN_PRIVILEGES;

下面的参数是个特权数组。上面的参数是要修改的特权数目LUID_AND_ATTRIBUTES 结构体

typedef struct _LUID_AND_ATTRIBUTES  
{ 
      
       LUID Luid;   
       DWORD Attributes; 
} LUID_AND_ATTRIBUTES;

第一个参数是Luid是一个标志,不同的Luid代表着各种不同的特权类型

第二个参数是要这个特权干嘛,如启用这个特权(SE_PRIVILEGE_ENABLED),这里的Luid的值需要用LookupPrivilegeValue来获取。

第四个参数

BufferLength 标志参数PreviousState指针以字节大小缓存区(sizeof).  
如果参数PreviousState是NULL,这个参数可以为NULL.

第五个参数:

PreviousState这个函数填充一个TOKEN_PRIVILEGES结构体【指针】,它包括该函数修改之前任何特权状态.这个参数可以为NULL.  如果指定的缓冲区太小,无法收到完整的修改权限列表,这个函数失败并不会修改任何特权.  这个函数设置了一个 拥有修改权限完成列表【 参数ReturnLength 】的字节数 的指针变量.[结果的Buffer]

第六个参数:

ReturnLength 接收 参数PreviousState的缓存区指针的 字节大小 的 变量指针(长度指针).  如果PreviousState为NULL,这个参数可以为NULL.

返回值

如果这个函数成功,返回非0.为了确定这个函数是否修改了所有指定的特权,可以调用GetLastError函数,当这个函数返回下面的值之一时就代表函数成功:

描述
ERROR_SUCCESS 这个函数修改了所有指定的特权.
ERROR_NOT_ALL_ASSIGNED 这个令牌没有参数NewState里指定一个或多个的权限.(一个或多个没有修改成功).  即使权限没有被修改.这个函数也可能成功(返回这个error值)  表明 参数PreviousState 被修改.

第一个参数为OpenProcessToken第三个指针参数传出的句柄值

第二个参数为是否禁用所有所有的特权(这里填false)

第三个参数为新的TOKEN_PRIVILEGES的特权结构体指针

第四个参数是上面结构体的字节长度(sizeof)

第五个参数是 接受原先的特权的结构体

第六个参数也是这个结构体的字节长度的指针

如果第五个参数不是NULL,在OpenProcessToken加特权时除了需要指定TOKEN_ADJUST_PRIVILEGES还必须指定TOKEN_QUERY

如果第五个参数是NULL,你不接受原先的结构体(第六个当然也是NULL), 就不用再指定附加的TOKEN_QUERY的特权了。

还要注意:就算这个函数返回为真,还要调用GetLastError()来检验是否完全成功。如果返回ERROR_SUCCESS就代表修改非常成功 。还有就是Vista和Window7 里 一定要开管理员模式 才能获取成功

备注

AdjustTokenPrivileges函数不能添加新的特权到访问令牌.它只能启用或禁用令牌现行的令牌.要想确定这个令牌的特权,调用GetTokenInformation函数.  
请注意,参数NewState可以不给令牌指定权限,这不会导致函数失败.  在这种情况下,这个函数修改令牌现有的特权,其他特权无效,并成功返回.  
调用GetLastError函数,以确定这个函数修改了所有指定的特权.  PreviousState参数表明特权被修改.  参数PreviousState 返回一个 包含 修改权限 原始状态的结构体 TOKEN_PRIVILEGES,  这样就可以在随后调用AdjustTokenPrivileges函数时,传递PreviousState指针到 参数NewState ,来恢复原来的状态.

代码实现:(利用AdjustTokenPrivileges提升权限(准确的说不是提升,而是将访问令牌中禁用的权限启用),)

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);
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/152917.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 粒子群优化算法matlab程序_多目标优化算法

    粒子群优化算法matlab程序_多目标优化算法1.粒子群优化算法概述2.粒子群优化算法求解     2.1连续解空间问题     2.2构成要素     2.3算法过程描述     2.4粒子速度更新公式     2.5速度更新参数分析3.粒子群优化算法小结4.MATLAB

    2022年10月11日
    0
  • yum 安装vsftp_yum安装vsftp「建议收藏」

    yum 安装vsftp_yum安装vsftp「建议收藏」1、安装vsftp,本文采用yum安装:#yuminstallvsftpd2、安装后运行:#servicevsftpdrestartShuttingdownvsftpd:[OK]Startingvsftpdforvsftpd:[OK]3、新增加系统用户ftptest:#useradd-d/var/www-s/sbin/nologinftptest//增加新用…

    2022年9月16日
    0
  • screentogif怎么做动图_iphone录屏转gif

    screentogif怎么做动图_iphone录屏转gif下载ScreenToGif可以从本身电脑的电脑管家下载,也可以百度下载,该软件轻量,方便,可自行添加水印,免费启动软件打开录像机可以调整帧数和调整要录制的屏幕区域点击-录制点击-停止另存为有保存文件的地址和名称以及其他配置可以根据情况调整保存成功…

    2022年9月20日
    0
  • Tomcat 下载、安装、配置图文教程

    Tomcat 下载、安装、配置图文教程ApacheTomcat下载、安装、配置图文教程自我心得1、Tomcat下载(1)Tomcat官网:Tomcat官方网址,可以在此处下载Tomcat。(2)点击左侧Download下的对应版本。注意有zip和exe两种格式的,zip是免安装版的,exe是安装版。同时观察自己的电脑是64位系统还是32位系统。例如进入:Tomcat9版本下载页面,下滑,到core处选择自己需要的版本,如图所示:…

    2022年5月12日
    43
  • JAVA面试题:SWITCH能否作用在BYTE、LONG、STRING上?

    JAVA面试题:SWITCH能否作用在BYTE、LONG、STRING上?

    2021年9月29日
    48
  • Cordova App 打包全揭秘

    本文作者:大师兄(高武军)现就职于某公司移动端架构师兼产品开发。主要开发产品:mdn(适配app和微信的移动端解决方案),pageui(移动端ui组件库),formBuilder(可以让前端建表和操作表的表单设计器)。课程介绍点击查看原文Cordova是一个开源的移动开发框架。允许你用标准的Web技术——HTML5,CSS3和JavaScript做跨平台开发。应用在每个平台的

    2022年4月7日
    68

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号