48 lines
1.4 KiB
Go
48 lines
1.4 KiB
Go
//go:build windows
|
|
|
|
package winpwn
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
// ImportedLibs returns the distinct DLLs listed in this PE's import table,
|
|
// each loaded into the current process (via LoadLibrary -- already-loaded
|
|
// system DLLs just hand back their existing mapping and a bumped refcount,
|
|
// which is immediately released again) to report its current live image
|
|
// base.
|
|
//
|
|
// This is useful on Windows specifically because a system DLL's base is
|
|
// randomized once per boot, not once per process: every process on the
|
|
// machine sees kernel32.dll/ntdll.dll/etc. at the same address until the
|
|
// next reboot. So the base reported here is a real, reusable value for
|
|
// planning an exploit against this machine -- not a property of some
|
|
// already-running target you'd otherwise have to leak from first.
|
|
func (p *PEFile) ImportedLibs() ([]ImportedLib, error) {
|
|
imports, err := p.ListImports()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
seen := make(map[string]bool, len(imports))
|
|
var out []ImportedLib
|
|
for _, im := range imports {
|
|
key := strings.ToLower(im.DLL)
|
|
if im.DLL == "" || seen[key] {
|
|
continue
|
|
}
|
|
seen[key] = true
|
|
|
|
h, err := windows.LoadLibrary(im.DLL)
|
|
if err != nil {
|
|
out = append(out, ImportedLib{Name: im.DLL, Err: err})
|
|
continue
|
|
}
|
|
out = append(out, ImportedLib{Name: im.DLL, Base: uint64(h)})
|
|
windows.FreeLibrary(h)
|
|
}
|
|
return out, nil
|
|
}
|