日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RtlAdjustPrivilege 一行代码提升进程权限

發布時間:2025/3/21 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RtlAdjustPrivilege 一行代码提升进程权限 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言:今天逆向一個非常實用的函數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);正文:下面我們看一下這個函數是怎么運行的,順便學習下強大的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_7C929A7ACurrentThread == 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]@11v7 = dword_7C97B0C8; IsEnabled = Enabled; if ( CurrentThread == 1 )result = ZwOpenThreadToken(-2, 40, 0, &TokenHandle); elseresult = 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;elsereturnValue = 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; }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?? = 0x14if (!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);

還是不成功,可能還需要其它權限,繼續研究中。。。


總結

以上是生活随笔為你收集整理的RtlAdjustPrivilege 一行代码提升进程权限的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。