windows程序提权方法

Windows下应用程序如果需要做一些系统管理或进程管理之类的工作,经常需要将本进程提权(获取权限令牌);

而通常windows下提权方法有两种,主要的方法是:

1)win32API——AdjustTokenPrivileges;

2)ntdll.dll——RtlAdjustPrivilege;

前者是已公开的win32系统API,后者是非公开的导出函数(藏在ntdll.dll里);

两者的用法也有些差别;

先看第一种方式:

1)win32API——AdjustTokenPrivileges

//Win32Api:
    void AdjustPrivilege()
    {
        HANDLE hToken;
        if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
        {
            TOKEN_PRIVILEGES tp;
            tp.PrivilegeCount = 1;
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid))
            {
                AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
            }
            CloseHandle(hToken);
        }
    }

可以看出AdjustTokenPrivileges提权是针对当前进程的句柄与对应系统权限令牌的特权值的结构体LUID(也就是LARGE_INTEGER)的;

也就是说这种方式需要先使用LookupPrivilegeValue方法查询令牌(比如SE_DEBUG_NAME)对应的特权值;

2)ntdll.dll——RtlAdjustPrivilege

//ntdll.dll
const unsigned long SE_DEBUG_PRIVILEGE = 0x14;
typedef int (__stdcall *fRtlAdjustPrivilege)(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN);

void NtAdjustPrivilege()
{
	HMODULE hNtDll = LoadLibrary(_T("ntdll.dll"));
	if (!hNtDll)
		return;
	fRtlAdjustPrivilege funcAdjustPrivilege =
		(fRtlAdjustPrivilege)GetProcAddress(hNtDll, "RtlAdjustPrivilege");
	if (funcAdjustPrivilege)
	{
		BOOLEAN oldStatus;
		funcAdjustPrivilege(SE_DEBUG_PRIVILEGE, true, false, &oldStatus);
	}
	FreeLibrary(hNtDll);
}
这种导出RtlAdjustPrivilege的方式没有依赖其它方法,但是需要自己定义权限值SE_DEBUG_PRIVILEGE为0x14,显然这样写死的方式总是一种不太好的方式;

我们应该让windows自己定义这些值,我们通过变量名使用这些值,这样的设计更好;

当然,在特定的windows平台下,只要windows对ntdll.dll导出的函数改动不大,这样使用也可以。

总结一下,第一种方式使用的公开API,有官方文档,名正言顺,不用担心API的改动问题,但是需要用到不止一个方法(LookupPrivilegeValue与AdjustTokenPrivileges)组合使用,才能达到效果,稍显繁琐;第二种方式虽然不依赖其它方法就能达到效果,简洁强大,但是使用的非公开的导出方法RtlAdjustPrivilege名不正言不顺,说不定以后windows在以后的版本中对ntdll.dll的修改可能会引起API不兼容的问题;所以如果第一种方式能满足需求,尽量避免使用第二种方式,毕竟也多不了几行代码;

你可能感兴趣的:(windows)