Windows下提升进程权限(转)
from: http://www.oschina.net/code/snippet_222150_19533
windows的每个用户登录系统后,系统会产生一个访问令牌(access token) ,其中关联了当前用户的权限信息,用户登录后创建的每一个进程都含有用户access token的拷贝,当进程试图执行某些需要特殊权限的操作或是访问受保护的内核对象时,系统会检查其acess token中的权限信息以决定是否授权操作。Administrator组成员的access token中会含有一些可以执行系统级操作的特权(privileges) ,如终止任意进程、关闭/重启系统、加载设备驱动和更改系统时间等,不过这些特权默认是被禁用的,当Administrator组成员创建的进程中包含一 些需要特权的操作时,进程必须首先打开这些禁用的特权以提升自己的权限,否则系统将拒绝进程的操作。注意,非Administrator组成员创建的进程 无法提升自身的权限,因此下面提到的进程均指Administrator组成员创建的进程。
Windows以字符串的形式表示系统特权,如“SeCreatePagefilePrivilege”表示该特权用于创建页面文 件,“SeDebugPrivilege”表示该特权可用于调试及更改其它进程的内存,为了便于在代码中引用这些字符串,微软在winnt.h中定义了一 组宏,如 #define SE_DEBUG_NAME TEXT("SeDebugPrivilege")。完整的特权列表可以查阅msdn的security一章。虽然Windows使用字符串表示特权,但 查询或更改特权的API需要LUID来引用相应的特权,LUID表示local unique identifier,它是一个64位值,在当前系统中是唯一的。为了提升进程权限到指定的特权,我们必须先找到该特权对应的LUID,这时要调用 LookupPrivilegeValue函数。
获得特权对应的LUID之后,我们要打开该特权。此时要用到LUID_AND_ATTRIBUTES结构,其定义如下:
typedef struct _LUID_AND_ATTRIBUTES {
LUID Luid;
DWORD Attributes;
} LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES;
Attributes取SE_PRIVILEGE_ENABLED时将打开Luid对应的特权。设置完成后,我们需要调用 AdjustTokenPrivileges函数通知操作系统将指定的access token权限中的特权置为打开状态,前面我们说过,进程执行需要特列权限的操作时系统将检查其access token,因此更改了进程的access token特权设置,也就是更改了所属进程的特权设置。AdjustTokenPrivileges函数的原型如下:
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
);
TokenHandle是要更改特权设置的acess token的句柄,DisableAllPrivileges表示是否禁用该access token的所有特权,NewState用来传递要新的特权设置,注意它的类型是 PTOKEN_PRIVILEGES,PTOKEN_PRIVILEGES是TOKEN_PRIVILEGES结构的指针,定义如下:
typedef struct _TOKEN_PRIVILEGES {
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
其中ANYSIZE_ARRAY被定义为1,可以看到TOKEN_PRIVILEGES中包含了用于设置特权信息的 LUID_AND_ATTRIBUTES结构,在使用时,只需要将PrivilegeCount赋为1,然后把Privileges数组的第1个元素 (Privileges[0])的Luid域设置为指定特权的Luid,再将其Attributes域设置为SE_PRIVILEGE_ENABLED, 就可以完成TokenHandle表示的access token权限的提升了。
下面是一个实际的例子,用来将执行promoteProcessPrivilege的当前进程的指定特权打开,函数参数为指定的特权名,可以传递其宏定义,也可以是完整的字符串表示:
BOOL promoteProcessPrivileges(const TCHAR* newPrivileges)
{
HANDLE tokenHandle;
//获得当前进程的access token句柄
if(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &tokenHandle) == FALSE)
return FALSE;
TOKEN_PRIVILEGES structTkp;
//查找newPrivileges参数对应的Luid,并将结果写入structTkp.Privileges[0]的Luid域中
if(::LookupPrivilegeValue(NULL, newPrivileges, &structTkp.Privileges[0].Luid) == FALSE){
CloseHandle(tokenHandle);
return FASLE;
}
//设置structTkp结构
structTkp.PrivilegeCount = 1;
structTkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//通知操作系统更改权限
if(::AdjustTokenPrivileges(tokenHandle, FALSE, &structTkp, sizeof(structTkp), NULL, NULL) == FALSE){
CloseHandle(tokenHandle);
return FALSE;
}
CloseHandle(tokenHandle);
return TRUE;
}
我们来用一个简单的例子验证promoteProcessPrivileges函数。下面的traceSystemProcess用于遍历当前系统进程, 如果调用traceSystemProcess函数的进程以默认权限运行,对于如csrss.exe之类的进程,函数将没有足够的权限获得其模块名。如果 在traceSystemProcess之前调用了promoteProcessPrivileges将进程权限提升至SE_DEBUG_NAME级 别,traceSystemProcess函数将能正确打印出如csrss.exe等关键进程的路径:
BOOL traceSystemProcess()
{
PROCESSENTRY32 processEntry;
processEntry.dwSize = sizeof(processEntry); HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hProcessSnap == INVALID_HANDLE_VALUE){
_tprintf(_T("CreateToolhelp32Snapshot 调用失败!/n"));
return FALSE;
} BOOL bMore = ::Process32First(hProcessSnap, &processEntry);
while(bMore){
_tprintf(_T("进程名称:%s /n"), processEntry.szExeFile);
_tprintf(_T("进程ID号:%u /n"), processEntry.th32ProcessID);
HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, processEntry.th32ProcessID);
if(hProcess != NULL){
TCHAR szBuffer[MAX_PATH] = {_T('/0')};
if(::GetModuleFileNameEx(hProcess, NULL, szBuffer, MAX_PATH)){
_tprintf(_T("进程路径:%s /n"), szBuffer);
}
::CloseHandle(hProcess);
}
_tprintf(_T("/n"));
bMore = ::Process32Next(hProcessSnap,&processEntry);
}
::CloseHandle(hProcessSnap);
return TRUE;
}
代码片段(2)[全屏查看所有代码]
1. [代码][C/C++]代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
BOOL promoteProcessPrivileges(const TCHAR* newPrivileges){ HANDLE tokenHandle; //获得当前进程的access token句柄 if(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &tokenHandle) == FALSE) return FALSE; TOKEN_PRIVILEGES structTkp; //查找newPrivileges参数对应的Luid,并将结果写入structTkp.Privileges[0]的Luid域中 if(::LookupPrivilegeValue(NULL, newPrivileges, &structTkp.Privileges[0].Luid) == FALSE){ CloseHandle(tokenHandle); return FASLE; } //设置structTkp结构 structTkp.PrivilegeCount = 1; structTkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //通知操作系统更改权限 if(::AdjustTokenPrivileges(tokenHandle, FALSE, &structTkp, sizeof(structTkp), NULL, NULL) == FALSE){ CloseHandle(tokenHandle); return FALSE; } CloseHandle(tokenHandle); return TRUE;} |
2. [代码][C/C++]代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
BOOL traceSystemProcess(){ PROCESSENTRY32 processEntry; processEntry.dwSize = sizeof(processEntry); HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if(hProcessSnap == INVALID_HANDLE_VALUE){ _tprintf(_T("CreateToolhelp32Snapshot 调用失败!/n")); return FALSE; } BOOL bMore = ::Process32First(hProcessSnap, &processEntry); while(bMore){ _tprintf(_T("进程名称:%s /n"), processEntry.szExeFile); _tprintf(_T("进程ID号:%u /n"), processEntry.th32ProcessID); HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processEntry.th32ProcessID); if(hProcess != NULL){ TCHAR szBuffer[MAX_PATH] = {_T('/0')}; if(::GetModuleFileNameEx(hProcess, NULL, szBuffer, MAX_PATH)){ _tprintf(_T("进程路径:%s /n"), szBuffer); } ::CloseHandle(hProcess); } _tprintf(_T("/n")); bMore = ::Process32Next(hProcessSnap,&processEntry); } ::CloseHandle(hProcessSnap); return TRUE;} |
Windows下提升进程权限(转)的更多相关文章
- Windows下提升进程权限
windows的每个用户登录系统后,系统会产生一个访问令牌(access token) ,其中关联了当前用户的权限信息,用户登录后创建的每一个进程都含有用户access token的拷贝,当进程试图执 ...
- Windows下使用Xshell建立反向隧道
反向隧道是一个进行内网穿透的简单而有用的方法.在Linux下通过OpenSSH和AutoSSH可以很容易地建立稳定的反向隧道.但是在Windows下,还能看到有人特意装个Cygwin来运行这些工具…… ...
- redis windows下使用及redis命令
出自:http://www.cnblogs.com/chenping-987123/archive/2012/01/29/2331079.html Redis 是一个开源,高级的键值对的存储.它经常作 ...
- Windows下干活儿辅助软件
桌面下高速文件搜索软件:Listary Pro(收费)和Everything(开源免费),Everything推荐Beta版,明显比老旧的稳定版好用. 桌面太乱,可以试试Fences(收费). 需要文 ...
- 提升进程权限为DEBUG权限
在网上也看到了一些提升进程令牌的函数但都不怎么好用,最后我还是从一个黑客后门程序的源代码中提取出了一个好的提升进程令牌的函数,不敢独享,跟大家分享下.那个后门真的写的很好... Hysia提示你: 这 ...
- Qt Windows下链接子系统与入口函数(终结版)(可同时存在main和WinMain函数)
Qt Windows下链接子系统与入口函数(终结版) 转载自:http://blog.csdn.net/dbzhang800/article/details/6358996 能力所限,本讨论仅局限于M ...
- 【1】windows下IOS开发基础环境搭建
一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包: ...
- Windows下使用MakeFile(Mingw)文件
下面是我基于<C++GUI QT4编程(第二版)> 2.3节快速设计对话框编写例子地址: https://files.cnblogs.com/files/senior-engineer/g ...
- PythonQt在windows下的编译
笔者最近在做Qt方面的开发工作,然后需要用到脚本程序对程序内部进行扩展,就很自然的想到了Python,度娘一下发现了一款神器,也就是今天给大家介绍的主角:PythonQt 今天首先给大家介绍下Pyth ...
随机推荐
- Python学习入门基础教程(learning Python)--8.3 字典常用的方法函数介绍
本节的主要讨论内容是有关dict字典的一些常用的方法函数的使用和范例展示. 1. clear清除字典数据 语法结构如下: dict_obj.clear() 示例代码如下: dict1 = {'web' ...
- Spring中自己主动装配
自己主动装配 在我们了解过constructor-arg和property装配中.都须要配置对应的属性和值或者引用,假设在比較复杂的项目中.就会使得XML的配置变得复杂,自己主动装配能够使用较少的配置 ...
- 【玩转Ubuntu】01. Ubuntu上配置JDK
一.安装JDK 提示:这里我们使用jdk1.6,因为android开发要求使用1.6.如果不信你可以打开android studio,它会提示你选择JDK6的路径 下载地址: http://www.o ...
- js清空页面控件值
function funClear() {var txts = document.getElementsByTagName("input");for (var i = 0; i & ...
- TSQL 根据经纬度计算两点间的距离;返回米(m)
-- ============================================= -- Author:Forrest -- Create date: 2013-07-16 -- Des ...
- js——DOM操作(一)
DOM:Document Object Model 文档对象模型 文档:html页面 文档对象:页面中元素 文档对象模型:定义 为了能够让程序(js)去操作页面中的元素 DOM会把文档看作是一棵树 ...
- su 切换用户
大部分Linux发行版的默认账户是普通账户,而更改系统文件或者执行某些命令,需要root身份才能进行,这就需要从当前用户切换到root用户,Linux中切换用户的命令是su或su - 前者只是切换ro ...
- 回调函数 callback 的简单理解
回调函数指当我执行完某一段代码之后在回过头来调用 jquery 最简单的例子 $(".className").each(function(i){alert(i)}) 她这个形参i是 ...
- Android minHeight/Width,maxHeight/Width
在layout文件中,设置IamgeView的最大(最小)高度(宽度)时,需要同时设置android:adjustViewBounds="true",这样设置才会生效.在代码中设置 ...
- Windows2008RT搭建VPN服务器
总结一下2008系统搭建VPN的步骤和过程,自己有个人网站和服务要通过互联网发布出来.服务器放在自己家里,宽带是民用的.也就产生了服务发布的一些问题.用无法映射出真实的公网IP,或是一些其他内部的问题 ...