mirror of
https://github.com/NomanNasirMinhas/Ringer
synced 2026-08-19 05:01:13 +00:00
80 lines
2.1 KiB
Go
80 lines
2.1 KiB
Go
// Package runtime discovers live driver state: loaded kernel modules, device
|
|
// names, and named sections in the object manager namespace.
|
|
package runtime
|
|
|
|
import (
|
|
"strings"
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
// Module is a loaded kernel module.
|
|
type Module struct {
|
|
ImageBase uintptr
|
|
ImageSize uint32
|
|
Path string
|
|
}
|
|
|
|
// Modules returns the list of loaded kernel modules via
|
|
// NtQuerySystemInformation(SystemModuleInformation).
|
|
func Modules() ([]Module, error) {
|
|
size := uint32(1 << 20) // 1 MiB initial; grows on STATUS_INFO_LENGTH_MISMATCH
|
|
for {
|
|
buf := make([]byte, size)
|
|
err := windows.NtQuerySystemInformation(windows.SystemModuleInformation, unsafe.Pointer(&buf[0]), size, &size)
|
|
if err == nil {
|
|
return parseModules(buf), nil
|
|
}
|
|
if err != windows.STATUS_INFO_LENGTH_MISMATCH {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
|
|
// parseModules decodes an RTL_PROCESS_MODULES buffer into a slice of Module.
|
|
func parseModules(buf []byte) []Module {
|
|
mods := (*windows.RTL_PROCESS_MODULES)(unsafe.Pointer(&buf[0]))
|
|
out := make([]Module, 0, mods.NumberOfModules)
|
|
base := unsafe.Pointer(&mods.Modules[0])
|
|
entrySize := unsafe.Sizeof(windows.RTL_PROCESS_MODULE_INFORMATION{})
|
|
for i := uint32(0); i < mods.NumberOfModules; i++ {
|
|
mi := (*windows.RTL_PROCESS_MODULE_INFORMATION)(unsafe.Pointer(uintptr(base) + uintptr(i)*entrySize))
|
|
out = append(out, Module{
|
|
ImageBase: mi.ImageBase,
|
|
ImageSize: mi.ImageSize,
|
|
Path: modulePath(mi),
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// modulePath extracts the null-terminated ANSI path from a module info entry.
|
|
func modulePath(mi *windows.RTL_PROCESS_MODULE_INFORMATION) string {
|
|
b := mi.FullPathName[:]
|
|
n := 0
|
|
for n < len(b) && b[n] != 0 {
|
|
n++
|
|
}
|
|
return string(b[:n])
|
|
}
|
|
|
|
// FindModule returns the loaded module whose file name matches name
|
|
// (case-insensitive), or ok=false if it is not loaded.
|
|
func FindModule(name string) (Module, bool) {
|
|
mods, err := Modules()
|
|
if err != nil {
|
|
return Module{}, false
|
|
}
|
|
for _, m := range mods {
|
|
base := m.Path
|
|
if i := strings.LastIndexAny(base, `\/`); i >= 0 {
|
|
base = base[i+1:]
|
|
}
|
|
if strings.EqualFold(base, name) {
|
|
return m, true
|
|
}
|
|
}
|
|
return Module{}, false
|
|
}
|