Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add logger & GetTokenBySessionID #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 52 additions & 9 deletions gettoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand All @@ -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)
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}
38 changes: 19 additions & 19 deletions wintoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -73,21 +73,21 @@ 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,
typ: typ,
}
}

//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
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)
}
Expand Down