github.com/saferwall/pe@v1.5.2/security_test.go (about) 1 // Copyright 2018 Saferwall. All rights reserved. 2 // Use of this source code is governed by Apache v2 license 3 // license that can be found in the LICENSE file. 4 5 package pe 6 7 import ( 8 "crypto/x509" 9 "fmt" 10 "reflect" 11 "runtime" 12 "testing" 13 "time" 14 ) 15 16 type TestSecurityEntry struct { 17 Header WinCertificate 18 Info CertInfo 19 Verified bool 20 SignatureValid bool 21 err error 22 } 23 24 func TestParseSecurityDirectory(t *testing.T) { 25 26 tests := []struct { 27 in string 28 out TestSecurityEntry 29 }{ 30 { 31 getAbsoluteFilePath("test/putty.exe"), 32 TestSecurityEntry{ 33 Header: WinCertificate{ 34 Length: 0x3D90, 35 Revision: 0x200, 36 CertificateType: 0x2, 37 }, 38 Info: CertInfo{ 39 Issuer: "GB, Greater Manchester, Salford, COMODO RSA Code Signing CA", 40 Subject: "GB, Cambridgeshire, Cambridge, Simon Tatham, Simon Tatham", 41 NotBefore: time.Date(2018, time.November, 13, 00, 00, 0, 0, time.UTC), 42 NotAfter: time.Date(2021, time.November, 8, 23, 59, 59, 0, time.UTC), 43 SerialNumber: "7c1118cbbadc95da3752c46e47a27438", 44 PublicKeyAlgorithm: x509.RSA, 45 SignatureAlgorithm: x509.SHA256WithRSA, 46 }, 47 Verified: true, 48 SignatureValid: true, 49 err: nil, 50 }, 51 }, 52 { 53 getAbsoluteFilePath("test/putty_modified.exe"), 54 TestSecurityEntry{ 55 Header: WinCertificate{ 56 Length: 0x3D90, 57 Revision: 0x200, 58 CertificateType: 0x2, 59 }, 60 Info: CertInfo{ 61 Issuer: "GB, Greater Manchester, Salford, COMODO RSA Code Signing CA", 62 Subject: "GB, Cambridgeshire, Cambridge, Simon Tatham, Simon Tatham", 63 NotBefore: time.Date(2018, time.November, 13, 00, 00, 0, 0, time.UTC), 64 NotAfter: time.Date(2021, time.November, 8, 23, 59, 59, 0, time.UTC), 65 SerialNumber: "7c1118cbbadc95da3752c46e47a27438", 66 PublicKeyAlgorithm: x509.RSA, 67 SignatureAlgorithm: x509.SHA256WithRSA, 68 }, 69 Verified: true, 70 SignatureValid: false, 71 err: nil, 72 }, 73 }, 74 { 75 getAbsoluteFilePath("test/579fd8a0385482fb4c789561a30b09f25671e86422f40ef5cca2036b28f99648"), 76 TestSecurityEntry{ 77 Header: WinCertificate{ 78 Length: 0x3488, 79 Revision: 0x200, 80 CertificateType: 0x2, 81 }, 82 Info: CertInfo{ 83 Issuer: "US, VeriSign Class 3 Code Signing 2010 CA", 84 Subject: "US, California, Mountain View, Symantec Corporation, Symantec Corporation", 85 NotBefore: time.Date(2016, time.December, 16, 00, 00, 0, 0, time.UTC), 86 NotAfter: time.Date(2017, time.December, 17, 23, 59, 59, 0, time.UTC), 87 SerialNumber: "0ebfea68d677b3e26cab41c33f3e69de", 88 PublicKeyAlgorithm: x509.RSA, 89 SignatureAlgorithm: x509.SHA1WithRSA, 90 }, 91 Verified: false, 92 SignatureValid: false, 93 err: nil, 94 }, 95 }, 96 97 { 98 getAbsoluteFilePath("test/00121dae38f26a33da2990987db58738c5a5966930126a42f606a3b40e014624"), 99 TestSecurityEntry{ 100 err: ErrSecurityDataDirInvalid, 101 }, 102 }, 103 } 104 105 for _, tt := range tests { 106 t.Run(tt.in, func(t *testing.T) { 107 ops := Options{Fast: true} 108 file, err := New(tt.in, &ops) 109 if err != nil { 110 t.Fatalf("New(%s) failed, reason: %v", tt.in, err) 111 } 112 113 err = file.Parse() 114 if err != nil { 115 t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err) 116 } 117 118 var va, size uint32 119 if file.Is64 { 120 oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64) 121 dirEntry := oh64.DataDirectory[ImageDirectoryEntryCertificate] 122 va = dirEntry.VirtualAddress 123 size = dirEntry.Size 124 } else { 125 oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32) 126 dirEntry := oh32.DataDirectory[ImageDirectoryEntryCertificate] 127 va = dirEntry.VirtualAddress 128 size = dirEntry.Size 129 } 130 131 err = file.parseSecurityDirectory(va, size) 132 if err != tt.out.err { 133 t.Fatalf("parseSecurityDirectory(%s) failed, reason: %v", tt.in, err) 134 } 135 136 got := file.Certificates 137 if tt.out.err == nil { 138 if !reflect.DeepEqual(got.Header, tt.out.Header) { 139 t.Fatalf("certificate header assertion failed, got %v, want %v", got.Header, tt.out.Header) 140 } 141 if !reflect.DeepEqual(got.Info, tt.out.Info) { 142 t.Fatalf("certificate info assertion failed, got %v, want %v", got.Info, tt.out.Info) 143 } 144 } 145 if tt.out.SignatureValid != got.SignatureValid { 146 t.Fatalf("signature verification failed, got %v, want %v", got.SignatureValid, tt.out.SignatureValid) 147 } 148 if runtime.GOOS == "linux" { 149 if tt.out.Verified != got.Verified { 150 t.Fatalf("certificate verification failed, got %v, want %v", got.Verified, tt.out.Verified) 151 } 152 } 153 }) 154 } 155 } 156 157 func TestAuthentihash(t *testing.T) { 158 159 tests := []struct { 160 in string 161 out string 162 }{ 163 {getAbsoluteFilePath("test/putty.exe"), 164 "8be7d65593b0fff2e8b29004640261b8a0d4fcc651a14cd0b8b702b7928f8ee0"}, 165 {getAbsoluteFilePath("test/mscorlib.dll"), 166 "a52bd7784efbf206dbda2db058f3928deaf15f6fedf2773affae56023e2f0edb"}, 167 {getAbsoluteFilePath("test/liblzo2-2.dll"), 168 "ae603480b92c7ea3feca164010d2594f9a5282f8b732ecaa0aca29f3225835f6"}, 169 {getAbsoluteFilePath("test/kernel32.dll"), 170 "595e4eb556587a1363ff297df9f354a377963ecac0bed19230992b9601426aae"}, 171 {getAbsoluteFilePath("test/mfc40u.dll"), 172 "5c8acdf9b2c7854c6b8e22e973d2fbae9c68fc22513d24c68c8e8010b1663e67"}, 173 {getAbsoluteFilePath("test/000057fd78f66e64e15f5070364c824a8923b6216bd8bcf6368857fb9674c483"), 174 ""}, 175 } 176 177 for _, tt := range tests { 178 t.Run(tt.in, func(t *testing.T) { 179 file, err := New(tt.in, &Options{}) 180 if err != nil { 181 t.Fatalf("New(%s) failed, reason: %v", tt.in, err) 182 } 183 err = file.Parse() 184 if err != nil { 185 t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err) 186 } 187 188 hash := file.Authentihash() 189 got := fmt.Sprintf("%x", hash) 190 if string(got) != tt.out { 191 t.Errorf("Authentihash(%s) got %v, want %v", tt.in, got, tt.out) 192 } 193 }) 194 } 195 }