Chromium Code Reviews| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <set> | 11 #include <set> |
| 12 | 12 |
| 13 #include "base/i18n/streaming_utf8_validator.h" | 13 #include "base/i18n/streaming_utf8_validator.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "build/build_config.h" | |
| 16 #include "chrome/common/safe_browsing/archive_analyzer_results.h" | 17 #include "chrome/common/safe_browsing/archive_analyzer_results.h" |
| 17 #include "chrome/common/safe_browsing/binary_feature_extractor.h" | 18 #include "chrome/common/safe_browsing/binary_feature_extractor.h" |
| 18 #include "chrome/common/safe_browsing/download_protection_util.h" | 19 #include "chrome/common/safe_browsing/download_protection_util.h" |
| 19 #include "chrome/common/safe_browsing/file_type_policies.h" | 20 #include "chrome/common/safe_browsing/file_type_policies.h" |
| 21 #include "chrome/common/safe_browsing/mach_o_image_reader_mac.h" | |
|
Robert Sesek
2017/08/03 18:36:31
I think this will probably need to move after line
mortonm
2017/08/03 18:45:21
Done.
| |
| 20 #include "components/safe_browsing/csd.pb.h" | 22 #include "components/safe_browsing/csd.pb.h" |
| 21 #include "crypto/secure_hash.h" | 23 #include "crypto/secure_hash.h" |
| 22 #include "crypto/sha2.h" | 24 #include "crypto/sha2.h" |
| 23 #include "third_party/zlib/google/zip_reader.h" | 25 #include "third_party/zlib/google/zip_reader.h" |
| 24 | 26 |
| 27 #if defined(OS_MACOSX) | |
| 28 #include <mach-o/fat.h> | |
| 29 #include <mach-o/loader.h> | |
| 30 #endif // OS_MACOSX | |
| 31 | |
| 25 namespace safe_browsing { | 32 namespace safe_browsing { |
| 26 namespace zip_analyzer { | 33 namespace zip_analyzer { |
| 27 | 34 |
| 28 namespace { | 35 namespace { |
| 29 | 36 |
| 30 // A writer delegate that computes a SHA-256 hash digest over the data while | 37 // A writer delegate that computes a SHA-256 hash digest over the data while |
| 31 // writing it to a file. | 38 // writing it to a file. |
| 32 class HashingFileWriter : public zip::FileWriterDelegate { | 39 class HashingFileWriter : public zip::FileWriterDelegate { |
| 33 public: | 40 public: |
| 34 explicit HashingFileWriter(base::File* file); | 41 explicit HashingFileWriter(base::File* file); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 53 if (!zip::FileWriterDelegate::WriteBytes(data, num_bytes)) | 60 if (!zip::FileWriterDelegate::WriteBytes(data, num_bytes)) |
| 54 return false; | 61 return false; |
| 55 sha256_->Update(data, num_bytes); | 62 sha256_->Update(data, num_bytes); |
| 56 return true; | 63 return true; |
| 57 } | 64 } |
| 58 | 65 |
| 59 void HashingFileWriter::ComputeDigest(uint8_t* digest, size_t digest_length) { | 66 void HashingFileWriter::ComputeDigest(uint8_t* digest, size_t digest_length) { |
| 60 sha256_->Finish(digest, digest_length); | 67 sha256_->Finish(digest, digest_length); |
| 61 } | 68 } |
| 62 | 69 |
| 70 #if defined(OS_MACOSX) | |
| 71 bool StringIsMachOMagic(std::string bytes) { | |
| 72 if (bytes.length() < sizeof(uint32_t)) | |
| 73 return false; | |
| 74 | |
| 75 uint32_t magic; | |
| 76 memcpy(&magic, bytes.c_str(), sizeof(uint32_t)); | |
| 77 | |
| 78 return MachOImageReader::IsMachOMagicValue(magic); | |
| 79 } | |
| 80 #endif // OS_MACOSX | |
| 81 | |
| 63 void AnalyzeContainedFile( | 82 void AnalyzeContainedFile( |
| 64 const scoped_refptr<BinaryFeatureExtractor>& binary_feature_extractor, | 83 const scoped_refptr<BinaryFeatureExtractor>& binary_feature_extractor, |
| 65 const base::FilePath& file_path, | 84 const base::FilePath& file_path, |
| 66 zip::ZipReader* reader, | 85 zip::ZipReader* reader, |
| 67 base::File* temp_file, | 86 base::File* temp_file, |
| 68 ClientDownloadRequest::ArchivedBinary* archived_binary) { | 87 ClientDownloadRequest::ArchivedBinary* archived_binary) { |
| 69 std::string file_basename(file_path.BaseName().AsUTF8Unsafe()); | 88 std::string file_basename(file_path.BaseName().AsUTF8Unsafe()); |
| 70 if (base::StreamingUtf8Validator::Validate(file_basename)) | 89 if (base::StreamingUtf8Validator::Validate(file_basename)) |
| 71 archived_binary->set_file_basename(file_basename); | 90 archived_binary->set_file_basename(file_basename); |
| 72 archived_binary->set_download_type( | 91 archived_binary->set_download_type( |
| 73 download_protection_util::GetDownloadType(file_path)); | 92 download_protection_util::GetDownloadType(file_path)); |
| 74 archived_binary->set_length(reader->current_entry_info()->original_size()); | 93 archived_binary->set_length(reader->current_entry_info()->original_size()); |
| 75 HashingFileWriter writer(temp_file); | 94 HashingFileWriter writer(temp_file); |
| 76 if (reader->ExtractCurrentEntry(&writer)) { | 95 if (reader->ExtractCurrentEntry(&writer, |
| 96 std::numeric_limits<uint64_t>::max())) { | |
| 77 uint8_t digest[crypto::kSHA256Length]; | 97 uint8_t digest[crypto::kSHA256Length]; |
| 78 writer.ComputeDigest(&digest[0], arraysize(digest)); | 98 writer.ComputeDigest(&digest[0], arraysize(digest)); |
| 79 archived_binary->mutable_digests()->set_sha256(&digest[0], | 99 archived_binary->mutable_digests()->set_sha256(&digest[0], |
| 80 arraysize(digest)); | 100 arraysize(digest)); |
| 81 if (!binary_feature_extractor->ExtractImageFeaturesFromFile( | 101 if (!binary_feature_extractor->ExtractImageFeaturesFromFile( |
| 82 temp_file->Duplicate(), | 102 temp_file->Duplicate(), |
| 83 BinaryFeatureExtractor::kDefaultOptions, | 103 BinaryFeatureExtractor::kDefaultOptions, |
| 84 archived_binary->mutable_image_headers(), | 104 archived_binary->mutable_image_headers(), |
| 85 archived_binary->mutable_signature()->mutable_signed_data())) { | 105 archived_binary->mutable_signature()->mutable_signed_data())) { |
| 86 archived_binary->clear_image_headers(); | 106 archived_binary->clear_image_headers(); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 110 for (; reader.HasMore(); advanced = reader.AdvanceToNextEntry()) { | 130 for (; reader.HasMore(); advanced = reader.AdvanceToNextEntry()) { |
| 111 if (!advanced) { | 131 if (!advanced) { |
| 112 DVLOG(1) << "Could not advance to next entry, aborting zip scan."; | 132 DVLOG(1) << "Could not advance to next entry, aborting zip scan."; |
| 113 return; | 133 return; |
| 114 } | 134 } |
| 115 if (!reader.OpenCurrentEntryInZip()) { | 135 if (!reader.OpenCurrentEntryInZip()) { |
| 116 DVLOG(1) << "Failed to open current entry in zip file"; | 136 DVLOG(1) << "Failed to open current entry in zip file"; |
| 117 continue; | 137 continue; |
| 118 } | 138 } |
| 119 const base::FilePath& file = reader.current_entry_info()->file_path(); | 139 const base::FilePath& file = reader.current_entry_info()->file_path(); |
| 140 bool current_entry_is_executable; | |
| 141 #if defined(OS_MACOSX) | |
| 142 std::string magic; | |
| 143 reader.ExtractCurrentEntryToString(sizeof(uint32_t), &magic); | |
| 144 current_entry_is_executable = | |
| 145 FileTypePolicies::GetInstance()->IsCheckedBinaryFile(file) || | |
| 146 StringIsMachOMagic(magic); | |
| 147 #else | |
| 148 current_entry_is_executable = | |
| 149 FileTypePolicies::GetInstance()->IsCheckedBinaryFile(file); | |
| 150 #endif // OS_MACOSX | |
| 151 | |
| 120 if (FileTypePolicies::GetInstance()->IsArchiveFile(file)) { | 152 if (FileTypePolicies::GetInstance()->IsArchiveFile(file)) { |
| 121 DVLOG(2) << "Downloaded a zipped archive: " << file.value(); | 153 DVLOG(2) << "Downloaded a zipped archive: " << file.value(); |
| 122 results->has_archive = true; | 154 results->has_archive = true; |
| 123 archived_archive_filenames.insert(file.BaseName()); | 155 archived_archive_filenames.insert(file.BaseName()); |
| 124 ClientDownloadRequest::ArchivedBinary* archived_archive = | 156 ClientDownloadRequest::ArchivedBinary* archived_archive = |
| 125 results->archived_binary.Add(); | 157 results->archived_binary.Add(); |
| 126 std::string file_basename_utf8(file.BaseName().AsUTF8Unsafe()); | 158 std::string file_basename_utf8(file.BaseName().AsUTF8Unsafe()); |
| 127 if (base::StreamingUtf8Validator::Validate(file_basename_utf8)) | 159 if (base::StreamingUtf8Validator::Validate(file_basename_utf8)) |
| 128 archived_archive->set_file_basename(file_basename_utf8); | 160 archived_archive->set_file_basename(file_basename_utf8); |
| 129 archived_archive->set_download_type( | 161 archived_archive->set_download_type( |
| 130 ClientDownloadRequest::ZIPPED_ARCHIVE); | 162 ClientDownloadRequest::ZIPPED_ARCHIVE); |
| 131 } else if (FileTypePolicies::GetInstance()->IsCheckedBinaryFile(file)) { | 163 } else if (current_entry_is_executable) { |
| 132 DVLOG(2) << "Downloaded a zipped executable: " << file.value(); | 164 #if defined(OS_MACOSX) |
| 133 results->has_executable = true; | 165 // This check prevents running analysis on .app files since they are |
| 134 AnalyzeContainedFile(binary_feature_extractor, file, &reader, &temp_file, | 166 // really just directories and will cause binary feature extraction |
| 135 results->archived_binary.Add()); | 167 // to fail. |
| 168 if (file.Extension().compare(".app") == 0) { | |
| 169 DVLOG(2) << "Downloaded a zipped .app directory: " << file.value(); | |
| 170 } else { | |
| 171 #endif // OS_MACOSX | |
| 172 DVLOG(2) << "Downloaded a zipped executable: " << file.value(); | |
| 173 results->has_executable = true; | |
| 174 AnalyzeContainedFile(binary_feature_extractor, file, &reader, | |
| 175 &temp_file, results->archived_binary.Add()); | |
| 176 #if defined(OS_MACOSX) | |
| 177 } | |
| 178 #endif // OS_MACOSX | |
| 136 } else { | 179 } else { |
| 137 DVLOG(3) << "Ignoring non-binary file: " << file.value(); | 180 DVLOG(3) << "Ignoring non-binary file: " << file.value(); |
| 138 } | 181 } |
| 139 } | 182 } |
| 140 results->archived_archive_filenames.assign(archived_archive_filenames.begin(), | 183 results->archived_archive_filenames.assign(archived_archive_filenames.begin(), |
| 141 archived_archive_filenames.end()); | 184 archived_archive_filenames.end()); |
| 142 results->success = true; | 185 results->success = true; |
| 143 } | 186 } |
| 144 | 187 |
| 145 } // namespace zip_analyzer | 188 } // namespace zip_analyzer |
| 146 } // namespace safe_browsing | 189 } // namespace safe_browsing |
| OLD | NEW |