Java教程

第六章 提权技术---进程访问令牌权限提升

本文主要是介绍第六章 提权技术---进程访问令牌权限提升,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、API

1、OpenProcessToken函数
打开与进程关联的访问令牌
https://docs.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocesstoken
2、LookupPrivilegeValue函数
查看系统权限的特权值,返回信息到一个LUID结构体里
https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lookupprivilegevaluea
3、AdjustTokenPrivileges函数
启用或禁用指定访问令牌中的权限。在访问令牌中启用或禁用权限时需要TOKEN_ADJUST_PRIVILEGES访问
https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-adjusttokenprivileges

二、实现原理

访问控制模型:https://docs.microsoft.com/zh-cn/windows/win32/secauthz/authorization-portal
进程访问令牌权限提升的实现步骤较为固定。要想提升访问令牌权限,首先要获取进程的访问令牌,然后将访问令牌的权限修改为指定权限,但是系统内部并不直接识别权限名称,而是识别LUID值,所以需要根据权限名称获取对应的LUID值,实现进程访问令牌权限的修改。
具体实现步骤如下所示.
首先,程序需要调用OpenProcessToken函数打开指定的进程令牌,并获取TOKEN_ADJUST_PRIVILEGES权限的令牌句柄。之所以要指定进程令牌权限为TOKEN_ADJUST_PRIVILEGES,是因为AdjustTokenPrivileges函数要求有此权限,方可修改进程令牌的访问权限。

//打开进程令牌并获取具有TOKEN_ADJUST_PRIVILEGES权限的进程令牌句柄
OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES,&hToken)l;

其中,第一个参数表示要打开的进程令牌的进程句柄;第二个参数表示程序对进程令牌具有的权限,TOKEN_ADJUST_PRIVILEGES表示具有修改进程令牌的权限;第三个参数表示返回的进程令牌句柄。
再接着调用LookupPrivilegeValue函数,获取本地系统指定特权名称的LUID值,这个LUID值相当于该特权的身份标识号。

//获取本地系统的pszPrivilegesName特权的LUID值
LookupPrivilegeValue(NULL,pszPrivilegesName,&luidValue);

其中,第一个参数表示系统,NULL表示本地系统;第二个参数表示特权名称;第三个参数表示获取到的LUID返回值。
接着,程序就开始对进程令牌特权结构体TOKEN_PRIVILEGES进行赋值,设置新特权的数量、特权对应的LUID值以及特权的属性状态。

//设置提升权限信息
tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[0].Luid = luidValue;
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

其中,PrivilegeCount表示设置新特权的数量;Privileges[0].Luid表示第一个特权对应的LUID值;Privileges[0].Attributes表示第一个特权的属性,SE_PRIVILEGE_ENABLED表示启动该特权。
最后,程序调用AdjustTokenPrivileges函数对进程令牌的特权进行修改,将上面设置好的新特权设置到进程令牌中,这样就完成了进程访问令牌的修改工作。

//修改进程令牌访问权限
AdjustTokenPrivileges(hToken,FALSE,&tokenPrivileges,0,NULL,NULL);

其中,第一个参数表示进程令牌;第二个参数表示是否禁用所有令牌的权限,FALSE表示不禁用;第三个参数是新设置的特权,指向设置好的令牌特权结构体;第四个参数表示返回上一个特权数据缓冲区的大小,若不获取,则可以设为零;第五个参数表示返回上一个特权数据缓冲区,若不接收返回数据,可以设为NULL;第六个参数表示返回上一个特权数据缓冲区应该有的大小。

三、编码实现

AdjustTokenPrivileges.h

#ifndef _ADJUST_TOKEN_PRIVILEGES_H_
#define _ADJUST_TOKEN_PRIVILEGES_H_
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>

BOOL EnbalePrivileges(HANDLE hProcess, char* pszPrivilegesName);

#endif

AdjustTokenPrivileges_Test.cpp

// AdjustTokenPrivileges_Test.cpp : 定义控制台应用程序的入口点。
//
#include "AdjustTokenPrivileges.h"

int _tmain(int argc, _TCHAR* argv[])
{
	// 修改当前进程令牌访问权限
	if (FALSE == EnbalePrivileges(GetCurrentProcess(), SE_DEBUG_NAME))
	{
		printf("Enable Privileges Error!\n");
	}

	printf("Enable Privileges OK!\n");
	system("pause");
	return 0;
}

AdjustTokenPrivilegesTest.cpp

#include "AdjustTokenPrivileges.h"

void ShowError(char* pszText)
{
	char szErr[MAX_PATH] = { 0 };
	::wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
	::MessageBox(NULL, szErr, "ERROR", MB_OK);
}


BOOL EnbalePrivileges(HANDLE hProcess, char* pszPrivilegesName)
{
	HANDLE hToken = NULL;
	LUID luidValue = { 0 };
	TOKEN_PRIVILEGES tokenPrivileges = { 0 };
	BOOL bRet = FALSE;
	DWORD dwRet = 0;


	// 打开进程令牌并获取具有 TOKEN_ADJUST_PRIVILEGES 权限的进程令牌句柄
	bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
	if (FALSE == bRet)
	{
		ShowError("OpenProcessToken");
		return FALSE;
	}
	// 获取本地系统的 pszPrivilegesName 特权的LUID值
	bRet = LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue);
	if (FALSE == bRet)
	{
		ShowError("LookupPrivilegeValue");
		return FALSE;
	}
	// 设置提升权限信息
	tokenPrivileges.PrivilegeCount = 1;
	tokenPrivileges.Privileges[0].Luid = luidValue;
	tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	// 提升进程令牌访问权限
	bRet = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL);
	if (FALSE == bRet)
	{
		ShowError("AdjustTokenPrivileges");
		return FALSE;
	}
	else
	{
		// 根据错误码判断是否特权都设置成功
		dwRet = ::GetLastError();
		if (ERROR_SUCCESS == dwRet)
		{
			return TRUE;
		}
		else if (ERROR_NOT_ALL_ASSIGNED == dwRet)
		{
			ShowError("ERROR_NOT_ALL_ASSIGNED");
			return FALSE;
		}
	}

	return FALSE;
}

以管理员身份运行程序

四、小结

如果再程序中只提升一个访问令牌特权,且错误码为ERROR_NOT_ALL_ASSIGNED,则提升失败。如果程序运行再Windows 7或者以上版本的操作系统,可以尝试以管理员身份运行程序,然后在进行测试

这篇关于第六章 提权技术---进程访问令牌权限提升的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!