1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CreateProcessAsUser を用いて Go で作成したサービスからリンクドトークンでプロセスを起動する

Last updated at Posted at 2020-04-30

blono/win にまたいくつかの API を追加したので、サービスからのプロセスの起動がコーディングしやすくなった

main.go
func GetActiveSession() uint32 {
	var si *win.WTS_SESSION_INFO
	var count uint32

	if win.WTSEnumerateSessions(win.WTS_CURRENT_SERVER_HANDLE, 0, 1, &si, &count) != 0 {
		defer win.WTSFreeMemory(uintptr(unsafe.Pointer(si)))

		size := int(unsafe.Sizeof(win.WTS_SESSION_INFO{}))

		for i := 0; i < int(count); i++ {
			sipi := unsafe.Pointer(uintptr(unsafe.Pointer(si)) + uintptr(i*size))
			sii := *(*win.WTS_SESSION_INFO)(sipi)

			if sii.State == win.WTSActive {
				return sii.SessionId
			}
		}
	}

	return 0
}

func CreateProcessAsUser(app, param string, token win.HANDLE, creationFlags uint32, env uintptr, ppi *win.PROCESS_INFORMATION) win.BOOL {
	var pi win.PROCESS_INFORMATION
	var si win.STARTUPINFO
	var arg string

	si.Cb = uint32(unsafe.Sizeof(si))
	si.LpDesktop = NewUTF16(`winsta0\default`)

	if param == "" {
		arg = app
	} else {
		arg = app + " " + param
	}

	result := win.CreateProcessAsUser(token, nil, &arg, nil, nil, win.FALSE, creationFlags, env, nil, &si, &pi)
	if ppi == nil {
		win.CloseHandle(pi.HThread)
		win.CloseHandle(pi.HProcess)
	} else {
		*ppi = pi
	}

	return result
}

func CreateProcessAsActiveUser(app, param string, ppi *win.PROCESS_INFORMATION) win.BOOL {
	activeSession := GetActiveSession()
	var userToken win.HANDLE

	if win.WTSQueryUserToken(activeSession, &userToken) != 0 {
		defer win.CloseHandle(userToken)

		var linkedToken win.HANDLE
		var size uint32 = uint32(unsafe.Sizeof(linkedToken))

		if win.GetTokenInformation(userToken, win.TokenLinkedToken, uintptr(unsafe.Pointer(&linkedToken)), size, &size) != 0 {
			defer win.CloseHandle(linkedToken)

			var duplicatedToken win.HANDLE

			if win.DuplicateTokenEx(linkedToken, win.MAXIMUM_ALLOWED, nil, win.SecurityImpersonation, win.TokenPrimary, &duplicatedToken) != 0 {
				var creationFlags uint32 = win.CREATE_NEW_CONSOLE | win.NORMAL_PRIORITY_CLASS
				var env uintptr

				if win.CreateEnvironmentBlock(&env, duplicatedToken, win.TRUE) != 0 {
					creationFlags |= win.CREATE_UNICODE_ENVIRONMENT
					defer win.DestroyEnvironmentBlock(env)
				}

				return CreateProcessAsUser(app, param, duplicatedToken, creationFlags, env, ppi)
			}
		}
	}

	return win.FALSE
}

Go で Windows Service を作成する で作成した Windows サービスから呼び出すことで動作を確認可能。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?