OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/common/safe_browsing/zip_analyzer.h" | 5 #include "chrome/common/safe_browsing/zip_analyzer.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/macros.h" |
| 9 #include "chrome/common/safe_browsing/binary_feature_extractor.h" |
| 10 #include "chrome/common/safe_browsing/csd.pb.h" |
8 #include "chrome/common/safe_browsing/download_protection_util.h" | 11 #include "chrome/common/safe_browsing/download_protection_util.h" |
| 12 #include "chrome/common/safe_browsing/zip_analyzer_results.h" |
| 13 #include "crypto/secure_hash.h" |
| 14 #include "crypto/sha2.h" |
9 #include "third_party/zlib/google/zip_reader.h" | 15 #include "third_party/zlib/google/zip_reader.h" |
10 | 16 |
11 namespace safe_browsing { | 17 namespace safe_browsing { |
12 namespace zip_analyzer { | 18 namespace zip_analyzer { |
13 | 19 |
14 void AnalyzeZipFile(base::File zip_file, Results* results) { | 20 namespace { |
| 21 |
| 22 // A writer delegate that computes a SHA-256 hash digest over the data while |
| 23 // writing it to a file. |
| 24 class HashingFileWriter : public zip::FileWriterDelegate { |
| 25 public: |
| 26 explicit HashingFileWriter(base::File* file); |
| 27 |
| 28 // zip::FileWriterDelegate methods: |
| 29 bool WriteBytes(const char* data, int num_bytes) override; |
| 30 |
| 31 void ComputeDigest(uint8_t* digest, size_t digest_length); |
| 32 |
| 33 private: |
| 34 scoped_ptr<crypto::SecureHash> sha256_; |
| 35 |
| 36 DISALLOW_COPY_AND_ASSIGN(HashingFileWriter); |
| 37 }; |
| 38 |
| 39 HashingFileWriter::HashingFileWriter(base::File* file) |
| 40 : zip::FileWriterDelegate(file), |
| 41 sha256_(crypto::SecureHash::Create(crypto::SecureHash::SHA256)) { |
| 42 } |
| 43 |
| 44 bool HashingFileWriter::WriteBytes(const char* data, int num_bytes) { |
| 45 if (!zip::FileWriterDelegate::WriteBytes(data, num_bytes)) |
| 46 return false; |
| 47 sha256_->Update(data, num_bytes); |
| 48 return true; |
| 49 } |
| 50 |
| 51 void HashingFileWriter::ComputeDigest(uint8_t* digest, size_t digest_length) { |
| 52 sha256_->Finish(digest, digest_length); |
| 53 } |
| 54 |
| 55 void AnalyzeContainedFile( |
| 56 const scoped_refptr<BinaryFeatureExtractor>& binary_feature_extractor, |
| 57 const base::FilePath& file_path, |
| 58 zip::ZipReader* reader, |
| 59 base::File* temp_file, |
| 60 ClientDownloadRequest_ArchivedBinary* archived_binary) { |
| 61 archived_binary->set_file_basename(file_path.BaseName().AsUTF8Unsafe()); |
| 62 archived_binary->set_download_type( |
| 63 download_protection_util::GetDownloadType(file_path)); |
| 64 archived_binary->set_length(reader->current_entry_info()->original_size()); |
| 65 HashingFileWriter writer(temp_file); |
| 66 if (reader->ExtractCurrentEntry(&writer)) { |
| 67 uint8_t digest[crypto::kSHA256Length]; |
| 68 writer.ComputeDigest(&digest[0], arraysize(digest)); |
| 69 archived_binary->mutable_digests()->set_sha256(&digest[0], |
| 70 arraysize(digest)); |
| 71 if (!binary_feature_extractor->ExtractImageHeadersFromFile( |
| 72 temp_file->Duplicate(), |
| 73 BinaryFeatureExtractor::kDefaultOptions, |
| 74 archived_binary->mutable_image_headers())) { |
| 75 archived_binary->clear_image_headers(); |
| 76 } |
| 77 } |
| 78 } |
| 79 |
| 80 } // namespace |
| 81 |
| 82 void AnalyzeZipFile(base::File zip_file, |
| 83 base::File temp_file, |
| 84 Results* results) { |
| 85 scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor( |
| 86 new BinaryFeatureExtractor()); |
15 zip::ZipReader reader; | 87 zip::ZipReader reader; |
16 if (!reader.OpenFromPlatformFile(zip_file.GetPlatformFile())) { | 88 if (!reader.OpenFromPlatformFile(zip_file.GetPlatformFile())) { |
17 DVLOG(1) << "Failed to open zip file"; | 89 DVLOG(1) << "Failed to open zip file"; |
18 return; | 90 return; |
19 } | 91 } |
20 | 92 |
21 bool advanced = true; | 93 bool advanced = true; |
22 for (; reader.HasMore(); advanced = reader.AdvanceToNextEntry()) { | 94 for (; reader.HasMore(); advanced = reader.AdvanceToNextEntry()) { |
23 if (!advanced) { | 95 if (!advanced) { |
24 DVLOG(1) << "Could not advance to next entry, aborting zip scan."; | 96 DVLOG(1) << "Could not advance to next entry, aborting zip scan."; |
25 return; | 97 return; |
26 } | 98 } |
27 if (!reader.OpenCurrentEntryInZip()) { | 99 if (!reader.OpenCurrentEntryInZip()) { |
28 DVLOG(1) << "Failed to open current entry in zip file"; | 100 DVLOG(1) << "Failed to open current entry in zip file"; |
29 continue; | 101 continue; |
30 } | 102 } |
31 const base::FilePath& file = reader.current_entry_info()->file_path(); | 103 const base::FilePath& file = reader.current_entry_info()->file_path(); |
32 if (download_protection_util::IsBinaryFile(file)) { | 104 if (download_protection_util::IsBinaryFile(file)) { |
33 // Don't consider an archived archive to be executable, but record | 105 // Don't consider an archived archive to be executable, but record |
34 // a histogram. | 106 // a histogram. |
35 if (download_protection_util::IsArchiveFile(file)) { | 107 if (download_protection_util::IsArchiveFile(file)) { |
36 results->has_archive = true; | 108 results->has_archive = true; |
37 } else { | 109 } else { |
38 DVLOG(2) << "Downloaded a zipped executable: " << file.value(); | 110 DVLOG(2) << "Downloaded a zipped executable: " << file.value(); |
39 results->has_executable = true; | 111 results->has_executable = true; |
40 break; | 112 AnalyzeContainedFile(binary_feature_extractor, file, &reader, |
| 113 &temp_file, results->archived_binary.Add()); |
41 } | 114 } |
42 } else { | 115 } else { |
43 DVLOG(3) << "Ignoring non-binary file: " << file.value(); | 116 DVLOG(3) << "Ignoring non-binary file: " << file.value(); |
44 } | 117 } |
45 } | 118 } |
46 results->success = true; | 119 results->success = true; |
47 } | 120 } |
48 | 121 |
49 } // namespace zip_analyzer | 122 } // namespace zip_analyzer |
50 } // namespace safe_browsing | 123 } // namespace safe_browsing |
OLD | NEW |