ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { zbyte temp_code_slice_data[256] = {0}; ZzArm64Writer *arm64_writer = NULL; ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zaddr target_addr = (zaddr)entry->target_ptr; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); /* prepare 2 stack space: 1. next_hop 2. entry arg */ zz_arm64_writer_put_sub_reg_reg_imm(arm64_writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 0x8); zz_arm64_writer_put_ldr_b_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)entry); zz_arm64_writer_put_str_reg_reg_offset(arm64_writer, ZZ_ARM64_REG_X17, ZZ_ARM64_REG_SP, 0x0); /* jump to half thunk */ zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->half_thunk); /* code patch */ code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); if (code_slice) entry->on_half_trampoline = code_slice->data; else return ZZ_FAILED; return status; }
ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { zbyte temp_code_slice_data[256] = {0}; ZzArm64Writer *arm64_writer = NULL; ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zaddr target_addr = (zaddr)entry->target_ptr; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)entry->on_enter_trampoline); code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, target_addr, zz_arm64_writer_near_jump_range_size()); if (code_slice) entry->on_enter_transfer_trampoline = code_slice->data; else return ZZ_FAILED; if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildEnterTransferTrampoline:"); sprintf(buffer + strlen(buffer), "LogInfo: on_enter_transfer_trampoline at %p, length: %ld. and will jump to on_enter_trampoline(%p).\n", code_slice->data, code_slice->size, entry->on_enter_trampoline); ZzInfoLog("%s", buffer); } free(code_slice); return status; }
ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { zbyte temp_code_slice_data[256] = {0}; ZzArm64Writer *arm64_writer = NULL; ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zaddr target_addr = (zaddr)entry->target_ptr; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); /* prepare 2 stack space: 1. next_hop 2. entry arg */ zz_arm64_writer_put_sub_reg_reg_imm(arm64_writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 0x8); zz_arm64_writer_put_ldr_b_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)entry); zz_arm64_writer_put_str_reg_reg_offset(arm64_writer, ZZ_ARM64_REG_X17, ZZ_ARM64_REG_SP, 0x0); /* jump to enter thunk */ zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->enter_thunk); /* code patch */ code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); if (code_slice) entry->on_enter_trampoline = code_slice->data; else return ZZ_FAILED; /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildEnterTrampoline:"); sprintf(buffer + strlen(buffer), "LogInfo: on_enter_trampoline at %p, length: %ld. hook-entry: %p. and will jump to enter_thunk(%p).\n", code_slice->data, code_slice->size, (void *)entry, (void *)self->enter_thunk); ZzInfoLog("%s", buffer); } if (entry_backend->redirect_code_size == ZZ_ARM64_TINY_REDIRECT_SIZE) { ZzBuildEnterTransferTrampoline(self, entry); } free(code_slice); return status; }
ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { char temp_code_slice_data[512] = {0}; ZzArm64Writer *arm64_writer = NULL; ZzCodeSlice *code_slice = NULL; ZZSTATUS status = ZZ_SUCCESS; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); /* build enter_thunk */ zz_arm64_thunker_build_enter_thunk(arm64_writer); /* code patch */ code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); if (code_slice) self->enter_thunk = (void *)enter_thunk_template; // self->enter_thunk = code_slice->data; else return ZZ_FAILED; /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); sprintf(buffer + strlen(buffer), "LogInfo: enter_thunk at %p, use enter_thunk_template.\n", (void *)enter_thunk_template); // sprintf(buffer + strlen(buffer), "LogInfo: enter_thunk at %p, length: %ld.\n", code_slice->data, // code_slice->size); ZzDebugInfoLog("%s", buffer); } zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); /* build leave_thunk */ zz_arm64_thunker_build_leave_thunk(arm64_writer); /* code patch */ code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); if (code_slice) self->leave_thunk = code_slice->data; else return ZZ_FAILED; /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); sprintf(buffer + strlen(buffer), "LogInfo: leave_thunk at %p, length: %ld.\n", code_slice->data, code_slice->size); ZzDebugInfoLog("%s", buffer); } zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); /* build half_thunk */ zz_arm64_thunker_build_half_thunk(arm64_writer); /* code patch */ code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); if (code_slice) self->half_thunk = code_slice->data; else return ZZ_FAILED; /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); sprintf(buffer + strlen(buffer), "LogInfo: half_thunk at %p, length: %ld.\n", code_slice->data, code_slice->size); ZzDebugInfoLog("%s", buffer); } return status; }