1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares a class that allows for the normalization of a PE file and its
16 : // corresponding PDB file.
17 : //
18 : // TODO(chrisha): This currently works in-place only, but should be extended to
19 : // work to a new destination as well.
20 :
21 : #ifndef SYZYGY_ZAP_TIMESTAMP_ZAP_TIMESTAMP_H_
22 : #define SYZYGY_ZAP_TIMESTAMP_ZAP_TIMESTAMP_H_
23 :
24 : #include <vector>
25 :
26 : #include "base/string_piece.h"
27 : #include "base/files/file_path.h"
28 : #include "syzygy/block_graph/block_graph.h"
29 : #include "syzygy/common/application.h"
30 : #include "syzygy/core/address_space.h"
31 : #include "syzygy/pdb/pdb_file.h"
32 : #include "syzygy/pe/image_layout.h"
33 : #include "syzygy/pe/pe_file.h"
34 :
35 : namespace zap_timestamp {
36 :
37 : // Utility class for normalizing a PE file and the matching PDB file. They vary
38 : // largely in terms of timestamps and hash values, hence the name of the class.
39 : class ZapTimestamp {
40 : public:
41 : ZapTimestamp();
42 :
43 : // Prepares for modifying the given PE file. Tracks down all of the bytes
44 : // to be modified and prepares the new values to be stored. Searches for the
45 : // matching PDB file and does the same thing with it.
46 : // @param pe_path path to the PE file to be zapped.
47 : // @returns true on success, false otherwise.
48 : bool Init(const base::FilePath& pe_path);
49 :
50 : // Prepares for modifying the given PE file. Tracks down all of the bytes
51 : // to be modified and prepares the new values to be stored.
52 : // @param pe_path path to the PE file to be zapped.
53 : // @param pdb_path path the PDB file to be zapped.
54 : // @returns true on success, false otherwise.
55 : bool Init(const base::FilePath& pe_path, const base::FilePath& pdb_path);
56 :
57 : // Modifies the given PE file in place, as well as its associated PDB file.
58 : // @param modify_pe if true then the PE file will be updated in place.
59 : // @param modify_pdb if true then the PDB file will be updated in place.
60 : // @returns true on success, false on failure.
61 : // @pre Init has been successfully called.
62 : bool Zap(bool modify_pe, bool modify_pdb);
63 :
64 : // @name Accessors.
65 : // @{
66 : const base::FilePath& pe_path() const { return pe_path_; }
67 E : const base::FilePath& pdb_path() const { return pdb_path_; }
68 : // @}
69 :
70 : // Forward declarations. These are public so they can be used by anonymous
71 : // helper functions in zap_timestamp.cc.
72 : struct PatchData;
73 : typedef core::AddressSpace<core::FileOffsetAddress, size_t, PatchData>
74 : PatchAddressSpace;
75 :
76 : private:
77 : // Ensures the PE file exists and is valid, and searches for the corresponding
78 : // PDB file. After this runs both pe_path_ and pdb_path_ are initialized and
79 : // point to valid corresponding files.
80 : bool ValidatePeAndPdbFiles();
81 :
82 : // Decomposes the PE file. After this is complete block_graph_, image_layout_
83 : // and pe_file_ and dos_header_block_ have been initialized.
84 : bool DecomposePeFile();
85 :
86 : // Paints the regions of the PE file that need to be modified.
87 : bool MarkPeFileRanges();
88 :
89 : // Calculates a PDB GUID using the non-changing parts of the PE file.
90 : bool CalculatePdbGuid();
91 :
92 : // Loads the PDB file and updates its in-memory representation.
93 : bool LoadAndUpdatePdbFile();
94 :
95 : // @{
96 : // These do the actual writing of the individual files.
97 : bool WritePeFile();
98 : bool WritePdbFile();
99 : // @}
100 :
101 : // Initialized by ValidatePeAndPdbFiles.
102 : base::FilePath pe_path_;
103 : base::FilePath pdb_path_;
104 :
105 : // Initialized by DecomposePeFile.
106 : block_graph::BlockGraph block_graph_;
107 : pe::ImageLayout image_layout_;
108 : pe::PEFile pe_file_;
109 : block_graph::BlockGraph::Block* dos_header_block_;
110 :
111 : // Populated by MarkPeFileRanges.
112 : PatchAddressSpace pe_file_addr_space_;
113 :
114 : // Populated by LoadPdbFile and modified by UpdatePdbFile.
115 : scoped_ptr<pdb::PdbFile> pdb_file_;
116 :
117 : // These house the new values to be written when the image is zapped.
118 : DWORD timestamp_data_;
119 : DWORD pdb_age_data_;
120 : GUID pdb_guid_data_;
121 :
122 : DISALLOW_COPY_AND_ASSIGN(ZapTimestamp);
123 : };
124 :
125 : // Used to keep track of data in the image that is to be changed, and the
126 : // new values to be written.
127 : struct ZapTimestamp::PatchData {
128 E : PatchData(const uint8* data, const base::StringPiece& name)
129 : : data(data) {
130 E : name.CopyToString(&this->name);
131 E : }
132 : const uint8* data;
133 : std::string name;
134 : };
135 :
136 : // The application class that actually runs ZapTimestamp.
137 : class ZapTimestampApp : public common::AppImplBase {
138 : public:
139 : ZapTimestampApp() : AppImplBase("Zap Timestamp") { }
140 :
141 : // @name Implementation of the AppImplbase interface.
142 : // @{
143 : bool ParseCommandLine(const CommandLine* command_line);
144 : int Run();
145 : // @}
146 :
147 : private:
148 : // The input modules to be zapped. Each one must be a PE file.
149 : std::vector<base::FilePath> input_modules_;
150 :
151 : DISALLOW_COPY_AND_ASSIGN(ZapTimestampApp);
152 : };
153 :
154 : } // namespace zap_timestamp
155 :
156 : #endif // SYZYGY_ZAP_TIMESTAMP_ZAP_TIMESTAMP_H_
|