Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: syzygy/experimental/protect/protect_lib/integrity_check_transform.h

Issue 2535563002: Added all code for integrity check transform (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 #ifndef SYZYGY_PROTECT_PROTECT_LIB_INTEGRITY_CHECK_TRANSFORM_H_
16 #define SYZYGY_PROTECT_PROTECT_LIB_INTEGRITY_CHECK_TRANSFORM_H_
17
18 #define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS 1
19
20 #include "syzygy/block_graph/basic_block.h"
21 #include "syzygy/block_graph/basic_block_subgraph.h"
22 #include "syzygy/block_graph/block_graph.h"
23 #include "syzygy/block_graph/transforms/named_transform.h"
24 #include "syzygy/experimental/protect/protect_lib/protect_utils.h"
25
26 namespace protect {
27
28 class IntegrityCheckTransform
29 : public block_graph::transforms::
30 NamedBlockGraphTransformImpl<IntegrityCheckTransform> {
31 public:
32 typedef block_graph::BlockGraph BlockGraph;
33 typedef block_graph::BasicCodeBlock BasicCodeBlock;
34 typedef block_graph::BasicBlockSubGraph BasicBlockSubGraph;
35 typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
36
37 enum ProcessingType {
38 ADD_HASH_AND_RESPONSE,
39 PRECOMPUTE_HASHES,
40 INSERT_CHECKS,
41 COMPUTE_CHUNKS,
42 INSERT_CHUNK_CHECKS,
43 PATCH_REFERENCES_SIZES,
44 PATCH_PIVOT
45 };
46
47 enum ReferenceLabelType {
48 Original_Block_Chunk,
49 //Refers to a placeholder label that only after adding all integrity checks
50 //it will be determined
51 Integrity_Block_Chunk
52 };
53
54 // The transform name.
55 static const char kTransformName[];
56
57 // Constructor.
58 explicit IntegrityCheckTransform(FlummoxConfig* config) {
59 for (const std::string& target : config->target_set())
60 target_names_[target] = false;
61
62 this->chunk_checking_coverage = config->chunk_checking_coverage();
63 if (chunk_checking_coverage == 0.0f){
64 bool *pcc = config->perform_chunk_checks();
65 *pcc = false;
66 }
67 this->basic_block_sizes_ = config->basic_block_sizes();
68 this->checker_to_checkee_map_ = config->checker_to_checkee_map();
69 this->ic_block_chunk_index_map_ = config->ic_block_chunk_index_map();
70 this->ic_block_reference_free_chunks =
71 config->ic_block_reference_free_chunks();
72 this->ic_chunk_checker_to_checkee_map_ =
73 config->ic_chunk_checker_to_checkee_map();
74 this->id_to_label_ = config->id_to_label();
75 this->label_name_to_block_ = config->label_name_to_block();
76 this->nr_hashes_patched_ = config->nr_hashes_patched();
77 this->perform_chunk_checks_ = config->perform_chunk_checks();
78 this->precomputed_hashes_ = config->precomputed_hashes();
79 this->chunk_checking_coverage = config->chunk_checking_coverage();
80 }
81
82 // This is the main body of the transform. The transform decomposes each
83 // block into a subgraph, applies the series of transform and rebuilds the
84 // subgraph into a block.
85 //
86 // @param policy The policy object restricting how the transform is applied.
87 // @param block_graph the block graph being transformed.
88 // @param header_block the block to process.
89 // @returns true on success, false otherwise.
90 virtual bool TransformBlockGraph(const TransformPolicyInterface* policy,
91 BlockGraph* block_graph,
92 BlockGraph::Block* header_block) override;
93
94 ~IntegrityCheckTransform();
95
96 protected:
97 // Replaces the first basic block reference inside an instruction @p with a
98 // reference to a new block.
99 // @param inst_itr the instruction that contains the basic block reference.
100 // @param new_block the block to which the new reference should point to.
101 // @param new_offset the offset to which the new reference should have.
102 // @param use_new_block flag indicating whether the new_block should be used.
103 void PatchBlockReference(
104 block_graph::BasicBlock::Instructions::iterator inst_itr,
105 block_graph::BlockGraph::Block* new_block,
106 block_graph::BlockGraph::Offset new_offset,
107 bool use_new_block);
108
109 // Constant value defining unique chunks should be selected in the chunk
110 // combinator function
111 const bool kForceUniqueChunks = true;
112
113 // Constant value defining the number of chunks within original block
114 // that each checker must check
115 uint32_t num_chunks_per_block = 0;
116
117 bool* perform_chunk_checks_;
118 float chunk_checking_coverage =1.0f;
119
120 // Creates a label to block map for all blocks in block graph @p.
121 void GenerateLabelToBlockMap(BlockGraph *bgraph);
122
123 // Update label to block map only with changes in the given block @p.
124 void UpdateLabelToBlockMap(BlockGraph::Block *block);
125
126 // Computes and writes the Q matrix to an output file. Also generates
127 // combinations of basic blocks such that references to absolute addresses
128 // cancel out. Finally it picks a random basic block to dynamically check
129 // if the combination of precomputed hashes matches the runtime hashes.
130 void GenerateBasicBlockCombinations();
131
132 // Assigns random chunks(without absolute references) to basic blocks
133 //@chunks_vector - input proccessed chunks for assignment
134 //@assignment_map - output assigned chunks per basic block
135 //@no_chunks_per_checker - defines the number of chunks
136 // that being assigned to a checker
137 //@force_all_chunk_checks - This removes selected chunks from the random list
138 //so they cannot be picked more than once
139 std::map<uint64_t, std::set<uint32_t>> GenerateChunkCombinations(
140 const std::vector<ChunkInfo> chunks_vector,
141 const float chunk_coverage, const bool enforce_unique_chunks,
142 uint32_t *no_chunks_per_block);
143
144 // Iterates over all blocks of the block graph and decomposes them into
145 // basic block subgraphs, which are then processed individually according
146 // to the step parameter. The file parameter is optionally used to store
147 // results of the processing.
148 bool IntegrityCheckTransform::ProcessAllBlocks(
149 const TransformPolicyInterface* policy,
150 BlockGraph* block_graph,
151 IntegrityCheckTransform::ProcessingType step);
152
153
154 // Adds the assembly code which performs the integrity check
155 // @param bb - the basic block where the integrity check will be inserted
156 // @param checked_bb - the basic block that is actually checked
157 // @param offset_sizes a list of (offset, size) pairs that indicate at which
158 // offset from the beginning of the BB and how many bytes to hash
159 // @param hash the value of the precomputed code hash
160 // @param placeholder_flag a flag indicating if we need to insert
161 // a placeholder in this basic block or not
162 void AddIntegrityCheckCode(BasicCodeBlock* bb,
163 BasicBlockSubGraph* subgraph,
164 BlockGraph *block_graph);
165
166
167 // Process the basic block subgraph inserting the hash function and the
168 // integrity-checks
169 // @param bgraph - block graph from where the subgraph was taken
170 // @param subgraph - subgraph containing basic blocks we want to transform
171 // @param modifyCode - flag that indicates whether the PE should be modified
172 // @return - true if the transformation was successfull, false otherwise
173 bool TransformBasicBlockSubGraph(
174 BlockGraph* bgraph,
175 BasicBlockSubGraph* subgraph,
176 IntegrityCheckTransform::ProcessingType step);
177
178 // Adds reference to address
179 // @param bgraph - the block graph from where the subgraph was taken
180 // @param block - block where to make the reference
181 // @param offset - offset of reference in block
182 // @return the block containing the response function
183 BlockGraph::Block* AddReference(BlockGraph* bgraph, int dll_id);
184
185 // Adds vector index of a chunk into the chunk index map
186 // this index map is useful in chunk patching, basically O(n) to O(log(n))
187 // @param bb_id - basic block id where the chunk is located
188 // @param chunk_index - index of the chunk within the basic block
189 // @param vector_index - index of the chunk within the full chunks vector
190 void IntegrityCheckTransform::AddChunkIntoIndexMap(
191 const uint64_t bb_id,
192 const uint32_t chunk_index,
193 const uint32_t vector_index);
194
195 // Iterates over instructions and places label over reference free
196 // chunks. Appends discovered chunks references to
197 // ic_block_reference_free_chunks
198 // @bb_id - integrity checker block id
199 // @bb_instruction - reference to basic block instruction set
200 void ComputeChunks(BasicCodeBlock* bb);
201 // Retrieves the original block id that chunk is located in, this function
202 // relies on the label_name_to_block_ map
203 // @chunk - instruction chunk info to find its original block
204 uint64_t GetChunkOriginalBlockId(const ChunkInfo *chunk);
205
206 // Selects chunks from the provided partition index from blocks different from
207 // the checker block. It tries to use unique chunks, but if not enough chunks to
208 // pick, it reuses the used chunks
209 // @chunks_vector - vector of all chunks
210 // @partition_indexes - the indexes that chunk can be selected from
211 // (partitioning)
212 // @num_picks - number of chunks to be picked
213 // @checker_block_id - original block of the checker
214 // @used - map of the used chunks
215 std::set<uint32_t> IntegrityCheckTransform:: PickChunks(
216 const std::vector<ChunkInfo> chunks_vector,
217 const std::vector<uint32_t> partition_indexes,
218 const uint32_t num_picks,
219 const uint64_t checker_block_id,
220 const std::vector<uint32_t>::iterator end_chunk_it,
221 std::vector<uint32_t>::iterator last_visited_chunk,
222 std::set<uint32_t> *unused_chunks);
223 // Computes the hash that will be hard coded in the binary
224 // @param bb - basic block for which we want to compute the hash
225 // @param offset_sizes - list containing pairs of offsets and number of bytes
226 // to hash by the hash function in order to obtain the same hash at runtime
227 // @return - the hash value of the code
228 uint8_t PrecomputeHash(BasicCodeBlock* bb,
229 std::list<uint32_t> *offset_sizes,
230 BasicBlockSubGraph* subgraph);
231
232 // Retrieves the number of absolute references in the basic block indicated
233 // by @p. This coincides with its index in the partition map.
234 uint8_t IntegrityCheckTransform::GetPartitionKey(uint64_t bb_id);
235
236 // Adds the assembly code which performs the chunk integrity check
237 // @param bb - the basic block where the integrity check will be inserted
238 // @param bgraph - block graph from where the subgraph was taken
239 // @param subgraph - subgraph containing basic blocks we want to transform
240 bool AddChunkIntegrityCheckCode(
241 BasicCodeBlock* bb,
242 BasicBlockSubGraph* subgraph,
243 BlockGraph *block_graph);
244
245 // Patches block references and sizes within the integrity checker assembly code
246 // @param bb - the basic block where the patching will be done
247 // @param bgraph - block graph from where the subgraph was taken
248 // @param subgraph - subgraph containing basic blocks we want to transform
249 bool PatchBlockReferencesAndSizes(
250 BasicCodeBlock* bb,
251 BasicBlockSubGraph* subgraph,
252 BlockGraph *block_graph);
253
254 // Updates the chunk's hash corresponding to the given inputs
255 // with the value changes
256 // @param bb - the basic block where the patching will be done
257 // @param old_size - previous size value in included in the chunk
258 // @param new_size - replacement size value for the chunk
259 // @param chunk_bb_id - bb_id of the chunk
260 // @param chunk_index - index of the chunk within the basic block
261 bool RecomputeXorChunks(
262 const uint64_t bb_id, const uint8_t old_size[], const uint8_t new_size[],
263 const uint64_t chunk_bb_id, const uint32_t chunk_index);
264
265 // Randomly picks a basic block to check-the given tuple of basic blocks.
266 // Outputs the id of the basic block that was picked.
267 bool RandomlySelectChecker(std::list<uint32_t> tuple_blocks,
268 uint64_t *checker_id);
269
270 // Randomly assigns checkers to checkee tuples
271 void PopulateCheckMaps(std::set<uint64_t> part_block);
272
273 // Checks if all basic blocks in the given map are protected by integrity
274 // checks
275 bool AllBasicBlocksChecked(std::map<std::set<uint64_t>, int> checkOrder);
276
277 // Fills in the partition key multiset with names of the references.
278 // @param instr assembly instruction references to basic blocks.
279 // @param partitionKey set to fill out.
280 // @return true if the instruction has references, false otherwise.
281 bool PopulatePartitionKey(const block_graph::Instruction instr,
282 uint8_t *num_abs_references);
283
284 // Reference to the block that begins the computation of code hashes
285 block_graph::BlockGraph::Block *hash_block_;
286
287 // Reference to the block that begins the computation of code xor hashes
288 block_graph::BlockGraph::Block *xhash_block_;
289
290 // Reference to the block where the call to the reponse function is
291 block_graph::BlockGraph::Block *response_block_;
292
293 // Map of original custom basic block ID to a label
294 std::map<uint64_t, BlockGraph::Label>* id_to_label_;
295
296 // Map holding partition of relocation affected blocks
297 std::map<uint8_t, std::set<uint64_t>> partition_map_;
298
299 // Map holding precomputed hashes of original BB
300 std::map<uint64_t, uint32_t>* precomputed_hashes_;
301
302 // Map from BB address to its size
303 std::map<uint64_t, uint32_t>* basic_block_sizes_;
304
305 // Map containing the offset of the call to the hash function in the bb
306 std::map<uint64_t, uint32_t> basic_block_hash_call_offset_;
307
308 // Map containing true if basic block has a refenrece to another block
309 std::map<uint64_t, bool> basic_block_has_ref_;
310
311 // Map indicating which BB is checked by which other BBs
312 std::map<uint64_t, uint32_t> is_bb_checked_map_;
313
314 // Map indicating which BBs will be hashed by the checker
315 std::map<uint64_t, std::map<uint64_t, int>>* checker_to_checkee_map_;
316
317 // Vector indicating chunks within Integrity checker block without absolute
318 // references
319 std::vector<ChunkInfo>* ic_block_reference_free_chunks;
320 // Map for retrieveing chunk id(unit32) from bb_id + chunk_index
321 // useful in patching bb chunks
322 std::map<uint64_t, uint32_t>* ic_block_chunk_index_map_;
323
324 // Map< CheckerId, set < Chunk indexes > >
325 std::map<uint64_t, std::set<uint32_t>>* ic_chunk_checker_to_checkee_map_;
326
327 // File where to put the Q matrix
328 FILE *prefile_;
329 FILE *pfile_;
330 FILE *insert_file_= NULL;
331 FILE *fix_file_;
332
333 // TODO: remove vector of BBSGs
334 std::vector<block_graph::BasicBlockSubGraph*> subgraph_vector_;
335
336 // Map of label name to the number of bytes all references to it should be
337 // adjusted
338 std::map<BlockGraph::Label, uint32_t> adjust_label_by_offset_;
339
340 // This attribute keeps track of the address range that should be protected
341 // by integrity-checks
342 std::map<std::string, bool> target_names_;
343
344
345 // Number of precomputed hash values which were patched
346 int* nr_hashes_patched_;
347
348 uint32_t num_no_chunk_patched_labels = 0;
349 uint32_t num_no_chunk_labels = 0;
350 uint32_t num_chunk_reference_labels = 0;
351 uint32_t num_chunk_reference_patched_labels = 0;
352
353 uint32_t num_xor_labels = 0;
354 uint32_t num_xor_patched_labels = 0;
355
356 uint32_t num_size_reference_labels = 0;
357 uint32_t num_size_reference_patched_labels = 0;
358
359 double elapsed_secs_in_patching_chunks = 0;
360
361 // Map from ID of DLL to BlockReference
362 std::map<int, std::pair<uint32_t, size_t>> dll_id_to_block_reference_;
363
364 std::map<std::string, std::pair<BlockGraph::Block*, uint32_t>>*
365 label_name_to_block_;
366 private:
367 DISALLOW_COPY_AND_ASSIGN(IntegrityCheckTransform);
368 };
369
370 }// namespace protect
371
372 #endif// SYZYGY_PROTECT_PROTECT_LIB_INTEGRITY_CHECK_TRANSFORM_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698