Add ability to modify the similarity matrix to force matches
This commit is contained in:
@@ -15,7 +15,13 @@ from utils import HexIntParamType
|
|||||||
is_flag=True,
|
is_flag=True,
|
||||||
help="Prints a column of the similarity matrix given a new opcode",
|
help="Prints a column of the similarity matrix given a new opcode",
|
||||||
)
|
)
|
||||||
def debug_similarity_matrix(similarity_json_file, opcode, reverse):
|
@click.option(
|
||||||
|
"--accept",
|
||||||
|
default=None,
|
||||||
|
help="Modifies the similarity matrix file by accepting the match between the opcode argument and the argument to this option",
|
||||||
|
type=HexIntParamType(),
|
||||||
|
)
|
||||||
|
def debug_similarity_matrix(similarity_json_file, opcode, reverse, accept):
|
||||||
"""
|
"""
|
||||||
Given an old opcode, debug prints a row of the similarity matrix generated
|
Given an old opcode, debug prints a row of the similarity matrix generated
|
||||||
from generate_similarity_matrix.py.
|
from generate_similarity_matrix.py.
|
||||||
@@ -26,6 +32,12 @@ def debug_similarity_matrix(similarity_json_file, opcode, reverse):
|
|||||||
|
|
||||||
entries = dict()
|
entries = dict()
|
||||||
similarity = Similarity(similarity_json_file)
|
similarity = Similarity(similarity_json_file)
|
||||||
|
|
||||||
|
if accept is not None:
|
||||||
|
similarity.accept(opcode, accept)
|
||||||
|
similarity.write_to_file(similarity_json_file)
|
||||||
|
return
|
||||||
|
|
||||||
if reverse:
|
if reverse:
|
||||||
print("Checking column of matrix since --reverse was provided")
|
print("Checking column of matrix since --reverse was provided")
|
||||||
for old_opcode in similarity.old_opcodes:
|
for old_opcode in similarity.old_opcodes:
|
||||||
|
|||||||
@@ -99,6 +99,20 @@ def print_banner(text):
|
|||||||
print("")
|
print("")
|
||||||
|
|
||||||
|
|
||||||
|
def write_matrix_to_file(output_file, old_opcodes, new_opcodes, similarity_matrix):
|
||||||
|
with open(output_file, "w+") as f:
|
||||||
|
json.dump(
|
||||||
|
{
|
||||||
|
"old_opcodes": old_opcodes,
|
||||||
|
"new_opcodes": new_opcodes,
|
||||||
|
"matrix": similarity_matrix,
|
||||||
|
},
|
||||||
|
f,
|
||||||
|
indent=4,
|
||||||
|
)
|
||||||
|
print_banner(f"Output written to {output_file}")
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.argument(
|
@click.argument(
|
||||||
"old_traces", type=click.Path(exists=True, file_okay=False, resolve_path=True)
|
"old_traces", type=click.Path(exists=True, file_okay=False, resolve_path=True)
|
||||||
@@ -166,17 +180,7 @@ def generate_similarity_matrix(old_traces, new_traces, output_file):
|
|||||||
csm, old_trace_data, new_trace_data
|
csm, old_trace_data, new_trace_data
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(output_file, "w+") as f:
|
write_matrix_to_file(output_file, old_opcodes, new_opcodes, similarity_matrix)
|
||||||
json.dump(
|
|
||||||
{
|
|
||||||
"old_opcodes": old_opcodes,
|
|
||||||
"new_opcodes": new_opcodes,
|
|
||||||
"matrix": similarity_matrix,
|
|
||||||
},
|
|
||||||
f,
|
|
||||||
indent=4,
|
|
||||||
)
|
|
||||||
print_banner(f"Output written to {output_file}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
+31
-1
@@ -4,6 +4,7 @@ import numpy as np
|
|||||||
|
|
||||||
from vtable_diff import extract_opcode_data
|
from vtable_diff import extract_opcode_data
|
||||||
from utils import eprint
|
from utils import eprint
|
||||||
|
from generate_similarity_matrix import write_matrix_to_file
|
||||||
|
|
||||||
|
|
||||||
def needleman_wunsch(old_seq, new_seq, similarity, gap_penalty):
|
def needleman_wunsch(old_seq, new_seq, similarity, gap_penalty):
|
||||||
@@ -103,6 +104,21 @@ class Similarity:
|
|||||||
j = self.new_opcodes[new_opcode]
|
j = self.new_opcodes[new_opcode]
|
||||||
return self.matrix[i][j]
|
return self.matrix[i][j]
|
||||||
|
|
||||||
|
def accept(self, old_opcode, new_opcode):
|
||||||
|
if old_opcode not in self.old_opcodes:
|
||||||
|
self.warnings.add(
|
||||||
|
f"WARNING: Could not find old opcode {hex(old_opcode)} in similarity matrix"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
if new_opcode not in self.new_opcodes:
|
||||||
|
self.warnings.add(
|
||||||
|
f"WARNING: Could not find new opcode {hex(new_opcode)} in similarity matrix"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
i = self.old_opcodes[old_opcode]
|
||||||
|
j = self.new_opcodes[new_opcode]
|
||||||
|
self.matrix[i][j] = 1
|
||||||
|
|
||||||
def get_confident_matches(self, threshold=0.1):
|
def get_confident_matches(self, threshold=0.1):
|
||||||
"""
|
"""
|
||||||
Returns matches in the form of [(old,new), ...] that are confidently
|
Returns matches in the form of [(old,new), ...] that are confidently
|
||||||
@@ -149,6 +165,14 @@ class Similarity:
|
|||||||
for warning in self.warnings:
|
for warning in self.warnings:
|
||||||
eprint(warning)
|
eprint(warning)
|
||||||
|
|
||||||
|
def write_to_file(self, output_file):
|
||||||
|
write_matrix_to_file(
|
||||||
|
output_file,
|
||||||
|
list(self.old_opcodes.keys()),
|
||||||
|
list(self.new_opcodes.keys()),
|
||||||
|
self.matrix.tolist(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.argument(
|
@click.argument(
|
||||||
@@ -220,7 +244,13 @@ def vtable_alignment(old_exe, new_exe, similarity_json_file):
|
|||||||
for old, new in alignment:
|
for old, new in alignment:
|
||||||
if old in matched_old and matched_old[old] != new:
|
if old in matched_old and matched_old[old] != new:
|
||||||
truth = matched_old[old]
|
truth = matched_old[old]
|
||||||
eprint(f"Mismatch detected! {hex(old)} => {hex(truth)}, got {hex(new)}")
|
mismatch_text = ""
|
||||||
|
if new is not None:
|
||||||
|
mismatch_text = hex(new)
|
||||||
|
|
||||||
|
eprint(
|
||||||
|
f"Mismatch detected! {hex(old)} => {hex(truth)}, got {mismatch_text}"
|
||||||
|
)
|
||||||
mismatched_old.add(old)
|
mismatched_old.add(old)
|
||||||
mismatched_new[truth] = Placeholder(old, truth)
|
mismatched_new[truth] = Placeholder(old, truth)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user