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

Unified 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, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: syzygy/experimental/protect/protect_lib/integrity_check_transform.h
diff --git a/syzygy/experimental/protect/protect_lib/integrity_check_transform.h b/syzygy/experimental/protect/protect_lib/integrity_check_transform.h
new file mode 100644
index 0000000000000000000000000000000000000000..8755e06e55149b7aa40c561aee96467b94bcdda3
--- /dev/null
+++ b/syzygy/experimental/protect/protect_lib/integrity_check_transform.h
@@ -0,0 +1,372 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SYZYGY_PROTECT_PROTECT_LIB_INTEGRITY_CHECK_TRANSFORM_H_
+#define SYZYGY_PROTECT_PROTECT_LIB_INTEGRITY_CHECK_TRANSFORM_H_
+
+#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS 1
+
+#include "syzygy/block_graph/basic_block.h"
+#include "syzygy/block_graph/basic_block_subgraph.h"
+#include "syzygy/block_graph/block_graph.h"
+#include "syzygy/block_graph/transforms/named_transform.h"
+#include "syzygy/experimental/protect/protect_lib/protect_utils.h"
+
+namespace protect {
+
+class IntegrityCheckTransform
+ : public block_graph::transforms::
+ NamedBlockGraphTransformImpl<IntegrityCheckTransform> {
+ public:
+ typedef block_graph::BlockGraph BlockGraph;
+ typedef block_graph::BasicCodeBlock BasicCodeBlock;
+ typedef block_graph::BasicBlockSubGraph BasicBlockSubGraph;
+ typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
+
+ enum ProcessingType {
+ ADD_HASH_AND_RESPONSE,
+ PRECOMPUTE_HASHES,
+ INSERT_CHECKS,
+ COMPUTE_CHUNKS,
+ INSERT_CHUNK_CHECKS,
+ PATCH_REFERENCES_SIZES,
+ PATCH_PIVOT
+ };
+
+ enum ReferenceLabelType {
+ Original_Block_Chunk,
+ //Refers to a placeholder label that only after adding all integrity checks
+ //it will be determined
+ Integrity_Block_Chunk
+ };
+
+// The transform name.
+ static const char kTransformName[];
+
+// Constructor.
+ explicit IntegrityCheckTransform(FlummoxConfig* config) {
+ for (const std::string& target : config->target_set())
+ target_names_[target] = false;
+
+ this->chunk_checking_coverage = config->chunk_checking_coverage();
+ if (chunk_checking_coverage == 0.0f){
+ bool *pcc = config->perform_chunk_checks();
+ *pcc = false;
+ }
+ this->basic_block_sizes_ = config->basic_block_sizes();
+ this->checker_to_checkee_map_ = config->checker_to_checkee_map();
+ this->ic_block_chunk_index_map_ = config->ic_block_chunk_index_map();
+ this->ic_block_reference_free_chunks =
+ config->ic_block_reference_free_chunks();
+ this->ic_chunk_checker_to_checkee_map_ =
+ config->ic_chunk_checker_to_checkee_map();
+ this->id_to_label_ = config->id_to_label();
+ this->label_name_to_block_ = config->label_name_to_block();
+ this->nr_hashes_patched_ = config->nr_hashes_patched();
+ this->perform_chunk_checks_ = config->perform_chunk_checks();
+ this->precomputed_hashes_ = config->precomputed_hashes();
+ this->chunk_checking_coverage = config->chunk_checking_coverage();
+ }
+
+// This is the main body of the transform. The transform decomposes each
+// block into a subgraph, applies the series of transform and rebuilds the
+// subgraph into a block.
+//
+// @param policy The policy object restricting how the transform is applied.
+// @param block_graph the block graph being transformed.
+// @param header_block the block to process.
+// @returns true on success, false otherwise.
+ virtual bool TransformBlockGraph(const TransformPolicyInterface* policy,
+ BlockGraph* block_graph,
+ BlockGraph::Block* header_block) override;
+
+ ~IntegrityCheckTransform();
+
+ protected:
+ // Replaces the first basic block reference inside an instruction @p with a
+ // reference to a new block.
+ // @param inst_itr the instruction that contains the basic block reference.
+ // @param new_block the block to which the new reference should point to.
+ // @param new_offset the offset to which the new reference should have.
+ // @param use_new_block flag indicating whether the new_block should be used.
+ void PatchBlockReference(
+ block_graph::BasicBlock::Instructions::iterator inst_itr,
+ block_graph::BlockGraph::Block* new_block,
+ block_graph::BlockGraph::Offset new_offset,
+ bool use_new_block);
+
+// Constant value defining unique chunks should be selected in the chunk
+// combinator function
+ const bool kForceUniqueChunks = true;
+
+// Constant value defining the number of chunks within original block
+// that each checker must check
+ uint32_t num_chunks_per_block = 0;
+
+ bool* perform_chunk_checks_;
+ float chunk_checking_coverage =1.0f;
+
+ // Creates a label to block map for all blocks in block graph @p.
+ void GenerateLabelToBlockMap(BlockGraph *bgraph);
+
+// Update label to block map only with changes in the given block @p.
+ void UpdateLabelToBlockMap(BlockGraph::Block *block);
+
+// Computes and writes the Q matrix to an output file. Also generates
+// combinations of basic blocks such that references to absolute addresses
+// cancel out. Finally it picks a random basic block to dynamically check
+// if the combination of precomputed hashes matches the runtime hashes.
+ void GenerateBasicBlockCombinations();
+
+// Assigns random chunks(without absolute references) to basic blocks
+//@chunks_vector - input proccessed chunks for assignment
+//@assignment_map - output assigned chunks per basic block
+//@no_chunks_per_checker - defines the number of chunks
+// that being assigned to a checker
+//@force_all_chunk_checks - This removes selected chunks from the random list
+//so they cannot be picked more than once
+ std::map<uint64_t, std::set<uint32_t>> GenerateChunkCombinations(
+ const std::vector<ChunkInfo> chunks_vector,
+ const float chunk_coverage, const bool enforce_unique_chunks,
+ uint32_t *no_chunks_per_block);
+
+// Iterates over all blocks of the block graph and decomposes them into
+// basic block subgraphs, which are then processed individually according
+// to the step parameter. The file parameter is optionally used to store
+// results of the processing.
+ bool IntegrityCheckTransform::ProcessAllBlocks(
+ const TransformPolicyInterface* policy,
+ BlockGraph* block_graph,
+ IntegrityCheckTransform::ProcessingType step);
+
+
+// Adds the assembly code which performs the integrity check
+// @param bb - the basic block where the integrity check will be inserted
+// @param checked_bb - the basic block that is actually checked
+// @param offset_sizes a list of (offset, size) pairs that indicate at which
+// offset from the beginning of the BB and how many bytes to hash
+// @param hash the value of the precomputed code hash
+// @param placeholder_flag a flag indicating if we need to insert
+// a placeholder in this basic block or not
+ void AddIntegrityCheckCode(BasicCodeBlock* bb,
+ BasicBlockSubGraph* subgraph,
+ BlockGraph *block_graph);
+
+
+// Process the basic block subgraph inserting the hash function and the
+// integrity-checks
+// @param bgraph - block graph from where the subgraph was taken
+// @param subgraph - subgraph containing basic blocks we want to transform
+// @param modifyCode - flag that indicates whether the PE should be modified
+// @return - true if the transformation was successfull, false otherwise
+ bool TransformBasicBlockSubGraph(
+ BlockGraph* bgraph,
+ BasicBlockSubGraph* subgraph,
+ IntegrityCheckTransform::ProcessingType step);
+
+// Adds reference to address
+// @param bgraph - the block graph from where the subgraph was taken
+// @param block - block where to make the reference
+// @param offset - offset of reference in block
+// @return the block containing the response function
+ BlockGraph::Block* AddReference(BlockGraph* bgraph, int dll_id);
+
+// Adds vector index of a chunk into the chunk index map
+// this index map is useful in chunk patching, basically O(n) to O(log(n))
+// @param bb_id - basic block id where the chunk is located
+// @param chunk_index - index of the chunk within the basic block
+// @param vector_index - index of the chunk within the full chunks vector
+ void IntegrityCheckTransform::AddChunkIntoIndexMap(
+ const uint64_t bb_id,
+ const uint32_t chunk_index,
+ const uint32_t vector_index);
+
+// Iterates over instructions and places label over reference free
+// chunks. Appends discovered chunks references to
+// ic_block_reference_free_chunks
+// @bb_id - integrity checker block id
+// @bb_instruction - reference to basic block instruction set
+ void ComputeChunks(BasicCodeBlock* bb);
+// Retrieves the original block id that chunk is located in, this function
+// relies on the label_name_to_block_ map
+// @chunk - instruction chunk info to find its original block
+ uint64_t GetChunkOriginalBlockId(const ChunkInfo *chunk);
+
+// Selects chunks from the provided partition index from blocks different from
+// the checker block. It tries to use unique chunks, but if not enough chunks to
+// pick, it reuses the used chunks
+// @chunks_vector - vector of all chunks
+// @partition_indexes - the indexes that chunk can be selected from
+// (partitioning)
+// @num_picks - number of chunks to be picked
+// @checker_block_id - original block of the checker
+// @used - map of the used chunks
+ std::set<uint32_t> IntegrityCheckTransform:: PickChunks(
+ const std::vector<ChunkInfo> chunks_vector,
+ const std::vector<uint32_t> partition_indexes,
+ const uint32_t num_picks,
+ const uint64_t checker_block_id,
+ const std::vector<uint32_t>::iterator end_chunk_it,
+ std::vector<uint32_t>::iterator last_visited_chunk,
+ std::set<uint32_t> *unused_chunks);
+// Computes the hash that will be hard coded in the binary
+// @param bb - basic block for which we want to compute the hash
+// @param offset_sizes - list containing pairs of offsets and number of bytes
+// to hash by the hash function in order to obtain the same hash at runtime
+// @return - the hash value of the code
+ uint8_t PrecomputeHash(BasicCodeBlock* bb,
+ std::list<uint32_t> *offset_sizes,
+ BasicBlockSubGraph* subgraph);
+
+ // Retrieves the number of absolute references in the basic block indicated
+ // by @p. This coincides with its index in the partition map.
+ uint8_t IntegrityCheckTransform::GetPartitionKey(uint64_t bb_id);
+
+// Adds the assembly code which performs the chunk integrity check
+// @param bb - the basic block where the integrity check will be inserted
+// @param bgraph - block graph from where the subgraph was taken
+// @param subgraph - subgraph containing basic blocks we want to transform
+ bool AddChunkIntegrityCheckCode(
+ BasicCodeBlock* bb,
+ BasicBlockSubGraph* subgraph,
+ BlockGraph *block_graph);
+
+// Patches block references and sizes within the integrity checker assembly code
+// @param bb - the basic block where the patching will be done
+// @param bgraph - block graph from where the subgraph was taken
+// @param subgraph - subgraph containing basic blocks we want to transform
+ bool PatchBlockReferencesAndSizes(
+ BasicCodeBlock* bb,
+ BasicBlockSubGraph* subgraph,
+ BlockGraph *block_graph);
+
+// Updates the chunk's hash corresponding to the given inputs
+// with the value changes
+// @param bb - the basic block where the patching will be done
+// @param old_size - previous size value in included in the chunk
+// @param new_size - replacement size value for the chunk
+// @param chunk_bb_id - bb_id of the chunk
+// @param chunk_index - index of the chunk within the basic block
+ bool RecomputeXorChunks(
+ const uint64_t bb_id, const uint8_t old_size[], const uint8_t new_size[],
+ const uint64_t chunk_bb_id, const uint32_t chunk_index);
+
+// Randomly picks a basic block to check-the given tuple of basic blocks.
+// Outputs the id of the basic block that was picked.
+ bool RandomlySelectChecker(std::list<uint32_t> tuple_blocks,
+ uint64_t *checker_id);
+
+// Randomly assigns checkers to checkee tuples
+ void PopulateCheckMaps(std::set<uint64_t> part_block);
+
+// Checks if all basic blocks in the given map are protected by integrity
+// checks
+ bool AllBasicBlocksChecked(std::map<std::set<uint64_t>, int> checkOrder);
+
+// Fills in the partition key multiset with names of the references.
+// @param instr assembly instruction references to basic blocks.
+// @param partitionKey set to fill out.
+// @return true if the instruction has references, false otherwise.
+ bool PopulatePartitionKey(const block_graph::Instruction instr,
+ uint8_t *num_abs_references);
+
+// Reference to the block that begins the computation of code hashes
+ block_graph::BlockGraph::Block *hash_block_;
+
+// Reference to the block that begins the computation of code xor hashes
+ block_graph::BlockGraph::Block *xhash_block_;
+
+// Reference to the block where the call to the reponse function is
+ block_graph::BlockGraph::Block *response_block_;
+
+// Map of original custom basic block ID to a label
+ std::map<uint64_t, BlockGraph::Label>* id_to_label_;
+
+// Map holding partition of relocation affected blocks
+ std::map<uint8_t, std::set<uint64_t>> partition_map_;
+
+// Map holding precomputed hashes of original BB
+ std::map<uint64_t, uint32_t>* precomputed_hashes_;
+
+// Map from BB address to its size
+ std::map<uint64_t, uint32_t>* basic_block_sizes_;
+
+// Map containing the offset of the call to the hash function in the bb
+ std::map<uint64_t, uint32_t> basic_block_hash_call_offset_;
+
+// Map containing true if basic block has a refenrece to another block
+ std::map<uint64_t, bool> basic_block_has_ref_;
+
+// Map indicating which BB is checked by which other BBs
+ std::map<uint64_t, uint32_t> is_bb_checked_map_;
+
+// Map indicating which BBs will be hashed by the checker
+ std::map<uint64_t, std::map<uint64_t, int>>* checker_to_checkee_map_;
+
+// Vector indicating chunks within Integrity checker block without absolute
+// references
+ std::vector<ChunkInfo>* ic_block_reference_free_chunks;
+// Map for retrieveing chunk id(unit32) from bb_id + chunk_index
+// useful in patching bb chunks
+ std::map<uint64_t, uint32_t>* ic_block_chunk_index_map_;
+
+// Map< CheckerId, set < Chunk indexes > >
+ std::map<uint64_t, std::set<uint32_t>>* ic_chunk_checker_to_checkee_map_;
+
+// File where to put the Q matrix
+ FILE *prefile_;
+ FILE *pfile_;
+ FILE *insert_file_= NULL;
+ FILE *fix_file_;
+
+// TODO: remove vector of BBSGs
+ std::vector<block_graph::BasicBlockSubGraph*> subgraph_vector_;
+
+// Map of label name to the number of bytes all references to it should be
+// adjusted
+ std::map<BlockGraph::Label, uint32_t> adjust_label_by_offset_;
+
+// This attribute keeps track of the address range that should be protected
+// by integrity-checks
+ std::map<std::string, bool> target_names_;
+
+
+// Number of precomputed hash values which were patched
+ int* nr_hashes_patched_;
+
+ uint32_t num_no_chunk_patched_labels = 0;
+ uint32_t num_no_chunk_labels = 0;
+ uint32_t num_chunk_reference_labels = 0;
+ uint32_t num_chunk_reference_patched_labels = 0;
+
+ uint32_t num_xor_labels = 0;
+ uint32_t num_xor_patched_labels = 0;
+
+ uint32_t num_size_reference_labels = 0;
+ uint32_t num_size_reference_patched_labels = 0;
+
+ double elapsed_secs_in_patching_chunks = 0;
+
+// Map from ID of DLL to BlockReference
+ std::map<int, std::pair<uint32_t, size_t>> dll_id_to_block_reference_;
+
+ std::map<std::string, std::pair<BlockGraph::Block*, uint32_t>>*
+ label_name_to_block_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IntegrityCheckTransform);
+ };
+
+}// namespace protect
+
+#endif// SYZYGY_PROTECT_PROTECT_LIB_INTEGRITY_CHECK_TRANSFORM_H_

Powered by Google App Engine
This is Rietveld 408576698