前言:
今天逆向一个非常实用的函数RtlAdjustPrivliege

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

先来看看这个函数的定义(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);  //  获得 SE_DEBUG_NAME 特权
    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;
}

[转自“看雪论坛”]RtlAdjustPrivliege (http://bbs.pediy.com/showthread.php?t=76552)相关推荐

  1. 看雪论坛chrome浏览器无法登录

    在使用chrome浏览器点击登录看雪论坛(https://bbs.pediy.com/) 时,会跳到登录界面,登陆后跳转回来发现并没有登陆上,但是看雪安全培训(https://www.kanxue.c ...

  2. python爬取看雪论坛的所有主题帖的回复消息

    最近因为实验课题的需要,我们对看雪论坛的消息回复进行爬取, https://bbs.pediy.com/(看雪论坛) 对于看雪论坛的消息回复查看的一般顺序为: 进入看雪论坛的主页----->选择 ...

  3. 看雪论坛精华8正式发布

    首先祝贺看雪学院建站七周年! 感谢那些关心和支持看雪论坛发展的朋友们!每到论坛最困难的时候,是他们伸出援助之手才让论坛度过一个个的难关走到今天! 看雪论坛是大家交流加解密技术的一个场所,主要研究软件加 ...

  4. 看雪论坛ios反编译网址记录

    想要研究ios逆向工程的,可以多参考看雪论坛的帖子,高手无限... http://www.kanxue.com/bbs/showthread.php?t=174525  逆向iOS SDK -- &q ...

  5. 看雪论坛 第一届软件设计大赛

    看雪论坛  华章公司 第一届软件设计大赛  活动目标 (1)作为<Windows编程循序渐进>一书的宣传活动. (2)加强论坛整体的编程氛围,为论坛的精英提供展示自我实力的机会. (3)激 ...

  6. 《看雪论坛精华11》正式发布

    <看雪论坛精华11>正式发布,点击下载. 制作说明 1. 本论坛精华手册收集了看雪软件安全论坛 2010.1.1 - 2010.12.31 期间的精华内容,共八百余篇文章. 2. 本精华手 ...

  7. 看雪论坛,上次访问时间

    上次访问看雪论坛的时间!

  8. 堆溢出-House of orange 学习笔记(看雪论坛)

    https://www.jianshu.com/p/4b0a73f321f9 前几天把House of orange重新学习了一下,比照着glibc malloc的源码好好分析了一下,希望做到真正做到 ...

  9. 产业互联网时代的到来(内容摘自看雪论坛)

            产业互联网日益成为众多行业实现转型,获得发展新动能的趋势性选择,政务.金融.医疗.出行.教育.零售.工业等垂直领域,正在全面拥抱产业互联网.网络安全 作为互联网的基础保障,在产业互联网 ...

最新文章

  1. 在Eclipse中使用Maven构建Spring项目
  2. Silverlight C# 游戏开发:Silverlight开发环境
  3. Ubuntu 18.04安装中文输入法
  4. 《深入理解Hadoop(原书第2版)》——1.3大数据的编程模型
  5. fileoutputstream 转 byte数组_Java:如何实现文件与数组的相互转换?
  6. c语言中fflush的运用为什么没有效果呢,测试平台linux
  7. java jmail_java jmail
  8. buu robomunication
  9. mongodb中的副本集搭建实践(转自:http://www.cnblogs.com/visionwang/p/3290435.html)
  10. nginx长连接出现504的解决办法
  11. web前端开发最佳实践--(笔记之JavaScript最佳实践)
  12. 研究生必须过计算机和英语吗,计算机考研考英语一还是英语二
  13. 上车,在北京地铁10号线偶遇一下
  14. 使用UTL_SMTP包发送邮件
  15. ios 振动棒软件_iOS 14很棒
  16. 心动C++情牵汉洛塔
  17. 南开大学计算机学院博士毕业要求,南京大学博士研究生申请学位科研成果基本要求...
  18. RLC串联电路的谐振相关参数计算
  19. iis服务器里网站无法访问,IIS服务器网站无法访问解决方法(图文).doc
  20. ResNet详解:ResNet到底在解决什么问题?

热门文章

  1. CleanMyMac X全新版清理软件测评效果+功能
  2. CleanMyMac X软件到底值不值得安装下载?
  3. Python-OpenCV中的图像处理 » 轮廓:入门
  4. 编程实现日历输出,任一年,任一月。
  5. 电子作业票如何实现特殊作业审批规范管理?
  6. C语言求年利率利息计算优化来了
  7. 互融云|区块链如何保护知识产权
  8. Python小游戏——外星人入侵(保姆级教程)第一章 06让飞船移动
  9. 【Java基础系列教程】第八章 Java面向对象详解(三)_抽象类、接口、内部类、深拷贝与浅拷贝
  10. SpringBoot集成Redis并使用Knife4j测试