From 7d4e4c0b34a613dd3c0220475ae4e448197522c1 Mon Sep 17 00:00:00 2001 From: Treeki Date: Sat, 12 Mar 2011 23:17:12 +0100 Subject: initial commit. now I can start playing with stuff! --- tools/hooks.py | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100755 tools/hooks.py (limited to 'tools/hooks.py') diff --git a/tools/hooks.py b/tools/hooks.py new file mode 100755 index 0000000..13c4e19 --- /dev/null +++ b/tools/hooks.py @@ -0,0 +1,166 @@ +import binascii +import struct + +u32 = struct.Struct('>I') + +def make_branch_insn(fromAddr, toAddr, branchType): + branchTypes = ['b', 'bl', 'ba', 'bla'] + if branchType not in branchTypes: + raise ValueError, 'invalid branch type: %s' % branchType + + extra = branchTypes.index(branchType) + + distance = toAddr - fromAddr + if distance >= 0x2000000 or distance <= -0x2000000: + raise ValueError, 'branching too far: %08x to %08x' % (fromAddr, toAddr) + + return (distance & 0x3FFFFFC) | 0x48000000 | extra + + + +class HookContext(object): + """Object which can be used by each hook type to hold data.""" + + def __init__(self): + self.hooks = [] + + + +class Hook(object): + """Generic hook class""" + + has_context = False + required_data = [] + + def __init__(self, builder, module, data): + """Sets up a hook""" + self.builder = builder + self.module = module + self.data = data + + if self.has_context: + hookType = type(self) + self.context = builder._hook_contexts[hookType] + self.context.hooks.append(self) + + # validate the hook's data + current_config_name = builder._config_short_name + + for field in self.required_data: + field = field.replace('%CONFIG%', current_config_name) + if field not in data: + raise ValueError, 'hook %s : %s is missing the field %s' % (module.moduleName, data['name'], field) + + def create_patches(self): + pass + + + +class BasicPatchHook(Hook): + """Hook that simply patches data to an address""" + + required_data = ['addr_%CONFIG%', 'data'] + + def __init__(self, builder, module, data): + Hook.__init__(self, builder, module, data) + + def create_patches(self): + addr = self.data['addr_%s' % self.builder._config_short_name] + + hex_data = self.data['data'] + + whitespace = ' \n\r\t' + for char in whitespace: + hex_data = hex_data.replace(char, '') + + patch = binascii.unhexlify(hex_data) + + self.builder._add_patch(addr, patch) + + + +class BranchInsnHook(Hook): + """Hook that replaces the instruction at a specific address with a branch""" + + required_data = ['branch_type', 'src_addr_%CONFIG%'] + + def __init__(self, builder, module, data): + Hook.__init__(self, builder, module, data) + + def create_patches(self): + try: + target_func = self.data['target_func'] + except KeyError: + target_func = self.data['target_func_%s' % self.builder._config_short_name] + + if isinstance(target_func, str): + target_func = self.builder._find_func_by_symbol(target_func) + else: + # assume it's an address + pass + + + src_addr = self.data['src_addr_%s' % self.builder._config_short_name] + branch_insn = make_branch_insn(src_addr, target_func, self.data['branch_type']) + + self.builder._add_patch(src_addr, u32.pack(branch_insn)) + + + +class AddFunctionPointerHook(Hook): + """Hook that places a function pointer at an address""" + + required_data = ['src_addr_%CONFIG%'] + + def __init__(self, builder, module, data): + Hook.__init__(self, builder, module, data) + + def create_patches(self): + try: + target_func = self.data['target_func'] + except KeyError: + target_func = self.data['target_func_%s' % self.builder._config_short_name] + + if isinstance(target_func, str): + target_func = self.builder._find_func_by_symbol(target_func) + else: + # assume it's an address + pass + + + src_addr = self.data['src_addr_%s' % self.builder._config_short_name] + + self.builder._add_patch(src_addr, u32.pack(target_func)) + + + +class NopInsnHook(Hook): + """Hook that NOPs out the instruction(s) at an address""" + + required_data = ['area_%CONFIG%'] + + def __init__(self, builder, module, data): + Hook.__init__(self, builder, module, data) + + def create_patches(self): + area = self.data['area_%s' % self.builder._config_short_name] + + if isinstance(area, list): + addr, end = area + count = (end + 4 - addr) / 4 + nop_patch = '\x60\x00\x00\x00' * count + else: + addr = area + nop_patch = '\x60\x00\x00\x00' + + self.builder._add_patch(addr, nop_patch) + + + +HookTypes = { + 'patch': BasicPatchHook, + 'branch_insn': BranchInsnHook, + 'add_func_pointer': AddFunctionPointerHook, + 'nop_insn': NopInsnHook, +} + -- cgit v1.2.3