From 3c5bdffd74d21f6c156730a91d3c78b59eb83b42 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 23 Aug 2018 21:46:30 +0200 Subject: Added binary diffing examples. --- misc/Makefile | 16 ++++ misc/elf2diff.c | 16 ++++ python/alla_net.py | 4 +- python/diffing_dex.py | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++ python/diffing_elf.py | 222 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 482 insertions(+), 2 deletions(-) create mode 100644 misc/Makefile create mode 100644 misc/elf2diff.c create mode 100644 python/diffing_dex.py create mode 100644 python/diffing_elf.py diff --git a/misc/Makefile b/misc/Makefile new file mode 100644 index 0000000..a087b0b --- /dev/null +++ b/misc/Makefile @@ -0,0 +1,16 @@ + +BINARIES=elf2diff1 elf2diff2 hole + +all: $(BINARIES) + +hole: hole.cpp + g++ -o $@ $< + +elf2diff1: elf2diff.c + arm-linux-gnueabi-gcc -o $@ -DNUMBER=1 $< + +elf2diff2: elf2diff.c + arm-linux-gnueabi-gcc -o $@ -DNUMBER=2 $< + +clean: + rm -f $(BINARIES) *~ diff --git a/misc/elf2diff.c b/misc/elf2diff.c new file mode 100644 index 0000000..1057d3c --- /dev/null +++ b/misc/elf2diff.c @@ -0,0 +1,16 @@ + +#include + +static void show_me(int n) +{ + printf("Hello World %d\n", n); + +} + +int main(void) +{ + show_me(NUMBER); + + return 0; + +} diff --git a/python/alla_net.py b/python/alla_net.py index 02c5f8d..78c0510 100644 --- a/python/alla_net.py +++ b/python/alla_net.py @@ -65,7 +65,7 @@ class NeuralNetwork(): self._o_error = y - o self._o_delta = self._o_error * self.sigmoidPrime(o) - # How much the hidden layer weights contributed to output error? + # How much the hidden layer weights contributed to output error? self._z2_error = self._o_delta.dot(self._w2.T) self._z2_delta = self._z2_error * self.sigmoidPrime(self._z2) @@ -215,7 +215,7 @@ class DeepLearning(): inputs.append( self._vectorize_string(raw) ) - outputs.append( [ 1.0 if encrypted else 0.1 ] ) + outputs.append( [ 1.0 if encrypted else 0.0 ] ) return inputs, outputs diff --git a/python/diffing_dex.py b/python/diffing_dex.py new file mode 100644 index 0000000..8eba15d --- /dev/null +++ b/python/diffing_dex.py @@ -0,0 +1,226 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +import argparse +import sys +import pychrysalide +from pychrysalide.analysis.contents import FileContent +from pychrysalide.analysis import LoadedBinary +from pychrysalide.analysis.diffing import BinDiff, FingerprintList +from pychrysalide.format.dex import DexFormat + + +def display_matches(matches, methods): + """Show the matching routines.""" + + routine_a_name_len = len('Routine A') + routine_a_addr_len = len('Phys addr.') + routine_b_name_len = len('Routine B') + routine_b_addr_len = len('Phys addr.') + + # Length computing + + for match in matches: + + routine_name = match['routine'].label + + if len(routine_name) > routine_a_name_len: + routine_a_name_len = len(routine_name) + + phys = '0x%x' % match['routine'].range.addr.phys + + if len(phys) > routine_a_addr_len: + routine_a_addr_len = len(phys) + + matching = match['matching'] + + for i in range(len(matching)): + + routine_name = matching[i]['other'].label + + if len(routine_name) > routine_b_name_len: + routine_b_name_len = len(routine_name) + + phys = '0x%x' % matching[i]['other'].range.addr.phys + + if len(phys) > routine_b_addr_len: + routine_b_addr_len = len(phys) + + line = ' {:<%u} | {:>%u} | {:<%u} | {:>%u} | {:^%u}' \ + % (routine_a_name_len, routine_a_addr_len, routine_b_name_len, routine_b_addr_len, len('Similarity')) + + for meth in methods: + + length = len(meth.name) + + line += ' | {:^%u}' % length + + # Columns display + + names = [] + + for meth in methods: + names.append(meth.name) + + header = line.format('Routine A', 'Phys addr.', 'Routine B', 'Phys addr.', 'Similarity', *names) + + print(header) + + print('-' * (len(header) + 2)) + + # Matches display + + for match in matches: + + matching = match['matching'] + + for i in range(len(matching)): + + routine_a_name = match['routine'].label if i == 0 else '' + + if i == 0: + phys_a = '0x%x' % match['routine'].range.addr.phys + else: + phys_a = '' + + routine_b_name = matching[i]['other'].label + + if i == 0: + phys_b = '0x%x' % matching[i]['other'].range.addr.phys + else: + phys_b = '' + + similarity = '%.2f' % matching[i]['similarity'] + + values = [ 'X' if v else '' for v in list(matching[i]['values']) ] + + print(line.format(routine_a_name, phys_a, routine_b_name, phys_b, similarity, *values)) + + +def display_unmatches(routines): + """Show the unmatching routines.""" + + name_len = len('Routine') + addr_len = len('Phys addr.') + + # Length computing + + for r in routines: + + name = r.label + + if len(name) > name_len: + name_len = len(name) + + phys = '0x%x' % r.range.addr.phys + + if len(phys) > addr_len: + addr_len = len(phys) + + line = ' {:<%u} | {:>%u}' % (name_len, addr_len) + + # Columns display + + header = line.format('Routine', 'Phys addr.') + + print(header) + + print('-' * (len(header) + 2)) + + # Matches display + + for r in routines: + + phys = '0x%x' % r.range.addr.phys + + print(line.format(r.label, phys)) + + +if __name__ == '__main__': + """Entry point.""" + + parser = argparse.ArgumentParser(description='readdex - Displays information about DEX files.', add_help=False) + + parser.add_argument('-h', '--help', action='store_true', help='Display the command line options.') + + parser.add_argument('dexfile1', type=str, help='The first object file to be examined') + parser.add_argument('dexfile2', type=str, help='The second object file to be examined') + + args = parser.parse_args() + + if args.help: + parser.print_help() + sys.exit(1) + + cnt = FileContent(args.dexfile1) + fmt = DexFormat(cnt) + binary1 = LoadedBinary(fmt) + + binary1.analyze_and_wait() + + cnt = FileContent(args.dexfile2) + fmt = DexFormat(cnt) + binary2 = LoadedBinary(fmt) + + binary2.analyze_and_wait() + + fingerlist1 = FingerprintList(None, binary1, True) + print("list 1 ok") + fingerlist2 = FingerprintList(None, binary2, True) + print("list 1 ok") + + diff = BinDiff(fingerlist1, fingerlist2) + + print("analyzing...") + + diff.analyze_and_wait() + + print() + + matches = diff.single_matches + + if len(matches) > 0: + + print('Single match routines') + print('=====================') + print() + + display_matches(matches, fingerlist1.methods) + + print() + + matches = diff.multi_matches + + if len(matches) > 0: + + print('Multi match routines') + print('====================') + print() + + display_matches(matches, fingerlist1.methods) + + print() + + unmatched = diff.first_unmatches + + if len(unmatched) > 0: + + print('First binary unmatched routines') + print('===============================') + print() + + display_unmatches(unmatched) + + print() + + unmatched = diff.second_unmatches + + if len(unmatched) > 0: + + print('Second binary unmatched routines') + print('================================') + print() + + display_unmatches(unmatched) + + print() diff --git a/python/diffing_elf.py b/python/diffing_elf.py new file mode 100644 index 0000000..ccaaaa1 --- /dev/null +++ b/python/diffing_elf.py @@ -0,0 +1,222 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +import argparse +import sys +import pychrysalide +from pychrysalide.analysis.contents import FileContent +from pychrysalide.analysis import LoadedBinary +from pychrysalide.analysis.diffing import BinDiff, FingerprintList +from pychrysalide.format.elf import ElfFormat + + +def display_matches(matches, methods): + """Show the matching routines.""" + + routine_a_name_len = len('Routine A') + routine_a_addr_len = len('Virt addr.') + routine_b_name_len = len('Routine B') + routine_b_addr_len = len('Virt addr.') + + # Length computing + + for match in matches: + + routine_name = match['routine'].label + + if len(routine_name) > routine_a_name_len: + routine_a_name_len = len(routine_name) + + virt = '0x%x' % match['routine'].range.addr.virt + + if len(virt) > routine_a_addr_len: + routine_a_addr_len = len(virt) + + matching = match['matching'] + + for i in range(len(matching)): + + routine_name = matching[i]['other'].label + + if len(routine_name) > routine_b_name_len: + routine_b_name_len = len(routine_name) + + virt = '0x%x' % matching[i]['other'].range.addr.virt + + if len(virt) > routine_b_addr_len: + routine_b_addr_len = len(virt) + + line = ' {:<%u} | {:>%u} | {:<%u} | {:>%u} | {:^%u}' \ + % (routine_a_name_len, routine_a_addr_len, routine_b_name_len, routine_b_addr_len, len('Similarity')) + + for meth in methods: + + length = len(meth.name) + + line += ' | {:^%u}' % length + + # Columns display + + names = [] + + for meth in methods: + names.append(meth.name) + + header = line.format('Routine A', 'Virt addr.', 'Routine B', 'Virt addr.', 'Similarity', *names) + + print(header) + + print('-' * (len(header) + 2)) + + # Matches display + + for match in matches: + + matching = match['matching'] + + for i in range(len(matching)): + + routine_a_name = match['routine'].label if i == 0 else '' + + if i == 0: + virt_a = '0x%x' % match['routine'].range.addr.virt + else: + virt_a = '' + + routine_b_name = matching[i]['other'].label + + if i == 0: + virt_b = '0x%x' % matching[i]['other'].range.addr.virt + else: + virt_b = '' + + similarity = '%.2f' % matching[i]['similarity'] + + values = [ 'X' if v else '' for v in list(matching[i]['values']) ] + + print(line.format(routine_a_name, virt_a, routine_b_name, virt_b, similarity, *values)) + + +def display_unmatches(routines): + """Show the unmatching routines.""" + + name_len = len('Routine') + addr_len = len('Virt addr.') + + # Length computing + + for r in routines: + + name = r.label + + if len(name) > name_len: + name_len = len(name) + + virt = '0x%x' % r.range.addr.virt + + if len(virt) > addr_len: + addr_len = len(virt) + + line = ' {:<%u} | {:>%u}' % (name_len, addr_len) + + # Columns display + + header = line.format('Routine', 'Virt addr.') + + print(header) + + print('-' * (len(header) + 2)) + + # Matches display + + for r in routines: + + virt = '0x%x' % r.range.addr.virt + + print(line.format(r.label, virt)) + + +if __name__ == '__main__': + """Entry point.""" + + parser = argparse.ArgumentParser(description='readelf - Displays information about ELF files.', add_help=False) + + parser.add_argument('-h', '--help', action='store_true', help='Display the command line options.') + + parser.add_argument('elffile1', type=str, help='The first object file to be examined') + parser.add_argument('elffile2', type=str, help='The second object file to be examined') + + args = parser.parse_args() + + if args.help: + parser.print_help() + sys.exit(1) + + cnt = FileContent(args.elffile1) + fmt = ElfFormat(cnt) + binary1 = LoadedBinary(fmt) + + binary1.analyze_and_wait() + + cnt = FileContent(args.elffile2) + fmt = ElfFormat(cnt) + binary2 = LoadedBinary(fmt) + + binary2.analyze_and_wait() + + fingerlist1 = FingerprintList(None, binary1, True) + fingerlist2 = FingerprintList(None, binary2, True) + + diff = BinDiff(fingerlist1, fingerlist2) + + diff.analyze_and_wait() + + print() + + matches = diff.single_matches + + if len(matches) > 0: + + print('Single match routines') + print('=====================') + print() + + display_matches(matches, fingerlist1.methods) + + print() + + matches = diff.multi_matches + + if len(matches) > 0: + + print('Multi match routines') + print('====================') + print() + + display_matches(matches, fingerlist1.methods) + + print() + + unmatched = diff.first_unmatches + + if len(unmatched) > 0: + + print('First binary unmatched routines') + print('===============================') + print() + + display_unmatches(unmatched) + + print() + + unmatched = diff.second_unmatches + + if len(unmatched) > 0: + + print('Second binary unmatched routines') + print('================================') + print() + + display_unmatches(unmatched) + + print() -- cgit v0.11.2-87-g4458