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.
4 
5 #include "chrome/common/safe_browsing/binary_feature_extractor.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include "chrome/common/safe_browsing/mach_o_image_reader_mac.h"
11 #include "components/safe_browsing/core/proto/csd.pb.h"
12 
13 namespace safe_browsing {
14 
ExtractImageFeaturesFromData(const uint8_t * data,size_t data_size,ExtractHeadersOption options,ClientDownloadRequest_ImageHeaders * image_headers,google::protobuf::RepeatedPtrField<std::string> * signed_data)15 bool BinaryFeatureExtractor::ExtractImageFeaturesFromData(
16     const uint8_t* data, size_t data_size,
17     ExtractHeadersOption options,
18     ClientDownloadRequest_ImageHeaders* image_headers,
19     google::protobuf::RepeatedPtrField<std::string>* signed_data) {
20   MachOImageReader image_reader;
21   if (!image_reader.Initialize(data, data_size))
22     return false;
23 
24   // If the image is fat, get all its MachO images. Otherwise, just scan
25   // the thin image.
26   std::vector<MachOImageReader*> images;
27   if (image_reader.IsFat())
28     images = image_reader.GetFatImages();
29   else
30     images.push_back(&image_reader);
31 
32   for (auto* mach_o_reader : images) {
33     // Record the entire mach_header struct.
34     auto* mach_o_headers = image_headers->mutable_mach_o_headers()->Add();
35     if (mach_o_reader->Is64Bit()) {
36       const mach_header_64* header = mach_o_reader->GetMachHeader64();
37       mach_o_headers->set_mach_header(header, sizeof(*header));
38     } else {
39       const mach_header* header = mach_o_reader->GetMachHeader();
40       mach_o_headers->set_mach_header(header, sizeof(*header));
41     }
42 
43     // Store the load commands for the Mach-O binary.
44     auto* proto_load_commands = mach_o_headers->mutable_load_commands();
45     const std::vector<MachOImageReader::LoadCommand>& load_commands =
46         mach_o_reader->GetLoadCommands();
47     for (const auto& load_command : load_commands) {
48       auto* proto_load_command = proto_load_commands->Add();
49       proto_load_command->set_command_id(load_command.cmd());
50       proto_load_command->set_command(&load_command.data[0],
51                                       load_command.data.size());
52     }
53 
54     // Get the signature information.
55     if (signed_data) {
56       std::vector<uint8_t> code_signature;
57       if (mach_o_reader->GetCodeSignatureInfo(&code_signature)) {
58         signed_data->Add()->append(
59             reinterpret_cast<const char*>(&code_signature[0]),
60             code_signature.size());
61       }
62     }
63   }
64 
65   return true;
66 }
67 
68 }  // namespace safe_browsing
69