一句代码提升进程权限

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.
// 输出原来相应权限的状态(打开 | 关闭)


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

ExpandedBlockStart.gif 代码
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 真的是很牛啊... 
看看函数最开头...



ExpandedBlockStart.gif 代码
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了

ExpandedBlockStart.gif 代码
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;
}

 

可读性好像仍然不高,看看这个...

ExpandedBlockStart.gif 代码
/* *****************************************************************************
* 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;
}

 

易语言代码:

 

ExpandedBlockStart.gif 代码
.版本  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

 

转载:pediy

转载于:https://www.cnblogs.com/Chinasf/archive/2010/01/13/1646473.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值