v0.1 - initial commit
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
//go:build windows
|
||||
|
||||
package winpwn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// guid mirrors the Win32 GUID struct layout.
|
||||
type guid struct {
|
||||
Data1 uint32
|
||||
Data2 uint16
|
||||
Data3 uint16
|
||||
Data4 [8]byte
|
||||
}
|
||||
|
||||
// WINTRUST_ACTION_GENERIC_VERIFY_V2, from wintrust.h.
|
||||
var wintrustActionGenericVerifyV2 = guid{
|
||||
Data1: 0x00aac56b,
|
||||
Data2: 0xcd44,
|
||||
Data3: 0x11d0,
|
||||
Data4: [8]byte{0x8c, 0xc2, 0x00, 0xc0, 0x4f, 0xc2, 0x95, 0xee},
|
||||
}
|
||||
|
||||
// wintrustFileInfo mirrors WINTRUST_FILE_INFO (wintrust.h).
|
||||
type wintrustFileInfo struct {
|
||||
CbStruct uint32
|
||||
PcwszFilePath *uint16
|
||||
HFile windows.Handle
|
||||
PgKnownSubject *guid
|
||||
}
|
||||
|
||||
// wintrustData mirrors WINTRUST_DATA (wintrust.h). The struct is normally a
|
||||
// union of pFile/pCatalog/pBlob/pSgnr/pCert at the PFile position; we only
|
||||
// ever populate the file-info variant.
|
||||
type wintrustData struct {
|
||||
CbStruct uint32
|
||||
PPolicyCallbackData uintptr
|
||||
PSIPClientData uintptr
|
||||
DwUIChoice uint32
|
||||
FdwRevocationChecks uint32
|
||||
DwUnionChoice uint32
|
||||
PFile *wintrustFileInfo
|
||||
DwStateAction uint32
|
||||
HWVTStateData windows.Handle
|
||||
PwszURLReference *uint16
|
||||
DwProvFlags uint32
|
||||
DwUIContext uint32
|
||||
PSignatureSettings uintptr
|
||||
}
|
||||
|
||||
const (
|
||||
wtdUINone = 2
|
||||
wtdRevokeNone = 0
|
||||
wtdChoiceFile = 1
|
||||
|
||||
wtdStateActionVerify = 1
|
||||
wtdStateActionClose = 2
|
||||
|
||||
wtdSaferFlag = 0x00000100
|
||||
wtdCacheOnlyURLRetrieval = 0x00001000
|
||||
wtdDisableMD2MD4 = 0x00002000
|
||||
)
|
||||
|
||||
var (
|
||||
modWintrust = windows.NewLazySystemDLL("wintrust.dll")
|
||||
procWinVerifyTrust = modWintrust.NewProc("WinVerifyTrust")
|
||||
)
|
||||
|
||||
// VerifyAuthenticodeSignature asks the OS to validate the Authenticode
|
||||
// signature on path via WinVerifyTrust — a real cryptographic chain/hash
|
||||
// check, unlike CheckSecResult.AuthenticodeSigned which only checks whether
|
||||
// a signature directory is present in the PE at all. Revocation checking is
|
||||
// disabled, so this makes no network calls; it verifies the embedded
|
||||
// certificate chain and file hash only.
|
||||
//
|
||||
// Most Windows system binaries (System32) are catalog-signed (.cat files)
|
||||
// rather than embedded-signed and will report TRUST_E_NOSIGNATURE here even
|
||||
// though Windows itself trusts them — this function only validates an
|
||||
// Authenticode signature embedded directly in the PE.
|
||||
func VerifyAuthenticodeSignature(path string) (bool, error) {
|
||||
pathPtr, err := windows.UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
fileInfo := wintrustFileInfo{
|
||||
CbStruct: uint32(unsafe.Sizeof(wintrustFileInfo{})),
|
||||
PcwszFilePath: pathPtr,
|
||||
}
|
||||
|
||||
data := wintrustData{
|
||||
CbStruct: uint32(unsafe.Sizeof(wintrustData{})),
|
||||
DwUIChoice: wtdUINone,
|
||||
FdwRevocationChecks: wtdRevokeNone,
|
||||
DwUnionChoice: wtdChoiceFile,
|
||||
PFile: &fileInfo,
|
||||
DwStateAction: wtdStateActionVerify,
|
||||
DwProvFlags: wtdSaferFlag | wtdCacheOnlyURLRetrieval | wtdDisableMD2MD4,
|
||||
}
|
||||
|
||||
ret, _, _ := procWinVerifyTrust.Call(
|
||||
0, // hwnd: NULL, dwUIChoice already suppresses any UI
|
||||
uintptr(unsafe.Pointer(&wintrustActionGenericVerifyV2)),
|
||||
uintptr(unsafe.Pointer(&data)),
|
||||
)
|
||||
status := uint32(ret)
|
||||
|
||||
// WinVerifyTrust requires releasing the verification state it allocated,
|
||||
// regardless of the outcome above.
|
||||
data.DwStateAction = wtdStateActionClose
|
||||
procWinVerifyTrust.Call(
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&wintrustActionGenericVerifyV2)),
|
||||
uintptr(unsafe.Pointer(&data)),
|
||||
)
|
||||
|
||||
if status != 0 {
|
||||
return false, fmt.Errorf("WinVerifyTrust: signature not valid (status 0x%X)", status)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
Reference in New Issue
Block a user