1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/common/safe_browsing/binary_feature_extractor.h"
11 #include "base/files/file_path.h"
12 #include "base/logging.h"
13 #include "chrome/common/safe_browsing/csd.pb.h"
14 #include "chrome/common/safe_browsing/pe_image_reader_win.h"
16 #pragma comment(lib, "wintrust.lib")
18 namespace safe_browsing
{
22 // An EnumCertificatesCallback that collects each SignedData blob.
23 bool OnCertificateEntry(uint16_t revision
,
24 uint16_t certificate_type
,
25 const uint8_t* certificate_data
,
26 size_t certificate_data_size
,
28 google::protobuf::RepeatedPtrField
<std::string
>* signed_data
=
29 reinterpret_cast<google::protobuf::RepeatedPtrField
<std::string
>*>(
32 if (revision
== WIN_CERT_REVISION_2_0
&&
33 certificate_type
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
34 signed_data
->Add()->assign(certificate_data
,
35 certificate_data
+ certificate_data_size
);
42 void BinaryFeatureExtractor::CheckSignature(
43 const base::FilePath
& file_path
,
44 ClientDownloadRequest_SignatureInfo
* signature_info
) {
45 DVLOG(2) << "Checking signature for " << file_path
.value();
47 WINTRUST_FILE_INFO file_info
= {0};
48 file_info
.cbStruct
= sizeof(file_info
);
49 file_info
.pcwszFilePath
= file_path
.value().c_str();
50 file_info
.hFile
= NULL
;
51 file_info
.pgKnownSubject
= NULL
;
53 WINTRUST_DATA wintrust_data
= {0};
54 wintrust_data
.cbStruct
= sizeof(wintrust_data
);
55 wintrust_data
.pPolicyCallbackData
= NULL
;
56 wintrust_data
.pSIPClientData
= NULL
;
57 wintrust_data
.dwUIChoice
= WTD_UI_NONE
;
58 wintrust_data
.fdwRevocationChecks
= WTD_REVOKE_NONE
;
59 wintrust_data
.dwUnionChoice
= WTD_CHOICE_FILE
;
60 wintrust_data
.pFile
= &file_info
;
61 wintrust_data
.dwStateAction
= WTD_STATEACTION_VERIFY
;
62 wintrust_data
.hWVTStateData
= NULL
;
63 wintrust_data
.pwszURLReference
= NULL
;
64 // Disallow revocation checks over the network.
65 wintrust_data
.dwProvFlags
= WTD_CACHE_ONLY_URL_RETRIEVAL
;
66 wintrust_data
.dwUIContext
= WTD_UICONTEXT_EXECUTE
;
68 // The WINTRUST_ACTION_GENERIC_VERIFY_V2 policy verifies that the certificate
69 // chains up to a trusted root CA, and that it has appropriate permission to
71 GUID policy_guid
= WINTRUST_ACTION_GENERIC_VERIFY_V2
;
73 LONG result
= WinVerifyTrust(static_cast<HWND
>(INVALID_HANDLE_VALUE
),
77 CRYPT_PROVIDER_DATA
* prov_data
= WTHelperProvDataFromStateData(
78 wintrust_data
.hWVTStateData
);
80 if (prov_data
->csSigners
> 0) {
81 signature_info
->set_trusted(result
== ERROR_SUCCESS
);
83 for (DWORD i
= 0; i
< prov_data
->csSigners
; ++i
) {
84 const CERT_CHAIN_CONTEXT
* cert_chain_context
=
85 prov_data
->pasSigners
[i
].pChainContext
;
86 if (!cert_chain_context
)
88 for (DWORD j
= 0; j
< cert_chain_context
->cChain
; ++j
) {
89 CERT_SIMPLE_CHAIN
* simple_chain
= cert_chain_context
->rgpChain
[j
];
90 ClientDownloadRequest_CertificateChain
* chain
=
91 signature_info
->add_certificate_chain();
94 for (DWORD k
= 0; k
< simple_chain
->cElement
; ++k
) {
95 CERT_CHAIN_ELEMENT
* element
= simple_chain
->rgpElement
[k
];
96 chain
->add_element()->set_certificate(
97 element
->pCertContext
->pbCertEncoded
,
98 element
->pCertContext
->cbCertEncoded
);
103 // Free the provider data.
104 wintrust_data
.dwStateAction
= WTD_STATEACTION_CLOSE
;
105 WinVerifyTrust(static_cast<HWND
>(INVALID_HANDLE_VALUE
),
106 &policy_guid
, &wintrust_data
);
110 bool BinaryFeatureExtractor::ExtractImageFeaturesFromData(
111 const uint8_t* data
, size_t data_size
,
112 ExtractHeadersOption options
,
113 ClientDownloadRequest_ImageHeaders
* image_headers
,
114 google::protobuf::RepeatedPtrField
<std::string
>* signed_data
) {
115 PeImageReader pe_image
;
116 if (!pe_image
.Initialize(data
, data_size
))
120 ClientDownloadRequest_PEImageHeaders
* pe_headers
=
121 image_headers
->mutable_pe_headers();
122 pe_headers
->set_dos_header(pe_image
.GetDosHeader(), sizeof(IMAGE_DOS_HEADER
));
123 pe_headers
->set_file_header(pe_image
.GetCoffFileHeader(),
124 sizeof(IMAGE_FILE_HEADER
));
125 size_t optional_header_size
= 0;
126 const uint8_t* optional_header_data
=
127 pe_image
.GetOptionalHeaderData(&optional_header_size
);
128 if (pe_image
.GetWordSize() == PeImageReader::WORD_SIZE_32
) {
129 pe_headers
->set_optional_headers32(optional_header_data
,
130 optional_header_size
);
132 pe_headers
->set_optional_headers64(optional_header_data
,
133 optional_header_size
);
135 const size_t number_of_sections
= pe_image
.GetNumberOfSections();
136 for (size_t i
= 0; i
!= number_of_sections
; ++i
) {
137 pe_headers
->add_section_header(pe_image
.GetSectionHeaderAt(i
),
138 sizeof(IMAGE_SECTION_HEADER
));
140 if (!(options
& BinaryFeatureExtractor::kOmitExports
)) {
141 size_t export_size
= 0;
142 const uint8_t* export_section
= pe_image
.GetExportSection(&export_size
);
144 pe_headers
->set_export_section_data(export_section
, export_size
);
146 size_t number_of_debug_entries
= pe_image
.GetNumberOfDebugEntries();
147 for (size_t i
= 0; i
!= number_of_debug_entries
; ++i
) {
148 const uint8_t* raw_data
= NULL
;
149 size_t raw_data_size
= 0;
150 const IMAGE_DEBUG_DIRECTORY
* directory_entry
=
151 pe_image
.GetDebugEntry(i
, &raw_data
, &raw_data_size
);
152 if (directory_entry
) {
153 ClientDownloadRequest_PEImageHeaders_DebugData
* debug_data
=
154 pe_headers
->add_debug_data();
155 debug_data
->set_directory_entry(directory_entry
,
156 sizeof(*directory_entry
));
158 debug_data
->set_raw_data(raw_data
, raw_data_size
);
163 pe_image
.EnumCertificates(&OnCertificateEntry
, signed_data
);
168 } // namespace safe_browsing