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下提升进程权限(转)的更多相关文章

  1. Windows下提升进程权限

    windows的每个用户登录系统后,系统会产生一个访问令牌(access token) ,其中关联了当前用户的权限信息,用户登录后创建的每一个进程都含有用户access token的拷贝,当进程试图执 ...

  2. Windows下使用Xshell建立反向隧道

    反向隧道是一个进行内网穿透的简单而有用的方法.在Linux下通过OpenSSH和AutoSSH可以很容易地建立稳定的反向隧道.但是在Windows下,还能看到有人特意装个Cygwin来运行这些工具…… ...

  3. redis windows下使用及redis命令

    出自:http://www.cnblogs.com/chenping-987123/archive/2012/01/29/2331079.html Redis 是一个开源,高级的键值对的存储.它经常作 ...

  4. Windows下干活儿辅助软件

    桌面下高速文件搜索软件:Listary Pro(收费)和Everything(开源免费),Everything推荐Beta版,明显比老旧的稳定版好用. 桌面太乱,可以试试Fences(收费). 需要文 ...

  5. 提升进程权限为DEBUG权限

    在网上也看到了一些提升进程令牌的函数但都不怎么好用,最后我还是从一个黑客后门程序的源代码中提取出了一个好的提升进程令牌的函数,不敢独享,跟大家分享下.那个后门真的写的很好... Hysia提示你: 这 ...

  6. Qt Windows下链接子系统与入口函数(终结版)(可同时存在main和WinMain函数)

    Qt Windows下链接子系统与入口函数(终结版) 转载自:http://blog.csdn.net/dbzhang800/article/details/6358996 能力所限,本讨论仅局限于M ...

  7. 【1】windows下IOS开发基础环境搭建

    一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包:       ...

  8. Windows下使用MakeFile(Mingw)文件

    下面是我基于<C++GUI QT4编程(第二版)> 2.3节快速设计对话框编写例子地址: https://files.cnblogs.com/files/senior-engineer/g ...

  9. PythonQt在windows下的编译

    笔者最近在做Qt方面的开发工作,然后需要用到脚本程序对程序内部进行扩展,就很自然的想到了Python,度娘一下发现了一款神器,也就是今天给大家介绍的主角:PythonQt 今天首先给大家介绍下Pyth ...

随机推荐

  1. mysql中多个字段共同确定唯一性

    create table tbl_table ( id integer not null auto_increment, fname varchar(255), lname varchar(255), ...

  2. html系列教程--标题,水平线,注释以及段落

    HTML标题 标题,用来显示文章重要性的文字,包含了文章的主旨,类似于作文题目. 标题(Heading)是通过 <h1> - <h6> 等标签进行定义的,由大到小一次排列,h1 ...

  3. centos防火墙端口配置

    增加防火墙配置,允许8080端口: # vi /etc/sysconfig/iptables 在允许ssh的下面增加一条: -A INPUT -m state --state NEW -m tcp - ...

  4. 《Microsoft SQL Server企业级平台管理实践》笔记

    - 页是 SQL Server 中数据存储的基本单位,大小为 8KB. - 区是空间管理的基本单位,8个物理上连续的页的集合(64KB). - 页的类型包括: 1. Data 2. Index 3. ...

  5. SQL初级阶段笔记

    DataBase Management Stystem(数据库管理系统)简称:DBSM:虽然DBSM并不等于数据库,但行业内通常将DBSM称为数据库,所以一般来说数据库就指的是DBSM. 简单来讲DB ...

  6. Objective-c开发教程--MRC和ARC混编

    iOS5.0以后就开始可以使用ARC来代替之前的MRC. 1.ARC中使用MRC的类.方法如下: 在targets的build phases选项下Compile Sources下选择要不使用arc编译 ...

  7. 浏览器检测JS代码(兼容目前各大主流浏览器)

    var BrowserMatch = { init: function () { this.browser = this.getBrowser().browser || "An Unknow ...

  8. python 文件夹比较

    参考:http://blog.csdn.net/imzoer/article/details/8675078 文件比较:filecmp模块:filecmp '''Created on 2014-6-6 ...

  9. 修改host文件的P处理

    notepad C:\WINDOWS\system32\drivers\etc\hosts 用文档创建hosts文件,添加上面代码.把文件后缀修改为 .bat 就不用每次很麻烦的查找host文件了.

  10. avalon.js实践 svg地图配置工具

    MVVM模式,在很多复杂交互逻辑下面,有很大的优势.现在相关的框架也很多,现在项目中使用了avalon.js,选择它的原因,是兼容性的考虑,当然也要支持下国内开发大牛,至于性能方面的,没有实际测试过, ...