Manko Posted March 4, 2010 Share Posted March 4, 2010 Hi! Yes it's been done before, but I found a shorter variant and thought it should be documented on this site... Func _GetPrivilege_SeDebug() $ret=DllCall("ntdll.dll", "int", "RtlAdjustPrivilege", "int", 20, "int", 1, "int", 0, "int*", 0) ; 20 is SeDebug privilege... If @error Then SetError( 1, @error, False ) ; 1=error dllcall. Set dllcall-error as extended. Return false. Else if $ret[0] Then SetError( 2, $ret[0], False) ; 2=error RtlAdjustPrivilege. Set it's errorcode as extended. Return False. Return( True ) ; Return true if it worked. (RtlAdjustPrivilege returns 0 if it works.) EndIf EndFunc Or if you like to code dirty like me... DllCall("ntdll.dll", "int", "RtlAdjustPrivilege", "int", 20, "int", 1, "int", 0, "int*", 0) ; 20 is SeDebug privilege... ...though in this way you won't know but, at best, indirecly if it failed... /Manko Skitty 1 Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually... Link to comment Share on other sites More sharing options...
wraithdu Posted March 4, 2010 Share Posted March 4, 2010 Nice find. I'll post this from the SysInternals Forum, as it is quite useful: Link to comment Share on other sites More sharing options...
Manko Posted March 4, 2010 Author Share Posted March 4, 2010 Yes, it makes me think I ought to excavate those systemfiles on a regular basis... Great table! /Manko Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually... Link to comment Share on other sites More sharing options...
trancexx Posted March 5, 2010 Share Posted March 5, 2010 (edited) I'm completely tired of studying. My head is full of things boring by nature. ...I think I will do some reversing (for learning purposes) to see what RtlAdjustPrivilege do exactly. Maybe translate it to AutoIt to see if I'll get it right. That should be interesting. edit: will post it when I'm done. Edited March 5, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
trancexx Posted March 5, 2010 Share Posted March 5, 2010 (edited) Ok, here goes...I wrote this:$hModule = _LoadLibraryEx("ntdll.dll", 0) $pAddress = _GetAddress($hModule, "RtlAdjustPrivilege") ConsoleWrite("RtlAdjustPrivilege address = " & $pAddress & @CRLF) $tByteStructure = DllStructCreate("byte[256]", $pAddress) ; 256 bytes (will see if that's enough) ConsoleWrite(DllStructGetData($tByteStructure, 1) & @CRLF) ;FUNCTIONS: Func _LoadLibraryEx($sModule, $iFlag) Local $aCall = DllCall("kernel32.dll", "handle", "LoadLibraryExW", "wstr", $sModule, "handle", 0, "dword", $iFlag) If @error Then Return SetError(1, @error, 0) Return $aCall[0] EndFunc ;==>_LoadLibraryEx Func _GetAddress($hModule, $vFuncName) Local $sType = "str" If IsNumber($vFuncName) Then $sType = "int" ; if ordinal value passed Local $aCall = DllCall("kernel32.dll", "ptr", "GetProcAddress", "handle", $hModule, $sType, $vFuncName) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) EndIf Return $aCall[0] EndFunc ;==>_GetAddressThe result on my XP SP3 was:0x8BFF558BEC83EC30807D1001A1C8E0977C8945FC8B45148945D48D45D8500F842A9D00006A286AFFE8743BFEFF85C07C668B45088945F08A450C33C9F6D856C745EC01000000894DF41BC083E0028945F88D45D0508D45DC506A108D45EC5051FF75D8E83934FEFFFF75D88BF0E80F35FEFF81FE060100000F843701020085F67C12837DDC008B4DD40F85BD0300008A450C88018BC65E8B4DFCE86B63FEFFC9C210000FB7C0EB5790909090908BFF558BEC807D1000568B750C668B06578B7D080F8502250200663B47020F871B2502000FB7166A00D1EA59895508894D10742E538B4604668B04486683F84172B46683F85A0F87DC7C00000FB7C083C0208BSo what's that. That's the code at the address of RtlAdjustPrivilege function.To make it clearer I went byte by byte and tried to make some sense. The result was this formatted code:expandcollapse popup8BFF 55 8BEC 83EC30 807D1001 A1C8E0977C 8945FC 8B4514 8945D4 8D45D8 50 0F842A9D0000 6A28 6AFF E8743BFEFF 85C0 7C66 8B4508 8945F0 8A450C 33C9 F6D8 56 C745EC01000000 894DF4 1BC0 83E002 8945F8 8D45D0 50 8D45DC 50 6A10 8D45EC 50 51 FF75D8 E83934FEFF FF75D8 8BF0 E80F35FEFF 81FE06010000 0F8437010200 85F6 7C12 837DDC00 8B4DD4 0F85BD030000 8A450C 8801 8BC6 5E 8B4DFC E86B63FEFF C9 C21000 ...Then I added interpretation of the code (and comments) to make it human understandable. Knowing the definitions (hints):NTSTATUS RtlAdjustPrivilege( IN ULONG Privilege, IN BOOLEAN Enable, IN BOOLEAN CurrentThread, OUT PBOOLEAN Enabled ) NtAdjustPrivilegesToken( IN HANDLE TokenHandle, IN BOOLEAN DisableAllPrivileges, IN PTOKEN_PRIVILEGES TokenPrivileges, IN ULONG PreviousPrivilegesLength, OUT PTOKEN_PRIVILEGES PreviousPrivileges OPTIONAL, OUT PULONG RequiredLength OPTIONAL ) NtOpenProcessToken( IN HANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, OUT PHANDLE TokenHandle ) NtOpenThreadToken( IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, OUT PHANDLE TokenHandle ) NTSTATUS NtClose( IN HANDLE Handle )the result is:expandcollapse popup--------- ; BLOCK 10 --------- 8BFF mov edi, edi ; --NOT RELEVANT-- 55 push ebp ; save the value of ebp 8BEC mov ebp, esp ; ebp now points to the top of the stack 83EC30 sub esp, 48d ; allocate 48 bytes on the stack 807D1001 cmp byte[ebp+16d], 1d ; check byte value 16 bytes "into" the ebp. This is third passed parameter (BOOLEAN CurrentThread). A1C8B0977C mov eax, dword[7C97B0C8] ; --NOT RELEVANT-- this is some internal handler stuff. Not relevant for what's shown here. 8945FC mov dword[ebp-4d], eax ; --NOT RELEVANT-- set some variable to eax value. Again not relevant here. 8B4514 mov eax, dword[ebp+20d] ; set eax to (PBOOLEAN Enabled) parameter. 8945D4 mov dword[ebp-44d], eax ; set another variable to eax value (PBOOLEAN Enabled). 8D45D8 lea eax, dword[ebp-40d] ; load address to eax (at ebp-40 will obviously be TokenHandle on return of below action) 50 push eax ; push pointer to buffer - TokenHandle parameter of NtOpenThreadToken/NtOpenProcessToken function 0F841A9D0000 je 40218d ; if (BOOLEAN CurrentThread) = 1 then go forward 40218 bytes ; To BLOCK 80 6A28 push 40d ; push 40 - DesiredAccess parameter of NtOpenProcessToken function - hardcoded value 6AFF push -1d ; push -1 - ProcessHandle parameter of NtOpenProcessToken function - hardcoded value E8763BFEFF call -115850d ; call function at 115850 bytes back (NtOpenProcessToken coincidently) --------- ; BLOCK 20 --------- 85C0 test eax, eax ; check eax 7C66 jl 102d ; if (eax) go forward 102 bytes ; To BLOCK 60 8B4508 mov eax, dword[ebp+8d] ; (ULONG Privilege) parameter 8945F0 mov dword[ebp-16d], eax ; set some dword (at -16) to eax (passed ULONG Privilege) 8A450C mov al, byte[ebp+12d] ; (BOOLEAN Enable) parameter to al (eax effectively) 33C9 xor ecx, ecx ; ecx = 0 F6D8 neg al ; change sign of al (eax effectively) 56 push esi ; pushing esi (purpose will be shown later) C745EC01000000 mov dword[ebp-20d], 1d ; set some dword (at -20) to 1 894DF4 mov dword[ebp-12d], ecx ; set other dword (at -12) to value of ecx (0) 1BC0 sbb eax, eax ; subtract with borrow 83E002 and eax, 2d ; add 2 to eax 8945F8 mov dword[ebp-8d], eax ; set third dword (at -8) to eax value (0 or 2) 8D45D0 lea eax, dword[ebp-48d] ; pointer to some dword space 50 push eax ; push that pointer - RequiredLength parameter of NtAdjustPrivilegesToken function 8D45DC lea eax, dword[ebp-36d] ; pointer to some other dword space 50 push eax ; push that pointer - PreviousPrivileges parameter of NtAdjustPrivilegesToken function 6A10 push 16d ; push 16 - PreviousPrivilegesLength parameter (hardcoded value) of NtAdjustPrivilegesToken function 8D45EC lea eax, dword[ebp-20d] ; pointer to some space (structure TOKEN_PRIVILEGES filled above) 50 push eax ; TokenPrivileges pointer parameter of NtAdjustPrivilegesToken function 51 push ecx ; push ecx (0) - DisableAllPrivileges parameter of NtAdjustPrivilegesToken function FF75D8 push dword[ebp-40d] ; TokenHandle parameter (was stored at ebp-40, remenber?) E83B34FEFF call -117701d ; call function at 117701 bytes back (NtAdjustPrivilegesToken) FF75D8 push dword[ebp-40d] ; again push token handle 8BF0 mov esi, eax ; save the value of eax to esi. This is why esi was pushed. eax is return value of NtAdjustPrivilegesToken function. E81135FEFF call -117487d ; call function at 117487 bytes back (NtClose) 81FE06010000 cmp esi, 262d ; check if NtAdjustPrivilegesToken returned 262 (obviously some special situation) 0F8427E30100 je 123687d ; if for some reason it's 262 then jump forward 123687 bytes ; To BLOCK 90 --------- ; BLOCK 30 --------- 85F6 test esi, esi ; check esi 7C12 jl 18d ; if (esi) then jump forward 18 bytes ; To BLOCK 50 837DDC00 cmp dword[ebp-36d], 0d ; check the value of byref-ed PreviousPrivileges value 8B4DD4 mov ecx, dword[ebp-44d] ; set ecx to value at (PBOOLEAN Enabled) parameter - using that variable from the beginning. 0F85BD030000 jne 957d ; if PreviousPrivileges is NOT 0 then jump forward 957 bytes ; To BLOCK 70 8A450C mov al, byte[ebp+12d] ; set al to (BOOLEAN Enable) parameter --------- ; BLOCK 40 --------- 8801 mov byte[ecx], al ; set boolean at ecx (PBOOLEAN Enabled) to al (BOOLEAN Enable) --------- ; BLOCK 50 --------- 8BC6 mov eax, esi ; set eax to esi 5E pop esi ; pop --------- ; BLOCK 60 --------- 8B4DFC mov ecx, dword[ebp-4d] ; --NOT RELEVANT-- set ecx to the variable from the beginning E86B63FEFF call -105621d ; --NOT RELEVANT-- C9 leave ; set esp to ebp, then pop ebp (opposite from when the function was starting) C21000 ret 16d ; return and clear 16 bytes off the stack --------- --------- ; BLOCK 70 --------- 8B45E8 mov eax, dword[ebp-24d] ; set eax to value at ebp-24 D1E8 shr eax, 1d ; shift right (eax, 1) 2401 and al, 1d ; and (al, 1) E93AFCFFFF jmp -966d ; jump 966 bytes back ; To BLOCK 40 --------- ; BLOCK 80 --------- 6A00 push 0d ; push 0 - OpenAsSelf parameter of NtOpenThreadToken function - hardcoded value 6A28 push 40d ; push 40 - DesiredAccess parameter of NtOpenThreadToken function - hardcoded value 6AFE push -2d ; push -2 - ThreadHandle parameter of NtOpenThreadToken function - hardcoded value E8BA9EFDFF call -155974d ; call function at 155974 bytes back (NtOpenThreadToken) E9DF62FFFF jmp -40225d ; jump 40225 bytes back ; To BLOCK 20 --------- ; BLOCK 90 --------- BE610000C0 mov esi, C0000061 ; set esi to value of 0xC0000061 (STATUS_PRIVILEGE_NOT_HELD) E9CF1CFEFF jmp -123697d ; jump 123697 bytes back ; To BLOCK 30Obviously I had to use calculator to see what's at jumped/called addresses (used functions).Basically RtlAdjustPrivilege is wrapper function. It calls few other Nt... functions to do the job. Just like AutoIt's UDFs.Translated to Autoit (literally) it would be:expandcollapse popupFunc _RtlAdjustPrivilege($iPrivilege, $fEnable, $fCurrentThread, ByRef $fPreviouslyTheSame) Local $aCall, $hTokenHandle If $fCurrentThread Then $aCall = DllCall("ntdll.dll", "long", "NtOpenThreadToken", _ "handle", -2, _ ; ThreadHandle - hardcoded value "dword", 40, _ ; DesiredAccess - hardcoded value "boolean", 0, _ ; OpenAsSelf - hardcoded value "handle*", 0) ; TokenHandle to collect to If @error Or $aCall[0] Then Return SetError(1, 0, -1) EndIf $hTokenHandle = $aCall[4] Else $aCall = DllCall("ntdll.dll", "long", "NtOpenProcessToken", _ "handle", -1, _ ; ProcessHandle - hardcoded value "dword", 40, _ ; DesiredAccess - hardcoded value "handle*", 0) ; TokenHandle to collect to If @error Or $aCall[0] Then Return SetError(1, 0, -1) EndIf $hTokenHandle = $aCall[3] EndIf #cs typedef struct _LUID { DWORD LowPart; LONG HighPart; } LUID, *PLUID; typedef struct _LUID_AND_ATTRIBUTES { LUID Luid; DWORD Attributes; } LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES; typedef struct _TOKEN_PRIVILEGES { DWORD PrivilegeCount; LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES; #ce Local $tTOKEN_PRIVILEGES = DllStructCreate("dword PrivilegeCount;" & _ "dword LowPart;" & _ ;...from LUID structure........; from LUID_AND_ATTRIBUTES structure "long HighPart;" & _ ;...from LUID structure........; from LUID_AND_ATTRIBUTES structure "dword Attributes;") ;..............................; from LUID_AND_ATTRIBUTES structure DllStructSetData($tTOKEN_PRIVILEGES, "PrivilegeCount", 1) ; - hardcoded value DllStructSetData($tTOKEN_PRIVILEGES, "LowPart", $iPrivilege) DllStructSetData($tTOKEN_PRIVILEGES, "HighPart", 0) ; - hardcoded value If $fEnable Then DllStructSetData($tTOKEN_PRIVILEGES, "Attributes", 2) Else DllStructSetData($tTOKEN_PRIVILEGES, "Attributes", 0) ; this is redundant in AutoIt but still... EndIf $aCall = DllCall("ntdll.dll", "long", "NtAdjustPrivilegesToken", _ "handle", $hTokenHandle, _ ; TokenHandle "boolean", 0, _ ; DisableAllPrivileges "ptr", DllStructGetPtr($tTOKEN_PRIVILEGES), _ ; TokenPrivileges "dword", 16, _ ; PreviousPrivilegesLength - hardcoded value "dword*", 0, _ ; PreviousPrivileges "dword*", 0) ; RequiredLength DllCall("ntdll.dll", "long", "NtClose", "handle", $hTokenHandle) ; close TokenHandle If $aCall[0] = 262 Then Return SetError(2, 0, -1) EndIf $fPreviouslyTheSame = Not $aCall[5] EndFunc ;==>_RtlAdjustPrivilegeCool function that RtlAdjustPrivilege.AutoIt code can be tested like this (you need some tool to monitor privileges status):expandcollapse popupGlobal $fPreviouslyTheSame _RtlAdjustPrivilege(20, 0, 0, $fPreviouslyTheSame) ConsoleWrite("- " & $fPreviouslyTheSame & @CRLF) MsgBox(0, '', $fPreviouslyTheSame) _RtlAdjustPrivilege(20, 1, 0, $fPreviouslyTheSame) ConsoleWrite("- " & $fPreviouslyTheSame & @CRLF) MsgBox(0, '', $fPreviouslyTheSame) _RtlAdjustPrivilege(20, 1, 0, $fPreviouslyTheSame) ConsoleWrite("- " & $fPreviouslyTheSame & @CRLF) MsgBox(0, '', $fPreviouslyTheSame) _RtlAdjustPrivilege(20, 0, 0, $fPreviouslyTheSame) ConsoleWrite("- " & $fPreviouslyTheSame & @CRLF) MsgBox(0, '', $fPreviouslyTheSame) _RtlAdjustPrivilege(20, 0, 0, $fPreviouslyTheSame) ConsoleWrite("- " & $fPreviouslyTheSame & @CRLF) MsgBox(0, '', $fPreviouslyTheSame) MsgBox(0, '', $fPreviouslyTheSame) Func _RtlAdjustPrivilege($iPrivilege, $fEnable, $fCurrentThread, ByRef $fPreviouslyTheSame) Local $aCall, $hTokenHandle If $fCurrentThread Then $aCall = DllCall("ntdll.dll", "long", "NtOpenThreadToken", _ "handle", -2, _ ; ThreadHandle "dword", 40, _ ; DesiredAccess "boolean", 0, _ ; OpenAsSelf "handle*", 0) If @error Or $aCall[0] Then Return SetError(1, 0, -1) EndIf $hTokenHandle = $aCall[4] Else $aCall = DllCall("ntdll.dll", "long", "NtOpenProcessToken", _ "handle", -1, _ ; ProcessHandle "dword", 40, _ ; DesiredAccess "handle*", 0) If @error Or $aCall[0] Then Return SetError(1, 0, -1) EndIf $hTokenHandle = $aCall[3] EndIf Local $tTOKEN_PRIVILEGES = DllStructCreate("dword PrivilegeCount;" & _ "dword LowPart;" & _ "long HighPart;" & _ "dword Attributes;") DllStructSetData($tTOKEN_PRIVILEGES, "PrivilegeCount", 1) ; - hardcoded value DllStructSetData($tTOKEN_PRIVILEGES, "LowPart", $iPrivilege) If $fEnable Then DllStructSetData($tTOKEN_PRIVILEGES, "Attributes", 2) $aCall = DllCall("ntdll.dll", "long", "NtAdjustPrivilegesToken", _ "handle", $hTokenHandle, _ ; TokenHandle "boolean", 0, _ ; DisableAllPrivileges "ptr", DllStructGetPtr($tTOKEN_PRIVILEGES), _ ; TokenPrivileges "dword", 16, _ ; PreviousPrivilegesLength - hardcoded value "dword*", 0, _ ; PreviousPrivileges "dword*", 0) ; RequiredLength DllCall("ntdll.dll", "long", "NtClose", "handle", $hTokenHandle) ; close TokenHandle If $aCall[0] = 262 Then Return SetError(2, 0, -1) EndIf $fPreviouslyTheSame = Not $aCall[5] EndFunc ;==>_RtlAdjustPrivilegeBtw, this shows for example that NtAdjustPrivilegesToken description is somewhere wrong.Word on: neg al sbb eax, eax and eax, 2dThat's basically (plus irrelevant BitShift): If $eax Then $eax = 2 Else $eax = 0 EndIf Edited March 6, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
wraithdu Posted March 5, 2010 Share Posted March 5, 2010 (edited) Here's the function I've had around for a while. It's included in some of my UDFs, I guess I never posted the whole thing though: expandcollapse popup; #FUNCTION# ;=============================================================================== ; ; Name...........: _GetPrivilege_SEDEBUG ; Description ...: Obtains the SE_DEBUG privilege for the running process ; Syntax.........: _GetPrivilege_SEDEBUG() ; Parameters ....: ; Return values .: Success - Returns True ; Failure - Returns False and Sets @Error to 1 ; Author ........: Erik Pilsits ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _GetPrivilege_SEDEBUG() Local $return = False Local $tagLUIDANDATTRIB = "int64 Luid;dword Attributes" Local $count = 1 Local $tagTOKENPRIVILEGES = "dword PrivilegeCount;byte LUIDandATTRIB[" & $count * 12 & "]" ; count of LUID structs * sizeof LUID struct Local $TOKEN_ADJUST_PRIVILEGES = 0x20 Local $SE_PRIVILEGE_ENABLED = 0x2 Local $curProc = DllCall("kernel32.dll", "ptr", "GetCurrentProcess") If @error Then Return False Local $call = DllCall("advapi32.dll", "int", "OpenProcessToken", "ptr", $curProc[0], "dword", $TOKEN_ADJUST_PRIVILEGES, "ptr*", 0) If (@error Or (Not $call[0])) Then Return False Local $hToken = $call[3] $call = DllCall("advapi32.dll", "int", "LookupPrivilegeValue", "ptr", 0, "str", "SeDebugPrivilege", "int64*", 0) If ((Not @error) And $call[0]) Then Local $iLuid = $call[3] Local $TP = DllStructCreate($tagTOKENPRIVILEGES) Local $LUID = DllStructCreate($tagLUIDANDATTRIB, DllStructGetPtr($TP, "LUIDandATTRIB")) DllStructSetData($TP, "PrivilegeCount", $count) DllStructSetData($LUID, "Luid", $iLuid) DllStructSetData($LUID, "Attributes", $SE_PRIVILEGE_ENABLED) $call = DllCall("advapi32.dll", "int", "AdjustTokenPrivileges", "ptr", $hToken, "int", 0, "ptr", DllStructGetPtr($TP), "dword", 0, "ptr", 0, "ptr", 0) If Not @error Then $return = ($call[0] <> 0) ; $call[0] <> 0 is success EndIf DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hToken) Return SetError(Number(Not $return), 0, $return) EndFunc ;==>_GetPrivilege_SEDEBUG And here's the site where I got the table I posted above. It also somewhat explains what RtlAdjustPrivilege is doing (thought not nearly as well as your writeup): http://forum.sysinternals.com/forum_posts.asp?TID=15745 Edited March 5, 2010 by wraithdu Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now