首页
社区
课程
招聘
[分享]一句代码提升进程权限
发表于: 2010-1-2 10:34 17010

[分享]一句代码提升进程权限

2010-1-2 10:34
17010
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE,1,0,NULL);

这个函数封装在NtDll.dll中(在所有DLL加载之前加载),被微软严格保密,就是说你在MSDN上查不到关于他的任何信息。

.常量 SE_BACKUP_PRIVILEGE, "17", 公开
.常量 SE_RESTORE_PRIVILEGE, "18", 公开
.常量 SE_SHUTDOWN_PRIVILEGE, "19", 公开
.常量 SE_DEBUG_PRIVILEGE, "20", 公开

先来看看这个函数的定义(Winehq给出):
NTSTATUS RtlAdjustPrivilege
(
ULONG    Privilege,
BOOLEAN Enable,
BOOLEAN CurrentThread,
PBOOLEAN Enabled
)

参数的含义:
Privilege [In] Privilege index to change.                        
// 所需要的权限名称,可以到MSDN查找关于Process Token & Privilege内容可以查到

Enable [In] If TRUE, then enable the privilege otherwise disable.
// 如果为True 就是打开相应权限,如果为False 则是关闭相应权限

CurrentThread [In] If TRUE, then enable in calling thread, otherwise process.
// 如果为True 则仅提升当前线程权限,否则提升整个进程的权限

Enabled [Out] Whether privilege was previously enabled or disabled.
// 输出原来相应权限的状态(打开 | 关闭)

很多人大概没有听说过他的大名,但是相信有很多人见过进程提权的过程
拷一段我写的提权上来吧

BOOL ImproveProcPriv()
{
    HANDLE token;
    //提升权限
    if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&token))
    {
        MessageBox(NULL,"打开进程令牌失败...","错误",MB_ICONSTOP);
        return FALSE;
    }
    TOKEN_PRIVILEGES tkp;
    tkp.PrivilegeCount = 1;
    ::LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid);
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if(!AdjustTokenPrivileges(token,FALSE,&tkp,sizeof(tkp),NULL,NULL))
    {
        MessageBox(NULL,"调整令牌权限失败...","错误",MB_ICONSTOP);
        return FALSE;
    }
    CloseHandle(token);
    return TRUE;
}

看看吧,这个提权快要累死了...

但是 如果有这个函数就不一样了,你可以只用一个函数就实现这个功能,甚至功能远多于上面的代码...

通过恰当的IDE设置和必要的Defination,上面这个函数的功能你完全可以通过一行代码来实现。

RtlAdjustPrivilege(SE_DEBUG_NAME,1,0,NULL);

正文:

下面我们看一下这个函数是怎么运行的,顺便学习下强大的IDA
IDA 载入ntdll.dll (我这里载入的是 WinDBG自动下载的 Symbol里面的英文版本 可能不同的Windows版本略有不同)

先把函数的原型给输入IDA 方便一下阅读,然后开始阅读汇编代码了(党和国家考验我们的时候到了)。
看看Graph View 真的是很牛啊...
看看函数最开头...

mov     edi, edi        ; 这句话是废指令
push    ebp
mov     ebp, esp
sub     esp, 30h        ; 48个字节的子过程域Auto变量
cmp     [ebp+CurrentThread], 1 ; 判断CurrentThread参数是否被指定为1
mov     eax, dword_7C97B0C8
mov     [ebp+var_4], eax
mov     eax, [ebp+Enabled]
mov     [ebp+IsEnabled], eax ; BOOL *IsEnabled = Enabled;
lea     eax, [ebp+var_28]
push    eax
jz      loc_7C93378B

判断是调整进程权限还是线程权限,
CurrentThread == TRUE
push    0
push    28h             ; TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
push    0FFFFFFFEh      ; GetCurrentThread()
call    ZwOpenThreadToken
jmp     loc_7C929A7A

CurrentThread == FALSE
push    28h             ; TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
push    0FFFFFFFFh      ; GetCurrentProcess()
call    NtOpenProcessToken

然后两个代码块同时指向这里
loc_7C929A7A:           ; 很明白了吧 判断进程/线程令牌是否成功被打开
test    eax, eax
jl      short loc_7C929AE4 ; 没成功则跳

若 执行成功

mov     eax, [ebp+Privilege]
mov     [ebp+dwPrivilege], eax
mov     al, [ebp+Enable]
xor     ecx, ecx        ; ecx清零
neg     al
push    esi
mov     [ebp+NewState], 1
mov     [ebp+var_C], ecx
sbb     eax, eax
and     eax, 2
mov     [ebp+var_8], eax
lea     eax, [ebp+ReturnLength] ; 实际返回长度
push    eax
lea     eax, [ebp+OldState]
push    eax             ; 旧的特权 指针
push    10h             ; sizeof(TOKEN_PRIVILEGES)
lea     eax, [ebp+NewState]
push    eax             ; 新的特权 指针
push    ecx             ; FALSE 因为上面有xor ecx,ecx
push    [ebp+TokenHandle]
call    NtAdjustPrivilegesToken ; 调用 AdjustPrivilegesToken提权
push    [ebp+TokenHandle]
mov     esi, eax        ; eax备份
call    ZwClose         ; 关闭 内核对象句柄
cmp     esi, 106h       ; 判断NtAdjustPrivilege执行情况 106h = STATUS_NOT_ALL_ASSIGNED
jz      loc_7C947DF2

判断是否执行成功之后,开始输出最后一个参数

cmp     [ebp+OldState], 0
mov     ecx, [ebp+IsEnabled]
jnz     loc_7C929E99

若 OldState != 0 则

mov     al, [ebp+Enable]         ; 应该很明显了 把Enable变量赋给al 也就是eax最后两位

若 OldState == 0 则

mov     eax, [ebp+var_18]
shr     eax, 1
and     al, 1
jmp     loc_7C929ADF

这个函数大致流程就是这样。

到这里差不多可以按一下传说中的F5了

int __stdcall RtlAdjustPrivilege(int Privilege, char Enable, char CurrentThread, int Enabled)
{
int result; // eax@2
signed int AdjustResult; // esi@4
char returnValue; // al@7
int v7; // [sp+2Ch] [bp-4h]@1
int IsEnabled; // [sp+4h] [bp-2Ch]@1
int TokenHandle; // [sp+8h] [bp-28h]@2
int dwPrivilege; // [sp+20h] [bp-10h]@4
signed int NewState; // [sp+1Ch] [bp-14h]@4
int v12; // [sp+24h] [bp-Ch]@4
int v13; // [sp+28h] [bp-8h]@4
int OldState; // [sp+Ch] [bp-24h]@4
char ReturnLength; // [sp+0h] [bp-30h]@4
unsigned int v16; // [sp+18h] [bp-18h]@11

v7 = dword_7C97B0C8;
IsEnabled = Enabled;
if ( CurrentThread == 1 )
    result = ZwOpenThreadToken(-2, 40, 0, &TokenHandle);
else
    result = NtOpenProcessToken(-1, 40, &TokenHandle);
if ( result >= 0 )
{
    dwPrivilege = Privilege;
    NewState = 1;
    v12 = 0;
    v13 = -(Enable != 0) & 2;
    AdjustResult = NtAdjustPrivilegesToken(TokenHandle, 0, &NewState, 16, &OldState, &ReturnLength);
    ZwClose(TokenHandle);
    if ( AdjustResult == 262 )
      AdjustResult = -1073741727;
    if ( AdjustResult >= 0 )
    {
      if ( OldState )
        returnValue = (v16 >> 1) & 1;
      else
        returnValue = Enable;
      *(_BYTE *)IsEnabled = returnValue;
    }
    result = AdjustResult;
}
return result;
}
可读性好像仍然不高,看看这个...

/******************************************************************************
* RtlAdjustPrivilege          [NTDLL.@]
*
* Enables or disables a privilege from the calling thread or process.
*
* PARAMS
* Privilege     [I] Privilege index to change.
* Enable        [I] If TRUE, then enable the privilege otherwise disable.
* CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
* Enabled       [O] Whether privilege was previously enabled or disabled.
*
* RETURNS
* Success: STATUS_SUCCESS.
* Failure: NTSTATUS code.
*
* SEE ALSO
* NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
*
*/
NTSTATUS WINAPI
RtlAdjustPrivilege(ULONG Privilege,
                   BOOLEAN Enable,
                   BOOLEAN CurrentThread,
                   PBOOLEAN Enabled)
{
    TOKEN_PRIVILEGES NewState;
    TOKEN_PRIVILEGES OldState;
    ULONG ReturnLength;
    HANDLE TokenHandle;
    NTSTATUS Status;

    TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
        CurrentThread ? "TRUE" : "FALSE", Enabled);

    if (CurrentThread)
    {
        Status = NtOpenThreadToken(GetCurrentThread(),
                                   TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                                   FALSE,
                                   &TokenHandle);
    }
    else
    {
        Status = NtOpenProcessToken(GetCurrentProcess(),
                                    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                                    &TokenHandle);
    }

    if (!NT_SUCCESS(Status))
    {
        WARN("Retrieving token handle failed (Status %x)\n", Status);
        return Status;
    }

    OldState.PrivilegeCount = 1;

    NewState.PrivilegeCount = 1;
    NewState.Privileges[0].Luid.LowPart = Privilege;
    NewState.Privileges[0].Luid.HighPart = 0;
    NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;

    Status = NtAdjustPrivilegesToken(TokenHandle,
                                     FALSE,
                                     &NewState,
                                     sizeof(TOKEN_PRIVILEGES),
                                     &OldState,
                                     &ReturnLength);
    NtClose (TokenHandle);
    if (Status == STATUS_NOT_ALL_ASSIGNED)
    {
        TRACE("Failed to assign all privileges\n");
        return STATUS_PRIVILEGE_NOT_HELD;
    }
    if (!NT_SUCCESS(Status))
    {
        WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
        return Status;
    }

    if (OldState.PrivilegeCount == 0)
        *Enabled = Enable;
    else
        *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);

    return STATUS_SUCCESS;
}

易语言代码:

.版本 2

.常量 SE_BACKUP_PRIVILEGE, "17", , 公开
.常量 SE_RESTORE_PRIVILEGE, "18", , 公开
.常量 SE_SHUTDOWN_PRIVILEGE, "19", , 公开
.常量 SE_DEBUG_PRIVILEGE, "20", , 公开

.DLL命令 提升自身进程权限, 整数型, "ntdll.dll", "RtlAdjustPrivilege"
    .参数 Privilege, 整数型, , 需要的权限,以SE_开头的常量,比如SE_DEBUG_PRIVILEGE表示提升到调试权限
    .参数 Enable, 逻辑型, , 如果为真就是打开相应权限,如果为假则是关闭相应权限
    .参数 CurrentThread, 整数型, , 如果为真则仅提升当前线程权限,否则提升整个进程的权限
    .参数 RetEnable, 整数型, 传址, 输出原来相应权限的状态(打开 | 关闭)

.版本 2

提升自身进程权限 (#SE_DEBUG_PRIVILEGE, 真, 0, 0)

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (25)
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
2
很老很火星:
http://bbs.pediy.com/showthread.php?t=40712&highlight=RtlAdjustPrivilege
2010-1-2 11:03
0
雪    币: 45
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
RtlAdjustPrivilege 调用这个函数需要什么权限?
2010-1-2 11:45
0
雪    币: 808
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
好啊,最近正在研究这个问题呢。
2010-1-2 15:26
0
雪    币: 109
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
今天比较多新贴,,这个user用户权限可以提升不,
2010-1-2 17:11
0
雪    币: 56
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
。。。。。。。。。。。。。。。很老的东西
2010-1-2 17:18
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
7
楼主很火星啊~
2010-1-2 17:27
0
雪    币: 695
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
似乎见过n 次 了
2010-1-2 17:46
0
雪    币: 33
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
重在分析,

很好,学习到了
2010-1-2 17:51
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
http://bbs.pediy.com/showthread.php?t=76552
2010-1-2 18:03
0
雪    币: 33
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
这个排版真是太好看了
2010-1-2 18:14
0
雪    币: 216
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
LZ怎么抄别人的文章
2010-1-2 19:48
0
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
13
呵呵,我没说是我的啊,分享而已
2010-1-3 14:32
0
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
14
是程序就可以用
2010-1-3 14:34
0
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
15


我火星了
2010-1-3 14:35
0
雪    币: 17
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
谢谢楼主提供,辛苦啦
2010-1-4 09:35
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
谢谢楼主提供
学习了
2010-1-8 15:34
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
请问一下这个是不是只支持 window XP sp3   还是支持全部的 XP 系统
2010-1-8 22:10
0
雪    币: 160
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
作坊模块也老早使用这个函数提权了
2010-1-9 22:34
0
雪    币: 808
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
20
这两天实验了一下RtlAdjustPrivilege函数,结果编译提示错误:SE_DEBUG_PRIVILEGE符号没有定义,参数不匹配。。。。
我用的是MASM10
看了下windows.inc,发现只有SE_DEBUG_NAME  equ  ("sedebugprivilege"),RtlAdjustPrivilege函数有声明。查了google   and   baidu,没什么发现,那位大侠知道或遇到过,请赐教。谢谢先。
2010-1-11 00:14
0
雪    币: 808
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
21
等了两天没人来看,自己搞定了。
2010-1-12 22:21
0
雪    币: 269
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
22
被微软严格保密


.....。。。。
2010-1-13 10:06
0
雪    币: 145
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
23
标记一下,学习了
2010-11-25 17:01
0
雪    币: 89
活跃值: (214)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
哈哈|……楼主哇~俺还是很支持你的~
2010-11-26 00:37
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
引用:
最初由 qihoocom发布  
很老很火星:
http://bbs.pediy.com/showthread.php?t=40712&highlight=RtlAdjustPrivilege

我火星了
2011-10-8 14:41
0
游客
登录 | 注册 方可回帖
返回
//