Jump to content

How to interpret raw bytes as SID_AND_ATTRIBUTES struct?


Recommended Posts

Overview

_Security__GetTokenInformation() returns a struct containing raw bytes that represents the requested token information.

Take for example, if _Security__GetTokenInformation()  called with  $iClass parameter is set to $TokenUser, the function returns raw bytes that represents a TOKEN_USER struct, which is defined as follows:

typedef struct _TOKEN_USER {
  SID_AND_ATTRIBUTES User;
} TOKEN_USER, *PTOKEN_USER;

Subsequently, the SID_AND_ATTRIBUTES struct is defined as follows:

typedef struct _SID_AND_ATTRIBUTES {
  PSID  Sid;
  DWORD Attributes;
} SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES;

Problems

Since SID has variable length, I suppose that interpreting the returned bytes as SID_AND_ATTRIBUTES struct won't be easy as usual.

Questions

Please inspect my GetTokenInfoUser function below.

  1. Have I got a correct value of Attributes member of SID_AND_ATTRIBUTES struct?
  2. If I have got the correct value, is my approach efficient?
#include <Security.au3>
#include <WinAPIHObj.au3>
#include <Array.au3>

Opt("MustDeclareVars", 1)

Func GetTokenInfoUser($hToken)
  Do
    ; _Security__GetTokenInformation() returns a struct containing bytes that represents the
    ; requested token information.
    Local $tRawTokenInfo = _Security__GetTokenInformation($hToken, $TokenUser)
    If @error Then
      MsgBox($MB_SYSTEMMODAL, _WinAPI_GetLastError(), "_Security__GetTokenInformation() fails.")
      ExitLoop
    EndIf
    Local $pRawTokenInfo = DllStructGetPtr($tRawTokenInfo)

    ; Since SID has variable length, I do not know how to interpret the raw bytes as SID_AND_ATTRIBUTES
    ; struct unless the SID length is known.
    Local $tagPtrSid = "align 4; PTR Sid"
    Local $tPtrSid = DllStructCreate($tagPtrSid, $pRawTokenInfo)
    Local $pSid = DllStructGetData($tPtrSid, 1)
    If Not _Security__IsValidSid($pSid) Then  ; Just to make sure $pSid is a pointer to a valid SID
      MsgBox($MB_SYSTEMMODAL, "", "The SID is invalid.")
      ExitLoop
    EndIf
    Local $iSidBytesLen = _Security__GetLengthSid($pSid)  ; The length of the binary SID, in bytes

    ; After the SID length is known, the raw bytes are interpreted as SID_AND_ATTRIBUTES struct
    Local $tagSID_AND_ATTRIBUTES = "align 4; PTR Sid; BYTE[" & $iSidBytesLen & "]; ULONG Attributes"
    Local $tSID_AND_ATTRIBUTES = DllStructCreate($tagSID_AND_ATTRIBUTES, $pRawTokenInfo)

    ; Return the results
    Local $avResults[2]
    $avResults[0] = $pSid
    $avResults[1] = DllStructGetData($tSID_AND_ATTRIBUTES, "Attributes")
    Return $avResults
  Until False

  Return SetError(1, 0, 0)
EndFunc  ; GetTokenInfoUser


Func Main()
  Do
    Local $hToken = _Security__OpenProcessToken(_WinAPI_GetCurrentProcess(), $TOKEN_QUERY)
    If Not $hToken Then
      MsgBox($MB_SYSTEMMODAL, _WinAPI_GetLastError(), "_Security__OpenProcessToken() fails.")
      ExitLoop
    EndIf

    Local $avResults = GetTokenInfoUser($hToken)
    If @error Then ExitLoop

    _ArrayDisplay($avResults)  ; Display the results of GetTokenInfoUser()

    If $hToken Then _WinAPI_CloseHandle($hToken)
    Return
  Until False

  If $hToken Then _WinAPI_CloseHandle($hToken)
EndFunc  ; Main


Main()

Thanks in advance.

Edited by tukangusil7
Link to comment
Share on other sites

maybe have a look at 

_Security__GetTokenInformation in security.au3 it's already getting the length of the struct when its created

also since the struct already exists you could get the byte length with DllStructGetSize ( Struct )

Link to comment
Share on other sites

My comments below based on my way of thinking in AutoIt world, which can be wrong, because I'm still a newbie in AutoIt.

I think knowing the size of SID_AND_ATTRIBUTES struct won't help in interpreting bytes as SID_AND_ATTRIBUTES struct because the struct has the SID member that has an arbitrary length of bytes.

Even if I can make use the size of SID_AND_ATTRIBUTES struct to interpret the bytes as follows:

Local Const $SIZE_OF_PTR = DllStructGetSize(DllStructCreate("PTR"))  ; The size of a pointer
Local $iSidBytesLen = DllStructGetSize($tRawTokenInfo) - $SIZE_OF_PTR - 4  ; 4 is size of "ULONG Attributes"
Local $tagSID_AND_ATTRIBUTES = "align 4; PTR Sid; BYTE[" & $iSidBytesLen & "]; ULONG Attributes"
Local $tSID_AND_ATTRIBUTES = DllStructCreate($tagSID_AND_ATTRIBUTES, $pRawTokenInfo)

that way will make my life harder when I want to (for example) interpret the bytes returned by _Security__GetTokenInformation() as TOKEN_ACCESS_INFORMATION struct, which is a more complex struct.

OK, to make it simpler, I just need a confirmation whether the following portion of my GetTokenInfoUser() above will return a correct result:

; Since SID has variable length, I do not know how to interpret the raw bytes as SID_AND_ATTRIBUTES
; struct unless the SID length is known.
Local $tagPtrSid = "align 4; PTR Sid"
Local $tPtrSid = DllStructCreate($tagPtrSid, $pRawTokenInfo)
Local $pSid = DllStructGetData($tPtrSid, 1)
If Not _Security__IsValidSid($pSid) Then  ; Just to make sure $pSid is a pointer to a valid SID
  MsgBox($MB_SYSTEMMODAL, "", "The SID is invalid.")
  ExitLoop
EndIf
Local $iSidBytesLen = _Security__GetLengthSid($pSid)  ; The length of the binary SID, in bytes

; After the SID length is known, the raw bytes are interpreted as SID_AND_ATTRIBUTES struct
Local $tagSID_AND_ATTRIBUTES = "align 4; PTR Sid; BYTE[" & $iSidBytesLen & "]; ULONG Attributes"
Local $tSID_AND_ATTRIBUTES = DllStructCreate($tagSID_AND_ATTRIBUTES, $pRawTokenInfo)

; Return the results
Local $avResults[2]
$avResults[0] = $pSid
$avResults[1] = DllStructGetData($tSID_AND_ATTRIBUTES, "Attributes")
Return $avResults

I need a confirmation whether it is a right way to interpret a struct whose one of its members has an arbitrary bytes length.

Thanks in advanced.

Edited by tukangusil7
Link to comment
Share on other sites

Hello You need to declare _SID_AND_ATTRIBUTES like this:

 

"ptr psid;dword Attributes"

 

The you can the correct Windows API to manage the SID

So then you can do this:

#include <SecurityConstants.au3>
#include <WinAPI.au3>

Example_TokInfo()

Func Example_TokInfo()
    Local $hProcess = _WinAPI_GetCurrentProcess()
    If @error Then Return ; check for possible errors

    Local $hToken = _Security__OpenProcessToken($hProcess, $TOKEN_ALL_ACCESS)
    ; If token is get...
    If $hToken Then

        Local Const $sTag_SID_AND_ATTRIBUTES = "ptr psid;dword Attributes"
        ; Get information about the type of this token:
        Local $tInfo = _Security__GetTokenInformation($hToken, $TOKENUSER)

        Local $tsa = DllStructCreate($sTag_SID_AND_ATTRIBUTES, DllStructGetPtr($tInfo))
        Local $pSID = $tsa.psid

        Local $aCall = DllCall("Advapi32.dll", "dword", "GetLengthSid", "ptr", $pSID)
        Local $iSidLength = $aCall[0]

        $aCall = DllCall("Advapi32.dll", "bool", "IsValidSid", "ptr", $pSID)
        Local $IsValidSid = $aCall[0]

        If $IsValidSid Then
            Local $tBytes = DllStructCreate("byte[" & $iSidLength & "]", $pSID)
            ConsoleWrite("Sid Hex: " & DllStructGetData($tBytes, 1) & @CRLF)
        EndIf

        ; Close the token handle
        _WinAPI_CloseHandle($hToken)
    EndIf
EndFunc   ;==>Example_TokInfo

Saludos

 

Link to comment
Share on other sites

sorry I missed the second pointer 

Local $pSid = DllStructGetData($tPtrSid, 1)
    If Not _Security__IsValidSid($pSid) Then  ; Just to make sure $pSid is a pointer to a valid SID
      MsgBox($MB_SYSTEMMODAL, "", "The SID is invalid.")
      ExitLoop
    EndIf
    Local $iSidBytesLen = _Security__GetLengthSid($pSid)

I believe he has pretty much what you have there danyfirex

also I'm guessing (.) dot access of structs is here to stay its been there over 4 years since you asked??

Thats wonderful news!

#include <SecurityConstants.au3>
#include <WinAPI.au3>

Example_TokInfo()

Func Example_TokInfo()
    Local $hProcess = _WinAPI_GetCurrentProcess()
    If @error Then Return ; check for possible errors

    Local $hToken = _Security__OpenProcessToken($hProcess, $TOKEN_ALL_ACCESS)
    ; If token is get...
    If $hToken Then

        Local Const $sTag_SID_AND_ATTRIBUTES = "ptr psid;dword Attributes"
        ; Get information about the type of this token:
        Local $tInfo = _Security__GetTokenInformation($hToken, $TOKENUSER)

        Local $tsa = DllStructCreate($sTag_SID_AND_ATTRIBUTES, DllStructGetPtr($tInfo))
        Local $pSid = $tsa.psid

        Local $IsValidSid = _Security__IsValidSid($pSid)
        Local $tBytes, $iSidLength
        If $IsValidSid Then
            $iSidLength = _Security__GetLengthSid($pSid)
            $tBytes = DllStructCreate("ALIGN 4;byte[" & $iSidLength & "]", $pSid)
            ConsoleWrite("Sid Hex: " & DllStructGetData($tBytes, 1) & @CRLF)
            ConsoleWrite("Sid: " & _Security__SidToStringSid ($pSid) & @CRLF)
        EndIf

        ; Close the token handle
        _WinAPI_CloseHandle($hToken)
    EndIf
    Return
EndFunc   ;==>Example_TokInfo

I'm still not sure what having the raw struct does for you I was under the impression that you were to pass the pointer directly or convert the sid to a string first and use that form in other functions

@tukangusil7 I think you will have to supply more information as far as what you want to do with this data

 

Link to comment
Share on other sites

Thanks to you both, Bilgus and Danyfirex :). I will investigate the inputs from both of you later because I'm having a toothache right now :'(.

What I can say right now is that I'm creating a wrapper for GetTokenInformation(), something similar to _Security__GetTokenInformation(), but my UDF will return the requested token information in form of an array that represents information from the requested struct, instead of just returning raw bytes that need to be interpreted later. The goal is to let the complicated works done in the UDF instead of troubling the caller.

Edited by tukangusil7
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...