Skip to content

Instantly share code, notes, and snippets.

@thewh1teagle
Created October 29, 2024 12:31
Show Gist options
  • Select an option

  • Save thewh1teagle/f9d73348f326b332cd0cdb6c35b7e724 to your computer and use it in GitHub Desktop.

Select an option

Save thewh1teagle/f9d73348f326b332cd0cdb6c35b7e724 to your computer and use it in GitHub Desktop.
impersonate system privileges in golang on Windows
package main
import (
"fmt"
"log"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
_ "modernc.org/sqlite"
)
var (
advapi32 = syscall.NewLazyDLL("advapi32.dll")
procImpersonateLoggedOnUser = advapi32.NewProc("ImpersonateLoggedOnUser")
procRevertToSelf = advapi32.NewProc("RevertToSelf")
ntdll = syscall.NewLazyDLL("ntdll.dll")
procRtlAdjustPrivilege = ntdll.NewProc("RtlAdjustPrivilege")
)
func enablePrivilege() error {
var privilege uint32 = 20
var previousValue uint32 = 0
ret, _, _ := procRtlAdjustPrivilege.Call(
uintptr(privilege),
uintptr(1),
uintptr(0),
uintptr(unsafe.Pointer(&previousValue)),
)
if ret != 0 {
return fmt.Errorf("RtlAdjustPrivilege failed with status: %x", ret)
}
return nil
}
func findLsassProcess() (*windows.Handle, error) {
h, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0)
if err != nil {
return nil, fmt.Errorf("CreateToolhelp32Snapshot failed: %v", err)
}
defer windows.CloseHandle(h)
var pe windows.ProcessEntry32
pe.Size = uint32(unsafe.Sizeof(pe))
if err = windows.Process32First(h, &pe); err != nil {
return nil, fmt.Errorf("Process32First failed: %v", err)
}
for {
name := windows.UTF16ToString(pe.ExeFile[:])
if name == "lsass.exe" {
handle, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, pe.ProcessID)
if err != nil {
return nil, fmt.Errorf("OpenProcess failed: %v", err)
}
return &handle, nil
}
err = windows.Process32Next(h, &pe)
if err != nil {
if err == syscall.ERROR_NO_MORE_FILES {
break
}
return nil, fmt.Errorf("Process32Next failed: %v", err)
}
}
return nil, fmt.Errorf("lsass.exe not found")
}
func getSystemToken() (windows.Token, error) {
if err := enablePrivilege(); err != nil {
return 0, fmt.Errorf("failed to enable privileges: %v", err)
}
processHandle, err := findLsassProcess()
if err != nil {
return 0, fmt.Errorf("failed to find LSASS process: %v", err)
}
defer windows.CloseHandle(*processHandle)
var token windows.Token
err = windows.OpenProcessToken(*processHandle, windows.TOKEN_DUPLICATE|windows.TOKEN_QUERY, &token)
if err != nil {
return 0, fmt.Errorf("OpenProcessToken failed: %v", err)
}
var duplicatedToken windows.Token
err = windows.DuplicateTokenEx(token, windows.TOKEN_ALL_ACCESS, nil, windows.SecurityImpersonation, windows.TokenPrimary, &duplicatedToken)
if err != nil {
token.Close()
return 0, fmt.Errorf("DuplicateTokenEx failed: %v", err)
}
token.Close()
return duplicatedToken, nil
}
func impersonateSystem() (windows.Token, error) {
token, err := getSystemToken()
if err != nil {
return 0, err
}
ret, _, err := procImpersonateLoggedOnUser.Call(uintptr(token))
if ret == 0 {
token.Close()
return 0, fmt.Errorf("ImpersonateLoggedOnUser failed: %v", err)
}
return token, nil
}
func getTokenUser(token windows.Token) (string, error) {
tokenUser, err := token.GetTokenUser()
if err != nil {
return "", fmt.Errorf("GetTokenUser failed: %v", err)
}
sid := tokenUser.User.Sid.String()
return sid, nil
}
func getCurrentProcessTokenUser() (string, error) {
var token windows.Token
// Get the current process token
err := windows.OpenProcessToken(windows.CurrentProcess(), windows.TOKEN_QUERY, &token)
if err != nil {
return "", fmt.Errorf("OpenProcessToken failed: %v", err)
}
defer token.Close()
// Retrieve the token user
tokenUser, err := token.GetTokenUser()
if err != nil {
return "", fmt.Errorf("GetTokenUser failed: %v", err)
}
// Convert SID to a readable string
sid := tokenUser.User.Sid.String()
return sid, nil
}
func main() {
currentUser, err := getCurrentProcessTokenUser()
if err != nil {
log.Fatalf("Failed to get current process token user: %v", err)
}
log.Printf("Current process user before impersonation: %s", currentUser)
token, err := impersonateSystem()
if err != nil {
log.Fatalf("failed to impersonate SYSTEM: %v", err)
}
defer token.Close()
defer procRevertToSelf.Call()
systemUser, err := getTokenUser(token)
if err != nil {
log.Fatalf("Failed to retrieve impersonated token user: %v", err)
}
log.Printf("Impersonated as: %s", systemUser)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment