1 // Copyright 2015 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/sandboxed_zip_analyzer.h"
10 #include "base/bind_helpers.h"
11 #include "base/files/file_path.h"
12 #include "base/path_service.h"
13 #include "base/run_loop.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "chrome/common/safe_browsing/zip_analyzer_results.h"
16 #include "content/public/test/test_browser_thread_bundle.h"
17 #include "content/public/test/test_utils.h"
18 #include "crypto/sha2.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 namespace safe_browsing
{
23 class SandboxedZipAnalyzerTest
: public ::testing::Test
{
25 // Constants for validating the data reported by the analyzer.
27 const char* file_basename
;
28 ClientDownloadRequest_DownloadType download_type
;
29 const uint8_t* sha256_digest
;
34 // A helper that provides a SandboxedZipAnalyzer::ResultCallback that will
35 // store a copy of an analyzer's results and then run a closure.
38 ResultsGetter(const base::Closure
& quit_closure
,
39 zip_analyzer::Results
* results
)
40 : quit_closure_(quit_closure
),
43 results
->success
= false;
46 SandboxedZipAnalyzer::ResultCallback
GetCallback() {
47 return base::Bind(&ResultsGetter::OnZipAnalyzerResults
,
48 base::Unretained(this));
52 void OnZipAnalyzerResults(const zip_analyzer::Results
& results
) {
57 base::Closure quit_closure_
;
58 zip_analyzer::Results
* results_
;
59 DISALLOW_COPY_AND_ASSIGN(ResultsGetter
);
62 SandboxedZipAnalyzerTest()
63 : browser_thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
) {}
65 void SetUp() override
{
66 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &dir_test_data_
));
67 dir_test_data_
= dir_test_data_
.AppendASCII("safe_browsing");
68 dir_test_data_
= dir_test_data_
.AppendASCII("download_protection");
71 // Runs a sandboxed zip analyzer on |file_path|, writing its results into
73 void RunAnalyzer(const base::FilePath
& file_path
,
74 zip_analyzer::Results
* results
) {
76 base::RunLoop run_loop
;
77 ResultsGetter
results_getter(run_loop
.QuitClosure(), results
);
78 scoped_refptr
<SandboxedZipAnalyzer
> analyzer(
79 new SandboxedZipAnalyzer(file_path
, results_getter
.GetCallback()));
85 void ExpectPEHeaders(const BinaryData
& data
,
86 const ClientDownloadRequest_ArchivedBinary
& binary
) {
87 ASSERT_EQ(data
.is_signed
, binary
.has_signature());
89 ASSERT_LT(0, binary
.signature().signed_data_size());
90 ASSERT_NE(0U, binary
.signature().signed_data(0).size());
92 ASSERT_TRUE(binary
.has_image_headers());
93 ASSERT_TRUE(binary
.image_headers().has_pe_headers());
94 EXPECT_TRUE(binary
.image_headers().pe_headers().has_dos_header());
95 EXPECT_TRUE(binary
.image_headers().pe_headers().has_file_header());
96 EXPECT_TRUE(binary
.image_headers().pe_headers().has_optional_headers32());
97 EXPECT_FALSE(binary
.image_headers().pe_headers().has_optional_headers64());
101 // Verifies expectations about a binary found by the analyzer.
102 void ExpectBinary(const BinaryData
& data
,
103 const ClientDownloadRequest_ArchivedBinary
& binary
) {
104 ASSERT_TRUE(binary
.has_file_basename());
105 EXPECT_EQ(data
.file_basename
, binary
.file_basename());
106 ASSERT_TRUE(binary
.has_download_type());
107 EXPECT_EQ(data
.download_type
, binary
.download_type());
108 ASSERT_TRUE(binary
.has_digests());
109 ASSERT_TRUE(binary
.digests().has_sha256());
110 EXPECT_EQ(std::string(data
.sha256_digest
,
111 data
.sha256_digest
+ crypto::kSHA256Length
),
112 binary
.digests().sha256());
113 EXPECT_FALSE(binary
.digests().has_sha1());
114 EXPECT_FALSE(binary
.digests().has_md5());
115 ASSERT_TRUE(binary
.has_length());
116 EXPECT_EQ(data
.length
, binary
.length());
118 // ExtractImageFeatures only implemented for Windows, and only works on PE
120 if (binary
.file_basename().find(".exe") != std::string::npos
) {
121 ExpectPEHeaders(data
, binary
);
125 ASSERT_FALSE(binary
.has_signature());
126 ASSERT_FALSE(binary
.has_image_headers());
129 static const uint8_t kUnsignedDigest
[];
130 static const uint8_t kSignedDigest
[];
131 static const uint8_t kJSEFileDigest
[];
132 static const BinaryData kUnsignedExe
;
133 static const BinaryData kSignedExe
;
134 static const BinaryData kJSEFile
;
136 base::FilePath dir_test_data_
;
137 content::TestBrowserThreadBundle browser_thread_bundle_
;
138 content::InProcessUtilityThreadHelper utility_thread_helper_
;
142 const uint8_t SandboxedZipAnalyzerTest::kUnsignedDigest
[] = {
143 0x1e, 0x95, 0x4d, 0x9c, 0xe0, 0x38, 0x9e, 0x2b, 0xa7, 0x44, 0x72,
144 0x16, 0xf2, 0x17, 0x61, 0xf9, 0x8d, 0x1e, 0x65, 0x40, 0xc2, 0xab,
145 0xec, 0xdb, 0xec, 0xff, 0x57, 0x0e, 0x36, 0xc4, 0x93, 0xdb};
146 const uint8_t SandboxedZipAnalyzerTest::kSignedDigest
[] = {
147 0xe1, 0x1f, 0xfa, 0x0c, 0x9f, 0x25, 0x23, 0x44, 0x53, 0xa9, 0xed,
148 0xd1, 0xcb, 0x25, 0x1d, 0x46, 0x10, 0x7f, 0x34, 0xb5, 0x36, 0xad,
149 0x74, 0x64, 0x2a, 0x85, 0x84, 0xac, 0xa8, 0xc1, 0xa8, 0xce};
150 const uint8_t SandboxedZipAnalyzerTest::kJSEFileDigest
[] = {
151 0x58, 0x91, 0xb5, 0xb5, 0x22, 0xd5, 0xdf, 0x08, 0x6d, 0x0f, 0xf0,
152 0xb1, 0x10, 0xfb, 0xd9, 0xd2, 0x1b, 0xb4, 0xfc, 0x71, 0x63, 0xaf,
153 0x34, 0xd0, 0x82, 0x86, 0xa2, 0xe8, 0x46, 0xf6, 0xbe, 0x03};
154 const SandboxedZipAnalyzerTest::BinaryData
155 SandboxedZipAnalyzerTest::kUnsignedExe
= {
157 ClientDownloadRequest_DownloadType_WIN_EXECUTABLE
,
162 const SandboxedZipAnalyzerTest::BinaryData
163 SandboxedZipAnalyzerTest::kSignedExe
= {
165 ClientDownloadRequest_DownloadType_WIN_EXECUTABLE
,
170 const SandboxedZipAnalyzerTest::BinaryData
SandboxedZipAnalyzerTest::kJSEFile
=
173 ClientDownloadRequest_DownloadType_WIN_EXECUTABLE
,
179 TEST_F(SandboxedZipAnalyzerTest
, NoBinaries
) {
180 zip_analyzer::Results results
;
181 RunAnalyzer(dir_test_data_
.AppendASCII("zipfile_no_binaries.zip"), &results
);
182 ASSERT_TRUE(results
.success
);
183 EXPECT_FALSE(results
.has_executable
);
184 EXPECT_FALSE(results
.has_archive
);
185 EXPECT_EQ(0, results
.archived_binary
.size());
188 TEST_F(SandboxedZipAnalyzerTest
, OneUnsignedBinary
) {
189 zip_analyzer::Results results
;
190 RunAnalyzer(dir_test_data_
.AppendASCII("zipfile_one_unsigned_binary.zip"),
192 ASSERT_TRUE(results
.success
);
193 EXPECT_TRUE(results
.has_executable
);
194 EXPECT_FALSE(results
.has_archive
);
195 ASSERT_EQ(1, results
.archived_binary
.size());
196 ExpectBinary(kUnsignedExe
, results
.archived_binary
.Get(0));
199 TEST_F(SandboxedZipAnalyzerTest
, TwoBinariesOneSigned
) {
200 zip_analyzer::Results results
;
201 RunAnalyzer(dir_test_data_
.AppendASCII("zipfile_two_binaries_one_signed.zip"),
203 ASSERT_TRUE(results
.success
);
204 EXPECT_TRUE(results
.has_executable
);
205 EXPECT_FALSE(results
.has_archive
);
206 ASSERT_EQ(2, results
.archived_binary
.size());
207 ExpectBinary(kUnsignedExe
, results
.archived_binary
.Get(0));
208 ExpectBinary(kSignedExe
, results
.archived_binary
.Get(1));
211 TEST_F(SandboxedZipAnalyzerTest
, ZippedArchiveNoBinaries
) {
212 zip_analyzer::Results results
;
213 RunAnalyzer(dir_test_data_
.AppendASCII("zipfile_archive_no_binaries.zip"),
215 ASSERT_TRUE(results
.success
);
216 EXPECT_FALSE(results
.has_executable
);
217 EXPECT_TRUE(results
.has_archive
);
218 EXPECT_EQ(0, results
.archived_binary
.size());
219 ASSERT_EQ(1u, results
.archived_archive_filetypes
.size());
220 EXPECT_EQ(FILE_PATH_LITERAL(".zip"), results
.archived_archive_filetypes
[0]);
223 TEST_F(SandboxedZipAnalyzerTest
, ZippedRarArchiveNoBinaries
) {
224 zip_analyzer::Results results
;
225 RunAnalyzer(dir_test_data_
.AppendASCII("zipfile_rar_archive_no_binaries.zip"),
227 ASSERT_TRUE(results
.success
);
228 EXPECT_FALSE(results
.has_executable
);
229 EXPECT_TRUE(results
.has_archive
);
230 EXPECT_EQ(0, results
.archived_binary
.size());
231 ASSERT_EQ(1u, results
.archived_archive_filetypes
.size());
232 EXPECT_EQ(FILE_PATH_LITERAL(".rar"), results
.archived_archive_filetypes
[0]);
235 TEST_F(SandboxedZipAnalyzerTest
, ZippedArchiveAndBinaries
) {
236 zip_analyzer::Results results
;
237 RunAnalyzer(dir_test_data_
.AppendASCII("zipfile_archive_and_binaries.zip"),
239 ASSERT_TRUE(results
.success
);
240 EXPECT_TRUE(results
.has_executable
);
241 EXPECT_TRUE(results
.has_archive
);
242 ASSERT_EQ(1, results
.archived_binary
.size());
243 ExpectBinary(kSignedExe
, results
.archived_binary
.Get(0));
244 ASSERT_EQ(1u, results
.archived_archive_filetypes
.size());
245 EXPECT_EQ(FILE_PATH_LITERAL(".7z"), results
.archived_archive_filetypes
[0]);
248 TEST_F(SandboxedZipAnalyzerTest
, ZippedJSEFile
) {
249 zip_analyzer::Results results
;
250 RunAnalyzer(dir_test_data_
.AppendASCII("zipfile_one_jse_file.zip"), &results
);
251 ASSERT_TRUE(results
.success
);
252 EXPECT_TRUE(results
.has_executable
);
253 EXPECT_FALSE(results
.has_archive
);
254 ASSERT_EQ(1, results
.archived_binary
.size());
255 ExpectBinary(kJSEFile
, results
.archived_binary
.Get(0));
256 EXPECT_TRUE(results
.archived_archive_filetypes
.empty());
259 } // namespace safe_browsing