From aa4add9a1721dea93eb12c21ba4881155c7cdfb8 Mon Sep 17 00:00:00 2001 From: "Lazarenko.AN" Date: Thu, 1 Jun 2023 21:03:13 +0300 Subject: [PATCH] add logger & GetTokenBySessionID --- gettoken.go | 61 +++++++++++++++++++++++++++++++++++++++++++++-------- wintoken.go | 38 ++++++++++++++++----------------- 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/gettoken.go b/gettoken.go index bf5d158..61b9751 100644 --- a/gettoken.go +++ b/gettoken.go @@ -11,7 +11,21 @@ const ( WTS_CURRENT_SERVER_HANDLE windows.Handle = 0 ) -//OpenProcessToken opens a process token using PID, pass 0 as PID for self token +type iLogger interface { + Debug(args ...interface{}) + Info(args ...interface{}) + Error(args ...interface{}) +} + +type quasiLogger func(args ...interface{}) + +var logger iLogger + +func init() { + logger = quasiLogger(func(args ...interface{}) {}) +} + +// OpenProcessToken opens a process token using PID, pass 0 as PID for self token func OpenProcessToken(pid int, tokenType tokenType) (*Token, error) { var ( t windows.Token @@ -44,7 +58,6 @@ func OpenProcessToken(pid int, tokenType tokenType) (*Token, error) { if err := windows.DuplicateTokenEx(t, windows.MAXIMUM_ALLOWED, nil, windows.SecurityImpersonation, windows.TokenImpersonation, &duplicatedToken); err != nil { return nil, fmt.Errorf("error while DuplicateTokenEx: %w", err) } - case TokenLinked: if err := windows.DuplicateTokenEx(t, windows.MAXIMUM_ALLOWED, nil, windows.SecurityDelegation, windows.TokenPrimary, &duplicatedToken); err != nil { return nil, fmt.Errorf("error while DuplicateTokenEx: %w", err) @@ -60,8 +73,8 @@ func OpenProcessToken(pid int, tokenType tokenType) (*Token, error) { return &Token{token: duplicatedToken, typ: tokenType}, nil } -//GetInteractiveToken gets the interactive token associated with current logged in user -//It uses windows API WTSEnumerateSessions, WTSQueryUserToken and DuplicateTokenEx to return a valid wintoken +// GetInteractiveToken gets the interactive token associated with current logged in user +// It uses windows API WTSEnumerateSessions, WTSQueryUserToken and DuplicateTokenEx to return a valid wintoken func GetInteractiveToken(tokenType tokenType) (*Token, error) { switch tokenType { @@ -71,11 +84,9 @@ func GetInteractiveToken(tokenType tokenType) (*Token, error) { } var ( - sessionPointer uintptr - sessionCount uint32 - interactiveToken windows.Token - duplicatedToken windows.Token - sessionID uint32 + sessionPointer uintptr + sessionCount uint32 + sessionID uint32 ) err := windows.WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, (**windows.WTS_SESSION_INFO)(unsafe.Pointer(&sessionPointer)), &sessionCount) @@ -101,6 +112,22 @@ func GetInteractiveToken(tokenType tokenType) (*Token, error) { return nil, ErrNoActiveSession } + logger.Debug(fmt.Sprintf("will be used sessionID: %d", sessionID)) + return GetTokenBySessionID(tokenType, sessionID) +} + +func GetTokenBySessionID(tokenType tokenType, sessionID uint32) (*Token, error) { + switch tokenType { + case TokenPrimary, TokenImpersonation, TokenLinked: + default: + return nil, fmt.Errorf("only primary or impersonation token types allowed") + } + + var ( + interactiveToken windows.Token + duplicatedToken windows.Token + ) + if err := windows.WTSQueryUserToken(sessionID, &interactiveToken); err != nil { return nil, fmt.Errorf("error while WTSQueryUserToken: %w", err) } @@ -134,3 +161,19 @@ func GetInteractiveToken(tokenType tokenType) (*Token, error) { return &Token{typ: tokenType, token: duplicatedToken}, nil } + +func SetLogger(l iLogger) { + logger = l +} + +func (q quasiLogger) Debug(args ...interface{}) { + q(args) +} + +func (q quasiLogger) Info(args ...interface{}) { + q(args) +} + +func (q quasiLogger) Error(args ...interface{}) { + q(args) +} diff --git a/wintoken.go b/wintoken.go index 145e73d..83979b5 100644 --- a/wintoken.go +++ b/wintoken.go @@ -31,8 +31,8 @@ type Token struct { token windows.Token } -//TokenUserDetail is the structure that exposes token details -//Details contain Username, Domain, Account Type, User Profile Directory, Environment +// TokenUserDetail is the structure that exposes token details +// Details contain Username, Domain, Account Type, User Profile Directory, Environment type TokenUserDetail struct { Username string Domain string @@ -45,8 +45,8 @@ func (t TokenUserDetail) String() string { return fmt.Sprintf("Username: %s, Domain: %s, Account Type: %d, UserProfileDir: %s", t.Username, t.Domain, t.AccountType, t.UserProfileDir) } -//Privilege is the structure which exposes privilege details -//Details contain Name, Description, Enabled, EnabledByDefault, Removed, UsedForAccess +// Privilege is the structure which exposes privilege details +// Details contain Name, Description, Enabled, EnabledByDefault, Removed, UsedForAccess type Privilege struct { Name string Description string @@ -73,8 +73,8 @@ const ( TokenLinked ) -//NewToken can be used to supply your own token for the wintoken struct -//so you can use the same flexiblity provided by the package +// NewToken can be used to supply your own token for the wintoken struct +// so you can use the same flexiblity provided by the package func NewToken(token windows.Token, typ tokenType) *Token { return &Token{ token: token, @@ -82,12 +82,12 @@ func NewToken(token windows.Token, typ tokenType) *Token { } } -//Token returns the underlying token for use +// Token returns the underlying token for use func (t *Token) Token() windows.Token { return t.token } -//Close closes the underlying token +// Close closes the underlying token func (t *Token) Close() { windows.Close(windows.Handle(t.token)) t.token = 0 @@ -123,7 +123,7 @@ func lookupPrivilegeNameByLUID(luid uint64) (string, string, error) { return windows.UTF16ToString(nameBuffer), windows.UTF16ToString(displayNameBuffer), nil } -//UserDetails gets User details associated with token +// UserDetails gets User details associated with token func (t *Token) UserDetails() (TokenUserDetail, error) { uSid, err := t.token.GetTokenUser() if err != nil { @@ -144,7 +144,7 @@ func (t *Token) UserDetails() (TokenUserDetail, error) { return TokenUserDetail{Username: user, Domain: domain, AccountType: typ, UserProfileDir: uProfDir, Environ: env}, nil } -//GetPrivileges lists all Privileges from the token +// GetPrivileges lists all Privileges from the token func (t *Token) GetPrivileges() ([]Privilege, error) { if err := t.errIfTokenClosed(); err != nil { return nil, err @@ -200,7 +200,7 @@ func (t *Token) GetPrivileges() ([]Privilege, error) { return privDetails, nil } -//EnableAllPrivileges enables all privileges in the token +// EnableAllPrivileges enables all privileges in the token func (t *Token) EnableAllPrivileges() error { if err := t.errIfTokenClosed(); err != nil { return err @@ -221,7 +221,7 @@ func (t *Token) EnableAllPrivileges() error { return t.modifyTokenPrivileges(toBeEnabled, PrivEnable) } -//DisableAllPrivileges disables all privileges in the token +// DisableAllPrivileges disables all privileges in the token func (t *Token) DisableAllPrivileges() error { if err := t.errIfTokenClosed(); err != nil { return err @@ -242,7 +242,7 @@ func (t *Token) DisableAllPrivileges() error { return t.modifyTokenPrivileges(toBeDisabled, PrivDisable) } -//RemoveAllPrivileges removes all privileges from the token +// RemoveAllPrivileges removes all privileges from the token func (t *Token) RemoveAllPrivileges() error { if err := t.errIfTokenClosed(); err != nil { return err @@ -263,32 +263,32 @@ func (t *Token) RemoveAllPrivileges() error { return t.modifyTokenPrivileges(toBeRemoved, PrivRemove) } -//EnableTokenPrivileges enables token privileges by list of privilege names +// EnableTokenPrivileges enables token privileges by list of privilege names func (t *Token) EnableTokenPrivileges(privs []string) error { return t.modifyTokenPrivileges(privs, PrivEnable) } -//DisableTokenPrivileges disables token privileges by list of privilege names +// DisableTokenPrivileges disables token privileges by list of privilege names func (t *Token) DisableTokenPrivileges(privs []string) error { return t.modifyTokenPrivileges(privs, PrivDisable) } -//RemoveTokenPrivileges removes token privileges by list of privilege names +// RemoveTokenPrivileges removes token privileges by list of privilege names func (t *Token) RemoveTokenPrivileges(privs []string) error { return t.modifyTokenPrivileges(privs, PrivRemove) } -//EnableTokenPrivileges enables token privileges by privilege name +// EnableTokenPrivileges enables token privileges by privilege name func (t *Token) EnableTokenPrivilege(priv string) error { return t.modifyTokenPrivilege(priv, PrivEnable) } -//DisableTokenPrivilege disables token privileges by privilege name +// DisableTokenPrivilege disables token privileges by privilege name func (t *Token) DisableTokenPrivilege(priv string) error { return t.modifyTokenPrivilege(priv, PrivDisable) } -//RemoveTokenPrivilege removes token privileges by privilege name +// RemoveTokenPrivilege removes token privileges by privilege name func (t *Token) RemoveTokenPrivilege(priv string) error { return t.modifyTokenPrivilege(priv, PrivRemove) }