RtlAdjustPrivilege 一行代码提升进程权限
来源:互联网 发布:linux 父目录 编辑:程序博客网 时间:2024/05/22 06:21
前言:今天逆向一个非常实用的函数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); 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);正文:下面我们看一下这个函数是怎么运行的,顺便学习下强大的IDAIDA 载入ntdll.dll (我这里载入的是 WinDBG自动下载的 Symbol里面的英文版本 可能不同的Windows版本略有不同)先把函数的原型给输入IDA 方便一下阅读,然后开始阅读汇编代码了(党和国家考验我们的时候到了)。看看Graph View 真的是很牛啊...看看函数最开头...mov edi, edi ; 这句话是废指令push ebpmov ebp, espsub esp, 30h ; 48个字节的子过程域Auto变量cmp [ebp+CurrentThread], 1 ; 判断CurrentThread参数是否被指定为1mov eax, dword_7C97B0C8mov [ebp+var_4], eaxmov eax, [ebp+Enabled]mov [ebp+IsEnabled], eax ; BOOL *IsEnabled = Enabled;lea eax, [ebp+var_28]push eaxjz loc_7C93378B判断是调整进程权限还是线程权限,CurrentThread == TRUEpush 0push 28h ; TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERYpush 0FFFFFFFEh ; GetCurrentThread()call ZwOpenThreadTokenjmp loc_7C929A7ACurrentThread == FALSEpush 28h ; TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERYpush 0FFFFFFFFh ; GetCurrentProcess()call NtOpenProcessToken然后两个代码块同时指向这里loc_7C929A7A: ; 很明白了吧 判断进程/线程令牌是否成功被打开test eax, eaxjl short loc_7C929AE4 ; 没成功则跳若 执行成功mov eax, [ebp+Privilege]mov [ebp+dwPrivilege], eaxmov al, [ebp+Enable]xor ecx, ecx ; ecx清零neg alpush esimov [ebp+NewState], 1mov [ebp+var_C], ecxsbb eax, eaxand eax, 2mov [ebp+var_8], eaxlea eax, [ebp+ReturnLength] ; 实际返回长度push eaxlea eax, [ebp+OldState]push eax ; 旧的特权 指针push 10h ; sizeof(TOKEN_PRIVILEGES)lea eax, [ebp+NewState]push eax ; 新的特权 指针push ecx ; FALSE 因为上面有xor ecx,ecxpush [ebp+TokenHandle]call NtAdjustPrivilegesToken ; 调用 AdjustPrivilegesToken提权push [ebp+TokenHandle]mov esi, eax ; eax备份call ZwClose ; 关闭 内核对象句柄cmp esi, 106h ; 判断NtAdjustPrivilege执行情况 106h = STATUS_NOT_ALL_ASSIGNEDjz loc_7C947DF2判断是否执行成功之后,开始输出最后一个参数cmp [ebp+OldState], 0mov ecx, [ebp+IsEnabled]jnz loc_7C929E99若 OldState != 0 则mov al, [ebp+Enable] ; 应该很明显了 把Enable变量赋给al 也就是eax最后两位若 OldState == 0 则mov eax, [ebp+var_18]shr eax, 1and al, 1jmp loc_7C929ADF这个函数大致流程就是这样。到这里差不多可以按一下传说中的F5了int __stdcall RtlAdjustPrivilege(int Privilege, char Enable, char CurrentThread, int Enabled){int result; // eax@2signed int AdjustResult; // esi@4char returnValue; // al@7int v7; // [sp+2Ch] [bp-4h]@1int IsEnabled; // [sp+4h] [bp-2Ch]@1int TokenHandle; // [sp+8h] [bp-28h]@2int dwPrivilege; // [sp+20h] [bp-10h]@4signed int NewState; // [sp+1Ch] [bp-14h]@4int v12; // [sp+24h] [bp-Ch]@4int v13; // [sp+28h] [bp-8h]@4int OldState; // [sp+Ch] [bp-24h]@4char ReturnLength; // [sp+0h] [bp-30h]@4unsigned int v16; // [sp+18h] [bp-18h]@11v7 = 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 WINAPIRtlAdjustPrivilege(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;}http://hi.baidu.com/xuzheng1111/item/e328b2f0d16d042d743c4c1f
对比了一下,其实也就比以往的调用少了一个函数。
以下新的API调用:
TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;int res = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);if (!res){int err = ::GetLastError();TRACE(_T("LookupPrivilegeValue(SE_DEBUG_NAME) Fail!!")); return -1; } typedef int (__stdcall *PRtlAdjustPrivilege)(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN); PRtlAdjustPrivilege RtlAdjustPrivilege = (PRtlAdjustPrivilege)GetProcAddress(GetModuleHandle(_T("ntdll")), "RtlAdjustPrivilege"); while (!RtlAdjustPrivilege) { int err = ::GetLastError(); TRACE(_T("GetProcAddress(ntdll.dll::RtlAdjustPrivilege) Fail!!")); return -1; } // 实验了下 提权成功了 但是返回值还是NULL 如果这个时候验证返回值将不准确了. BOOLEAN enabled = 0; res = RtlAdjustPrivilege(tp.Privileges[0].Luid.LowPart, TRUE, FALSE, &enabled);//...LowPart = 0x14 if (!res) { } int err = ::GetLastError();
以下旧的API调用:
TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;int res = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);if (!res){int err = ::GetLastError();TRACE(_T("LookupPrivilegeValue(SE_DEBUG_NAME) Fail!!")); return -1; }tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;res = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);if(!res){int err = ::GetLastError(); TRACE(_T("OpenProcessToken(TOKEN_ADJUST_PRIVILEGES) Fail!!"));return -1; }res = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);CloseHandle(hToken);if (!res){int err = ::GetLastError();TRACE(_T("AdjustTokenPrivileges(SE_PRIVILEGE_ENABLED) Fail!!"));CloseHandle(hToken);return -1;}
经过以上提权,能使用 ProcessIdToSessionId得到另一用户的进程的sessionid,
但 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
还是不成功,可能还需要其它权限,继续研究中。。。
0 0
- RtlAdjustPrivilege 一行代码提升进程权限
- 提升进程权限代码
- 提升进程权限代码 .
- VB 进程权限提升 代码
- RtlAdjustPrivilege进程提权,权限ID对照表
- VC 一句代码提升进程权限
- 【分享】一句代码提升进程权限
- 一句代码提升进程权限
- 一句代码提升进程权限
- [代码片段]提升Win32进程权限
- 提升进程的权限
- [ZT]提升进程权限
- 提升进程权限
- 提升进程权限
- 如何提升进程权限
- 进程提升权限
- 提升进程访问权限
- 提升进程权限
- enum与typedef enum的用法
- 存储过程中使用事务Transaction实例
- 窗口显示类
- Mina、Netty、Twisted一起学(四):定制自己的协议
- poj 1127(线段相交)
- RtlAdjustPrivilege 一行代码提升进程权限
- OK6410 linux内核移植
- 仿酷狗音乐播放器开发日志二十三 修复Option控件显示状态不全的bug(附源码)
- Unable to execute dex: Multiple dex files define 解决方法
- cocos2dx 3.2从零学习(六)——CocosStudio(VS2013工程导入及环境设置)
- Category隐藏UIImagePickerController的StatusBar
- lightbird json not JSON serializable
- [算法竞赛入门经典] UVA 12174 - Shuffle
- 求两个数的最大公约数——辗转相除法