diff --git a/qiling/loader/elf.py b/qiling/loader/elf.py index c1d3eb970..a6131f4fa 100644 --- a/qiling/loader/elf.py +++ b/qiling/loader/elf.py @@ -21,6 +21,7 @@ from qiling.const import QL_ARCH, QL_ENDIAN, QL_OS from qiling.exception import QlErrorELFFormat, QlMemoryMappedError from qiling.loader.loader import QlLoader, Image +from qiling.os.memory import QlMemoryHeap from qiling.os.linux.function_hook import FunctionHook from qiling.os.linux.syscall_nums import SYSCALL_NR from qiling.os.linux.kernel_api.hook import * @@ -57,7 +58,7 @@ class AUXV(IntEnum): # start area memory for API hooking # we will reserve 0x1000 bytes for this (which contains multiple slots of 4/8 bytes, each for one api) -API_HOOK_MEM = 0x1000000 +API_HOOK_MEM = 0x2000000 # memory for syscall table SYSCALL_MEM = API_HOOK_MEM + 0x1000 @@ -87,6 +88,9 @@ def run(self): stack_size = self.profile.getint('stack_size') self.ql.mem.map(stack_address, stack_size, info='[stack]') + # Setup heap + self.ql.os.heap = QlMemoryHeap(self.ql, 0x3000000, 0x3000000 + 0x1000000) + self.path = self.ql.path with open(self.path, 'rb') as infile: @@ -97,7 +101,7 @@ def run(self): # is it a driver? if elftype == 'ET_REL': - self.load_driver(elffile, stack_address + stack_size, loadbase=0x8000000) + self.load_driver(elffile, stack_address + stack_size, loadbase=0x1000000) self.ql.hook_code(hook_kernel_api) # is it an executable? @@ -414,10 +418,19 @@ def lkm_get_init(self, elffile: ELFFile) -> int: raise QlErrorELFFormat('invalid module: symbol init_module not found') def lkm_dynlinker(self, elffile: ELFFile, mem_start: int) -> Mapping[str, int]: + self._symbol_name_map = None def __get_symbol(name: str) -> Optional[Symbol]: _symtab = elffile.get_section_by_name('.symtab') - _sym = _symtab.get_symbol_by_name(name) + # Cache + if self._symbol_name_map == None: + self._symbol_name_map = {} + for i, sym in enumerate(_symtab.iter_symbols()): + if sym.name not in self._symbol_name_map: + self._symbol_name_map[sym.name] = [] + self._symbol_name_map[sym.name].append(sym) + + _sym = None if name not in self._symbol_name_map else self._symbol_name_map[name] return _sym[0] if _sym else None ql = self.ql @@ -555,6 +568,22 @@ def __get_symbol(name: str) -> Optional[Symbol]: ql.mem.write_ptr(prev_mips_hi16_loc + 2, (val >> 16), 2) ql.mem.write_ptr(loc + 2, (val & 0xFFFF), 2) + elif desc in ('R_ARM_CALL', 'R_ARM_JUMP24'): + ins = ql.mem.read_ptr(loc, 4) & 0xFF000000 + val = (((rev_reloc_symbols[symbol_name] - loc) >> 2) - 2) & 0x00FFFFFF + ql.mem.write_ptr(loc, ins | val) + + elif desc == "R_ARM_ABS32": + val = ql.mem.read_ptr(loc, 4) + val += rev_reloc_symbols[symbol_name] + ql.mem.write_ptr(loc, (val & 0xFFFFFFFF), 4) + + elif desc == "R_ARM_PREL31": + ql.log.warning(f'Ignoring relocation type {desc} at 0x{loc:x} for symbol "{symbol_name}" (0x{rev_reloc_symbols[symbol_name]:x})') + + elif desc == "R_ARM_NONE": + ql.log.warning(f'Ignoring relocation type {desc} at 0x{loc:x} for symbol "{symbol_name}" (0x{rev_reloc_symbols[symbol_name]:x})') + else: raise NotImplementedError(f'Relocation type {desc} not implemented') diff --git a/qiling/os/linux/kernel_api/hook.py b/qiling/os/linux/kernel_api/hook.py index 236a881ca..69f906713 100644 --- a/qiling/os/linux/kernel_api/hook.py +++ b/qiling/os/linux/kernel_api/hook.py @@ -4,7 +4,7 @@ # from qiling import Qiling -from qiling.const import QL_INTERCEPT +from qiling.const import QL_INTERCEPT, QL_ARCH from qiling.exception import QlErrorSyscallError, QlErrorSyscallNotFound # import all kernel api hooks to global namespace @@ -25,6 +25,11 @@ def hook_kernel_api(ql: Qiling, address: int, size): if api_func: try: api_func(ql, address, api_name) + + # Restore PC + if ql.arch.type == QL_ARCH.ARM: + ql.arch.regs.arch_sp -= ql.arch.pointersize + ql.arch.regs.arch_pc = ql.arch.regs.lr except Exception: ql.log.exception("") ql.log.debug("%s Exception Found" % api_name) diff --git a/qiling/os/linux/kernel_api/kernel_api.py b/qiling/os/linux/kernel_api/kernel_api.py index c16ed3256..7209c9927 100644 --- a/qiling/os/linux/kernel_api/kernel_api.py +++ b/qiling/os/linux/kernel_api/kernel_api.py @@ -115,10 +115,28 @@ def hook_kmalloc_caches(ql, address, params): }) def hook_kmalloc(ql, address, params): size = params['size'] - addr = ql.heap.alloc(size) + addr = ql.os.heap.alloc(size) return addr +@linux_kernel_api(params={ + "size": SIZE_T, + "flags": INT +}) +def hook___kmalloc(ql, address, params): + size = params['size'] + addr = ql.os.heap.alloc(size) + return addr + + +@linux_kernel_api(params={ + "p": POINTER +}) +def hook_ksize(ql, address, params): + p = params['p'] + size = ql.os.heap.size(p) + return size + @linux_kernel_api(params={ "dest": POINTER, "c": INT, @@ -147,10 +165,11 @@ def hook_get_by_key(ql, address, params): @linux_kernel_api(params={ - "Ptr": POINTER + "p": POINTER }) def hook_kfree(ql, address, params): - pass + p = params['p'] + ql.os.heap.free(p) @linux_kernel_api(params={