def test_serialize_odb_file(self): before = OdbFile( BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) before.execute(LoadOperation()) before.execute(PassiveScanOperation()) sodb_file = before.serialize() after = OdbFile.deserialize(sodb_file) self.assertIsNotNone(after) # verify options self.assertEqual(before.binary, after.binary) # verify structures for stype in STRUCTURE_TYPES: self.assertEqual(len(before._items[stype.__name__]), len(after._items[stype.__name__])) for b, a in zip(before.get_structure_list(stype), after.get_structure_list(stype)): self.assertEqual(b, a) # verify operations self.assertEqual(len(before.operations), len(after.operations)) for b, a in zip(before.operations, after.operations): self.assertEqual(b.__dict__, a.__dict__)
def test_total_lines(self): odb_file = OdbFile(BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) dasm = Disassembler(odb_file) total_lines = dasm.total_lines() self.assertEquals(41614, total_lines)
def DeserializeBinary(d): if d['kind'] == 'file': return BinaryFile.deserialize(d) elif d['kind'] == 'string': return BinaryString.deserialize(d) elif d['kind'] == 'file_model': return BinaryFileModel.deserialize(d) else: raise Exception("Unrecognized binary kind %s" % d['kind'])
def test_size(self): odb_file = OdbFile( BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) self.assertEqual(114032, odb_file.get_binary().size) s = '01 20 40 E2 02 20 61 E0 01 30 D1 E4 00 00 53 E3 02 30 C1 E7 FB FF FF 1A 1E FF 2F E1' odb_file = OdbFile(BinaryString(s, 'arm')) self.assertEqual(28, odb_file.get_binary().size)
def test_decompile_by_addr_nonexistent(self): odb_file = OdbFile( BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) decompiler = OdaDecompiler(odb_file) with self.assertRaises(OdaDecompilerException): decompiler.decompile(0x306b26)
def test_decompile_by_addr_good(self): odb_file = OdbFile( BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) decompiler = OdaDecompiler(odb_file) results = decompiler.decompile(0x406b26) self.assertEquals(0x4067A0, results.start) self.assertEquals(0x406BC0, results.end) self.assertNotEquals("", results.source)
def test_serialize(self): odb_file = OdbFile( BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) serialized = DefaultOdbSerializer().dumps(odb_file) loaded_odb_file = DefaultOdbSerializer().load(serialized) self.assertEqual(len(odb_file.get_structure_list(Function)), len(loaded_odb_file.get_structure_list(Function)))
def test_basic_binary_loader(self): odb_file = OdbFile( BinaryFile(self.get_test_bin_path('ls.bin.x86-64'), 'binary', 'i386:x86-64')) odb_file.execute(LoadOperation()) self.assertEquals(1, len(odb_file.get_structure_list(Section))) self.assertEquals(0, len(odb_file.get_structure_list(Symbol))) self.assertEquals(0, len(odb_file.get_structure_list(Function))) self.assertEquals(857, len(odb_file.get_structure_list(DataString)))
def test_basic_scan(self): odb_file = OdbFile( BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) self.assertEqual(215, len(odb_file.get_structure_list(Function))) for f in odb_file.get_structure_list(Function): print(f.name) self.assertEqual(2814, len(odb_file.get_structure_list(Branch)))
def test_analyzer_output(self): odb_file = OdbFile(BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) dasm = Disassembler(odb_file) # Disassemble at a provided vma units = dasm.display(0x4095e0, 200, False) # The provided address should be the first instruction self.assertEquals(0x4095e0, units[0].vma) self.assertEquals("mov", units[0].opcode) # Another random instruction self.assertEquals("test", units[18].opcode) self.assertEquals("al,al", units[18].operands) # Disassemble at a provided negative vma units = dasm.display(0x4095e0, -10, False) # The provided address should be the last instruction self.assertEquals(0x4095e0, units[9].vma) self.assertEquals("mov", units[9].opcode) # IDA finds this one through a function pointer in data section # self.assertEquals(True, units[9].isFunction) # 9 instructions earlier self.assertEquals(0x4095BB, units[0].vma) self.assertEquals("call", units[0].opcode) # Disassemble a function units = dasm.display(0x40BEE0, 10, False) self.assertEquals(True, units[0].isFunction) # Cross Parcel Boundaries units = dasm.display(0x412BF4, -10, False) self.assertEquals(0x412BF4, units[9].vma) self.assertEquals("ret", units[9].opcode) self.assertEquals(".fini", units[9].section_name) self.assertEquals(0x412BE1, units[2].vma) self.assertEquals("jmp", units[2].opcode) self.assertEquals(".text", units[2].section_name) # Cross Code/Data Boundaries units = dasm.display(0x412BF4, 10, False) self.assertEquals(0x412BF4, units[0].vma) self.assertEquals(0x412C00, units[1].vma) self.assertEquals(1, units[1].dataSize)
def load_examples(owner=None): EXAMPLES_DIR = os.path.join( os.path.dirname(oda.apps.odaweb.examples.__file__), 'examples') for example in Examples: short_name = example['short_name'] valid_file_storage_id = True if OdaMaster.objects.filter(short_name=short_name).exists(): print('Example %s already exists in the database' % short_name) oda_master = OdaMaster.objects.filter( short_name=short_name).first() else: oda_master = OdaMaster( short_name=short_name, project_name=example['project_name'], owner=owner, default_permission=OdaMasterPermissionLevel.read.value) print('Adding example %s to database' % short_name) if 'data' in example: example_data = ''.join(example['data'].split()) odb_file = OdbFile( BinaryString(example_data, example['options']['architecture'])) elif 'file_name' in example: odb_file = OdbFile( BinaryFile(os.path.join(EXAMPLES_DIR, example['file_name']), example['options']['target'], example['options']['architecture'])) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) if 'comments' in example: for vma, msg in example['comments']: odb_file.execute(CreateCommentOperation(vma, msg)) print("Adding Comment %s To %s" % (msg, str(odb_file))) if 'labels' in example: for vma, label in example['labels']: odb_file.execute(CreateLabelOperation(vma, label)) print("Saving label %s To %s" % (label, str(odb_file))) oda_master.odb_file = odb_file oda_master.save()
def test_basic_graph_nodes(self): # we load this ELF as a raw binary, because it has an invalid opcode fairly early on odb_file = OdbFile( BinaryFile(self.get_test_bin_path('mkdir'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) bgv = BranchGraphView(odb_file, 0x401980) expectedNodes = [ BranchGraphNode(0x401980, 0x401990, 0x12, 0x4019dd, 0x401992), BranchGraphNode(0x401992, 0x4019b0, 0x20, 0x4019d6, 0x4019b2), BranchGraphNode(0x4019b2, 0x4019b2, 0x06, 0x4019b8, None), BranchGraphNode(0x4019b8, 0x4019d4, 0x1e, 0x4019b8, 0x4019d6), BranchGraphNode(0x4019d6, 0x4019d6, 0x07, 0x4019dd, None), BranchGraphNode(0x4019dd, 0x4019e4, 0x13, None, None), ] self.assertCountEqual(expectedNodes, bgv._nodes.values())
def failing_test_follow_jmps_i386(self): odb_file = OdbFile( BinaryFile( self.get_test_bin_path( 'active_scan_follow_jmps/active_scan_follow_jmps.bin'), 'binary', 'i386')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) parcels_before = ParcelList(odb_file.get_structure_list(Parcel)) # number of parcels before the split self.assertEquals(1, len(parcels_before)) # execute the active scan operation odb_file.execute(ActiveScanOperation(0x0)) # number of parcels after the split parcels_after = ParcelList(odb_file.get_structure_list(Parcel)) self.assertEquals(11, len(parcels_after))
def test_basic_loader(self): odb_file = OdbFile( BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) self.assertEquals(26, len(odb_file.get_structure_list(Section))) self.assertEquals(120, len(odb_file.get_structure_list(Symbol))) self.assertEquals(2, len(odb_file.get_structure_list(Function))) self.assertEquals( 1, len([ x for x in odb_file.get_structure_list(Function) if x.name == '_init' ])) self.assertEquals( 1, len([ x for x in odb_file.get_structure_list(Function) if x.name == '_fini' ])) self.assertEquals(1304, len(odb_file.get_structure_list(DataString))) self.assertEquals( 1, len([ s for s in odb_file.get_structure_list(DataString) if s.value == 'hide-control-chars' ])) self.assertEquals( 1, len([ s for s in odb_file.get_structure_list(DataString) if s.value == 'error initializing month strings' ]))
def test_basic_active_scan(self): # we load this ELF as a raw binary, because it has an invalid opcode fairly early on odb_file = OdbFile( BinaryFile(self.get_test_bin_path('mkdir'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) parcels_before = ParcelList(odb_file.get_structure_list(Parcel)) p = parcels_before.find_parcel_by_vma(0x4002ce) gnu_hash_lda_before = parcels_before.vma_to_lda(0x4002cd) dynsym_lda_before = parcels_before.vma_to_lda(0x4002e0) dynstr_lda_before = parcels_before.vma_to_lda(0x400a18) # number of parcels before the split self.assertEquals(24, len(parcels_before)) # execute the split operation odb_file.execute(ActiveScanOperation(0x4002ce)) # number of parcels after the split parcels_after = ParcelList(odb_file.get_structure_list(Parcel)) self.assertEquals(26, len(parcels_after)) # get the three parcels p1 = parcels_after.find_parcel_by_vma(0x400298) p2 = parcels_after.find_parcel_by_vma(0x4002ce) p3 = parcels_after.find_parcel_by_vma(0x4002d5) # make sure they are all unique self.assertNotEqual(p1, p2) self.assertNotEqual(p1, p3) self.assertNotEqual(p2, p3) # check num_ldas in p1 (54 bytes) self.assertEquals(54, p1.num_ldas) # check num_ldas in p2 (3 instructions) self.assertEquals(3, p2.num_ldas) # check num_ldas in p3 (7 bytes) self.assertEquals(7, p3.num_ldas) # make sure vmas line up self.assertEquals(0x400298, p1.vma_start) self.assertEquals(0x4002ce, p1.vma_end) self.assertEquals(0x4002ce, p2.vma_start) self.assertEquals(0x4002d5, p2.vma_end) self.assertEquals(0x4002d5, p3.vma_start) self.assertEquals(0x4002dc, p3.vma_end) # # make sure vma->lda mappings line up # # these shouldn't have changed self.assertEquals(gnu_hash_lda_before, parcels_after.vma_to_lda(0x4002cd)) self.assertEquals(gnu_hash_lda_before + 1, parcels_after.vma_to_lda(0x4002ce)) self.assertEquals(False, p1.is_code) self.assertEquals(False, p3.is_code) # these changed self.assertEquals(gnu_hash_lda_before + 2, parcels_after.vma_to_lda(0x4002d0)) self.assertEquals(gnu_hash_lda_before + 3, parcels_after.vma_to_lda(0x4002d2)) self.assertEquals(gnu_hash_lda_before + 4, parcels_after.vma_to_lda(0x4002d5)) self.assertEquals(gnu_hash_lda_before + 5, parcels_after.vma_to_lda(0x4002d6)) self.assertEquals(gnu_hash_lda_before + 6, parcels_after.vma_to_lda(0x4002d7)) self.assertEquals(gnu_hash_lda_before + 7, parcels_after.vma_to_lda(0x4002d8)) self.assertEquals(gnu_hash_lda_before + 8, parcels_after.vma_to_lda(0x4002d9)) self.assertEquals(gnu_hash_lda_before + 9, parcels_after.vma_to_lda(0x4002da)) self.assertEquals(gnu_hash_lda_before + 10, parcels_after.vma_to_lda(0x4002db)) self.assertEquals(True, p2.is_code) # 7 bytes turned into 3 instructions, so it shifted the following parcels by -4 ldas self.assertEquals(dynsym_lda_before - 4, parcels_after.vma_to_lda(0x4002e0)) self.assertEquals(dynstr_lda_before - 4, parcels_after.vma_to_lda(0x400a18)) # # make sure lda->vma mappings line up # # these shouldn't have changed self.assertEquals(0x4002cd, parcels_after.lda_to_vma(gnu_hash_lda_before)) self.assertEquals(0x4002ce, parcels_after.lda_to_vma(gnu_hash_lda_before + 1)) # these changed self.assertEquals(0x4002d0, parcels_after.lda_to_vma(gnu_hash_lda_before + 2)) self.assertEquals(0x4002d2, parcels_after.lda_to_vma(gnu_hash_lda_before + 3)) self.assertEquals(0x4002d5, parcels_after.lda_to_vma(gnu_hash_lda_before + 4)) self.assertEquals(0x4002d6, parcels_after.lda_to_vma(gnu_hash_lda_before + 5)) self.assertEquals(0x4002d7, parcels_after.lda_to_vma(gnu_hash_lda_before + 6)) self.assertEquals(0x4002d8, parcels_after.lda_to_vma(gnu_hash_lda_before + 7)) self.assertEquals(0x4002d9, parcels_after.lda_to_vma(gnu_hash_lda_before + 8)) self.assertEquals(0x4002da, parcels_after.lda_to_vma(gnu_hash_lda_before + 9)) self.assertEquals(0x4002db, parcels_after.lda_to_vma(gnu_hash_lda_before + 10)) # 7 bytes turned into 3 instructions, so it shifted the following parcels by -4 ldas self.assertEquals(0x4002e0, parcels_after.lda_to_vma(dynsym_lda_before - 4)) self.assertEquals(0x400a18, parcels_after.lda_to_vma(dynstr_lda_before - 4))
def test_desc(self): odb_file = OdbFile( BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) self.assertEqual(8, len(odb_file.get_binary().desc()))
def test_split_to_data_single_inst_in_parcel(self): odb_file = OdbFile(BinaryFile( self.get_test_bin_path('code_split_single_instruction/split_parcel_single'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) parcels_before = ParcelList(odb_file.get_structure_list(Parcel)) # only one instruction in .single p = parcels_before.find_parcel_by_vma(0x400598) p_text = parcels_before.find_parcel_by_vma(0x400597) p_fini = parcels_before.find_parcel_by_vma(0x4005a0) p_got = parcels_before.find_parcel_by_vma(0x600fe0) num_ldas_before = p.num_ldas num_text_ldas_before = p_text.num_ldas num_fini_ldas_before = p_fini.num_ldas single_lda_before = p.lda_start fini_lda_before = p_fini.lda_start text_lda_before = p_text.lda_start got_lda_before = p_got.lda_start # number of parcels before the split self.assertEquals(25, len(parcels_before)) # execute the split operation odb_file.execute(SplitParcelOperation(0x400598)) # number of parcels after the split (should not have changed) parcels_after = ParcelList(odb_file.get_structure_list(Parcel)) self.assertEquals(25, len(parcels_after)) # get the parcels p = parcels_after.find_parcel_by_vma(0x400598) p_text = parcels_after.find_parcel_by_vma(0x400597) p_fini = parcels_after.find_parcel_by_vma(0x4005a0) # make sure they are all unique self.assertNotEqual(p, p_text) self.assertNotEqual(p, p_fini) self.assertNotEqual(p_text, p_fini) # check num_ldas in p (1 instruction become 7 data bytes) self.assertEquals(7, p.num_ldas) # check num_ldas in text didn't change self.assertEquals(num_text_ldas_before, p_text.num_ldas) # check num_ldas in fini didn't change self.assertEquals(num_fini_ldas_before, p_fini.num_ldas) # make sure vmas line up self.assertEquals(0x4003d0, p_text.vma_start) self.assertEquals(0x400598, p_text.vma_end) self.assertEquals(0x400598, p.vma_start) self.assertEquals(0x40059f, p.vma_end) self.assertEquals(0x4005a0, p_fini.vma_start) self.assertEquals(0x4005ae, p_fini.vma_end) # # make sure vma->lda mappings line up # # these shouldn't have changed self.assertEquals(text_lda_before, parcels_after.vma_to_lda(0x4003d0)) self.assertEquals(text_lda_before+num_text_ldas_before-1, parcels_after.vma_to_lda(0x400597)) self.assertEquals(single_lda_before, parcels_after.vma_to_lda(0x400598)) self.assertEquals(True, p_text.is_code) self.assertEquals(True, p_fini.is_code) # these changed self.assertEquals(single_lda_before+1, parcels_after.vma_to_lda(0x400599)) self.assertEquals(single_lda_before+2, parcels_after.vma_to_lda(0x40059a)) self.assertEquals(single_lda_before+3, parcels_after.vma_to_lda(0x40059b)) self.assertEquals(single_lda_before+4, parcels_after.vma_to_lda(0x40059c)) self.assertEquals(single_lda_before+5, parcels_after.vma_to_lda(0x40059d)) self.assertEquals(single_lda_before+6, parcels_after.vma_to_lda(0x40059e)) self.assertEquals(False, p.is_code) # 1 instruction turned into 7 data bytes, so it shifted the following parcels by 6 ldas self.assertEquals(fini_lda_before+6, parcels_after.vma_to_lda(0x4005a0)) self.assertEquals(got_lda_before+6, parcels_after.vma_to_lda(0x600fe0)) # # make sure lda->vma mappings line up # self.assertEquals(text_lda_before, parcels_after.vma_to_lda(0x4003d0)) self.assertEquals(text_lda_before+num_text_ldas_before-1, parcels_after.vma_to_lda(0x400597)) self.assertEquals(single_lda_before, parcels_after.vma_to_lda(0x400598)) # these shouldn't have changed self.assertEquals(0x4003d0, parcels_after.lda_to_vma(text_lda_before)) self.assertEquals(0x400597, parcels_after.lda_to_vma(text_lda_before+num_text_ldas_before-1)) self.assertEquals(0x400598, parcels_after.lda_to_vma(single_lda_before)) # these changed self.assertEquals(0x400599, parcels_after.lda_to_vma(single_lda_before+1)) self.assertEquals(0x40059a, parcels_after.lda_to_vma(single_lda_before+2)) self.assertEquals(0x40059b, parcels_after.lda_to_vma(single_lda_before+3)) self.assertEquals(0x40059c, parcels_after.lda_to_vma(single_lda_before+4)) self.assertEquals(0x40059d, parcels_after.lda_to_vma(single_lda_before+5)) self.assertEquals(0x40059e, parcels_after.lda_to_vma(single_lda_before+6)) # 1 instruction turned into 7 data bytes, so it shifted the following parcels by 6 ldas self.assertEquals(0x4005a0, parcels_after.lda_to_vma(fini_lda_before+6)) self.assertEquals(0x600fe0, parcels_after.lda_to_vma(got_lda_before+6))
def test_split_to_data_at_end_of_parcel(self): odb_file = OdbFile(BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) parcels_before = ParcelList(odb_file.get_structure_list(Parcel)) # last instruction in .plt p = parcels_before.find_parcel_by_vma(0x4029bb) p3 = parcels_before.find_parcel_by_vma(0x4029c0) num_p1_ldas_before = p.num_ldas num_p3_ldas_before = p3.num_ldas plt_lda_before = parcels_before.vma_to_lda(0x402320) text_lda_before = parcels_before.vma_to_lda(0x4029c0) # number of parcels before the split self.assertEquals(25, len(parcels_before)) # execute the split operation odb_file.execute(SplitParcelOperation(0x4029bb)) # number of parcels after the split (should only add one more) parcels_after = ParcelList(odb_file.get_structure_list(Parcel)) self.assertEquals(26, len(parcels_after)) # get the two parcels (plus the .text one following) p1 = parcels_after.find_parcel_by_vma(0x402320) p2 = parcels_after.find_parcel_by_vma(0x4029bb) p3 = parcels_after.find_parcel_by_vma(0x4029c0) # make sure they are all unique self.assertNotEqual(p1, p2) self.assertNotEqual(p1, p3) self.assertNotEqual(p2, p3) # check num_ldas in p1 (5 instructions) self.assertEquals(num_p1_ldas_before - 1, p1.num_ldas) # check num_ldas in p2 (this one instruction has now become 5 data bytes) self.assertEquals(5, p2.num_ldas) # check num_ldas in p3 (should not have changed) self.assertEquals(num_p3_ldas_before, p3.num_ldas) # make sure vmas line up self.assertEquals(0x402320, p1.vma_start) self.assertEquals(0x4029bb, p1.vma_end) self.assertEquals(0x4029bb, p2.vma_start) self.assertEquals(0x4029c0, p2.vma_end) self.assertEquals(0x4029c0, p3.vma_start) self.assertEquals(0x412bec, p3.vma_end) # # make sure vma->lda mappings line up # # these shouldn't have changed self.assertEquals(plt_lda_before, parcels_after.vma_to_lda(0x402320)) self.assertEquals(plt_lda_before+num_p1_ldas_before-2, parcels_after.vma_to_lda(0x4029b6)) self.assertEquals(plt_lda_before+num_p1_ldas_before-1, parcels_after.vma_to_lda(0x4029bb)) self.assertEquals(True, p1.is_code) self.assertEquals(True, p3.is_code) # these changed self.assertEquals(plt_lda_before+num_p1_ldas_before, parcels_after.vma_to_lda(0x4029bc)) self.assertEquals(plt_lda_before+num_p1_ldas_before+1, parcels_after.vma_to_lda(0x4029bd)) self.assertEquals(plt_lda_before+num_p1_ldas_before+2, parcels_after.vma_to_lda(0x4029be)) self.assertEquals(plt_lda_before+num_p1_ldas_before+3, parcels_after.vma_to_lda(0x4029bf)) self.assertEquals(plt_lda_before+num_p1_ldas_before+4, parcels_after.vma_to_lda(0x4029c0)) self.assertEquals(False, p2.is_code) # 1 instruction turned into 5 data bytes, so it shifted the following parcels by 4 ldas self.assertEquals(text_lda_before+4, parcels_after.vma_to_lda(0x4029c0)) # # make sure lda->vma mappings line up # # these shouldn't have changed self.assertEquals(0x402320, parcels_after.lda_to_vma(plt_lda_before)) self.assertEquals(0x4029b6, parcels_after.lda_to_vma(plt_lda_before+num_p1_ldas_before-2)) self.assertEquals(0x4029bb, parcels_after.lda_to_vma(plt_lda_before+num_p1_ldas_before-1)) # these changed self.assertEquals(0x4029bc, parcels_after.lda_to_vma(plt_lda_before+num_p1_ldas_before)) self.assertEquals(0x4029bd, parcels_after.lda_to_vma(plt_lda_before+num_p1_ldas_before+1)) self.assertEquals(0x4029be, parcels_after.lda_to_vma(plt_lda_before+num_p1_ldas_before+2)) self.assertEquals(0x4029bf, parcels_after.lda_to_vma(plt_lda_before+num_p1_ldas_before+3)) self.assertEquals(0x4029c0, parcels_after.lda_to_vma(plt_lda_before+num_p1_ldas_before+4)) # 1 instruction turned into 5 data bytes, so it shifted the following parcels by 4 ldas self.assertEquals(0x4029c0, parcels_after.lda_to_vma(text_lda_before+4))
def test_split_to_data_basic(self): odb_file = OdbFile(BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) parcels_before = ParcelList(odb_file.get_structure_list(Parcel)) p = parcels_before.find_parcel_by_vma(0x4029c0) num_p1_ldas_before = p.num_ldas text_lda_before = parcels_before.vma_to_lda(0x4029c0) fini_lda_before = parcels_before.vma_to_lda(0x412bec) # number of parcels before the split self.assertEquals(25, len(parcels_before)) # execute the split operation odb_file.execute(SplitParcelOperation(0x4029d5)) # number of parcels after the split parcels_after = ParcelList(odb_file.get_structure_list(Parcel)) self.assertEquals(27, len(parcels_after)) # get the three parcels p1 = parcels_after.find_parcel_by_vma(0x4029c0) p2 = parcels_after.find_parcel_by_vma(0x4029d5) p3 = parcels_after.find_parcel_by_vma(0x4029da) # make sure they are all unique self.assertNotEqual(p1, p2) self.assertNotEqual(p1, p3) self.assertNotEqual(p2, p3) # check num_ldas in p1 (5 instructions) self.assertEquals(5, p1.num_ldas) # check num_ldas in p2 (this one instruction has now become 5 data bytes) self.assertEquals(5, p2.num_ldas) # check num_ldas in p3 (less 5 from p1 and less 1 from p2 - remember it used to only be 1 lda before the split) self.assertEquals(num_p1_ldas_before - 5 - 1, p3.num_ldas) # make sure vmas line up self.assertEquals(0x4029c0, p1.vma_start) self.assertEquals(0x4029d5, p1.vma_end) self.assertEquals(0x4029d5, p2.vma_start) self.assertEquals(0x4029da, p2.vma_end) self.assertEquals(0x4029da, p3.vma_start) self.assertEquals(0x412bec, p3.vma_end) # # make sure vma->lda mappings line up # # these shouldn't have changed self.assertEquals(text_lda_before, parcels_after.vma_to_lda(0x4029c0)) self.assertEquals(text_lda_before+5, parcels_after.vma_to_lda(0x4029d5)) self.assertEquals(True, p1.is_code) self.assertEquals(True, p3.is_code) # these changed self.assertEquals(text_lda_before+6, parcels_after.vma_to_lda(0x4029d6)) self.assertEquals(text_lda_before+7, parcels_after.vma_to_lda(0x4029d7)) self.assertEquals(text_lda_before+8, parcels_after.vma_to_lda(0x4029d8)) self.assertEquals(text_lda_before+9, parcels_after.vma_to_lda(0x4029d9)) self.assertEquals(text_lda_before+10, parcels_after.vma_to_lda(0x4029da)) self.assertEquals(text_lda_before+11, parcels_after.vma_to_lda(0x4029db)) self.assertEquals(False, p2.is_code) # 1 instruction turned into 5 data bytes, so it shifted the following parcels by 4 ldas self.assertEquals(fini_lda_before+4, parcels_after.vma_to_lda(0x412bec)) # # make sure lda->vma mappings line up # # these shouldn't have changed self.assertEquals(0x4029c0, parcels_after.lda_to_vma(text_lda_before)) self.assertEquals(0x4029d5, parcels_after.lda_to_vma(text_lda_before+5)) # these changed self.assertEquals(0x4029d6, parcels_after.lda_to_vma(text_lda_before+6)) self.assertEquals(0x4029d7, parcels_after.lda_to_vma(text_lda_before+7)) self.assertEquals(0x4029d8, parcels_after.lda_to_vma(text_lda_before+8)) self.assertEquals(0x4029d9, parcels_after.lda_to_vma(text_lda_before+9)) self.assertEquals(0x4029da, parcels_after.lda_to_vma(text_lda_before+10)) self.assertEquals(0x4029db, parcels_after.lda_to_vma(text_lda_before+11)) # 1 instruction turned into 5 data bytes, so it shifted the following parcels by 4 ldas self.assertEquals(0x412bec, parcels_after.lda_to_vma(fini_lda_before+4))
def test_split_to_data_at_start_of_parcel(self): odb_file = OdbFile(BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64')) odb_file.execute(LoadOperation()) odb_file.execute(PassiveScanOperation()) parcels_before = ParcelList(odb_file.get_structure_list(Parcel)) # start of .fini section p = parcels_before.find_parcel_by_vma(0x412bec) num_p1_ldas_before = p.num_ldas fini_lda_before = parcels_before.vma_to_lda(0x412bec) # number of parcels before the split self.assertEquals(25, len(parcels_before)) # execute the split operation odb_file.execute(SplitParcelOperation(0x412bec)) # number of parcels after the split (should only add one more) parcels_after = ParcelList(odb_file.get_structure_list(Parcel)) self.assertEquals(26, len(parcels_after)) # get the two parcels p1 = parcels_after.find_parcel_by_vma(0x412bec) p2 = parcels_after.find_parcel_by_vma(0x412bf0) # make sure they are unique self.assertNotEqual(p1, p2) # check num_ldas in p1 (4 data bytes) self.assertEquals(4, p1.num_ldas) # check num_ldas in p2 self.assertEquals(2, p2.num_ldas) # make sure vmas line up self.assertEquals(0x412bec, p1.vma_start) self.assertEquals(0x412bf0, p1.vma_end) self.assertEquals(0x412bf0, p2.vma_start) self.assertEquals(0x412bf5, p2.vma_end) # # make sure vma->lda mappings line up # # these shouldn't have changed self.assertEquals(fini_lda_before, parcels_after.vma_to_lda(0x412bec)) self.assertEquals(True, p2.is_code) # these changed self.assertEquals(fini_lda_before+1, parcels_after.vma_to_lda(0x412bed)) self.assertEquals(fini_lda_before+2, parcels_after.vma_to_lda(0x412bee)) self.assertEquals(fini_lda_before+3, parcels_after.vma_to_lda(0x412bef)) self.assertEquals(fini_lda_before+4, parcels_after.vma_to_lda(0x412bf0)) self.assertEquals(fini_lda_before+5, parcels_after.vma_to_lda(0x412bf4)) self.assertEquals(False, p1.is_code) # # make sure lda->vma mappings line up # # these shouldn't have changed self.assertEquals(0x412bec, parcels_after.lda_to_vma(fini_lda_before)) # these changed self.assertEquals(0x412bed, parcels_after.lda_to_vma(fini_lda_before+1)) self.assertEquals(0x412bee, parcels_after.lda_to_vma(fini_lda_before+2)) self.assertEquals(0x412bef, parcels_after.lda_to_vma(fini_lda_before+3)) self.assertEquals(0x412bf0, parcels_after.lda_to_vma(fini_lda_before+4)) self.assertEquals(0x412bf4, parcels_after.lda_to_vma(fini_lda_before+5))