mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-02 07:07:33 -04:00
windows: add process module related syscalls
Add EnumProcessModules, EnumProcessModulesEx, GetModuleInformation, GetModuleFileNameEx and GetModuleBaseName. https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocessmodules https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocessmodulesex https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmoduleinformation https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmodulefilenameexw https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmodulebasenamew Change-Id: I75b062daec7a2cc9685e803dfa851825acee32b6 GitHub-Last-Rev: 7c208d6d3eedfbcd536470c6dbde4f4aecdae61e GitHub-Pull-Request: golang/sys#116 Reviewed-on: https://go-review.googlesource.com/c/sys/+/350870 Trust: Alex Brainman <alex.brainman@gmail.com> Trust: Minux Ma <minux@golang.org> Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
@@ -398,6 +398,11 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
|||||||
|
|
||||||
// Process Status API (PSAPI)
|
// Process Status API (PSAPI)
|
||||||
//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
|
//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
|
||||||
|
//sys EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) = psapi.EnumProcessModules
|
||||||
|
//sys EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) = psapi.EnumProcessModulesEx
|
||||||
|
//sys GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) = psapi.GetModuleInformation
|
||||||
|
//sys GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) = psapi.GetModuleFileNameExW
|
||||||
|
//sys GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) = psapi.GetModuleBaseNameW
|
||||||
|
|
||||||
// NT Native APIs
|
// NT Native APIs
|
||||||
//sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb
|
//sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||||
|
|||||||
@@ -701,3 +701,79 @@ func TestWinVerifyTrust(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProcessModules(t *testing.T) {
|
||||||
|
process, err := windows.GetCurrentProcess()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to get current process: %v", err)
|
||||||
|
}
|
||||||
|
// NB: Assume that we're always the first module. This technically isn't documented anywhere (that I could find), but seems to always hold.
|
||||||
|
var module windows.Handle
|
||||||
|
var cbNeeded uint32
|
||||||
|
err = windows.EnumProcessModules(process, &module, uint32(unsafe.Sizeof(module)), &cbNeeded)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EnumProcessModules failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var moduleEx windows.Handle
|
||||||
|
err = windows.EnumProcessModulesEx(process, &moduleEx, uint32(unsafe.Sizeof(moduleEx)), &cbNeeded, windows.LIST_MODULES_DEFAULT)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EnumProcessModulesEx failed: %v", err)
|
||||||
|
}
|
||||||
|
if module != moduleEx {
|
||||||
|
t.Fatalf("module from EnumProcessModules does not match EnumProcessModulesEx: %v != %v", module, moduleEx)
|
||||||
|
}
|
||||||
|
|
||||||
|
exePath, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to get current executable path: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
modulePathUTF16 := make([]uint16, len(exePath)+1)
|
||||||
|
err = windows.GetModuleFileNameEx(process, module, &modulePathUTF16[0], uint32(len(modulePathUTF16)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetModuleFileNameEx failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
modulePath := windows.UTF16ToString(modulePathUTF16)
|
||||||
|
if modulePath != exePath {
|
||||||
|
t.Fatalf("module does not match executable for GetModuleFileNameEx: %s != %s", modulePath, exePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = windows.GetModuleBaseName(process, module, &modulePathUTF16[0], uint32(len(modulePathUTF16)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetModuleBaseName failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
modulePath = windows.UTF16ToString(modulePathUTF16)
|
||||||
|
baseExePath := filepath.Base(exePath)
|
||||||
|
if modulePath != baseExePath {
|
||||||
|
t.Fatalf("module does not match executable for GetModuleBaseName: %s != %s", modulePath, baseExePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
var moduleInfo windows.ModuleInfo
|
||||||
|
err = windows.GetModuleInformation(process, module, &moduleInfo, uint32(unsafe.Sizeof(moduleInfo)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetModuleInformation failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
peFile, err := pe.Open(exePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to open current executable: %v", err)
|
||||||
|
}
|
||||||
|
defer peFile.Close()
|
||||||
|
|
||||||
|
var peSizeOfImage uint32
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "amd64", "arm64":
|
||||||
|
peSizeOfImage = peFile.OptionalHeader.(*pe.OptionalHeader64).SizeOfImage
|
||||||
|
case "386", "arm":
|
||||||
|
peSizeOfImage = peFile.OptionalHeader.(*pe.OptionalHeader32).SizeOfImage
|
||||||
|
default:
|
||||||
|
t.Fatalf("unable to test GetModuleInformation on arch %v", runtime.GOARCH)
|
||||||
|
}
|
||||||
|
|
||||||
|
if moduleInfo.SizeOfImage != peSizeOfImage {
|
||||||
|
t.Fatalf("module size does not match executable: %v != %v", moduleInfo.SizeOfImage, peSizeOfImage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -242,6 +242,14 @@ const (
|
|||||||
TH32CS_INHERIT = 0x80000000
|
TH32CS_INHERIT = 0x80000000
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// flags for EnumProcessModulesEx
|
||||||
|
LIST_MODULES_32BIT = 0x01
|
||||||
|
LIST_MODULES_64BIT = 0x02
|
||||||
|
LIST_MODULES_ALL = 0x03
|
||||||
|
LIST_MODULES_DEFAULT = 0x00
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// filters for ReadDirectoryChangesW and FindFirstChangeNotificationW
|
// filters for ReadDirectoryChangesW and FindFirstChangeNotificationW
|
||||||
FILE_NOTIFY_CHANGE_FILE_NAME = 0x001
|
FILE_NOTIFY_CHANGE_FILE_NAME = 0x001
|
||||||
@@ -2773,3 +2781,9 @@ const (
|
|||||||
|
|
||||||
// Flag for QueryFullProcessImageName.
|
// Flag for QueryFullProcessImageName.
|
||||||
const PROCESS_NAME_NATIVE = 1
|
const PROCESS_NAME_NATIVE = 1
|
||||||
|
|
||||||
|
type ModuleInfo struct {
|
||||||
|
BaseOfDll uintptr
|
||||||
|
SizeOfImage uint32
|
||||||
|
EntryPoint uintptr
|
||||||
|
}
|
||||||
|
|||||||
@@ -377,7 +377,12 @@ var (
|
|||||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||||
procCoUninitialize = modole32.NewProc("CoUninitialize")
|
procCoUninitialize = modole32.NewProc("CoUninitialize")
|
||||||
procStringFromGUID2 = modole32.NewProc("StringFromGUID2")
|
procStringFromGUID2 = modole32.NewProc("StringFromGUID2")
|
||||||
|
procEnumProcessModules = modpsapi.NewProc("EnumProcessModules")
|
||||||
|
procEnumProcessModulesEx = modpsapi.NewProc("EnumProcessModulesEx")
|
||||||
procEnumProcesses = modpsapi.NewProc("EnumProcesses")
|
procEnumProcesses = modpsapi.NewProc("EnumProcesses")
|
||||||
|
procGetModuleBaseNameW = modpsapi.NewProc("GetModuleBaseNameW")
|
||||||
|
procGetModuleFileNameExW = modpsapi.NewProc("GetModuleFileNameExW")
|
||||||
|
procGetModuleInformation = modpsapi.NewProc("GetModuleInformation")
|
||||||
procSubscribeServiceChangeNotifications = modsechost.NewProc("SubscribeServiceChangeNotifications")
|
procSubscribeServiceChangeNotifications = modsechost.NewProc("SubscribeServiceChangeNotifications")
|
||||||
procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications")
|
procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications")
|
||||||
procGetUserNameExW = modsecur32.NewProc("GetUserNameExW")
|
procGetUserNameExW = modsecur32.NewProc("GetUserNameExW")
|
||||||
@@ -3225,6 +3230,22 @@ func stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procEnumProcessModules.Addr(), 4, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procEnumProcessModulesEx.Addr(), 5, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), uintptr(filterFlag), 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) {
|
func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) {
|
||||||
var _p0 *uint32
|
var _p0 *uint32
|
||||||
if len(processIds) > 0 {
|
if len(processIds) > 0 {
|
||||||
@@ -3237,6 +3258,30 @@ func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procGetModuleBaseNameW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(baseName)), uintptr(size), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procGetModuleFileNameExW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procGetModuleInformation.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(modinfo)), uintptr(cb), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) {
|
func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) {
|
||||||
ret = procSubscribeServiceChangeNotifications.Find()
|
ret = procSubscribeServiceChangeNotifications.Find()
|
||||||
if ret != nil {
|
if ret != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user