Skip to content

Instantly share code, notes, and snippets.

@heaths
Last active April 19, 2023 00:28
Show Gist options
  • Save heaths/ebbca7d956f0b42bbb33193f0837e272 to your computer and use it in GitHub Desktop.
Save heaths/ebbca7d956f0b42bbb33193f0837e272 to your computer and use it in GitHub Desktop.
Check Authenticode signature on Windows with Go
//go:build windows
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type WTD_UI uint32
type WTD_REVOKE uint32
type WTD_CHOICE uint32
type WTD_STATEACTION uint32
type WTD_FLAGS uint32
type WTD_UICONTEXT uint32
const (
INVALID_HANDLE_VALUE syscall.Handle = syscall.Handle(1<<(unsafe.Sizeof(uintptr(0))*8-1)<<1 - 1)
WTD_UI_NONE WTD_UI = 2
WTD_REVOKE_NONE WTD_REVOKE = 0
WTD_REVOKE_WHOLECHAIN WTD_REVOKE = 1
WTD_CHOICE_FILE WTD_CHOICE = 1
WTD_STATEACTION_VERIFY WTD_STATEACTION = 1
WTD_STATEACTION_CLOSE WTD_STATEACTION = 2
WTD_REVOCATION_CHECK_NONE WTD_FLAGS = 16
WTD_REVOCATION_CHECK_CHAIN WTD_FLAGS = 64
WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT WTD_FLAGS = 128
WTD_CACHE_ONLY_URL_RETRIEVAL WTD_FLAGS = 4096
WTD_UICONTEXT_EXECUTE WTD_UICONTEXT = 0
WTD_UICONTEXT_INSTALL WTD_UICONTEXT = 1
)
var (
WINTRUST_ACTION_GENERIC_VERIFY_V2 = syscall.GUID{
Data1: 0xaac56b,
Data2: 0xcd44,
Data3: 0x11d0,
Data4: [8]byte{0x8c, 0xc2, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee},
}
modwintrust = windows.NewLazySystemDLL("wintrust.dll")
procWinVerifyTrust = modwintrust.NewProc("WinVerifyTrust")
)
type WinTrustData struct {
cbStruct uint32
pPolicyCallbackData uintptr
pSIPClientData uintptr
dwUIChoice WTD_UI
fdwRevocationChecks WTD_REVOKE
dwUnionChoice WTD_CHOICE
pFile *WINTRUST_FILE_INFO
dwStateAction WTD_STATEACTION
hWVTStateData syscall.Handle
pwszURLReference *uint16
dwProvFlags WTD_FLAGS
dwUIContext WTD_UICONTEXT
}
type WINTRUST_FILE_INFO struct {
cbStruct uint32
pcwszFilePath *uint16
hFile syscall.Handle
pgKnownSubject *syscall.GUID
}
func WinVerifyTrust(
hwnd syscall.Handle,
pgActionID *syscall.GUID,
pWVTData *WinTrustData,
) error {
r1, _, err := syscall.SyscallN(
procWinVerifyTrust.Addr(),
uintptr(hwnd),
uintptr(unsafe.Pointer(pgActionID)),
uintptr(unsafe.Pointer(pWVTData)),
)
if r1 != uintptr(windows.ERROR_SUCCESS) {
return err
}
return nil
}
func main() {
checkRevocation := flag.Bool("check-revocation", false, "Check revocation from the local cache")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Verify the Authenticode signature of a file\n\n")
fmt.Fprintf(os.Stderr, "Usage of %s:\n\b", os.Args[0])
fmt.Fprintf(os.Stderr, " %s [flags] path\n\n", filepath.Base(os.Args[0]))
fmt.Fprintf(os.Stderr, "Arguments\n")
fmt.Fprintf(os.Stderr, " path\n")
fmt.Fprintf(os.Stderr, " Path of the file to verify\n")
fmt.Fprintln(os.Stderr)
fmt.Fprintf(os.Stderr, "Flags:\n")
flag.PrintDefaults()
}
flag.Parse()
path := flag.Arg(0)
if path == "" {
log.Fatal("requires path to verify")
}
wtd, err := NewWinTrustFileData(path, *checkRevocation)
if err != nil {
log.Fatal(err)
}
defer wtd.Close()
err = WinVerifyTrust(INVALID_HANDLE_VALUE, &WINTRUST_ACTION_GENERIC_VERIFY_V2, wtd)
if err != nil {
log.Fatalf("failed to verify %s: %s", path, err)
}
fmt.Printf("%q is valid\n", path)
}
func NewWinTrustFileData(path string, checkRevocation bool) (*WinTrustData, error) {
var err error
fileInfo := new(WINTRUST_FILE_INFO)
fileInfo.cbStruct = uint32(unsafe.Sizeof(*fileInfo))
fileInfo.pcwszFilePath, err = syscall.UTF16PtrFromString(path)
if err != nil {
return nil, err
}
wtd := new(WinTrustData)
wtd.cbStruct = uint32(unsafe.Sizeof(*wtd))
wtd.dwUIChoice = WTD_UI_NONE
wtd.fdwRevocationChecks = WTD_REVOKE_NONE
wtd.dwUnionChoice = WTD_CHOICE_FILE
wtd.dwStateAction = WTD_STATEACTION_VERIFY
wtd.pFile = fileInfo
if checkRevocation {
wtd.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL
} else {
wtd.dwProvFlags = WTD_REVOCATION_CHECK_NONE
}
return wtd, nil
}
func (wtd *WinTrustData) Close() {
wtd.dwStateAction = WTD_STATEACTION_CLOSE
WinVerifyTrust(INVALID_HANDLE_VALUE, &WINTRUST_ACTION_GENERIC_VERIFY_V2, wtd)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment