def read_version(settings): if 'printRtsInfo' in settings.name_to_address: for insn in disasm.disasm_from_until(settings, settings.name_to_address['printRtsInfo'], lambda insn: insn.group(capstone.x86.X86_GRP_RET)): if insn.mnemonic == 'mov' and insn.operands[1].type == capstone.x86.X86_OP_IMM: str_start = settings.rodata_offset + insn.operands[1].imm if b'\0' in settings.binary[str_start:str_start+20]: str_len = settings.binary[str_start:str_start+20].index(b'\0') ver_str = settings.binary[str_start:str_start+str_len] parts = ver_str.split(b'.') if len(parts) == 3 and all(map(lambda part: part.isdigit(), parts)): return (int(parts[0]), int(parts[1]), int(parts[2]))
def gather_case_arms(settings, heaps, address, min_tag, max_tag, initial_stack, initial_registers, original_stack, original_inspection, path): mach = machine.Machine(settings, heaps, copy.deepcopy(initial_stack), copy.deepcopy(initial_registers)) first_instructions = disasm.disasm_from_until(settings, address, lambda insn: insn.group(capstone.x86.X86_GRP_JUMP)) mach.simulate(first_instructions) if first_instructions[-2].mnemonic == 'cmp' and isinstance(mach.load(first_instructions[-2].operands[0]), Tagged) and isinstance(mach.load(first_instructions[-2].operands[0]).untagged, Offset) and isinstance(mach.load(first_instructions[-2].operands[0]).untagged.base, CasePointer) and first_instructions[-2].operands[1].type == capstone.x86.X86_OP_IMM: assert first_instructions[-1].mnemonic == 'jae' small_address = sum(map(lambda insn: insn.size, first_instructions)) + address large_address = first_instructions[-1].operands[0].imm arms_small, tags_small, stacks_small, regs_small = gather_case_arms(settings, heaps, small_address, min_tag, first_instructions[-2].operands[1].imm - 1, mach.stack, mach.registers, original_stack, original_inspection, path + [address]) arms_large, tags_large, stacks_large, regs_large = gather_case_arms(settings, heaps, large_address, first_instructions[-2].operands[1].imm, max_tag, mach.stack, mach.registers, original_stack, original_inspection, path + [address]) arms = arms_small + arms_large tags = tags_small + tags_large stacks = stacks_small + stacks_large registers = regs_small + regs_large else: arms = [address] if min_tag == max_tag: tag = NumericTag(value = min_tag) else: tag = DefaultTag() tags = [tag] # Resimulate the steps taken to get to this point with the correctly tagged CasePointer mach = machine.Machine(settings, heaps, copy.deepcopy(original_stack), { settings.rt.main_register: ptrutil.make_tagged(settings, Offset(base = CasePointer(inspection = original_inspection, matched_tag = tag), index = 0))._replace(tag = min_tag), settings.rt.stack_register: ptrutil.make_tagged(settings, Offset(base = StackPointer(), index = -len(original_stack))) }) for step in path: mach.simulate(disasm.disasm_from_until(settings, step, lambda insn: insn.group(capstone.x86.X86_GRP_JUMP))) stacks = [mach.stack] registers = [mach.registers] return arms, tags, stacks, registers
def gather_case_arms(settings, heaps, address, min_tag, max_tag, initial_stack, initial_registers, original_stack, original_inspection, path): mach = machine.Machine(settings, heaps, copy.deepcopy(initial_stack), copy.deepcopy(initial_registers)) first_instructions = list(disasm.disasm_from_until(settings, address, lambda insn: insn.group(capstone.x86.X86_GRP_JUMP))) mach.simulate(first_instructions) if first_instructions[-2].mnemonic == 'cmp' and isinstance(mach.load(first_instructions[-2].operands[0]), Tagged) and isinstance(mach.load(first_instructions[-2].operands[0]).untagged, Offset) and isinstance(mach.load(first_instructions[-2].operands[0]).untagged.base, CasePointer) and first_instructions[-2].operands[1].type == capstone.x86.X86_OP_IMM: assert first_instructions[-1].mnemonic == 'jae' small_address = sum(map(lambda insn: insn.size, first_instructions)) + address large_address = first_instructions[-1].operands[0].imm arms_small, tags_small, stacks_small, regs_small = gather_case_arms(settings, heaps, small_address, min_tag, first_instructions[-2].operands[1].imm - 1, mach.stack, mach.registers, original_stack, original_inspection, path + [address]) arms_large, tags_large, stacks_large, regs_large = gather_case_arms(settings, heaps, large_address, first_instructions[-2].operands[1].imm, max_tag, mach.stack, mach.registers, original_stack, original_inspection, path + [address]) arms = arms_small + arms_large tags = tags_small + tags_large stacks = stacks_small + stacks_large registers = regs_small + regs_large else: arms = [address] if min_tag == max_tag: tag = NumericTag(value = min_tag) else: tag = DefaultTag() tags = [tag] # Resimulate the steps taken to get to this point with the correctly tagged CasePointer mach = machine.Machine(settings, heaps, copy.deepcopy(original_stack), { settings.rt.main_register: ptrutil.make_tagged(settings, Offset(base = CasePointer(inspection = original_inspection, matched_tag = tag), index = 0))._replace(tag = min_tag), settings.rt.stack_register: ptrutil.make_tagged(settings, Offset(base = StackPointer(), index = -len(original_stack))) }) for step in path: mach.simulate(disasm.disasm_from_until(settings, step, lambda insn: insn.group(capstone.x86.X86_GRP_JUMP))) stacks = [mach.stack] registers = [mach.registers] return arms, tags, stacks, registers