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/browser/safe_browsing/binary_feature_extractor.h"
11 #include "base/files/file_path.h"
12 #include "base/files/memory_mapped_file.h"
13 #include "base/logging.h"
14 #include "chrome/browser/safe_browsing/pe_image_reader_win.h"
15 #include "chrome/common/safe_browsing/csd.pb.h"
17 #pragma comment(lib, "wintrust.lib")
19 namespace safe_browsing
{
21 BinaryFeatureExtractor::BinaryFeatureExtractor() {}
23 BinaryFeatureExtractor::~BinaryFeatureExtractor() {}
25 void BinaryFeatureExtractor::CheckSignature(
26 const base::FilePath
& file_path
,
27 ClientDownloadRequest_SignatureInfo
* signature_info
) {
28 VLOG(2) << "Checking signature for " << file_path
.value();
30 WINTRUST_FILE_INFO file_info
= {0};
31 file_info
.cbStruct
= sizeof(file_info
);
32 file_info
.pcwszFilePath
= file_path
.value().c_str();
33 file_info
.hFile
= NULL
;
34 file_info
.pgKnownSubject
= NULL
;
36 WINTRUST_DATA wintrust_data
= {0};
37 wintrust_data
.cbStruct
= sizeof(wintrust_data
);
38 wintrust_data
.pPolicyCallbackData
= NULL
;
39 wintrust_data
.pSIPClientData
= NULL
;
40 wintrust_data
.dwUIChoice
= WTD_UI_NONE
;
41 wintrust_data
.fdwRevocationChecks
= WTD_REVOKE_NONE
;
42 wintrust_data
.dwUnionChoice
= WTD_CHOICE_FILE
;
43 wintrust_data
.pFile
= &file_info
;
44 wintrust_data
.dwStateAction
= WTD_STATEACTION_VERIFY
;
45 wintrust_data
.hWVTStateData
= NULL
;
46 wintrust_data
.pwszURLReference
= NULL
;
47 // Disallow revocation checks over the network.
48 wintrust_data
.dwProvFlags
= WTD_CACHE_ONLY_URL_RETRIEVAL
;
49 wintrust_data
.dwUIContext
= WTD_UICONTEXT_EXECUTE
;
51 // The WINTRUST_ACTION_GENERIC_VERIFY_V2 policy verifies that the certificate
52 // chains up to a trusted root CA, and that it has appropriate permission to
54 GUID policy_guid
= WINTRUST_ACTION_GENERIC_VERIFY_V2
;
56 LONG result
= WinVerifyTrust(static_cast<HWND
>(INVALID_HANDLE_VALUE
),
60 CRYPT_PROVIDER_DATA
* prov_data
= WTHelperProvDataFromStateData(
61 wintrust_data
.hWVTStateData
);
63 if (prov_data
->csSigners
> 0) {
64 signature_info
->set_trusted(result
== ERROR_SUCCESS
);
66 for (DWORD i
= 0; i
< prov_data
->csSigners
; ++i
) {
67 const CERT_CHAIN_CONTEXT
* cert_chain_context
=
68 prov_data
->pasSigners
[i
].pChainContext
;
69 if (!cert_chain_context
)
71 for (DWORD j
= 0; j
< cert_chain_context
->cChain
; ++j
) {
72 CERT_SIMPLE_CHAIN
* simple_chain
= cert_chain_context
->rgpChain
[j
];
73 ClientDownloadRequest_CertificateChain
* chain
=
74 signature_info
->add_certificate_chain();
77 for (DWORD k
= 0; k
< simple_chain
->cElement
; ++k
) {
78 CERT_CHAIN_ELEMENT
* element
= simple_chain
->rgpElement
[k
];
79 chain
->add_element()->set_certificate(
80 element
->pCertContext
->pbCertEncoded
,
81 element
->pCertContext
->cbCertEncoded
);
86 // Free the provider data.
87 wintrust_data
.dwStateAction
= WTD_STATEACTION_CLOSE
;
88 WinVerifyTrust(static_cast<HWND
>(INVALID_HANDLE_VALUE
),
89 &policy_guid
, &wintrust_data
);
93 void BinaryFeatureExtractor::ExtractImageHeaders(
94 const base::FilePath
& file_path
,
95 ClientDownloadRequest_ImageHeaders
* image_headers
) {
96 // Map the file into memory.
97 base::MemoryMappedFile file
;
98 if (!file
.Initialize(file_path
))
101 PeImageReader pe_image
;
102 if (!pe_image
.Initialize(file
.data(), file
.length()))
106 ClientDownloadRequest_PEImageHeaders
* pe_headers
=
107 image_headers
->mutable_pe_headers();
108 pe_headers
->set_dos_header(pe_image
.GetDosHeader(), sizeof(IMAGE_DOS_HEADER
));
109 pe_headers
->set_file_header(pe_image
.GetCoffFileHeader(),
110 sizeof(IMAGE_FILE_HEADER
));
111 size_t optional_header_size
= 0;
112 const uint8_t* optional_header_data
=
113 pe_image
.GetOptionalHeaderData(&optional_header_size
);
114 if (pe_image
.GetWordSize() == PeImageReader::WORD_SIZE_32
) {
115 pe_headers
->set_optional_headers32(optional_header_data
,
116 optional_header_size
);
118 pe_headers
->set_optional_headers64(optional_header_data
,
119 optional_header_size
);
121 const size_t number_of_sections
= pe_image
.GetNumberOfSections();
122 for (size_t i
= 0; i
!= number_of_sections
; ++i
) {
123 pe_headers
->add_section_header(pe_image
.GetSectionHeaderAt(i
),
124 sizeof(IMAGE_SECTION_HEADER
));
126 size_t export_size
= 0;
127 const uint8_t* export_section
= pe_image
.GetExportSection(&export_size
);
129 pe_headers
->set_export_section_data(export_section
, export_size
);
130 size_t number_of_debug_entries
= pe_image
.GetNumberOfDebugEntries();
131 for (size_t i
= 0; i
!= number_of_debug_entries
; ++i
) {
132 const uint8_t* raw_data
= NULL
;
133 size_t raw_data_size
= 0;
134 const IMAGE_DEBUG_DIRECTORY
* directory_entry
=
135 pe_image
.GetDebugEntry(i
, &raw_data
, &raw_data_size
);
136 if (directory_entry
) {
137 ClientDownloadRequest_PEImageHeaders_DebugData
* debug_data
=
138 pe_headers
->add_debug_data();
139 debug_data
->set_directory_entry(directory_entry
,
140 sizeof(*directory_entry
));
142 debug_data
->set_raw_data(raw_data
, raw_data_size
);
147 } // namespace safe_browsing