diff --git a/modules/syscaller.py b/modules/syscaller.py index b119ad0..f3c0876 100644 --- a/modules/syscaller.py +++ b/modules/syscaller.py @@ -23,84 +23,136 @@ 'linux-ppc64_le': 'syscalls_ppc64.json', } + # Simple database loader - assume all is in one file for now def load_database(data_db): - current_file_path = os.path.dirname(os.path.abspath(__file__)) - data_db_path = os.path.join(current_file_path, '..', 'data', data_db) - fh = open(data_db_path, 'r') - return json.load(fh) + current_file_path = os.path.dirname(os.path.abspath(__file__)) + data_db_path = os.path.join(current_file_path, '..', 'data', data_db) + fh = open(data_db_path, 'r') + return json.load(fh) + def check_arch(platform_name): - if platform_name not in supported_platforms: - bn.log_error('[x] Right now this plugin supports only the following platforms: ' + str(supported_platforms.keys())) - return False - - return True + if platform_name not in supported_platforms: + bn.log_error( + '[x] Right now this plugin supports only the following platforms: ' + + str(supported_platforms.keys())) + return False + + return True + def run_plugin_current(bv, function): - if check_arch(bv.platform.name): - db = load_database(supported_platforms[bv.platform.name]) + if check_arch(bv.platform.name): + db = load_database(supported_platforms[bv.platform.name]) + + task = SyscallerTask(bv, [function], db) + task.start() - task = SyscallerTask(bv, [function], db) - task.start() def run_plugin_all(bv): - if check_arch(bv.platform.name): - db = load_database(supported_platforms[bv.platform.name]) + if check_arch(bv.platform.name): + db = load_database(supported_platforms[bv.platform.name]) + + task = SyscallerTask(bv, bv.functions, db) + task.start() + - task = SyscallerTask(bv, bv.functions, db) - task.start() class SyscallerTask(bn.BackgroundTaskThread): - def __init__(self, bv, functions, db): - super(SyscallerTask, self).__init__('Decorating function ...') - self.bv = bv - self.functions = functions - self.db = db - self.registers = bv.platform.system_call_convention.int_arg_regs - - def run(self): - for function in self.functions: - for block in function.low_level_il: - for instruction in block: - if instruction.operation == bn.LowLevelILOperation.LLIL_SYSCALL: - possible_value = instruction.get_reg_value(self.registers[0]) - - if(possible_value.is_constant): - syscall = self.db[str(possible_value.value)] # Get corresponding syscall - else: - syscall = {'name': 'Unknown Syscall', 'args': []} - bn.log_info("[*] Found syscall {} in function {} at 0x{:x}".format(syscall['name'], - function.name, - instruction.address)) - - args = [] - # construct arguments - for i, arg in enumerate(syscall['args']): - possible_arg_value = instruction.get_reg_value(self.registers[i+1]) - - if(possible_arg_value.is_constant): + def __init__(self, bv, functions, db): + super(SyscallerTask, self).__init__('Decorating function ...') + self.bv = bv + self.functions = functions + self.db = db + self.registers = bv.platform.system_call_convention.int_arg_regs + + + def annotate_llil(self, function, block, instruction): + comment = self.format_comment(function, instruction, self.registers) + function.set_comment(instruction.address, comment) + + def is_constant_regval(self, what: bn.variable.RegisterValue): + return what.type in (bn.RegisterValueType.ConstantValue, bn.RegisterValueType.ConstantPointerValue) + + def format_comment(self, function, instruction, registers): + + possible_value = instruction.get_reg_value( + registers[0]) + + if self.is_constant_regval(possible_value): + syscall = self.db[str( + possible_value.value + )] # Get corresponding syscall + else: + syscall = {'name': 'Unknown Syscall', 'args': []} + + bn.log_info( + "[*] Found syscall {} in function {} at 0x{:x}". + format(syscall['name'], function.name, + instruction.address)) + + args = [] + # construct arguments + for i, arg in enumerate(syscall['args']): + possible_arg_value = instruction.get_reg_value( + registers[i + 1]) + + if self.is_constant_regval(possible_value): arg_value = possible_arg_value.value - else: + else: s = '{}: {}'.format(arg['name'], 'Unknown') args.append(s) continue - if arg['type'] == 'value': + if arg['type'] == 'value': value = arg_value - if arg['type'] == 'pointer': + if arg['type'] == 'pointer': value = '*{}'.format(hex(arg_value)) - if arg['type'] == 'string': - s = self.bv.read(arg_value, self.bv.find_next_data(arg_value, "\x00") - arg_value) + if arg['type'] == 'string': + s = self.bv.read( + arg_value, + self.bv.find_next_data(arg_value, "\x00") - + arg_value) if s: - value = '<{}>'.format(repr(s)) + value = '<{}>'.format(repr(s)) else: - value = '[{}]'.format(hex(arg_value)) - - s = '{}: {}'.format(arg['name'], value) - args.append(s) - - comment = '{syscall_name}({arguments})'.format(syscall_name=syscall['name'], arguments = ", ".join(args)) - function.set_comment(instruction.address, comment) - args = [] + value = '[{}]'.format(hex(arg_value)) + + s = '{}: {}'.format(arg['name'], value) + args.append(s) + + + # finally set comment + comment = '{syscall_name}({arguments})'.format( + syscall_name=syscall['name'], + arguments=", ".join(args)) + + return comment + + def annotate_syscall(self, function, block, instruction, target): + args = [] + # registers = self.bv.platform.calling_conventions[0].int_arg_regs + registers = target.calling_convention.int_arg_regs + if not registers: + bn.log_warning("Non-register based calling conventions are not yet implemented") + return + + comment = self.format_comment(function, instruction, registers) + function.set_comment(instruction.address, comment) + + + def run(self): + for function in self.functions: + for block in function.low_level_il: + for instruction in block: + if instruction.operation == bn.LowLevelILOperation.LLIL_SYSCALL: + self.annotate_llil(function, block, instruction) + elif instruction.operation == bn.LowLevelILOperation.LLIL_CALL: + dest = instruction.dest + if not isinstance(dest, bn.lowlevelil.LowLevelILConstPtr): + continue + target = self.bv.get_function_at(dest) + if target and target.name == "syscall": + self.annotate_syscall(function, block, instruction, target)