(c_function, python_function)
| 16 | CPUProgram.rt_lib["__clear_cache"](fxn_address_value, fxn_address_value + len(tramp)) |
| 17 | |
| 18 | def install_hook(c_function, python_function): |
| 19 | python_function_addr = ctypes.cast(ctypes.byref(python_function), ctypes.POINTER(ctypes.c_ulong)).contents.value |
| 20 | # AARCH64 trampoline to ioctl |
| 21 | if (processor:=platform.processor()) == "aarch64": |
| 22 | # 0x0000000000000000: 70 00 00 10 adr x16, #0xc |
| 23 | # 0x0000000000000004: 10 02 40 F9 ldr x16, [x16] |
| 24 | # 0x0000000000000008: 00 02 1F D6 br x16 |
| 25 | tramp = b"\x70\x00\x00\x10\x10\x02\x40\xf9\x00\x02\x1f\xd6" |
| 26 | tramp += struct.pack("Q", python_function_addr) |
| 27 | elif processor == "x86_64": |
| 28 | # 0x0000000000000000: 49 BB aa aa aa aa aa aa aa aa movabs r11, <address> |
| 29 | # 0x000000000000000a: 41 FF E3 jmp r11 |
| 30 | tramp = b"\x49\xBB" + struct.pack("Q", python_function_addr) + b"\x41\xFF\xE3" |
| 31 | else: |
| 32 | raise Exception(f"processor {processor} not supported") |
| 33 | tramp = ctypes.create_string_buffer(tramp) |
| 34 | |
| 35 | # get real function address |
| 36 | fxn_address = ctypes.cast(ctypes.byref(c_function), ctypes.POINTER(ctypes.c_ulong)) |
| 37 | fxn_address_value = fxn_address.contents.value |
| 38 | #print(f"** hooking function at 0x{fxn_address_value}") |
| 39 | |
| 40 | orig_save = (ctypes.c_char*len(tramp))() |
| 41 | libc.memcpy(orig_save, fxn_address_value, len(tramp)) |
| 42 | _hook(fxn_address_value, tramp) |
| 43 | |
| 44 | def original(*args): |
| 45 | _hook(fxn_address_value, orig_save) |
| 46 | ret = c_function(*args) |
| 47 | _hook(fxn_address_value, tramp) |
| 48 | return ret |
| 49 | return original |
| 50 | |
| 51 | hooked = {} |
| 52 |
no test coverage detected
searching dependent graphs…